[NETFILTER]: Introduce NF_INET_ hook values
[safe/jmp/linux-2.6] / net / ipv4 / netfilter / nf_nat_standalone.c
index 730a7a4..84172e9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_rule.h>
 #include <net/netfilter/nf_nat_protocol.h>
 #include <net/netfilter/nf_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING"  \
-                          : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
-                             : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT"  \
-                                : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN"  \
-                                   : "*ERROR*")))
-
 #ifdef CONFIG_XFRM
 static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 {
@@ -78,7 +67,7 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 
 static unsigned int
 nf_nat_fn(unsigned int hooknum,
-         struct sk_buff **pskb,
+         struct sk_buff *skb,
          const struct net_device *in,
          const struct net_device *out,
          int (*okfn)(struct sk_buff *))
@@ -86,29 +75,26 @@ nf_nat_fn(unsigned int hooknum,
        struct nf_conn *ct;
        enum ip_conntrack_info ctinfo;
        struct nf_conn_nat *nat;
-       struct nf_nat_info *info;
        /* maniptype == SRC for postrouting. */
        enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
 
        /* We never see fragments: conntrack defrags on pre-routing
           and local-out, and nf_nat_out protects post-routing. */
-       NF_CT_ASSERT(!((*pskb)->nh.iph->frag_off
-                      & htons(IP_MF|IP_OFFSET)));
+       NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
 
-       ct = nf_ct_get(*pskb, &ctinfo);
+       ct = nf_ct_get(skb, &ctinfo);
        /* Can't track?  It's not due to stress, or conntrack would
           have dropped it.  Hence it's the user's responsibilty to
           packet filter it out, or implement conntrack/NAT for that
           protocol. 8) --RR */
        if (!ct) {
                /* Exception: ICMP redirect to new connection (not in
-                   hash table yet).  We must not let this through, in
-                   case we're doing NAT to the same network. */
-               if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+                  hash table yet).  We must not let this through, in
+                  case we're doing NAT to the same network. */
+               if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
                        struct icmphdr _hdr, *hp;
 
-                       hp = skb_header_pointer(*pskb,
-                                               (*pskb)->nh.iph->ihl*4,
+                       hp = skb_header_pointer(skb, ip_hdrlen(skb),
                                                sizeof(_hdr), &_hdr);
                        if (hp != NULL &&
                            hp->type == ICMP_REDIRECT)
@@ -122,22 +108,26 @@ nf_nat_fn(unsigned int hooknum,
                return NF_ACCEPT;
 
        nat = nfct_nat(ct);
-       if (!nat)
-               return NF_DROP;
+       if (!nat) {
+               nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+               if (nat == NULL) {
+                       pr_debug("failed to add NAT extension\n");
+                       return NF_ACCEPT;
+               }
+       }
 
        switch (ctinfo) {
        case IP_CT_RELATED:
        case IP_CT_RELATED+IP_CT_IS_REPLY:
-               if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+               if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
                        if (!nf_nat_icmp_reply_translation(ct, ctinfo,
-                                                          hooknum, pskb))
+                                                          hooknum, skb))
                                return NF_DROP;
                        else
                                return NF_ACCEPT;
                }
                /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
        case IP_CT_NEW:
-               info = &nat->info;
 
                /* Seen it before?  This can happen for loopback, retrans,
                   or local packets.. */
@@ -146,57 +136,54 @@ nf_nat_fn(unsigned int hooknum,
 
                        if (unlikely(nf_ct_is_confirmed(ct)))
                                /* NAT module was loaded late */
-                               ret = alloc_null_binding_confirmed(ct, info,
-                                                                  hooknum);
-                       else if (hooknum == NF_IP_LOCAL_IN)
+                               ret = alloc_null_binding_confirmed(ct, hooknum);
+                       else if (hooknum == NF_INET_LOCAL_IN)
                                /* LOCAL_IN hook doesn't have a chain!  */
-                               ret = alloc_null_binding(ct, info, hooknum);
+                               ret = alloc_null_binding(ct, hooknum);
                        else
-                               ret = nf_nat_rule_find(pskb, hooknum, in, out,
-                                                      ct, info);
+                               ret = nf_nat_rule_find(skb, hooknum, in, out,
+                                                      ct);
 
                        if (ret != NF_ACCEPT) {
                                return ret;
                        }
                } else
-                       DEBUGP("Already setup manip %s for ct %p\n",
-                              maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
-                              ct);
+                       pr_debug("Already setup manip %s for ct %p\n",
+                                maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
+                                ct);
                break;
 
        default:
                /* ESTABLISHED */
                NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
                             ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
-               info = &nat->info;
        }
 
-       NF_CT_ASSERT(info);
-       return nf_nat_packet(ct, ctinfo, hooknum, pskb);
+       return nf_nat_packet(ct, ctinfo, hooknum, skb);
 }
 
 static unsigned int
 nf_nat_in(unsigned int hooknum,
-          struct sk_buff **pskb,
-          const struct net_device *in,
-          const struct net_device *out,
-          int (*okfn)(struct sk_buff *))
+         struct sk_buff *skb,
+         const struct net_device *in,
+         const struct net_device *out,
+         int (*okfn)(struct sk_buff *))
 {
        unsigned int ret;
-       __be32 daddr = (*pskb)->nh.iph->daddr;
+       __be32 daddr = ip_hdr(skb)->daddr;
 
-       ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+       ret = nf_nat_fn(hooknum, skb, in, out, okfn);
        if (ret != NF_DROP && ret != NF_STOLEN &&
-           daddr != (*pskb)->nh.iph->daddr) {
-               dst_release((*pskb)->dst);
-               (*pskb)->dst = NULL;
+           daddr != ip_hdr(skb)->daddr) {
+               dst_release(skb->dst);
+               skb->dst = NULL;
        }
        return ret;
 }
 
 static unsigned int
 nf_nat_out(unsigned int hooknum,
-          struct sk_buff **pskb,
+          struct sk_buff *skb,
           const struct net_device *in,
           const struct net_device *out,
           int (*okfn)(struct sk_buff *))
@@ -208,14 +195,14 @@ nf_nat_out(unsigned int hooknum,
        unsigned int ret;
 
        /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr) ||
-           (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+       if (skb->len < sizeof(struct iphdr) ||
+           ip_hdrlen(skb) < sizeof(struct iphdr))
                return NF_ACCEPT;
 
-       ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+       ret = nf_nat_fn(hooknum, skb, in, out, okfn);
 #ifdef CONFIG_XFRM
        if (ret != NF_DROP && ret != NF_STOLEN &&
-           (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
+           (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
                enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
                if (ct->tuplehash[dir].tuple.src.u3.ip !=
@@ -223,7 +210,7 @@ nf_nat_out(unsigned int hooknum,
                    || ct->tuplehash[dir].tuple.src.u.all !=
                       ct->tuplehash[!dir].tuple.dst.u.all
                    )
-                       return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
+                       return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP;
        }
 #endif
        return ret;
@@ -231,7 +218,7 @@ nf_nat_out(unsigned int hooknum,
 
 static unsigned int
 nf_nat_local_fn(unsigned int hooknum,
-               struct sk_buff **pskb,
+               struct sk_buff *skb,
                const struct net_device *in,
                const struct net_device *out,
                int (*okfn)(struct sk_buff *))
@@ -241,31 +228,33 @@ nf_nat_local_fn(unsigned int hooknum,
        unsigned int ret;
 
        /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr) ||
-           (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+       if (skb->len < sizeof(struct iphdr) ||
+           ip_hdrlen(skb) < sizeof(struct iphdr))
                return NF_ACCEPT;
 
-       ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+       ret = nf_nat_fn(hooknum, skb, in, out, okfn);
        if (ret != NF_DROP && ret != NF_STOLEN &&
-           (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
+           (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
                enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
                if (ct->tuplehash[dir].tuple.dst.u3.ip !=
-                   ct->tuplehash[!dir].tuple.src.u3.ip
+                   ct->tuplehash[!dir].tuple.src.u3.ip) {
+                       if (ip_route_me_harder(skb, RTN_UNSPEC))
+                               ret = NF_DROP;
+               }
 #ifdef CONFIG_XFRM
-                   || ct->tuplehash[dir].tuple.dst.u.all !=
-                      ct->tuplehash[!dir].tuple.src.u.all
-#endif
-                   )
-                       if (ip_route_me_harder(pskb, RTN_UNSPEC))
+               else if (ct->tuplehash[dir].tuple.dst.u.all !=
+                        ct->tuplehash[!dir].tuple.src.u.all)
+                       if (ip_xfrm_me_harder(skb))
                                ret = NF_DROP;
+#endif
        }
        return ret;
 }
 
 static unsigned int
 nf_nat_adjust(unsigned int hooknum,
-             struct sk_buff **pskb,
+             struct sk_buff *skb,
              const struct net_device *in,
              const struct net_device *out,
              int (*okfn)(struct sk_buff *))
@@ -273,11 +262,11 @@ nf_nat_adjust(unsigned int hooknum,
        struct nf_conn *ct;
        enum ip_conntrack_info ctinfo;
 
-       ct = nf_ct_get(*pskb, &ctinfo);
+       ct = nf_ct_get(skb, &ctinfo);
        if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
-               DEBUGP("nf_nat_standalone: adjusting sequence number\n");
-               if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
-                       return NF_DROP;
+               pr_debug("nf_nat_standalone: adjusting sequence number\n");
+               if (!nf_nat_seq_adjust(skb, ct, ctinfo))
+                       return NF_DROP;
        }
        return NF_ACCEPT;
 }
@@ -290,7 +279,7 @@ static struct nf_hook_ops nf_nat_ops[] = {
                .hook           = nf_nat_in,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
-               .hooknum        = NF_IP_PRE_ROUTING,
+               .hooknum        = NF_INET_PRE_ROUTING,
                .priority       = NF_IP_PRI_NAT_DST,
        },
        /* After packet filtering, change source */
@@ -298,7 +287,7 @@ static struct nf_hook_ops nf_nat_ops[] = {
                .hook           = nf_nat_out,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
-               .hooknum        = NF_IP_POST_ROUTING,
+               .hooknum        = NF_INET_POST_ROUTING,
                .priority       = NF_IP_PRI_NAT_SRC,
        },
        /* After conntrack, adjust sequence number */
@@ -306,7 +295,7 @@ static struct nf_hook_ops nf_nat_ops[] = {
                .hook           = nf_nat_adjust,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
-               .hooknum        = NF_IP_POST_ROUTING,
+               .hooknum        = NF_INET_POST_ROUTING,
                .priority       = NF_IP_PRI_NAT_SEQ_ADJUST,
        },
        /* Before packet filtering, change destination */
@@ -314,7 +303,7 @@ static struct nf_hook_ops nf_nat_ops[] = {
                .hook           = nf_nat_local_fn,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
-               .hooknum        = NF_IP_LOCAL_OUT,
+               .hooknum        = NF_INET_LOCAL_OUT,
                .priority       = NF_IP_PRI_NAT_DST,
        },
        /* After packet filtering, change source */
@@ -322,7 +311,7 @@ static struct nf_hook_ops nf_nat_ops[] = {
                .hook           = nf_nat_fn,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
-               .hooknum        = NF_IP_LOCAL_IN,
+               .hooknum        = NF_INET_LOCAL_IN,
                .priority       = NF_IP_PRI_NAT_SRC,
        },
        /* After conntrack, adjust sequence number */
@@ -330,33 +319,17 @@ static struct nf_hook_ops nf_nat_ops[] = {
                .hook           = nf_nat_adjust,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
-               .hooknum        = NF_IP_LOCAL_IN,
+               .hooknum        = NF_INET_LOCAL_IN,
                .priority       = NF_IP_PRI_NAT_SEQ_ADJUST,
        },
 };
 
 static int __init nf_nat_standalone_init(void)
 {
-       int size, ret = 0;
+       int ret = 0;
 
-       need_conntrack();
+       need_ipv4_conntrack();
 
-       size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
-              sizeof(struct nf_conn_nat);
-       ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
-       if (ret < 0) {
-               printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
-               return ret;
-       }
-
-       size = ALIGN(size, __alignof__(struct nf_conn_help)) +
-              sizeof(struct nf_conn_help);
-       ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
-                                         "nf_nat:help", size);
-       if (ret < 0) {
-               printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
-               goto cleanup_register_cache;
-       }
 #ifdef CONFIG_XFRM
        BUG_ON(ip_nat_decode_session != NULL);
        ip_nat_decode_session = nat_decode_session;
@@ -371,7 +344,6 @@ static int __init nf_nat_standalone_init(void)
                printk("nf_nat_init: can't register hooks.\n");
                goto cleanup_rule_init;
        }
-       nf_nat_module_is_loaded = 1;
        return ret;
 
  cleanup_rule_init:
@@ -381,9 +353,6 @@ static int __init nf_nat_standalone_init(void)
        ip_nat_decode_session = NULL;
        synchronize_net();
 #endif
-       nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
- cleanup_register_cache:
-       nf_conntrack_unregister_cache(NF_CT_F_NAT);
        return ret;
 }
 
@@ -391,7 +360,6 @@ static void __exit nf_nat_standalone_fini(void)
 {
        nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
        nf_nat_rule_cleanup();
-       nf_nat_module_is_loaded = 0;
 #ifdef CONFIG_XFRM
        ip_nat_decode_session = NULL;
        synchronize_net();