vserver 1.9.5.x5
[linux-2.6.git] / net / ipv4 / netfilter / ip_nat_snmp_basic.c
index 32d6e96..2a48b6e 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/moduleparam.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
 #include <linux/ip.h>
 #include <net/checksum.h>
@@ -65,7 +66,7 @@ MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
 #define NOCT1(n) (u_int8_t )((n) & 0xff)
 
 static int debug;
-static spinlock_t snmp_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(snmp_lock);
 
 /* 
  * Application layer address mapping mimics the NAT mapping, but 
@@ -1203,9 +1204,7 @@ static int snmp_parse_mangle(unsigned char *msg,
  * SNMP translation routine.
  */
 static int snmp_translate(struct ip_conntrack *ct,
-                          struct ip_nat_info *info,
                           enum ip_conntrack_info ctinfo,
-                          unsigned int hooknum,
                           struct sk_buff **pskb)
 {
        struct iphdr *iph = (*pskb)->nh.iph;
@@ -1234,101 +1233,86 @@ static int snmp_translate(struct ip_conntrack *ct,
        
        if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
                               paylen, &map, &udph->check)) {
-               printk(KERN_WARNING "bsalg: parser failed\n");
+               if (net_ratelimit())
+                       printk(KERN_WARNING "bsalg: parser failed\n");
                return NF_DROP;
        }
        return NF_ACCEPT;
 }
 
-/* 
- * NAT helper function, packets arrive here from NAT code.
- */
-static unsigned int nat_help(struct ip_conntrack *ct,
-                            struct ip_conntrack_expect *exp,
-                             struct ip_nat_info *info,
-                             enum ip_conntrack_info ctinfo,
-                             unsigned int hooknum,
-                             struct sk_buff **pskb)
+/* We don't actually set up expectations, just adjust internal IP
+ * addresses if this is being NATted */
+static int help(struct sk_buff **pskb,
+               struct ip_conntrack *ct,
+               enum ip_conntrack_info ctinfo)
 {
        int dir = CTINFO2DIR(ctinfo);
+       unsigned int ret;
        struct iphdr *iph = (*pskb)->nh.iph;
        struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
-       
-       if (!skb_ip_make_writable(pskb, (*pskb)->len))
-               return NF_DROP;
 
-       spin_lock_bh(&snmp_lock);
-       
-       /*
-        * Translate snmp replies on pre-routing (DNAT) and snmp traps
-        * on post routing (SNAT).
-        */
-       if (!((dir == IP_CT_DIR_REPLY && hooknum == NF_IP_PRE_ROUTING &&
-                       udph->source == ntohs(SNMP_PORT)) ||
-             (dir == IP_CT_DIR_ORIGINAL && hooknum == NF_IP_POST_ROUTING &&
-                       udph->dest == ntohs(SNMP_TRAP_PORT)))) {
-               spin_unlock_bh(&snmp_lock);
+       /* SNMP replies and originating SNMP traps get mangled */
+       if (udph->source == ntohs(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
+               return NF_ACCEPT;
+       if (udph->dest == ntohs(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
+               return NF_ACCEPT;
+
+       /* No NAT? */
+       if (!(ct->status & IPS_NAT_MASK))
                return NF_ACCEPT;
-       }
 
-       if (debug > 1) {
-               printk(KERN_DEBUG "bsalg: dir=%s hook=%d manip=%s len=%d "
-                      "src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u "
-                      "osrc=%u.%u.%u.%u odst=%u.%u.%u.%u "
-                      "rsrc=%u.%u.%u.%u rdst=%u.%u.%u.%u "
-                      "\n", 
-                      dir == IP_CT_DIR_REPLY ? "reply" : "orig", hooknum, 
-                      HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ? "snat" :
-                      "dnat", (*pskb)->len,
-                      NIPQUAD(iph->saddr), ntohs(udph->source),
-                      NIPQUAD(iph->daddr), ntohs(udph->dest),
-                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
-                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
-                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
-                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip));
-       }
-       
        /* 
         * Make sure the packet length is ok.  So far, we were only guaranteed
         * to have a valid length IP header plus 8 bytes, which means we have
         * enough room for a UDP header.  Just verify the UDP length field so we
         * can mess around with the payload.
         */
-        if (ntohs(udph->len) == (*pskb)->len - (iph->ihl << 2)) {
-               int ret = snmp_translate(ct, info, ctinfo, hooknum, pskb);
-               spin_unlock_bh(&snmp_lock);
-               return ret;
+       if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
+                if (net_ratelimit())
+                        printk(KERN_WARNING "SNMP: dropping malformed packet "
+                               "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
+                               NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+                return NF_DROP;
        }
-       
-       if (net_ratelimit())
-               printk(KERN_WARNING "bsalg: dropping malformed packet "
-                      "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
-                      NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+
+       if (!skb_ip_make_writable(pskb, (*pskb)->len))
+               return NF_DROP;
+
+       spin_lock_bh(&snmp_lock);
+       ret = snmp_translate(ct, ctinfo, pskb);
        spin_unlock_bh(&snmp_lock);
-       return NF_DROP;
+       return ret;
 }
 
-static struct ip_nat_helper snmp = { 
-       { NULL, NULL },
-       "snmp",
-       0,
-       THIS_MODULE,
-       { { 0, { .udp = { __constant_htons(SNMP_PORT) } } },
-         { 0, { 0 }, IPPROTO_UDP } },
-       { { 0, { .udp = { 0xFFFF } } },
-         { 0, { 0 }, 0xFFFF } },
-       nat_help, NULL };
-static struct ip_nat_helper snmp_trap = { 
-       { NULL, NULL },
-       "snmp_trap",
-       0,
-       THIS_MODULE,
-       { { 0, { .udp = { __constant_htons(SNMP_TRAP_PORT) } } },
-         { 0, { 0 }, IPPROTO_UDP } },
-       { { 0, { .udp = { 0xFFFF } } },
-         { 0, { 0 }, 0xFFFF } },
-       nat_help, NULL };
+static struct ip_conntrack_helper snmp_helper = {
+       .max_expected = 0,
+       .timeout = 180,
+       .me = THIS_MODULE,
+       .help = help,
+       .name = "snmp",
+
+       .tuple = { .src = { .u = { __constant_htons(SNMP_PORT) } },
+                  .dst = { .protonum = IPPROTO_UDP },
+       },
+       .mask = { .src = { .u = { 0xFFFF } },
+                .dst = { .protonum = 0xFF },
+       },
+};
+
+static struct ip_conntrack_helper snmp_trap_helper = {
+       .max_expected = 0,
+       .timeout = 180,
+       .me = THIS_MODULE,
+       .help = help,
+       .name = "snmp_trap",
+
+       .tuple = { .src = { .u = { __constant_htons(SNMP_TRAP_PORT) } },
+                  .dst = { .protonum = IPPROTO_UDP },
+       },
+       .mask = { .src = { .u = { 0xFFFF } },
+                .dst = { .protonum = 0xFF },
+       },
+};
 
 /*****************************************************************************
  *
@@ -1340,12 +1324,12 @@ static int __init init(void)
 {
        int ret = 0;
 
-       ret = ip_nat_helper_register(&snmp);
+       ret = ip_conntrack_helper_register(&snmp_helper);
        if (ret < 0)
                return ret;
-       ret = ip_nat_helper_register(&snmp_trap);
+       ret = ip_conntrack_helper_register(&snmp_trap_helper);
        if (ret < 0) {
-               ip_nat_helper_unregister(&snmp);
+               ip_conntrack_helper_unregister(&snmp_helper);
                return ret;
        }
        return ret;
@@ -1353,9 +1337,8 @@ static int __init init(void)
 
 static void __exit fini(void)
 {
-       ip_nat_helper_unregister(&snmp);
-       ip_nat_helper_unregister(&snmp_trap);
-       synchronize_net();
+       ip_conntrack_helper_unregister(&snmp_helper);
+       ip_conntrack_helper_unregister(&snmp_trap_helper);
 }
 
 module_init(init);