Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / ipv6 / netfilter / ip6t_LOG.c
index bfc3d01..73c6300 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/skbuff.h>
+#include <linux/if_arp.h>
 #include <linux/ip.h>
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
@@ -26,10 +27,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 +41,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 +50,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) {
@@ -60,9 +63,8 @@ static void dump_packet(const struct ip6t_log_info *info,
                return;
        }
 
-       /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */
-       printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr));
-       printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr));
+       /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
+       printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr));
 
        /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
        printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
@@ -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,59 +359,58 @@ 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)
 {
-       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+       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) {
+               unsigned int len;
                /* MAC logging for input chain only. */
                printk("MAC=");
-               if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
-                       if (skb->dev->type != ARPHRD_SIT){
-                         int i;
-                         unsigned char *p = skb->mac.raw;
-                         for (i = 0; i < skb->dev->hard_header_len; i++,p++)
-                               printk("%02x%c", *p,
-                                       i==skb->dev->hard_header_len - 1
-                                       ? ' ':':');
-                       } else {
-                         int i;
-                         unsigned char *p = skb->mac.raw;
-                         if ( p - (ETH_ALEN*2+2) > skb->head ){
-                           p -= (ETH_ALEN+2);
-                           for (i = 0; i < (ETH_ALEN); i++,p++)
-                               printk("%02x%s", *p,
-                                       i == ETH_ALEN-1 ? "->" : ":");
-                           p -= (ETH_ALEN*2);
-                           for (i = 0; i < (ETH_ALEN); i++,p++)
-                               printk("%02x%c", *p,
-                                       i == ETH_ALEN-1 ? ' ' : ':');
-                         }
-                         
-                         if ((skb->dev->addr_len == 4) &&
-                             skb->dev->hard_header_len > 20){
-                           printk("TUNNEL=");
-                           p = skb->mac.raw + 12;
-                           for (i = 0; i < 4; i++,p++)
-                               printk("%3d%s", *p,
-                                       i == 3 ? "->" : ".");
-                           for (i = 0; i < 4; i++,p++)
-                               printk("%3d%c", *p,
-                                       i == 3 ? ' ' : '.');
-                         }
+               if (skb->dev && (len = skb->dev->hard_header_len) &&
+                   skb->mac.raw != skb->nh.raw) {
+                       unsigned char *p = skb->mac.raw;
+                       int i;
+
+                       if (skb->dev->type == ARPHRD_SIT &&
+                           (p -= ETH_HLEN) < skb->head)
+                               p = NULL;
+
+                       if (p != NULL) {
+                               for (i = 0; i < len; i++)
+                                       printk("%02x%s", p[i],
+                                              i == len - 1 ? "" : ":");
+                       }
+                       printk(" ");
+
+                       if (skb->dev->type == ARPHRD_SIT) {
+                               struct iphdr *iph = (struct iphdr *)skb->mac.raw;
+                               printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
+                                      NIPQUAD(iph->saddr),
+                                      NIPQUAD(iph->daddr));
                        }
                } else
                        printk(" ");
@@ -425,85 +426,82 @@ ip6t_log_target(struct sk_buff **pskb,
                const struct net_device *in,
                const struct net_device *out,
                unsigned int hooknum,
+               const struct xt_target *target,
                const void *targinfo,
                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);
+       if (loginfo->logflags & IP6T_LOG_NFLOG)
+               nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
+                             "%s", loginfo->prefix);
+       else
+               ip6t_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,
+                              const void *entry,
+                              const struct xt_target *target,
                               void *targinfo,
                               unsigned int targinfosize,
                               unsigned int hook_mask)
 {
        const struct ip6t_log_info *loginfo = targinfo;
 
-       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_log_info))) {
-               DEBUGP("LOG: targinfosize %u != %u\n",
-                      targinfosize, IP6T_ALIGN(sizeof(struct ip6t_log_info)));
-               return 0;
-       }
-
        if (loginfo->level >= 8) {
                DEBUGP("LOG: level %u >= 8\n", loginfo->level);
                return 0;
        }
-
        if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
                DEBUGP("LOG: prefix term %i\n",
                       loginfo->prefix[sizeof(loginfo->prefix)-1]);
                return 0;
        }
-
        return 1;
 }
 
 static struct ip6t_target ip6t_log_reg = {
        .name           = "LOG",
        .target         = ip6t_log_target, 
+       .targetsize     = sizeof(struct ip6t_log_info),
        .checkentry     = ip6t_log_checkentry, 
        .me             = THIS_MODULE,
 };
 
-static int __init init(void)
+static struct nf_logger ip6t_logger = {
+       .name           = "ip6t_LOG",
+       .logfn          = &ip6t_log_packet,
+       .me             = THIS_MODULE,
+};
+
+static int __init ip6t_log_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)
+static void __exit ip6t_log_fini(void)
 {
-       if (nflog)
-               nf_log_unregister(PF_INET6, &ip6t_logfn);
+       nf_log_unregister_logger(&ip6t_logger);
        ip6t_unregister_target(&ip6t_log_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_log_init);
+module_exit(ip6t_log_fini);