Commit 608c8e4f authored by Harald Welte's avatar Harald Welte Committed by David S. Miller

[NETFILTER]: Extend netfilter logging API

This patch is in preparation to nfnetlink_log:
- loggers now have to register struct nf_logger instead of nf_logfn
- nf_log_unregister() replaced by nf_log_unregister_pf() and
  nf_log_unregister_logger()
- add comment to ip[6]t_LOG.h to assure nobody redefines flags
- add /proc/net/netfilter/nf_log to tell user which logger is currently
  registered for which address family
- if user has configured logging, but no logging backend (logger) is
  available, always spit a message to syslog, not just the first time.
- split ip[6]t_LOG.c into two parts:
  Backend: Always try to register as logger for the respective address family
  Frontend: Always log via nf_log_packet() API
- modify all users of nf_log_packet() to accomodate additional argument
Signed-off-by: default avatarHarald Welte <laforge@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 838ab636
...@@ -114,15 +114,51 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg); ...@@ -114,15 +114,51 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]; extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
typedef void nf_logfn(unsigned int hooknum, /* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
* disappear once iptables is replaced with pkttables. Please DO NOT use them
* for any new code! */
#define NF_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define NF_LOG_TCPOPT 0x02 /* Log TCP options */
#define NF_LOG_IPOPT 0x04 /* Log IP options */
#define NF_LOG_UID 0x08 /* Log UID owning local socket */
#define NF_LOG_MASK 0x0f
#define NF_LOG_TYPE_LOG 0x01
#define NF_LOG_TYPE_ULOG 0x02
struct nf_loginfo {
u_int8_t type;
union {
struct {
u_int32_t copy_len;
u_int16_t group;
u_int16_t qthreshold;
} ulog;
struct {
u_int8_t level;
u_int8_t logflags;
} log;
} u;
};
typedef void nf_logfn(unsigned int pf,
unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
const struct nf_loginfo *li,
const char *prefix); const char *prefix);
struct nf_logger {
struct module *me;
nf_logfn *logfn;
char *name;
};
/* Function to register/unregister log function. */ /* Function to register/unregister log function. */
int nf_log_register(int pf, nf_logfn *logfn); int nf_log_register(int pf, struct nf_logger *logger);
void nf_log_unregister(int pf, nf_logfn *logfn); void nf_log_unregister_pf(int pf);
void nf_log_unregister_logger(struct nf_logger *logger);
/* Calls the registered backend logging function */ /* Calls the registered backend logging function */
void nf_log_packet(int pf, void nf_log_packet(int pf,
...@@ -130,6 +166,7 @@ void nf_log_packet(int pf, ...@@ -130,6 +166,7 @@ void nf_log_packet(int pf,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
struct nf_loginfo *li,
const char *fmt, ...); const char *fmt, ...);
/* Activate hook; either okfn or kfree_skb called, unless a hook /* Activate hook; either okfn or kfree_skb called, unless a hook
...@@ -221,6 +258,11 @@ struct nf_queue_rerouter { ...@@ -221,6 +258,11 @@ struct nf_queue_rerouter {
extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer); extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
extern int nf_unregister_queue_rerouter(int pf); extern int nf_unregister_queue_rerouter(int pf);
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
extern struct proc_dir_entry *proc_net_netfilter;
#endif
#else /* !CONFIG_NETFILTER */ #else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
......
#ifndef _IPT_LOG_H #ifndef _IPT_LOG_H
#define _IPT_LOG_H #define _IPT_LOG_H
/* make sure not to change this without changing netfilter.h:NF_LOG_* (!) */
#define IPT_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */ #define IPT_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define IPT_LOG_TCPOPT 0x02 /* Log TCP options */ #define IPT_LOG_TCPOPT 0x02 /* Log TCP options */
#define IPT_LOG_IPOPT 0x04 /* Log IP options */ #define IPT_LOG_IPOPT 0x04 /* Log IP options */
......
#ifndef _IP6T_LOG_H #ifndef _IP6T_LOG_H
#define _IP6T_LOG_H #define _IP6T_LOG_H
/* make sure not to change this without changing netfilter.h:NF_LOG_* (!) */
#define IP6T_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */ #define IP6T_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */ #define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */
#define IP6T_LOG_IPOPT 0x04 /* Log IP options */ #define IP6T_LOG_IPOPT 0x04 /* Log IP options */
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/inetdevice.h> #include <linux/inetdevice.h>
#include <linux/proc_fs.h>
#include <net/sock.h> #include <net/sock.h>
/* In this code, we can be waiting indefinitely for userspace to /* In this code, we can be waiting indefinitely for userspace to
...@@ -535,11 +536,10 @@ EXPORT_SYMBOL(skb_make_writable); ...@@ -535,11 +536,10 @@ EXPORT_SYMBOL(skb_make_writable);
#define NF_LOG_PREFIXLEN 128 #define NF_LOG_PREFIXLEN 128
static nf_logfn *nf_logging[NPROTO]; /* = NULL */ static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
static int reported = 0;
static DEFINE_SPINLOCK(nf_log_lock); static DEFINE_SPINLOCK(nf_log_lock);
int nf_log_register(int pf, nf_logfn *logfn) int nf_log_register(int pf, struct nf_logger *logger)
{ {
int ret = -EBUSY; int ret = -EBUSY;
...@@ -547,54 +547,134 @@ int nf_log_register(int pf, nf_logfn *logfn) ...@@ -547,54 +547,134 @@ int nf_log_register(int pf, nf_logfn *logfn)
* substituting pointer. */ * substituting pointer. */
spin_lock(&nf_log_lock); spin_lock(&nf_log_lock);
if (!nf_logging[pf]) { if (!nf_logging[pf]) {
rcu_assign_pointer(nf_logging[pf], logfn); rcu_assign_pointer(nf_logging[pf], logger);
ret = 0; ret = 0;
} }
spin_unlock(&nf_log_lock); spin_unlock(&nf_log_lock);
return ret; return ret;
} }
void nf_log_unregister(int pf, nf_logfn *logfn) void nf_log_unregister_pf(int pf)
{ {
spin_lock(&nf_log_lock); spin_lock(&nf_log_lock);
if (nf_logging[pf] == logfn) nf_logging[pf] = NULL;
nf_logging[pf] = NULL;
spin_unlock(&nf_log_lock); spin_unlock(&nf_log_lock);
/* Give time to concurrent readers. */ /* Give time to concurrent readers. */
synchronize_net(); synchronize_net();
} }
void nf_log_unregister_logger(struct nf_logger *logger)
{
int i;
spin_lock(&nf_log_lock);
for (i = 0; i < NPROTO; i++) {
if (nf_logging[i] == logger)
nf_logging[i] = NULL;
}
spin_unlock(&nf_log_lock);
synchronize_net();
}
void nf_log_packet(int pf, void nf_log_packet(int pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
struct nf_loginfo *loginfo,
const char *fmt, ...) const char *fmt, ...)
{ {
va_list args; va_list args;
char prefix[NF_LOG_PREFIXLEN]; char prefix[NF_LOG_PREFIXLEN];
nf_logfn *logfn; struct nf_logger *logger;
rcu_read_lock(); rcu_read_lock();
logfn = rcu_dereference(nf_logging[pf]); logger = rcu_dereference(nf_logging[pf]);
if (logfn) { if (logger) {
va_start(args, fmt); va_start(args, fmt);
vsnprintf(prefix, sizeof(prefix), fmt, args); vsnprintf(prefix, sizeof(prefix), fmt, args);
va_end(args); va_end(args);
/* We must read logging before nf_logfn[pf] */ /* We must read logging before nf_logfn[pf] */
logfn(hooknum, skb, in, out, prefix); logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
} else if (!reported) { } else if (net_ratelimit()) {
printk(KERN_WARNING "nf_log_packet: can\'t log yet, " printk(KERN_WARNING "nf_log_packet: can\'t log since "
"no backend logging module loaded in!\n"); "no backend logging module loaded in! Please either "
reported++; "load one, or disable logging explicitly\n");
} }
rcu_read_unlock(); rcu_read_unlock();
} }
EXPORT_SYMBOL(nf_log_register); EXPORT_SYMBOL(nf_log_register);
EXPORT_SYMBOL(nf_log_unregister); EXPORT_SYMBOL(nf_log_unregister_pf);
EXPORT_SYMBOL(nf_log_unregister_logger);
EXPORT_SYMBOL(nf_log_packet); EXPORT_SYMBOL(nf_log_packet);
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_net_netfilter;
EXPORT_SYMBOL(proc_net_netfilter);
static void *seq_start(struct seq_file *seq, loff_t *pos)
{
rcu_read_lock();
if (*pos >= NPROTO)
return NULL;
return pos;
}
static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
{
(*pos)++;
if (*pos >= NPROTO)
return NULL;
return pos;
}
static void seq_stop(struct seq_file *s, void *v)
{
rcu_read_unlock();
}
static int seq_show(struct seq_file *s, void *v)
{
loff_t *pos = v;
const struct nf_logger *logger;
logger = rcu_dereference(nf_logging[*pos]);
if (!logger)
return seq_printf(s, "%2lld NONE\n", *pos);
return seq_printf(s, "%2lld %s\n", *pos, logger->name);
}
static struct seq_operations nflog_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
.show = seq_show,
};
static int nflog_open(struct inode *inode, struct file *file)
{
return seq_open(file, &nflog_seq_ops);
}
static struct file_operations nflog_file_ops = {
.owner = THIS_MODULE,
.open = nflog_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#endif /* PROC_FS */
/* This does not belong here, but locally generated errors need it if connection /* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, and hence tracking in use: without this, connection may not be in hash table, and hence
manufactured ICMP or RST packets will not be associated with it. */ manufactured ICMP or RST packets will not be associated with it. */
...@@ -613,6 +693,9 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) ...@@ -613,6 +693,9 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
void __init netfilter_init(void) void __init netfilter_init(void)
{ {
int i, h; int i, h;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *pde;
#endif
queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter), queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
GFP_KERNEL); GFP_KERNEL);
...@@ -624,6 +707,16 @@ void __init netfilter_init(void) ...@@ -624,6 +707,16 @@ void __init netfilter_init(void)
for (h = 0; h < NF_MAX_HOOKS; h++) for (h = 0; h < NF_MAX_HOOKS; h++)
INIT_LIST_HEAD(&nf_hooks[i][h]); INIT_LIST_HEAD(&nf_hooks[i][h]);
} }
#ifdef CONFIG_PROC_FS
proc_net_netfilter = proc_mkdir("netfilter", proc_net);
if (!proc_net_netfilter)
panic("cannot create netfilter proc entry");
pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter);
if (!pde)
panic("cannot create /proc/net/netfilter/nf_log");
pde->proc_fops = &nflog_file_ops;
#endif
} }
EXPORT_SYMBOL(ip_ct_attach); EXPORT_SYMBOL(ip_ct_attach);
......
...@@ -217,7 +217,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -217,7 +217,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih); icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih);
if (icmph == NULL) { if (icmph == NULL) {
if (LOG_INVALID(IPPROTO_ICMP)) if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: short packet "); "ip_ct_icmp: short packet ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -231,13 +231,13 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -231,13 +231,13 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
if (!(u16)csum_fold(skb->csum)) if (!(u16)csum_fold(skb->csum))
break; break;
if (LOG_INVALID(IPPROTO_ICMP)) if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: bad HW ICMP checksum "); "ip_ct_icmp: bad HW ICMP checksum ");
return -NF_ACCEPT; return -NF_ACCEPT;
case CHECKSUM_NONE: case CHECKSUM_NONE:
if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) { if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
if (LOG_INVALID(IPPROTO_ICMP)) if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: bad ICMP checksum "); "ip_ct_icmp: bad ICMP checksum ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -254,7 +254,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -254,7 +254,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
*/ */
if (icmph->type > NR_ICMP_TYPES) { if (icmph->type > NR_ICMP_TYPES) {
if (LOG_INVALID(IPPROTO_ICMP)) if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: invalid ICMP type "); "ip_ct_icmp: invalid ICMP type ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
......
...@@ -716,7 +716,7 @@ static int tcp_in_window(struct ip_ct_tcp *state, ...@@ -716,7 +716,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
res = 1; res = 1;
} else { } else {
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: %s ", "ip_ct_tcp: %s ",
before(seq, sender->td_maxend + 1) ? before(seq, sender->td_maxend + 1) ?
after(end, sender->td_end - receiver->td_maxwin - 1) ? after(end, sender->td_end - receiver->td_maxwin - 1) ?
...@@ -815,7 +815,7 @@ static int tcp_error(struct sk_buff *skb, ...@@ -815,7 +815,7 @@ static int tcp_error(struct sk_buff *skb,
sizeof(_tcph), &_tcph); sizeof(_tcph), &_tcph);
if (th == NULL) { if (th == NULL) {
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: short packet "); "ip_ct_tcp: short packet ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -823,7 +823,7 @@ static int tcp_error(struct sk_buff *skb, ...@@ -823,7 +823,7 @@ static int tcp_error(struct sk_buff *skb,
/* Not whole TCP header or malformed packet */ /* Not whole TCP header or malformed packet */
if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) { if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: truncated/malformed packet "); "ip_ct_tcp: truncated/malformed packet ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -840,7 +840,7 @@ static int tcp_error(struct sk_buff *skb, ...@@ -840,7 +840,7 @@ static int tcp_error(struct sk_buff *skb,
skb->ip_summed == CHECKSUM_HW ? skb->csum skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, tcplen, 0))) { : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: bad TCP checksum "); "ip_ct_tcp: bad TCP checksum ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -849,7 +849,7 @@ static int tcp_error(struct sk_buff *skb, ...@@ -849,7 +849,7 @@ static int tcp_error(struct sk_buff *skb,
tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR)); tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR));
if (!tcp_valid_flags[tcpflags]) { if (!tcp_valid_flags[tcpflags]) {
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: invalid TCP flag combination "); "ip_ct_tcp: invalid TCP flag combination ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -897,8 +897,9 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -897,8 +897,9 @@ static int tcp_packet(struct ip_conntrack *conntrack,
*/ */
write_unlock_bh(&tcp_lock); write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: killing out of sync session "); NULL, "ip_ct_tcp: "
"killing out of sync session ");
if (del_timer(&conntrack->timeout)) if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long) conntrack->timeout.function((unsigned long)
conntrack); conntrack);
...@@ -912,7 +913,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -912,7 +913,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
write_unlock_bh(&tcp_lock); write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: invalid packet ignored "); "ip_ct_tcp: invalid packet ignored ");
return NF_ACCEPT; return NF_ACCEPT;
case TCP_CONNTRACK_MAX: case TCP_CONNTRACK_MAX:
...@@ -922,7 +923,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -922,7 +923,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
old_state); old_state);
write_unlock_bh(&tcp_lock); write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: invalid state "); "ip_ct_tcp: invalid state ");
return -NF_ACCEPT; return -NF_ACCEPT;
case TCP_CONNTRACK_SYN_SENT: case TCP_CONNTRACK_SYN_SENT:
...@@ -943,7 +944,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -943,7 +944,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
write_unlock_bh(&tcp_lock); write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: invalid SYN"); NULL, "ip_ct_tcp: invalid SYN");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
case TCP_CONNTRACK_CLOSE: case TCP_CONNTRACK_CLOSE:
......
...@@ -98,7 +98,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -98,7 +98,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
hdr = skb_header_pointer(skb, iph->ihl*4, sizeof(_hdr), &_hdr); hdr = skb_header_pointer(skb, iph->ihl*4, sizeof(_hdr), &_hdr);
if (hdr == NULL) { if (hdr == NULL) {
if (LOG_INVALID(IPPROTO_UDP)) if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: short packet "); "ip_ct_udp: short packet ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -106,7 +106,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -106,7 +106,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
/* Truncated/malformed packets */ /* Truncated/malformed packets */
if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) { if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
if (LOG_INVALID(IPPROTO_UDP)) if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: truncated/malformed packet "); "ip_ct_udp: truncated/malformed packet ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -126,7 +126,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -126,7 +126,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
skb->ip_summed == CHECKSUM_HW ? skb->csum skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, udplen, 0))) { : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
if (LOG_INVALID(IPPROTO_UDP)) if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: bad UDP checksum "); "ip_ct_udp: bad UDP checksum ");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
......
...@@ -27,10 +27,6 @@ MODULE_LICENSE("GPL"); ...@@ -27,10 +27,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables syslog logging module"); MODULE_DESCRIPTION("iptables syslog logging module");
static unsigned int nflog = 1;
module_param(nflog, int, 0400);
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
#else #else
...@@ -41,11 +37,17 @@ MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); ...@@ -41,11 +37,17 @@ MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
static DEFINE_SPINLOCK(log_lock); static DEFINE_SPINLOCK(log_lock);
/* One level of recursion won't kill us */ /* One level of recursion won't kill us */
static void dump_packet(const struct ipt_log_info *info, static void dump_packet(const struct nf_loginfo *info,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int iphoff) unsigned int iphoff)
{ {
struct iphdr _iph, *ih; struct iphdr _iph, *ih;
unsigned int logflags;
if (info->type == NF_LOG_TYPE_LOG)
logflags = info->u.log.logflags;
else
logflags = NF_LOG_MASK;
ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
if (ih == NULL) { if (ih == NULL) {
...@@ -76,7 +78,7 @@ static void dump_packet(const struct ipt_log_info *info, ...@@ -76,7 +78,7 @@ static void dump_packet(const struct ipt_log_info *info,
if (ntohs(ih->frag_off) & IP_OFFSET) if (ntohs(ih->frag_off) & IP_OFFSET)
printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
if ((info->logflags & IPT_LOG_IPOPT) if ((logflags & IPT_LOG_IPOPT)
&& ih->ihl * 4 > sizeof(struct iphdr)) { && ih->ihl * 4 > sizeof(struct iphdr)) {
unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op; unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
unsigned int i, optsize; unsigned int i, optsize;
...@@ -119,7 +121,7 @@ static void dump_packet(const struct ipt_log_info *info, ...@@ -119,7 +121,7 @@ static void dump_packet(const struct ipt_log_info *info,
printk("SPT=%u DPT=%u ", printk("SPT=%u DPT=%u ",
ntohs(th->source), ntohs(th->dest)); ntohs(th->source), ntohs(th->dest));
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
if (info->logflags & IPT_LOG_TCPSEQ) if (logflags & IPT_LOG_TCPSEQ)
printk("SEQ=%u ACK=%u ", printk("SEQ=%u ACK=%u ",
ntohl(th->seq), ntohl(th->ack_seq)); ntohl(th->seq), ntohl(th->ack_seq));
/* Max length: 13 "WINDOW=65535 " */ /* Max length: 13 "WINDOW=65535 " */
...@@ -146,7 +148,7 @@ static void dump_packet(const struct ipt_log_info *info, ...@@ -146,7 +148,7 @@ static void dump_packet(const struct ipt_log_info *info,
/* Max length: 11 "URGP=65535 " */ /* Max length: 11 "URGP=65535 " */
printk("URGP=%u ", ntohs(th->urg_ptr)); printk("URGP=%u ", ntohs(th->urg_ptr));
if ((info->logflags & IPT_LOG_TCPOPT) if ((logflags & IPT_LOG_TCPOPT)
&& th->doff * 4 > sizeof(struct tcphdr)) { && th->doff * 4 > sizeof(struct tcphdr)) {
unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
unsigned char *op; unsigned char *op;
...@@ -328,7 +330,7 @@ static void dump_packet(const struct ipt_log_info *info, ...@@ -328,7 +330,7 @@ static void dump_packet(const struct ipt_log_info *info,
} }
/* Max length: 15 "UID=4294967295 " */ /* Max length: 15 "UID=4294967295 " */
if ((info->logflags & IPT_LOG_UID) && !iphoff && skb->sk) { if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
read_lock_bh(&skb->sk->sk_callback_lock); read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file) if (skb->sk->sk_socket && skb->sk->sk_socket->file)
printk("UID=%u ", skb->sk->sk_socket->file->f_uid); printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
...@@ -349,19 +351,31 @@ static void dump_packet(const struct ipt_log_info *info, ...@@ -349,19 +351,31 @@ static void dump_packet(const struct ipt_log_info *info,
/* maxlen = 230+ 91 + 230 + 252 = 803 */ /* maxlen = 230+ 91 + 230 + 252 = 803 */
} }
struct nf_loginfo default_loginfo = {
.type = NF_LOG_TYPE_LOG,
.u = {
.log = {
.level = 0,
.logflags = NF_LOG_MASK,
},
},
};
static void static void
ipt_log_packet(unsigned int hooknum, ipt_log_packet(unsigned int pf,
unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
const struct ipt_log_info *loginfo, const struct nf_loginfo *loginfo,
const char *level_string,
const char *prefix) const char *prefix)
{ {
if (!loginfo)
loginfo = &default_loginfo;
spin_lock_bh(&log_lock); spin_lock_bh(&log_lock);
printk(level_string); printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
printk("%sIN=%s OUT=%s ", prefix,
prefix == NULL ? loginfo->prefix : prefix,
in ? in->name : "", in ? in->name : "",
out ? out->name : ""); out ? out->name : "");
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
...@@ -405,28 +419,15 @@ ipt_log_target(struct sk_buff **pskb, ...@@ -405,28 +419,15 @@ ipt_log_target(struct sk_buff **pskb,
void *userinfo) void *userinfo)
{ {
const struct ipt_log_info *loginfo = targinfo; const struct ipt_log_info *loginfo = targinfo;
char level_string[4] = "< >"; struct nf_loginfo li;
level_string[1] = '0' + (loginfo->level % 8); li.type = NF_LOG_TYPE_LOG;
ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL); li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
return IPT_CONTINUE; nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix);
}
static void return IPT_CONTINUE;
ipt_logfn(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *prefix)
{
struct ipt_log_info loginfo = {
.level = 0,
.logflags = IPT_LOG_MASK,
.prefix = ""
};
ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
} }
static int ipt_log_checkentry(const char *tablename, static int ipt_log_checkentry(const char *tablename,
...@@ -464,20 +465,29 @@ static struct ipt_target ipt_log_reg = { ...@@ -464,20 +465,29 @@ static struct ipt_target ipt_log_reg = {
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
static struct nf_logger ipt_log_logger ={
.name = "ipt_LOG",
.logfn = &ipt_log_packet,
.me = THIS_MODULE,
};
static int __init init(void) static int __init init(void)
{ {
if (ipt_register_target(&ipt_log_reg)) if (ipt_register_target(&ipt_log_reg))
return -EINVAL; return -EINVAL;
if (nflog) if (nf_log_register(PF_INET, &ipt_log_logger) < 0) {
nf_log_register(PF_INET, &ipt_logfn); printk(KERN_WARNING "ipt_LOG: not logging via system console "
"since somebody else already registered for PF_INET\n");
/* we cannot make module load fail here, since otherwise
* iptables userspace would abort */
}
return 0; return 0;
} }
static void __exit fini(void) static void __exit fini(void)
{ {
if (nflog) nf_log_unregister_logger(&ipt_log_logger);
nf_log_unregister(PF_INET, &ipt_logfn);
ipt_unregister_target(&ipt_log_reg); ipt_unregister_target(&ipt_log_reg);
} }
......
...@@ -304,18 +304,27 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -304,18 +304,27 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
return IPT_CONTINUE; return IPT_CONTINUE;
} }
static void ipt_logfn(unsigned int hooknum, static void ipt_logfn(unsigned int pf,
unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
const struct nf_loginfo *li,
const char *prefix) const char *prefix)
{ {
struct ipt_ulog_info loginfo = { struct ipt_ulog_info loginfo;
.nl_group = ULOG_DEFAULT_NLGROUP,
.copy_range = 0, if (!li || li->type != NF_LOG_TYPE_ULOG) {
.qthreshold = ULOG_DEFAULT_QTHRESHOLD, loginfo.nl_group = ULOG_DEFAULT_NLGROUP;
.prefix = "" loginfo.copy_range = 0;
}; loginfo.qthreshold = ULOG_DEFAULT_QTHRESHOLD;
loginfo.prefix[0] = '\0';
} else {
loginfo.nl_group = li->u.ulog.group;
loginfo.copy_range = li->u.ulog.copy_len;
loginfo.qthreshold = li->u.ulog.qthreshold;
strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
}
ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
} }
...@@ -355,6 +364,12 @@ static struct ipt_target ipt_ulog_reg = { ...@@ -355,6 +364,12 @@ static struct ipt_target ipt_ulog_reg = {
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
static struct nf_logger ipt_ulog_logger = {
.name = "ipt_ULOG",
.logfn = &ipt_logfn,
.me = THIS_MODULE,
};
static int __init init(void) static int __init init(void)
{ {
int i; int i;
...@@ -382,7 +397,7 @@ static int __init init(void) ...@@ -382,7 +397,7 @@ static int __init init(void)
return -EINVAL; return -EINVAL;
} }
if (nflog) if (nflog)
nf_log_register(PF_INET, &ipt_logfn); nf_log_register(PF_INET, &ipt_ulog_logger);
return 0; return 0;
} }
...@@ -395,7 +410,7 @@ static void __exit fini(void) ...@@ -395,7 +410,7 @@ static void __exit fini(void)
DEBUGP("ipt_ULOG: cleanup_module\n"); DEBUGP("ipt_ULOG: cleanup_module\n");
if (nflog) if (nflog)
nf_log_unregister(PF_INET, &ipt_logfn); nf_log_unregister_logger(&ipt_ulog_logger);
ipt_unregister_target(&ipt_ulog_reg); ipt_unregister_target(&ipt_ulog_reg);
sock_release(nflognl->sk_socket); sock_release(nflognl->sk_socket);
......
...@@ -26,10 +26,6 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); ...@@ -26,10 +26,6 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
MODULE_DESCRIPTION("IP6 tables LOG target module"); MODULE_DESCRIPTION("IP6 tables LOG target module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static unsigned int nflog = 1;
module_param(nflog, int, 0400);
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
struct in_device; struct in_device;
#include <net/route.h> #include <net/route.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h> #include <linux/netfilter_ipv6/ip6t_LOG.h>
...@@ -44,7 +40,7 @@ struct in_device; ...@@ -44,7 +40,7 @@ struct in_device;
static DEFINE_SPINLOCK(log_lock); static DEFINE_SPINLOCK(log_lock);
/* One level of recursion won't kill us */ /* One level of recursion won't kill us */
static void dump_packet(const struct ip6t_log_info *info, static void dump_packet(const struct nf_loginfo *info,
const struct sk_buff *skb, unsigned int ip6hoff, const struct sk_buff *skb, unsigned int ip6hoff,
int recurse) int recurse)
{ {
...@@ -53,6 +49,12 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -53,6 +49,12 @@ static void dump_packet(const struct ip6t_log_info *info,
struct ipv6hdr _ip6h, *ih; struct ipv6hdr _ip6h, *ih;
unsigned int ptr; unsigned int ptr;
unsigned int hdrlen = 0; unsigned int hdrlen = 0;
unsigned int logflags;
if (info->type == NF_LOG_TYPE_LOG)
logflags = info->u.log.logflags;
else
logflags = NF_LOG_MASK;
ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
if (ih == NULL) { if (ih == NULL) {
...@@ -84,7 +86,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -84,7 +86,7 @@ static void dump_packet(const struct ip6t_log_info *info,
} }
/* Max length: 48 "OPT (...) " */ /* Max length: 48 "OPT (...) " */
if (info->logflags & IP6T_LOG_IPOPT) if (logflags & IP6T_LOG_IPOPT)
printk("OPT ( "); printk("OPT ( ");
switch (currenthdr) { switch (currenthdr) {
...@@ -119,7 +121,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -119,7 +121,7 @@ static void dump_packet(const struct ip6t_log_info *info,
case IPPROTO_ROUTING: case IPPROTO_ROUTING:
case IPPROTO_HOPOPTS: case IPPROTO_HOPOPTS:
if (fragment) { if (fragment) {
if (info->logflags & IP6T_LOG_IPOPT) if (logflags & IP6T_LOG_IPOPT)
printk(")"); printk(")");
return; return;
} }
...@@ -127,7 +129,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -127,7 +129,7 @@ static void dump_packet(const struct ip6t_log_info *info,
break; break;
/* Max Length */ /* Max Length */
case IPPROTO_AH: case IPPROTO_AH:
if (info->logflags & IP6T_LOG_IPOPT) { if (logflags & IP6T_LOG_IPOPT) {
struct ip_auth_hdr _ahdr, *ah; struct ip_auth_hdr _ahdr, *ah;
/* Max length: 3 "AH " */ /* Max length: 3 "AH " */
...@@ -158,7 +160,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -158,7 +160,7 @@ static void dump_packet(const struct ip6t_log_info *info,
hdrlen = (hp->hdrlen+2)<<2; hdrlen = (hp->hdrlen+2)<<2;
break; break;
case IPPROTO_ESP: case IPPROTO_ESP:
if (info->logflags & IP6T_LOG_IPOPT) { if (logflags & IP6T_LOG_IPOPT) {
struct ip_esp_hdr _esph, *eh; struct ip_esp_hdr _esph, *eh;
/* Max length: 4 "ESP " */ /* Max length: 4 "ESP " */
...@@ -190,7 +192,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -190,7 +192,7 @@ static void dump_packet(const struct ip6t_log_info *info,
printk("Unknown Ext Hdr %u", currenthdr); printk("Unknown Ext Hdr %u", currenthdr);
return; return;
} }
if (info->logflags & IP6T_LOG_IPOPT) if (logflags & IP6T_LOG_IPOPT)
printk(") "); printk(") ");
currenthdr = hp->nexthdr; currenthdr = hp->nexthdr;
...@@ -218,7 +220,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -218,7 +220,7 @@ static void dump_packet(const struct ip6t_log_info *info,
printk("SPT=%u DPT=%u ", printk("SPT=%u DPT=%u ",
ntohs(th->source), ntohs(th->dest)); ntohs(th->source), ntohs(th->dest));
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
if (info->logflags & IP6T_LOG_TCPSEQ) if (logflags & IP6T_LOG_TCPSEQ)
printk("SEQ=%u ACK=%u ", printk("SEQ=%u ACK=%u ",
ntohl(th->seq), ntohl(th->ack_seq)); ntohl(th->seq), ntohl(th->ack_seq));
/* Max length: 13 "WINDOW=65535 " */ /* Max length: 13 "WINDOW=65535 " */
...@@ -245,7 +247,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -245,7 +247,7 @@ static void dump_packet(const struct ip6t_log_info *info,
/* Max length: 11 "URGP=65535 " */ /* Max length: 11 "URGP=65535 " */
printk("URGP=%u ", ntohs(th->urg_ptr)); printk("URGP=%u ", ntohs(th->urg_ptr));
if ((info->logflags & IP6T_LOG_TCPOPT) if ((logflags & IP6T_LOG_TCPOPT)
&& th->doff * 4 > sizeof(struct tcphdr)) { && th->doff * 4 > sizeof(struct tcphdr)) {
u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
unsigned int i; unsigned int i;
...@@ -349,7 +351,7 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -349,7 +351,7 @@ static void dump_packet(const struct ip6t_log_info *info,
} }
/* Max length: 15 "UID=4294967295 " */ /* Max length: 15 "UID=4294967295 " */
if ((info->logflags & IP6T_LOG_UID) && recurse && skb->sk) { if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
read_lock_bh(&skb->sk->sk_callback_lock); read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file) if (skb->sk->sk_socket && skb->sk->sk_socket->file)
printk("UID=%u ", skb->sk->sk_socket->file->f_uid); printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
...@@ -357,19 +359,31 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -357,19 +359,31 @@ static void dump_packet(const struct ip6t_log_info *info,
} }
} }
static struct nf_loginfo default_loginfo = {
.type = NF_LOG_TYPE_LOG,
.u = {
.log = {
.level = 0,
.logflags = NF_LOG_MASK,
},
},
};
static void static void
ip6t_log_packet(unsigned int hooknum, ip6t_log_packet(unsigned int pf,
unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
const struct ip6t_log_info *loginfo, const struct nf_loginfo *loginfo,
const char *level_string,
const char *prefix) const char *prefix)
{ {
if (!loginfo)
loginfo = &default_loginfo;
spin_lock_bh(&log_lock); spin_lock_bh(&log_lock);
printk(level_string); printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
printk("%sIN=%s OUT=%s ", prefix,
prefix == NULL ? loginfo->prefix : prefix,
in ? in->name : "", in ? in->name : "",
out ? out->name : ""); out ? out->name : "");
if (in && !out) { if (in && !out) {
...@@ -416,29 +430,17 @@ ip6t_log_target(struct sk_buff **pskb, ...@@ -416,29 +430,17 @@ ip6t_log_target(struct sk_buff **pskb,
void *userinfo) void *userinfo)
{ {
const struct ip6t_log_info *loginfo = targinfo; const struct ip6t_log_info *loginfo = targinfo;
char level_string[4] = "< >"; struct nf_loginfo li;
li.type = NF_LOG_TYPE_LOG;
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
level_string[1] = '0' + (loginfo->level % 8); nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix);
ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
return IP6T_CONTINUE; return IP6T_CONTINUE;
} }
static void
ip6t_logfn(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *prefix)
{
struct ip6t_log_info loginfo = {
.level = 0,
.logflags = IP6T_LOG_MASK,
.prefix = ""
};
ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
}
static int ip6t_log_checkentry(const char *tablename, static int ip6t_log_checkentry(const char *tablename,
const struct ip6t_entry *e, const struct ip6t_entry *e,
...@@ -475,20 +477,29 @@ static struct ip6t_target ip6t_log_reg = { ...@@ -475,20 +477,29 @@ static struct ip6t_target ip6t_log_reg = {
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
static struct nf_logger ip6t_logger = {
.name = "ip6t_LOG",
.logfn = &ip6t_log_packet,
.me = THIS_MODULE,
};
static int __init init(void) static int __init init(void)
{ {
if (ip6t_register_target(&ip6t_log_reg)) if (ip6t_register_target(&ip6t_log_reg))
return -EINVAL; return -EINVAL;
if (nflog) if (nf_log_register(PF_INET6, &ip6t_logger) < 0) {
nf_log_register(PF_INET6, &ip6t_logfn); printk(KERN_WARNING "ip6t_LOG: not logging via system console "
"since somebody else already registered for PF_INET6\n");
/* we cannot make module load fail here, since otherwise
* ip6tables userspace would abort */
}
return 0; return 0;
} }
static void __exit fini(void) static void __exit fini(void)
{ {
if (nflog) nf_log_unregister_logger(&ip6t_logger);
nf_log_unregister(PF_INET6, &ip6t_logfn);
ip6t_unregister_target(&ip6t_log_reg); ip6t_unregister_target(&ip6t_log_reg);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment