[NETFILTER]: Extend netfilter logging API
authorHarald Welte <laforge@netfilter.org>
Wed, 10 Aug 2005 02:58:27 +0000 (19:58 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 22:38:07 +0000 (15:38 -0700)
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: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netfilter.h
include/linux/netfilter_ipv4/ipt_LOG.h
include/linux/netfilter_ipv6/ip6t_LOG.h
net/core/netfilter.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_proto_udp.c
net/ipv4/netfilter/ipt_LOG.c
net/ipv4/netfilter/ipt_ULOG.c
net/ipv6/netfilter/ip6t_LOG.c

index 711e05f..815583a 100644 (file)
@@ -114,15 +114,51 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
 
 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 net_device *in,
                      const struct net_device *out,
+                     const struct nf_loginfo *li,
                      const char *prefix);
 
+struct nf_logger {
+       struct module   *me;
+       nf_logfn        *logfn;
+       char            *name;
+};
+
 /* Function to register/unregister log function. */
-int nf_log_register(int pf, nf_logfn *logfn);
-void nf_log_unregister(int pf, nf_logfn *logfn);
+int nf_log_register(int pf, struct nf_logger *logger);
+void nf_log_unregister_pf(int pf);
+void nf_log_unregister_logger(struct nf_logger *logger);
 
 /* Calls the registered backend logging function */
 void nf_log_packet(int pf,
@@ -130,6 +166,7 @@ void nf_log_packet(int pf,
                   const struct sk_buff *skb,
                   const struct net_device *in,
                   const struct net_device *out,
+                  struct nf_loginfo *li,
                   const char *fmt, ...);
                    
 /* Activate hook; either okfn or kfree_skb called, unless a hook
@@ -221,6 +258,11 @@ struct nf_queue_rerouter {
 extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
 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 */
 #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) {}
index d25f782..22d1617 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _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_TCPOPT         0x02    /* Log TCP options */
 #define IPT_LOG_IPOPT          0x04    /* Log IP options */
index 42996a4..9008ff5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _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_TCPOPT                0x02    /* Log TCP options */
 #define IP6T_LOG_IPOPT         0x04    /* Log IP options */
index 3e38084..98cc61e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/if.h>
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
+#include <linux/proc_fs.h>
 #include <net/sock.h>
 
 /* In this code, we can be waiting indefinitely for userspace to
@@ -535,11 +536,10 @@ EXPORT_SYMBOL(skb_make_writable);
 
 #define NF_LOG_PREFIXLEN               128
 
-static nf_logfn *nf_logging[NPROTO]; /* = NULL */
-static int reported = 0;
+static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
 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;
 
@@ -547,54 +547,134 @@ int nf_log_register(int pf, nf_logfn *logfn)
         * substituting pointer. */
        spin_lock(&nf_log_lock);
        if (!nf_logging[pf]) {
-               rcu_assign_pointer(nf_logging[pf], logfn);
+               rcu_assign_pointer(nf_logging[pf], logger);
                ret = 0;
        }
        spin_unlock(&nf_log_lock);
        return ret;
 }              
 
-void nf_log_unregister(int pf, nf_logfn *logfn)
+void nf_log_unregister_pf(int pf)
 {
        spin_lock(&nf_log_lock);
-       if (nf_logging[pf] == logfn)
-               nf_logging[pf] = NULL;
+       nf_logging[pf] = NULL;
        spin_unlock(&nf_log_lock);
 
        /* Give time to concurrent readers. */
        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,
                   unsigned int hooknum,
                   const struct sk_buff *skb,
                   const struct net_device *in,
                   const struct net_device *out,
+                  struct nf_loginfo *loginfo,
                   const char *fmt, ...)
 {
        va_list args;
        char prefix[NF_LOG_PREFIXLEN];
-       nf_logfn *logfn;
+       struct nf_logger *logger;
        
        rcu_read_lock();
-       logfn = rcu_dereference(nf_logging[pf]);
-       if (logfn) {
+       logger = rcu_dereference(nf_logging[pf]);
+       if (logger) {
                va_start(args, fmt);
                vsnprintf(prefix, sizeof(prefix), fmt, args);
                va_end(args);
                /* We must read logging before nf_logfn[pf] */
-               logfn(hooknum, skb, in, out, prefix);
-       } else if (!reported) {
-               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
-                      "no backend logging module loaded in!\n");
-               reported++;
+               logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
+       } else if (net_ratelimit()) {
+               printk(KERN_WARNING "nf_log_packet: can\'t log since "
+                      "no backend logging module loaded in! Please either "
+                      "load one, or disable logging explicitly\n");
        }
        rcu_read_unlock();
 }
 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);
 
+#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
    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. */
@@ -613,6 +693,9 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
 void __init netfilter_init(void)
 {
        int i, h;
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *pde;
+#endif
 
        queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
                                 GFP_KERNEL);
@@ -624,6 +707,16 @@ void __init netfilter_init(void)
                for (h = 0; h < NF_MAX_HOOKS; 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);
index 3f90cb9..838d1d6 100644 (file)
@@ -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);
        if (icmph == NULL) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -231,13 +231,13 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
                if (!(u16)csum_fold(skb->csum)) 
                        break;
                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 ");
                return -NF_ACCEPT;
        case CHECKSUM_NONE:
                if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
                        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 ");
                        return -NF_ACCEPT;
                }
@@ -254,7 +254,7 @@ checksum_skipped:
         */
        if (icmph->type > NR_ICMP_TYPES) {
                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 ");
                return -NF_ACCEPT;
        }
index c2bce22..f23ef1f 100644 (file)
@@ -716,7 +716,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
                res = 1;
        } else {
                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 ",
                        before(seq, sender->td_maxend + 1) ?
                        after(end, sender->td_end - receiver->td_maxwin - 1) ?
@@ -815,7 +815,7 @@ static int tcp_error(struct sk_buff *skb,
                                sizeof(_tcph), &_tcph);
        if (th == NULL) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -823,7 +823,7 @@ static int tcp_error(struct sk_buff *skb,
        /* Not whole TCP header or malformed packet */
        if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -840,7 +840,7 @@ static int tcp_error(struct sk_buff *skb,
                                 skb->ip_summed == CHECKSUM_HW ? skb->csum
                                 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -849,7 +849,7 @@ static int tcp_error(struct sk_buff *skb,
        tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR));
        if (!tcp_valid_flags[tcpflags]) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -897,8 +897,9 @@ static int tcp_packet(struct ip_conntrack *conntrack,
                         */
                        write_unlock_bh(&tcp_lock);
                        if (LOG_INVALID(IPPROTO_TCP))
-                               nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
-                                         "ip_ct_tcp: killing out of sync session ");
+                               nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+                                             NULL, "ip_ct_tcp: "
+                                             "killing out of sync session ");
                        if (del_timer(&conntrack->timeout))
                                conntrack->timeout.function((unsigned long)
                                                            conntrack);
@@ -912,7 +913,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
                
                write_unlock_bh(&tcp_lock);
                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 ");
                return NF_ACCEPT;
        case TCP_CONNTRACK_MAX:
@@ -922,7 +923,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
                       old_state);
                write_unlock_bh(&tcp_lock);
                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 ");
                return -NF_ACCEPT;
        case TCP_CONNTRACK_SYN_SENT:
@@ -943,7 +944,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
                        write_unlock_bh(&tcp_lock);
                        if (LOG_INVALID(IPPROTO_TCP))
                                nf_log_packet(PF_INET, 0, skb, NULL, NULL,
-                                             "ip_ct_tcp: invalid SYN");
+                                             NULL, "ip_ct_tcp: invalid SYN");
                        return -NF_ACCEPT;
                }
        case TCP_CONNTRACK_CLOSE:
index 1413016..f2dcac7 100644 (file)
@@ -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);
        if (hdr == NULL) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -106,7 +106,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
        /* Truncated/malformed packets */
        if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
                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 ");
                return -NF_ACCEPT;
        }
@@ -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_checksum(skb, iph->ihl*4, udplen, 0))) {
                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 ");
                return -NF_ACCEPT;
        }
index ef08733..92ed050 100644 (file)
@@ -27,10 +27,6 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 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
 #define DEBUGP printk
 #else
@@ -41,11 +37,17 @@ MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
 static DEFINE_SPINLOCK(log_lock);
 
 /* 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,
                        unsigned int iphoff)
 {
        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);
        if (ih == NULL) {
@@ -76,7 +78,7 @@ static void dump_packet(const struct ipt_log_info *info,
        if (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)) {
                unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
                unsigned int i, optsize;
@@ -119,7 +121,7 @@ static void dump_packet(const struct ipt_log_info *info,
                printk("SPT=%u DPT=%u ",
                       ntohs(th->source), ntohs(th->dest));
                /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
-               if (info->logflags & IPT_LOG_TCPSEQ)
+               if (logflags & IPT_LOG_TCPSEQ)
                        printk("SEQ=%u ACK=%u ",
                               ntohl(th->seq), ntohl(th->ack_seq));
                /* Max length: 13 "WINDOW=65535 " */
@@ -146,7 +148,7 @@ static void dump_packet(const struct ipt_log_info *info,
                /* Max length: 11 "URGP=65535 " */
                printk("URGP=%u ", ntohs(th->urg_ptr));
 
-               if ((info->logflags & IPT_LOG_TCPOPT)
+               if ((logflags & IPT_LOG_TCPOPT)
                    && th->doff * 4 > sizeof(struct tcphdr)) {
                        unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
                        unsigned char *op;
@@ -328,7 +330,7 @@ static void dump_packet(const struct ipt_log_info *info,
        }
 
        /* 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);
                if (skb->sk->sk_socket && skb->sk->sk_socket->file)
                        printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
@@ -349,19 +351,31 @@ static void dump_packet(const struct ipt_log_info *info,
        /* 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
-ipt_log_packet(unsigned int hooknum,
+ipt_log_packet(unsigned int pf,
+              unsigned int hooknum,
               const struct sk_buff *skb,
               const struct net_device *in,
               const struct net_device *out,
-              const struct ipt_log_info *loginfo,
-              const char *level_string,
+              const struct nf_loginfo *loginfo,
               const char *prefix)
 {
+       if (!loginfo)
+               loginfo = &default_loginfo;
+
        spin_lock_bh(&log_lock);
-       printk(level_string);
-       printk("%sIN=%s OUT=%s ",
-              prefix == NULL ? loginfo->prefix : prefix,
+       printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
+              prefix,
               in ? in->name : "",
               out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -405,28 +419,15 @@ ipt_log_target(struct sk_buff **pskb,
               void *userinfo)
 {
        const struct ipt_log_info *loginfo = targinfo;
-       char level_string[4] = "< >";
+       struct nf_loginfo li;
 
-       level_string[1] = '0' + (loginfo->level % 8);
-       ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
+       li.type = NF_LOG_TYPE_LOG;
+       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
-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);
+       return IPT_CONTINUE;
 }
 
 static int ipt_log_checkentry(const char *tablename,
@@ -464,20 +465,29 @@ static struct ipt_target ipt_log_reg = {
        .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)
 {
        if (ipt_register_target(&ipt_log_reg))
                return -EINVAL;
-       if (nflog)
-               nf_log_register(PF_INET, &ipt_logfn);
+       if (nf_log_register(PF_INET, &ipt_log_logger) < 0) {
+               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;
 }
 
 static void __exit fini(void)
 {
-       if (nflog)
-               nf_log_unregister(PF_INET, &ipt_logfn);
+       nf_log_unregister_logger(&ipt_log_logger);
        ipt_unregister_target(&ipt_log_reg);
 }
 
index 4ea8371..b86f06e 100644 (file)
@@ -304,18 +304,27 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
        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 net_device *in,
                      const struct net_device *out,
+                     const struct nf_loginfo *li,
                      const char *prefix)
 {
-       struct ipt_ulog_info loginfo = { 
-               .nl_group = ULOG_DEFAULT_NLGROUP,
-               .copy_range = 0,
-               .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
-               .prefix = ""
-       };
+       struct ipt_ulog_info loginfo;
+
+       if (!li || li->type != NF_LOG_TYPE_ULOG) {
+               loginfo.nl_group = ULOG_DEFAULT_NLGROUP;
+               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);
 }
@@ -355,6 +364,12 @@ static struct ipt_target ipt_ulog_reg = {
        .me             = THIS_MODULE,
 };
 
+static struct nf_logger ipt_ulog_logger = {
+       .name           = "ipt_ULOG",
+       .logfn          = &ipt_logfn,
+       .me             = THIS_MODULE,
+};
+
 static int __init init(void)
 {
        int i;
@@ -382,7 +397,7 @@ static int __init init(void)
                return -EINVAL;
        }
        if (nflog)
-               nf_log_register(PF_INET, &ipt_logfn);
+               nf_log_register(PF_INET, &ipt_ulog_logger);
        
        return 0;
 }
@@ -395,7 +410,7 @@ static void __exit fini(void)
        DEBUGP("ipt_ULOG: cleanup_module\n");
 
        if (nflog)
-               nf_log_unregister(PF_INET, &ipt_logfn);
+               nf_log_unregister_logger(&ipt_ulog_logger);
        ipt_unregister_target(&ipt_ulog_reg);
        sock_release(nflognl->sk_socket);
 
index a692e26..0cd1d1b 100644 (file)
@@ -26,10 +26,6 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
 MODULE_DESCRIPTION("IP6 tables LOG target module");
 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;
 #include <net/route.h>
 #include <linux/netfilter_ipv6/ip6t_LOG.h>
@@ -44,7 +40,7 @@ struct in_device;
 static DEFINE_SPINLOCK(log_lock);
 
 /* 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,
                        int recurse)
 {
@@ -53,6 +49,12 @@ static void dump_packet(const struct ip6t_log_info *info,
        struct ipv6hdr _ip6h, *ih;
        unsigned int ptr;
        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);
        if (ih == NULL) {
@@ -84,7 +86,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                }
 
                /* Max length: 48 "OPT (...) " */
-               if (info->logflags & IP6T_LOG_IPOPT)
+               if (logflags & IP6T_LOG_IPOPT)
                        printk("OPT ( ");
 
                switch (currenthdr) {
@@ -119,7 +121,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                case IPPROTO_ROUTING:
                case IPPROTO_HOPOPTS:
                        if (fragment) {
-                               if (info->logflags & IP6T_LOG_IPOPT)
+                               if (logflags & IP6T_LOG_IPOPT)
                                        printk(")");
                                return;
                        }
@@ -127,7 +129,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                        break;
                /* Max Length */
                case IPPROTO_AH:
-                       if (info->logflags & IP6T_LOG_IPOPT) {
+                       if (logflags & IP6T_LOG_IPOPT) {
                                struct ip_auth_hdr _ahdr, *ah;
 
                                /* Max length: 3 "AH " */
@@ -158,7 +160,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                        hdrlen = (hp->hdrlen+2)<<2;
                        break;
                case IPPROTO_ESP:
-                       if (info->logflags & IP6T_LOG_IPOPT) {
+                       if (logflags & IP6T_LOG_IPOPT) {
                                struct ip_esp_hdr _esph, *eh;
 
                                /* Max length: 4 "ESP " */
@@ -190,7 +192,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                        printk("Unknown Ext Hdr %u", currenthdr);
                        return;
                }
-               if (info->logflags & IP6T_LOG_IPOPT)
+               if (logflags & IP6T_LOG_IPOPT)
                        printk(") ");
 
                currenthdr = hp->nexthdr;
@@ -218,7 +220,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                printk("SPT=%u DPT=%u ",
                       ntohs(th->source), ntohs(th->dest));
                /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
-               if (info->logflags & IP6T_LOG_TCPSEQ)
+               if (logflags & IP6T_LOG_TCPSEQ)
                        printk("SEQ=%u ACK=%u ",
                               ntohl(th->seq), ntohl(th->ack_seq));
                /* Max length: 13 "WINDOW=65535 " */
@@ -245,7 +247,7 @@ static void dump_packet(const struct ip6t_log_info *info,
                /* Max length: 11 "URGP=65535 " */
                printk("URGP=%u ", ntohs(th->urg_ptr));
 
-               if ((info->logflags & IP6T_LOG_TCPOPT)
+               if ((logflags & IP6T_LOG_TCPOPT)
                    && th->doff * 4 > sizeof(struct tcphdr)) {
                        u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
                        unsigned int i;
@@ -349,7 +351,7 @@ static void dump_packet(const struct ip6t_log_info *info,
        }
 
        /* 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);
                if (skb->sk->sk_socket && skb->sk->sk_socket->file)
                        printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
@@ -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
-ip6t_log_packet(unsigned int hooknum,
+ip6t_log_packet(unsigned int pf,
+               unsigned int hooknum,
                const struct sk_buff *skb,
                const struct net_device *in,
                const struct net_device *out,
-               const struct ip6t_log_info *loginfo,
-               const char *level_string,
+               const struct nf_loginfo *loginfo,
                const char *prefix)
 {
+       if (!loginfo)
+               loginfo = &default_loginfo;
+
        spin_lock_bh(&log_lock);
-       printk(level_string);
-       printk("%sIN=%s OUT=%s ",
-               prefix == NULL ? loginfo->prefix : prefix,
+       printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, 
+               prefix,
                in ? in->name : "",
                out ? out->name : "");
        if (in && !out) {
@@ -416,29 +430,17 @@ ip6t_log_target(struct sk_buff **pskb,
                void *userinfo)
 {
        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);
-       ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
+       nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix);
 
        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,
                               const struct ip6t_entry *e,
@@ -475,20 +477,29 @@ static struct ip6t_target ip6t_log_reg = {
        .me             = THIS_MODULE,
 };
 
+static struct nf_logger ip6t_logger = {
+       .name           = "ip6t_LOG",
+       .logfn          = &ip6t_log_packet,
+       .me             = THIS_MODULE,
+};
+
 static int __init init(void)
 {
        if (ip6t_register_target(&ip6t_log_reg))
                return -EINVAL;
-       if (nflog)
-               nf_log_register(PF_INET6, &ip6t_logfn);
+       if (nf_log_register(PF_INET6, &ip6t_logger) < 0) {
+               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;
 }
 
 static void __exit fini(void)
 {
-       if (nflog)
-               nf_log_unregister(PF_INET6, &ip6t_logfn);
+       nf_log_unregister_logger(&ip6t_logger);
        ip6t_unregister_target(&ip6t_log_reg);
 }