Name: Remove connection tracking stuff from skb Status: Compiles Signed-off-by: Rusty Russell Use skb_extend for connection tracking. Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_CONNMARK.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_CONNMARK.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_CONNMARK.c 2004-12-24 14:24:31.496805984 +1100 @@ -43,24 +43,24 @@ unsigned long diff; unsigned long nfmark; unsigned long newmark; + struct ip_conntrack_ext *ext; - enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); - if (ct) { + ext = skb_to_conntrack(*pskb); + if (ext) { switch(markinfo->mode) { case IPT_CONNMARK_SET: - newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; - if (newmark != ct->mark) - ct->mark = newmark; + newmark = (ext->ct->mark & ~markinfo->mask) | markinfo->mark; + if (newmark != ext->ct->mark) + ext->ct->mark = newmark; break; case IPT_CONNMARK_SAVE: - newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); - if (ct->mark != newmark) - ct->mark = newmark; + newmark = (ext->ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); + if (ext->ct->mark != newmark) + ext->ct->mark = newmark; break; case IPT_CONNMARK_RESTORE: nfmark = (*pskb)->nfmark; - diff = (ct->mark ^ nfmark) & markinfo->mask; + diff = (ext->ct->mark ^ nfmark) & markinfo->mask; if (diff != 0) { (*pskb)->nfmark = nfmark ^ diff; (*pskb)->nfcache |= NFC_ALTERED; Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_NOTRACK.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_NOTRACK.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_NOTRACK.c 2004-12-24 14:24:31.496805984 +1100 @@ -15,17 +15,23 @@ const void *targinfo, void *userinfo) { + struct ip_conntrack_ext ext; + /* Previously seen (loopback)? Ignore. */ - if ((*pskb)->nfct != NULL) + if (skb_to_conntrack(*pskb)) return IPT_CONTINUE; /* Attach fake conntrack entry. If there is a real ct entry correspondig to this packet, it'll hang aroun till timing out. We don't deal with it for performance reasons. JK */ - (*pskb)->nfct = &ip_conntrack_untracked.ct_general; - (*pskb)->nfctinfo = IP_CT_NEW; - nf_conntrack_get((*pskb)->nfct); + + /* Add conntrack info to skb. */ + ext.ct = &ip_conntrack_untracked; + ext.ctinfo = IP_CT_NEW; + if (!skb_extend_add(&(*pskb)->ext, SKB_EXT_IPCONN, &ext, GFP_KERNEL)) + return NF_DROP; + ip_conntrack_get(&ip_conntrack_untracked); return IPT_CONTINUE; } Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/ip_output.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/ip_output.c 2004-12-24 11:44:44.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/ip_output.c 2004-12-24 14:24:31.496805984 +1100 @@ -401,11 +401,7 @@ #ifdef CONFIG_NETFILTER to->nfmark = from->nfmark; to->nfcache = from->nfcache; - /* Connection association is same as pre-frag packet */ - nf_conntrack_put(to->nfct); - to->nfct = from->nfct; - nf_conntrack_get(to->nfct); - to->nfctinfo = from->nfctinfo; + to->ext = skb_extend_get(from->ext); #ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(to->nf_bridge); to->nf_bridge = from->nf_bridge; Index: linux-2.6.10-rc3-bk16-Netfilter/include/linux/skb_extend.h =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/include/linux/skb_extend.h 2004-12-24 14:24:10.454004976 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/include/linux/skb_extend.h 2004-12-24 14:24:31.497805832 +1100 @@ -4,6 +4,7 @@ enum skb_ext_type { + SKB_EXT_IPCONN, SKB_EXT_MAX, } __attribute__((packed)); Index: linux-2.6.10-rc3-bk16-Netfilter/include/linux/skbuff.h =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/include/linux/skbuff.h 2004-12-24 14:24:10.480001024 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/include/linux/skbuff.h 2004-12-24 14:24:31.497805832 +1100 @@ -28,6 +28,7 @@ #include #include #include +#include #define HAVE_ALLOC_SKB /* For the drivers to know */ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */ @@ -92,11 +93,6 @@ struct net_device; #ifdef CONFIG_NETFILTER -struct nf_conntrack { - atomic_t use; - void (*destroy)(struct nf_conntrack *); -}; - #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info { atomic_t use; @@ -181,8 +177,6 @@ * @destructor: Destruct function * @nfmark: Can be used for communication between hooks * @nfcache: Cache info - * @nfct: Associated connection, if any - * @nfctinfo: Relationship of this skb to the connection * @nf_debug: Netfilter debugging * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c * @private: Data which is private to the HIPPI implementation @@ -249,8 +243,6 @@ #ifdef CONFIG_NETFILTER unsigned long nfmark; __u32 nfcache; - __u32 nfctinfo; - struct nf_conntrack *nfct; #ifdef CONFIG_NETFILTER_DEBUG unsigned int nf_debug; #endif @@ -1137,21 +1129,10 @@ /* Call this if aborting loop before !skb_iter_next */ extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i); -#ifdef CONFIG_NETFILTER -static inline void nf_conntrack_put(struct nf_conntrack *nfct) -{ - if (nfct && atomic_dec_and_test(&nfct->use)) - nfct->destroy(nfct); -} -static inline void nf_conntrack_get(struct nf_conntrack *nfct) -{ - if (nfct) - atomic_inc(&nfct->use); -} static inline void nf_reset(struct sk_buff *skb) { - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; + skb_extend_put(skb->ext); + skb->ext = NULL; #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 0; #endif @@ -1175,9 +1156,6 @@ atomic_inc(&nf_bridge->use); } #endif /* CONFIG_BRIDGE_NETFILTER */ -#else /* CONFIG_NETFILTER */ -static inline void nf_reset(struct sk_buff *skb) {} -#endif /* CONFIG_NETFILTER */ #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_conntrack_standalone.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-24 14:24:09.889090856 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-24 14:24:31.498805680 +1100 @@ -151,7 +151,7 @@ return 1; #endif - if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use))) + if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->use))) return 1; return 0; @@ -364,14 +364,13 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; /* This is where we call the helper: as the packet goes out. */ - ct = ip_conntrack_get(*pskb, &ctinfo); - if (ct && ct->helper) { + ext = skb_to_conntrack(*pskb); + if (ext && ext->ct->helper) { unsigned int ret; - ret = ct->helper->help(pskb, ct, ctinfo); + ret = ext->ct->helper->help(pskb, ext->ct, ext->ctinfo); if (ret != NF_ACCEPT) return ret; } @@ -388,7 +387,7 @@ { /* Previously seen (loopback)? Ignore. Do this before fragment check. */ - if ((*pskb)->nfct) + if (skb_to_conntrack(*pskb)) return NF_ACCEPT; /* Gather fragments. */ @@ -916,6 +915,7 @@ EXPORT_SYMBOL(ip_conntrack_untracked); EXPORT_SYMBOL_GPL(ip_conntrack_find_get); EXPORT_SYMBOL_GPL(ip_conntrack_put); +EXPORT_SYMBOL_GPL(ip_conntrack_get); #ifdef CONFIG_IP_NF_NAT_NEEDED EXPORT_SYMBOL(ip_conntrack_tcp_update); #endif Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_nat_rule.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ip_nat_rule.c 2004-12-24 14:24:06.883547768 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_nat_rule.c 2004-12-24 14:24:31.498805680 +1100 @@ -124,20 +124,20 @@ const void *targinfo, void *userinfo) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; const struct ip_nat_multi_range_compat *mr = targinfo; IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); - ct = ip_conntrack_get(*pskb, &ctinfo); + ext = skb_to_conntrack(*pskb); /* Connection must be valid and new. */ - IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED - || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + IP_NF_ASSERT(ext->ct + && (ext->ctinfo==IP_CT_NEW || ext->ctinfo==IP_CT_RELATED + || ext->ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); IP_NF_ASSERT(out); - return ip_nat_setup_info(ct, &mr->range[0], hooknum); + return ip_nat_setup_info(ext->ct, &mr->range[0], hooknum); } static unsigned int ipt_dnat_target(struct sk_buff **pskb, @@ -147,19 +147,19 @@ const void *targinfo, void *userinfo) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; const struct ip_nat_multi_range_compat *mr = targinfo; IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT); - ct = ip_conntrack_get(*pskb, &ctinfo); + ext = skb_to_conntrack(*pskb); /* Connection must be valid and new. */ - IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); + IP_NF_ASSERT(ext && (ext->ctinfo == IP_CT_NEW + || ext->ctinfo == IP_CT_RELATED)); - return ip_nat_setup_info(ct, &mr->range[0], hooknum); + return ip_nat_setup_info(ext->ct, &mr->range[0], hooknum); } static int ipt_snat_checkentry(const char *tablename, Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_conntrack.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_conntrack.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_conntrack.c 2004-12-24 14:24:31.499805528 +1100 @@ -27,29 +27,28 @@ int *hotdrop) { const struct ipt_conntrack_info *sinfo = matchinfo; - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; unsigned int statebit; - ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); + ext = skb_to_conntrack(skb); #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) - if (ct == &ip_conntrack_untracked) + if (!ext) + statebit = IPT_CONNTRACK_STATE_INVALID; + else if (ext->ct == &ip_conntrack_untracked) statebit = IPT_CONNTRACK_STATE_UNTRACKED; - else if (ct) - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); else - statebit = IPT_CONNTRACK_STATE_INVALID; + statebit = IPT_CONNTRACK_STATE_BIT(ext->ctinfo); if(sinfo->flags & IPT_CONNTRACK_STATE) { - if (ct) { - if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != - ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) + if (ext->ct) { + if(ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != + ext->ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) statebit |= IPT_CONNTRACK_STATE_SNAT; - if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != - ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) + if(ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != + ext->ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) statebit |= IPT_CONNTRACK_STATE_DNAT; } @@ -58,42 +57,42 @@ } if(sinfo->flags & IPT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) + if (!ext || FWINV(ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) return 0; } if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) + if (!ext || FWINV((ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) return 0; } if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) + if (!ext || FWINV((ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) return 0; } if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) + if (!ext || FWINV((ext->ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) return 0; } if(sinfo->flags & IPT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) + if (!ext || FWINV((ext->ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) return 0; } if(sinfo->flags & IPT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) + if (!ext || FWINV((ext->ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) return 0; } if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { unsigned long expires; - if(!ct) + if(!ext) return 0; - expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; + expires = timer_pending(&ext->ct->timeout) ? (ext->ct->timeout.expires - jiffies)/HZ : 0; if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) return 0; Index: linux-2.6.10-rc3-bk16-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-12-24 14:24:09.143204248 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h 2004-12-24 14:24:31.499805528 +1100 @@ -134,7 +134,7 @@ { /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, plus 1 for any connection(s) we are `master' for */ - struct nf_conntrack ct_general; + atomic_t use; /* Have we seen traffic both ways yet? (bitset) */ unsigned long status; @@ -199,16 +199,23 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple, const struct ip_conntrack *ignored_conntrack); -/* Return conntrack_info and tuple hash for given skb. */ -static inline struct ip_conntrack * -ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo) +struct ip_conntrack_ext { - *ctinfo = skb->nfctinfo; - return (struct ip_conntrack *)skb->nfct; + __u32 ctinfo; + struct ip_conntrack *ct; +}; + +/* Return conntrack_info and for given skb. */ +static inline struct ip_conntrack_ext * +skb_to_conntrack(const struct sk_buff *skb) +{ + return skb_extend_find(skb->ext, SKB_EXT_IPCONN); } +/* increment reference count on a conntrack */ +extern void ip_conntrack_get(struct ip_conntrack *ct); /* decrement reference count on a conntrack */ -extern inline void ip_conntrack_put(struct ip_conntrack *ct); +extern void ip_conntrack_put(struct ip_conntrack *ct); /* call to create an explicit dependency on ip_conntrack. */ extern void need_ip_conntrack(void); Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_REDIRECT.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_REDIRECT.c 2004-12-24 14:24:06.931540472 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_REDIRECT.c 2004-12-24 14:24:31.499805528 +1100 @@ -71,8 +71,7 @@ const void *targinfo, void *userinfo) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; u_int32_t newdst; const struct ip_nat_multi_range_compat *mr = targinfo; struct ip_nat_range newrange; @@ -80,8 +79,8 @@ IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT); - ct = ip_conntrack_get(*pskb, &ctinfo); - IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); + ext = skb_to_conntrack(*pskb); + IP_NF_ASSERT(ext && (ext->ctinfo == IP_CT_NEW || ext->ctinfo == IP_CT_RELATED)); /* Local packets: make them go to loopback */ if (hooknum == NF_IP_LOCAL_OUT) @@ -105,7 +104,7 @@ mr->range[0].min, mr->range[0].max }); /* Hand modified range to generic setup. */ - return ip_nat_setup_info(ct, &newrange, hooknum); + return ip_nat_setup_info(ext->ct, &newrange, hooknum); } static struct ipt_target redirect_reg = { Index: linux-2.6.10-rc3-bk16-Netfilter/net/core/netfilter.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/core/netfilter.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/core/netfilter.c 2004-12-24 14:24:31.500805376 +1100 @@ -811,7 +811,7 @@ { void (*attach)(struct sk_buff *, struct sk_buff *); - if (skb->nfct && (attach = ip_ct_attach) != NULL) { + if (skb->ext && (attach = ip_ct_attach) != NULL) { mb(); /* Just to be sure: must be read before executing this */ attach(new, skb); } Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_connmark.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_connmark.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_connmark.c 2004-12-24 14:24:31.500805376 +1100 @@ -39,12 +39,13 @@ int *hotdrop) { const struct ipt_connmark_info *info = matchinfo; - enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); - if (!ct) + struct ip_conntrack_ext *ext; + + ext = skb_to_conntrack(skb); + if (!ext) return 0; - return ((ct->mark & info->mask) == info->mark) ^ info->invert; + return ((ext->ct->mark & info->mask) == info->mark) ^ info->invert; } static int Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_CLUSTERIP.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_CLUSTERIP.c 2004-12-24 14:24:09.941082952 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_CLUSTERIP.c 2004-12-24 14:24:31.501805224 +1100 @@ -317,15 +317,16 @@ void *userinfo) { const struct ipt_clusterip_tgt_info *cipinfo = targinfo; - enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); + struct ip_conntrack_ext *ext; u_int32_t hash; + ext = skb_to_conntrack(*pskb); + /* don't need to clusterip_config_get() here, since refcount * is only decremented by destroy() - and ip_tables guarantees * that the ->target() function isn't called after ->destroy() */ - if (!ct) { + if (!ext) { printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); /* FIXME: need to drop invalid ones, since replies * to outgoing connections of other nodes will be @@ -336,8 +337,8 @@ /* special case: ICMP error handling. conntrack distinguishes between * error messages (RELATED) and information requests (see below) */ if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP - && (ctinfo == IP_CT_RELATED - || ctinfo == IP_CT_IS_REPLY+IP_CT_IS_REPLY)) + && (ext->ctinfo == IP_CT_RELATED + || ext->ctinfo == IP_CT_IS_REPLY+IP_CT_IS_REPLY)) return IPT_CONTINUE; /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, @@ -346,9 +347,9 @@ hash = clusterip_hashfn(*pskb, cipinfo->config); - switch (ctinfo) { + switch (ext->ctinfo) { case IP_CT_NEW: - ct->mark = hash; + ext->ct->mark = hash; break; case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: @@ -365,7 +366,7 @@ #ifdef DEBUG_CLUSTERP DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); #endif - DEBUGP("hash=%u ct_hash=%lu ", hash, ct->mark); + DEBUGP("hash=%u ct_hash=%lu ", hash, ext->ct->mark); if (!clusterip_responsible(cipinfo->config, hash)) { DEBUGP("not responsible\n"); return NF_DROP; Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_nat_standalone.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ip_nat_standalone.c 2004-12-24 14:24:09.942082800 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_nat_standalone.c 2004-12-24 14:24:31.501805224 +1100 @@ -71,8 +71,7 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; struct ip_nat_info *info; /* maniptype == SRC for postrouting. */ enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum); @@ -89,12 +88,12 @@ if (skb_checksum_help(*pskb, (out == NULL))) return NF_DROP; - ct = ip_conntrack_get(*pskb, &ctinfo); + ext = skb_to_conntrack(*pskb); /* 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) { + if (!ext) { /* 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. */ @@ -111,19 +110,19 @@ return NF_ACCEPT; } - switch (ctinfo) { + switch (ext->ctinfo) { case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { - if (!icmp_reply_translation(pskb, ct, hooknum, - CTINFO2DIR(ctinfo))) + if (!icmp_reply_translation(pskb, ext->ct, hooknum, + CTINFO2DIR(ext->ctinfo))) return NF_DROP; else return NF_ACCEPT; } /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ case IP_CT_NEW: - info = &ct->nat.info; + info = &ext->ct->nat.info; WRITE_LOCK(&ip_nat_lock); /* Seen it before? This can happen for loopback, retrans, @@ -131,20 +130,20 @@ if (!(info->initialized & (1 << maniptype))) { unsigned int ret; - if (ct->master - && master_ct(ct)->nat.info.helper - && master_ct(ct)->nat.info.helper->expect) { - ret = call_expect(master_ct(ct), pskb, - hooknum, ct, info); + if (ext->ct->master + && master_ct(ext->ct)->nat.info.helper + && master_ct(ext->ct)->nat.info.helper->expect) { + ret = call_expect(master_ct(ext->ct), pskb, + hooknum, ext->ct, info); } else { /* LOCAL_IN hook doesn't have a chain! */ if (hooknum == NF_IP_LOCAL_IN) - ret = alloc_null_binding(ct, info, + ret = alloc_null_binding(ext->ct, info, hooknum); else ret = ip_nat_rule_find(pskb, hooknum, - in, out, ct, - info); + in, out, + ext->ct, info); } if (ret != NF_ACCEPT) { @@ -154,7 +153,7 @@ } else DEBUGP("Already setup manip %s for ct %p\n", maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", - ct); + ext->ct); WRITE_UNLOCK(&ip_nat_lock); break; @@ -162,11 +161,11 @@ /* ESTABLISHED */ IP_NF_ASSERT(ctinfo == IP_CT_ESTABLISHED || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); - info = &ct->nat.info; + info = &ext->ct->nat.info; } IP_NF_ASSERT(info); - return do_bindings(ct, ctinfo, info, hooknum, pskb); + return do_bindings(ext->ct, ext->ctinfo, info, hooknum, pskb); } static unsigned int Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_helper.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_helper.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_helper.c 2004-12-24 14:24:31.501805224 +1100 @@ -39,22 +39,21 @@ { const struct ipt_helper_info *info = matchinfo; struct ip_conntrack_expect *exp; - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; int ret = info->invert; - ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); - if (!ct) { + ext = skb_to_conntrack(skb); + if (!ext) { DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); return ret; } - if (!ct->master) { + if (!ext->ct->master) { DEBUGP("ipt_helper: conntrack %p has no master\n", ct); return ret; } - exp = ct->master; + exp = ext->ct->master; READ_LOCK(&ip_conntrack_lock); if (!exp->expectant) { DEBUGP("ipt_helper: expectation %p without expectant !?!\n", Index: linux-2.6.10-rc3-bk16-Netfilter/net/core/skbuff.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/core/skbuff.c 2004-12-24 14:24:10.550990232 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/core/skbuff.c 2004-12-24 14:24:31.502805072 +1100 @@ -242,12 +242,6 @@ "hard IRQ %p\n", NET_CALLER(skb)); skb->destructor(skb); } -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); -#ifdef CONFIG_BRIDGE_NETFILTER - nf_bridge_put(skb->nf_bridge); -#endif -#endif /* XXX: IS this still necessary? - JHS */ #ifdef CONFIG_NET_SCHED skb->tc_index = 0; @@ -314,9 +308,6 @@ #ifdef CONFIG_NETFILTER C(nfmark); C(nfcache); - C(nfct); - nf_conntrack_get(skb->nfct); - C(nfctinfo); #ifdef CONFIG_NETFILTER_DEBUG C(nf_debug); #endif @@ -381,10 +372,6 @@ new->security = old->security; #ifdef CONFIG_NETFILTER new->nfmark = old->nfmark; - new->nfcache = old->nfcache; - new->nfct = old->nfct; - nf_conntrack_get(old->nfct); - new->nfctinfo = old->nfctinfo; #ifdef CONFIG_NETFILTER_DEBUG new->nf_debug = old->nf_debug; #endif Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_conntrack_proto_icmp.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-12-24 14:24:31.503804920 +1100 @@ -132,7 +132,7 @@ static int icmp_error_message(struct sk_buff *skb, - enum ip_conntrack_info *ctinfo, + enum ip_conntrack_info *unused_ctinfo, /* FIXME */ unsigned int hooknum) { struct ip_conntrack_tuple innertuple, origtuple; @@ -142,6 +142,7 @@ } _in, *inside; struct ip_conntrack_protocol *innerproto; struct ip_conntrack_tuple_hash *h; + struct ip_conntrack_ext ext; int dataoff; IP_NF_ASSERT(skb->nfct == NULL); @@ -173,8 +174,7 @@ return NF_ACCEPT; } - *ctinfo = IP_CT_RELATED; - + ext.ctinfo = IP_CT_RELATED; h = ip_conntrack_find_get(&innertuple, NULL); if (!h) { /* Locally generated ICMPs will match inverted if they @@ -189,15 +189,17 @@ } /* Reverse direction from that found */ if (DIRECTION(h) != IP_CT_DIR_REPLY) - *ctinfo += IP_CT_IS_REPLY; + ext.ctinfo += IP_CT_IS_REPLY; } else { if (DIRECTION(h) == IP_CT_DIR_REPLY) - *ctinfo += IP_CT_IS_REPLY; + ext.ctinfo += IP_CT_IS_REPLY; } - /* Update skb to refer to this connection */ - skb->nfct = &h->ctrack->ct_general; - skb->nfctinfo = *ctinfo; + ext.ct = h->ctrack; + if (!skb_extend_add(&skb->ext, SKB_EXT_IPCONN, &ext, GFP_ATOMIC)) { + ip_conntrack_put(h->ctrack); + return -NF_DROP; + } return -NF_ACCEPT; } Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_NETMAP.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_NETMAP.c 2004-12-24 14:24:06.973534088 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_NETMAP.c 2004-12-24 14:24:31.503804920 +1100 @@ -69,15 +69,14 @@ const void *targinfo, void *userinfo) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; u_int32_t new_ip, netmask; const struct ip_nat_multi_range_compat *mr = targinfo; struct ip_nat_range newrange; IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_POST_ROUTING); - ct = ip_conntrack_get(*pskb, &ctinfo); + ext = skb_to_conntrack(*pskb); netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); @@ -93,7 +92,7 @@ mr->range[0].min, mr->range[0].max }); /* Hand modified range to generic setup. */ - return ip_nat_setup_info(ct, &newrange, hooknum); + return ip_nat_setup_info(ext->ct, &newrange, hooknum); } static struct ipt_target target_module = { Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_MASQUERADE.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_MASQUERADE.c 2004-12-24 14:24:08.666276752 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_MASQUERADE.c 2004-12-24 14:24:31.503804920 +1100 @@ -77,8 +77,7 @@ const void *targinfo, void *userinfo) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; const struct ip_nat_multi_range_compat *mr; struct ip_nat_range newrange; struct rtable *rt; @@ -91,9 +90,9 @@ if ((*pskb)->sk) return NF_ACCEPT; - ct = ip_conntrack_get(*pskb, &ctinfo); - IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED - || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + ext = skb_to_conntrack(*pskb); + IP_NF_ASSERT(ext && (ext->ctinfo == IP_CT_NEW || ext->ctinfo == IP_CT_RELATED + || ext->ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); mr = targinfo; rt = (struct rtable *)(*pskb)->dst; @@ -104,7 +103,7 @@ } WRITE_LOCK(&masq_lock); - strcpy(ct->nat.masq_iface, out->name); + strcpy(ext->ct->nat.masq_iface, out->name); WRITE_UNLOCK(&masq_lock); /* Transfer from original range. */ @@ -114,7 +113,7 @@ mr->range[0].min, mr->range[0].max }); /* Hand modified range to generic setup. */ - return ip_nat_setup_info(ct, &newrange, hooknum); + return ip_nat_setup_info(ext->ct, &newrange, hooknum); } static inline int Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_SAME.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_SAME.c 2004-12-24 14:24:06.975533784 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_SAME.c 2004-12-24 14:24:31.504804768 +1100 @@ -146,8 +146,7 @@ const void *targinfo, void *userinfo) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; u_int32_t tmpip, aindex, new_ip; const struct ipt_same_info *same = targinfo; struct ip_nat_range newrange; @@ -155,9 +154,9 @@ IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_POST_ROUTING); - ct = ip_conntrack_get(*pskb, &ctinfo); + ext = skb_to_conntrack(*pskb); - t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + t = &ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; /* Base new source on real src ip and optionally dst ip, giving some hope for consistency across reboots. @@ -185,7 +184,7 @@ same->range[0].min, same->range[0].max }); /* Hand modified range to generic setup. */ - return ip_nat_setup_info(ct, &newrange, hooknum); + return ip_nat_setup_info(ext->ct, &newrange, hooknum); } static struct ipt_target same_reg = { Index: linux-2.6.10-rc3-bk16-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_core.h =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-24 14:24:08.940235104 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-24 14:24:31.504804768 +1100 @@ -34,14 +34,16 @@ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple, const struct ip_conntrack *ignored_conntrack); -extern int __ip_conntrack_confirm(struct sk_buff **pskb); +extern int __ip_conntrack_confirm(struct sk_buff **pskb, + struct ip_conntrack_ext *ext); /* Confirm a connection: returns NF_DROP if packet must be dropped. */ static inline int ip_conntrack_confirm(struct sk_buff **pskb) { - if ((*pskb)->nfct - && !is_confirmed((struct ip_conntrack *)(*pskb)->nfct)) - return __ip_conntrack_confirm(pskb); + struct ip_conntrack_ext *ext = skb_to_conntrack(*pskb); + + if (ext && !is_confirmed(ext->ct)) + return __ip_conntrack_confirm(pskb, ext); return NF_ACCEPT; } Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_conntrack_core.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-24 14:24:09.991075352 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-24 14:25:52.941424520 +1100 @@ -78,11 +78,19 @@ DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat); -void -ip_conntrack_put(struct ip_conntrack *ct) +static void destroy_conntrack(struct ip_conntrack *ct); + +void ip_conntrack_put(struct ip_conntrack *ct) { IP_NF_ASSERT(ct); - nf_conntrack_put(&ct->ct_general); + if (atomic_dec_and_test(&ct->use)) + destroy_conntrack(ct); +} + +/* increment reference count on a conntrack */ +void ip_conntrack_get(struct ip_conntrack *ct) +{ + atomic_inc(&ct->use); } static int ip_conntrack_hash_rnd_initted; @@ -248,9 +256,9 @@ } static void -destroy_conntrack(struct nf_conntrack *nfct) +destroy_conntrack(struct ip_conntrack *ct) { - struct ip_conntrack *ct = (struct ip_conntrack *)nfct, *master = NULL; + struct ip_conntrack *master = NULL; struct ip_conntrack_protocol *proto; DEBUGP("destroy_conntrack(%p)\n", ct); @@ -349,7 +357,7 @@ READ_LOCK(&ip_conntrack_lock); h = __ip_conntrack_find(tuple, ignored_conntrack); if (h) - atomic_inc(&h->ctrack->ct_general.use); + ip_conntrack_get(h->ctrack); READ_UNLOCK(&ip_conntrack_lock); return h; @@ -357,23 +365,19 @@ /* Confirm a connection given skb; places it in hash table */ int -__ip_conntrack_confirm(struct sk_buff **pskb) +__ip_conntrack_confirm(struct sk_buff **pskb, struct ip_conntrack_ext *ext) { unsigned int hash, repl_hash; - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; - - ct = ip_conntrack_get(*pskb, &ctinfo); /* ipt_REJECT uses ip_conntrack_attach to attach related ICMP/TCP RST packets in other direction. Actual packet which created connection will be IP_CT_NEW or for an expected connection, IP_CT_RELATED. */ - if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) + if (CTINFO2DIR(ext->ctinfo) != IP_CT_DIR_ORIGINAL) return NF_ACCEPT; - hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + hash = hash_conntrack(&ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + repl_hash = hash_conntrack(&ext->ct->tuplehash[IP_CT_DIR_REPLY].tuple); /* We're not in hash table, and we refuse to set up related connections for unconfirmed conns. But packet copies and @@ -382,8 +386,8 @@ /* No external references means noone else could have confirmed us. */ - IP_NF_ASSERT(!is_confirmed(ct)); - DEBUGP("Confirming conntrack %p\n", ct); + IP_NF_ASSERT(!is_confirmed(ext->ct)); + DEBUGP("Confirming conntrack %p\n", ext->ct); WRITE_LOCK(&ip_conntrack_lock); /* See if there's one in the list already, including reverse: @@ -392,22 +396,22 @@ if (!LIST_FIND(&ip_conntrack_hash[hash], conntrack_tuple_cmp, struct ip_conntrack_tuple_hash *, - &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) + &ext->ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) && !LIST_FIND(&ip_conntrack_hash[repl_hash], conntrack_tuple_cmp, struct ip_conntrack_tuple_hash *, - &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { + &ext->ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { list_prepend(&ip_conntrack_hash[hash], - &ct->tuplehash[IP_CT_DIR_ORIGINAL]); + &ext->ct->tuplehash[IP_CT_DIR_ORIGINAL]); list_prepend(&ip_conntrack_hash[repl_hash], - &ct->tuplehash[IP_CT_DIR_REPLY]); + &ext->ct->tuplehash[IP_CT_DIR_REPLY]); /* Timer relative to confirmation time, not original setting time, otherwise we'd get timer wrap in weird delay cases. */ - ct->timeout.expires += jiffies; - add_timer(&ct->timeout); - atomic_inc(&ct->ct_general.use); - set_bit(IPS_CONFIRMED_BIT, &ct->status); + ext->ct->timeout.expires += jiffies; + add_timer(&ext->ct->timeout); + ip_conntrack_get(ext->ct); + set_bit(IPS_CONFIRMED_BIT, &ext->ct->status); CONNTRACK_STAT_INC(insert); WRITE_UNLOCK(&ip_conntrack_lock); return NF_ACCEPT; @@ -450,7 +454,7 @@ READ_LOCK(&ip_conntrack_lock); h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *); if (h) - atomic_inc(&h->ctrack->ct_general.use); + ip_conntrack_get(h->ctrack); READ_UNLOCK(&ip_conntrack_lock); if (!h) @@ -521,8 +525,7 @@ } memset(conntrack, 0, sizeof(*conntrack)); - atomic_set(&conntrack->ct_general.use, 1); - conntrack->ct_general.destroy = destroy_conntrack; + atomic_set(&conntrack->use, 1); conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack; conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple; @@ -572,7 +575,7 @@ #endif LIST_DELETE(&ip_conntrack_expect_list, expected); expected->expect.expectant->expecting--; - nf_conntrack_get(&master_ct(conntrack)->ct_general); + ip_conntrack_get(master_ct(conntrack)); /* this is a braindead... --pablo */ atomic_inc(&ip_conntrack_count); @@ -597,15 +600,15 @@ } /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */ -static inline struct ip_conntrack * +static inline struct ip_conntrack_ext * resolve_normal_ct(struct sk_buff *skb, struct ip_conntrack_protocol *proto, int *set_reply, - unsigned int hooknum, - enum ip_conntrack_info *ctinfo) + unsigned int hooknum) { struct ip_conntrack_tuple tuple; struct ip_conntrack_tuple_hash *h; + struct ip_conntrack_ext ext, *extp; IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0); @@ -625,7 +628,7 @@ /* It exists; we have (non-exclusive) reference. */ if (DIRECTION(h) == IP_CT_DIR_REPLY) { - *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY; + ext.ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY; /* Please set reply bit if this packet OK */ *set_reply = 1; } else { @@ -633,21 +636,27 @@ if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) { DEBUGP("ip_conntrack_in: normal packet for %p\n", h->ctrack); - *ctinfo = IP_CT_ESTABLISHED; + ext.ctinfo = IP_CT_ESTABLISHED; } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) { DEBUGP("ip_conntrack_in: related packet for %p\n", h->ctrack); - *ctinfo = IP_CT_RELATED; + ext.ctinfo = IP_CT_RELATED; } else { DEBUGP("ip_conntrack_in: new packet for %p\n", h->ctrack); - *ctinfo = IP_CT_NEW; + ext.ctinfo = IP_CT_NEW; } *set_reply = 0; } - skb->nfct = &h->ctrack->ct_general; - skb->nfctinfo = *ctinfo; - return h->ctrack; + + /* Add conntrack info to skb. */ + ext.ct = h->ctrack; + extp = skb_extend_add(&skb->ext, SKB_EXT_IPCONN, &ext, GFP_ATOMIC); + if (!extp) { + ip_conntrack_put(ext.ct); + return ERR_PTR(-ENOMEM); + } + return extp; } /* Netfilter hook itself. */ @@ -657,14 +666,14 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext *ext; struct ip_conntrack_protocol *proto; int set_reply; int ret; + enum ip_conntrack_info dummy_ctinfo; /* FIXME */ /* Previously seen (loopback or untracked)? Ignore. */ - if ((*pskb)->nfct) { + if (skb_extend_find((*pskb)->ext, SKB_EXT_IPCONN)) { CONNTRACK_STAT_INC(ignore); return NF_ACCEPT; } @@ -702,38 +711,39 @@ * inverse of the return code tells to the netfilter * core what to do with the packet. */ if (proto->error != NULL - && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0) { + && (ret = proto->error(*pskb, &dummy_ctinfo, hooknum)) <= 0) { CONNTRACK_STAT_INC(error); CONNTRACK_STAT_INC(invalid); return -ret; } - if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) { + if (!(ext = resolve_normal_ct(*pskb, proto, &set_reply, hooknum))) { /* Not valid part of a connection */ CONNTRACK_STAT_INC(invalid); return NF_ACCEPT; } - if (IS_ERR(ct)) { + if (IS_ERR(ext)) { /* Too stressed to deal. */ CONNTRACK_STAT_INC(drop); return NF_DROP; } - IP_NF_ASSERT((*pskb)->nfct); + IP_NF_ASSERT((*pskb)->ext); - ret = proto->packet(ct, *pskb, ctinfo); + ret = proto->packet(ext->ct, *pskb, ext->ctinfo); if (ret < 0) { /* Invalid: inverse of the return code tells * the netfilter core what to do*/ - nf_conntrack_put((*pskb)->nfct); - (*pskb)->nfct = NULL; + ip_conntrack_put(ext->ct); + (*pskb)->ext = skb_extend_del((*pskb)->ext, + SKB_EXT_IPCONN); CONNTRACK_STAT_INC(invalid); return -ret; } if (set_reply) - set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_SEEN_REPLY_BIT, &ext->ct->status); return ret; } @@ -1043,23 +1053,23 @@ } /* Used by ipt_REJECT. */ -static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) +void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; + struct ip_conntrack_ext ext, *p; /* This ICMP is in reverse direction to the packet which caused it */ - ct = ip_conntrack_get(skb, &ctinfo); - - if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) - ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY; + p = skb_to_conntrack(skb); + if (!p) + return; + + ext = *p; + if (CTINFO2DIR(ext.ctinfo) == IP_CT_DIR_ORIGINAL) + ext.ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY; else - ctinfo = IP_CT_RELATED; + ext.ctinfo = IP_CT_RELATED; - /* Attach to new skbuff, and increment count */ - nskb->nfct = &ct->ct_general; - nskb->nfctinfo = ctinfo; - nf_conntrack_get(nskb->nfct); + /* Silent failure. */ + skb_extend_add(&skb->ext, SKB_EXT_IPCONN, &ext, GFP_ATOMIC); } static inline int @@ -1083,7 +1093,7 @@ struct ip_conntrack_tuple_hash *, kill, data); } if (h) - atomic_inc(&h->ctrack->ct_general.use); + ip_conntrack_get(h->ctrack); READ_UNLOCK(&ip_conntrack_lock); return h; @@ -1205,6 +1215,27 @@ nf_unregister_sockopt(&so_getorigdst); } +static void ip_conntrack_ext_copy(struct skb_extend *e, unsigned int off) +{ + struct ip_conntrack_ext *ext = (void *)e->data + off; + ip_conntrack_get(ext->ct); +} + +static void ip_conntrack_ext_free(struct skb_extend *e, unsigned int off) +{ + struct ip_conntrack_ext *ext = (void *)e->data + off; + ip_conntrack_put(ext->ct); +} + +static struct skb_extend_type ip_ct_ext_type = +{ + .len = sizeof(struct ip_conntrack_ext), + .align = __alignof__(struct ip_conntrack_ext), + .copy = ip_conntrack_ext_copy, + .free = ip_conntrack_ext_free, + .type = SKB_EXT_IPCONN, +}; + static int hashsize; module_param(hashsize, int, 0400); @@ -1274,6 +1305,8 @@ goto err_free_conntrack_slab; } + register_skb_extend_type(&ip_ct_ext_type); + /* Don't NEED lock here, but good form anyway. */ WRITE_LOCK(&ip_conntrack_lock); for (i = 0; i < MAX_IP_CT_PROTO; i++) @@ -1292,7 +1325,7 @@ /* Set up fake conntrack: - to never be deleted, not in any hashes */ - atomic_set(&ip_conntrack_untracked.ct_general.use, 1); + atomic_set(&ip_conntrack_untracked.use, 1); /* - and look it like as a confirmed connection */ set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status); Index: linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_state.c =================================================================== --- linux-2.6.10-rc3-bk16-Netfilter.orig/net/ipv4/netfilter/ipt_state.c 2004-12-16 13:39:14.000000000 +1100 +++ linux-2.6.10-rc3-bk16-Netfilter/net/ipv4/netfilter/ipt_state.c 2004-12-24 14:24:31.504804768 +1100 @@ -27,15 +27,16 @@ int *hotdrop) { const struct ipt_state_info *sinfo = matchinfo; - enum ip_conntrack_info ctinfo; unsigned int statebit; - - if (skb->nfct == &ip_conntrack_untracked.ct_general) - statebit = IPT_STATE_UNTRACKED; - else if (!ip_conntrack_get(skb, &ctinfo)) + struct ip_conntrack_ext *ext; + + ext = skb_to_conntrack(skb); + if (!ext) statebit = IPT_STATE_INVALID; + else if (ext->ct == &ip_conntrack_untracked) + statebit = IPT_STATE_UNTRACKED; else - statebit = IPT_STATE_BIT(ctinfo); + statebit = IPT_STATE_BIT(ext->ctinfo); return (sinfo->statemask & statebit); }