Index: linux-2.6.x/include/linux/netfilter/nf_conntrack_tuple_common.h =================================================================== RCS file: /cvs/sw/linux-2.6.x/include/linux/netfilter/nf_conntrack_tuple_common.h,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 nf_conntrack_tuple_common.h --- linux-2.6.x/include/linux/netfilter/nf_conntrack_tuple_common.h 4 Jan 2006 00:42:51 -0000 1.1.1.1 +++ linux-2.6.x/include/linux/netfilter/nf_conntrack_tuple_common.h 26 Jun 2009 06:32:02 -0000 @@ -3,11 +3,23 @@ enum ip_conntrack_dir { - IP_CT_DIR_ORIGINAL, - IP_CT_DIR_REPLY, - IP_CT_DIR_MAX + IP_CT_DIR_ORIGINAL = 0x00, + IP_CT_DIR_REPLY = 0x01, }; +#define IP_CT_DIR_MAX 0x02 + +#define IP_CT_LOCAL_SRC 0x02 +#define IP_CT_LOCAL_DST 0x04 +#define IP_CT_LOCAL_MASK (IP_CT_LOCAL_SRC | IP_CT_LOCAL_DST) + +static inline u_int8_t nf_ct_invert_dir(u_int8_t ctdir) +{ + return ((ctdir ^ IP_CT_DIR_REPLY) & ~IP_CT_LOCAL_MASK) | + ((ctdir & IP_CT_LOCAL_SRC) << 1) | + ((ctdir & IP_CT_LOCAL_DST) >> 1); +} + #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) #endif /* _NF_CONNTRACK_TUPLE_COMMON_H */ Index: linux-2.6.x/include/linux/netfilter/nfnetlink_conntrack.h =================================================================== RCS file: /cvs/sw/linux-2.6.x/include/linux/netfilter/nfnetlink_conntrack.h,v retrieving revision 1.1.1.8 diff -u -p -r1.1.1.8 nfnetlink_conntrack.h --- linux-2.6.x/include/linux/netfilter/nfnetlink_conntrack.h 25 Mar 2009 01:16:58 -0000 1.1.1.8 +++ linux-2.6.x/include/linux/netfilter/nfnetlink_conntrack.h 26 Jun 2009 06:32:02 -0000 @@ -40,6 +40,7 @@ enum ctattr_type { CTA_NAT_SEQ_ADJ_ORIG, CTA_NAT_SEQ_ADJ_REPLY, CTA_SECMARK, + CTA_DIR, __CTA_MAX }; #define CTA_MAX (__CTA_MAX - 1) Index: linux-2.6.x/include/net/netfilter/nf_conntrack.h =================================================================== RCS file: /cvs/sw/linux-2.6.x/include/net/netfilter/nf_conntrack.h,v retrieving revision 1.7 diff -u -p -r1.7 nf_conntrack.h --- linux-2.6.x/include/net/netfilter/nf_conntrack.h 25 Mar 2009 06:28:27 -0000 1.7 +++ linux-2.6.x/include/net/netfilter/nf_conntrack.h 26 Jun 2009 06:32:02 -0000 @@ -149,7 +149,7 @@ static inline struct nf_conn * nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash) { return container_of(hash, struct nf_conn, - tuplehash[hash->tuple.dst.dir]); + tuplehash[NF_CT_DIRECTION(hash)]); } static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct) @@ -218,7 +218,8 @@ extern void nf_conntrack_hash_insert(str extern void nf_conntrack_flush(struct net *net, u32 pid, int report); extern bool nf_ct_get_tuplepr(const struct sk_buff *skb, - unsigned int nhoff, u_int16_t l3num, + unsigned int nhoff, unsigned int hooknum, + u_int16_t l3num, struct nf_conntrack_tuple *tuple); extern bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); Index: linux-2.6.x/include/net/netfilter/nf_conntrack_core.h =================================================================== RCS file: /cvs/sw/linux-2.6.x/include/net/netfilter/nf_conntrack_core.h,v retrieving revision 1.1.1.9 diff -u -p -r1.1.1.9 nf_conntrack_core.h --- linux-2.6.x/include/net/netfilter/nf_conntrack_core.h 25 Mar 2009 01:17:05 -0000 1.1.1.9 +++ linux-2.6.x/include/net/netfilter/nf_conntrack_core.h 26 Jun 2009 06:32:02 -0000 @@ -35,6 +35,7 @@ extern bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, unsigned int dataoff, + unsigned int hooknum, u_int16_t l3num, u_int8_t protonum, struct nf_conntrack_tuple *tuple, @@ -51,17 +52,18 @@ nf_ct_invert_tuple(struct nf_conntrack_t extern struct nf_conntrack_tuple_hash * nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); -extern int __nf_conntrack_confirm(struct sk_buff *skb); +extern int __nf_conntrack_confirm(struct sk_buff *skb, unsigned int hooknum); /* Confirm a connection: returns NF_DROP if packet must be dropped. */ -static inline int nf_conntrack_confirm(struct sk_buff *skb) +static inline int nf_conntrack_confirm(struct sk_buff *skb, + unsigned int hooknum) { struct nf_conn *ct = (struct nf_conn *)skb->nfct; int ret = NF_ACCEPT; if (ct && ct != &nf_conntrack_untracked) { if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) - ret = __nf_conntrack_confirm(skb); + ret = __nf_conntrack_confirm(skb, hooknum); if (likely(ret == NF_ACCEPT)) nf_ct_deliver_cached_events(ct); } Index: linux-2.6.x/include/net/netfilter/nf_conntrack_l3proto.h =================================================================== RCS file: /cvs/sw/linux-2.6.x/include/net/netfilter/nf_conntrack_l3proto.h,v retrieving revision 1.1.1.9 diff -u -p -r1.1.1.9 nf_conntrack_l3proto.h --- linux-2.6.x/include/net/netfilter/nf_conntrack_l3proto.h 24 Jul 2008 00:12:19 -0000 1.1.1.9 +++ linux-2.6.x/include/net/netfilter/nf_conntrack_l3proto.h 26 Jun 2009 06:32:02 -0000 @@ -24,6 +24,8 @@ struct nf_conntrack_l3proto /* Protocol name */ const char *name; + bool (*local_hook)(unsigned int hooknum); + /* * Try to fill in the third arg: nhoff is offset of l3 proto * hdr. Return true if possible. Index: linux-2.6.x/include/net/netfilter/nf_conntrack_tuple.h =================================================================== RCS file: /cvs/sw/linux-2.6.x/include/net/netfilter/nf_conntrack_tuple.h,v retrieving revision 1.5 diff -u -p -r1.5 nf_conntrack_tuple.h --- linux-2.6.x/include/net/netfilter/nf_conntrack_tuple.h 25 Mar 2009 06:28:27 -0000 1.5 +++ linux-2.6.x/include/net/netfilter/nf_conntrack_tuple.h 26 Jun 2009 06:32:02 -0000 @@ -95,7 +95,7 @@ struct nf_conntrack_tuple u_int8_t protonum; /* The direction (for tuplehash) */ - u_int8_t dir; + u_int8_t ctdir; } dst; }; @@ -104,6 +104,7 @@ struct nf_conntrack_tuple_mask struct { union nf_inet_addr u3; union nf_conntrack_man_proto u; + u_int8_t ctdir; } src; }; @@ -112,9 +113,11 @@ struct nf_conntrack_tuple_mask static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t) { #ifdef DEBUG - printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n", + printk("tuple %p: %s %u %pI4:%hu -> %s %pI4:%hu\n", t, t->dst.protonum, + (t->dst.ctdir & IP_CT_LOCAL_SRC) ? "local" : "remote", &t->src.u3.ip, ntohs(t->src.u.all), + (t->dst.ctdir & IP_CT_LOCAL_DST) ? "local" : "remote", &t->dst.u3.ip, ntohs(t->dst.u.all)); #endif } @@ -124,7 +127,9 @@ static inline void nf_ct_dump_tuple_ipv6 #ifdef DEBUG printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n", t, t->dst.protonum, + (t->dst.ctdir & IP_CT_LOCAL_SRC) ? "local" : "remote", t->src.u3.all, ntohs(t->src.u.all), + (t->dst.ctdir & IP_CT_LOCAL_DST) ? "local" : "remote", t->dst.u3.all, ntohs(t->dst.u.all)); #endif } @@ -143,7 +148,7 @@ static inline void nf_ct_dump_tuple(cons /* If we're the first tuple, it's the original dir. */ #define NF_CT_DIRECTION(h) \ - ((enum ip_conntrack_dir)(h)->tuple.dst.dir) + ((enum ip_conntrack_dir)((h)->tuple.dst.ctdir & IP_CT_DIR_REPLY)) /* Connections have two entries in the hash table: one for each way */ struct nf_conntrack_tuple_hash @@ -159,12 +164,15 @@ static inline bool __nf_ct_tuple_src_equ { return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) && t1->src.u.all == t2->src.u.all && - t1->src.l3num == t2->src.l3num); + t1->src.l3num == t2->src.l3num && + !((t1->dst.ctdir ^ t2->dst.ctdir) & IP_CT_LOCAL_SRC)); } static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1, const struct nf_conntrack_tuple *t2) { + /* Don't compare IP_CT_LOCAL_DST because it is undetermined for + * incoming packets. */ return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) && t1->dst.u.all == t2->dst.u.all && t1->dst.protonum == t2->dst.protonum); @@ -182,7 +190,8 @@ nf_ct_tuple_mask_equal(const struct nf_c const struct nf_conntrack_tuple_mask *m2) { return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) && - m1->src.u.all == m2->src.u.all); + m1->src.u.all == m2->src.u.all && + m1->src.ctdir == m2->src.ctdir); } static inline bool @@ -201,6 +210,9 @@ nf_ct_tuple_src_mask_cmp(const struct nf if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all) return false; + if ((t1->dst.ctdir ^ t2->dst.ctdir) & mask->src.ctdir) + return false; + if (t1->src.l3num != t2->src.l3num || t1->dst.protonum != t2->dst.protonum) return false; Index: linux-2.6.x/net/netfilter/nf_conntrack_core.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/netfilter/nf_conntrack_core.c,v retrieving revision 1.8 diff -u -p -r1.8 nf_conntrack_core.c --- linux-2.6.x/net/netfilter/nf_conntrack_core.c 25 Mar 2009 06:28:29 -0000 1.8 +++ linux-2.6.x/net/netfilter/nf_conntrack_core.c 26 Jun 2009 06:32:02 -0000 @@ -73,12 +73,13 @@ static u_int32_t __hash_conntrack(const /* The direction must be ignored, so we hash everything up to the * destination ports (which is a multiple of 4) and treat the last - * three bytes manually. + * four bytes manually. */ n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); h = jhash2((u32 *)tuple, n, rnd ^ (((__force __u16)tuple->dst.u.all << 16) | - tuple->dst.protonum)); + tuple->dst.protonum | + (tuple->dst.ctdir & IP_CT_LOCAL_SRC))); return ((u64)h * size) >> 32; } @@ -93,6 +94,7 @@ bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, unsigned int dataoff, + unsigned int hooknum, u_int16_t l3num, u_int8_t protonum, struct nf_conntrack_tuple *tuple, @@ -106,14 +108,17 @@ nf_ct_get_tuple(const struct sk_buff *sk return false; tuple->dst.protonum = protonum; - tuple->dst.dir = IP_CT_DIR_ORIGINAL; + tuple->dst.ctdir = IP_CT_DIR_ORIGINAL; + if (l3proto->local_hook(hooknum)) + tuple->dst.ctdir |= IP_CT_LOCAL_SRC; return l4proto->pkt_to_tuple(skb, dataoff, tuple); } EXPORT_SYMBOL_GPL(nf_ct_get_tuple); bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, - u_int16_t l3num, struct nf_conntrack_tuple *tuple) + unsigned int hooknum, u_int16_t l3num, + struct nf_conntrack_tuple *tuple) { struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; @@ -132,8 +137,8 @@ bool nf_ct_get_tuplepr(const struct sk_b l4proto = __nf_ct_l4proto_find(l3num, protonum); - ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple, - l3proto, l4proto); + ret = nf_ct_get_tuple(skb, nhoff, protoff, hooknum, l3num, protonum, + tuple, l3proto, l4proto); rcu_read_unlock(); return ret; @@ -152,7 +157,7 @@ nf_ct_invert_tuple(struct nf_conntrack_t if (l3proto->invert_tuple(inverse, orig) == 0) return false; - inverse->dst.dir = !orig->dst.dir; + inverse->dst.ctdir = nf_ct_invert_dir(orig->dst.ctdir); inverse->dst.protonum = orig->dst.protonum; return l4proto->invert_tuple(inverse, orig); @@ -320,8 +325,11 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash_inse /* Confirm a connection given skb; places it in hash table */ int -__nf_conntrack_confirm(struct sk_buff *skb) +__nf_conntrack_confirm(struct sk_buff *skb, unsigned int hooknum) { + struct nf_conntrack_l3proto *l3proto; + struct nf_conntrack_tuple *orig; + struct nf_conntrack_tuple *repl; unsigned int hash, repl_hash; struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; @@ -340,8 +348,17 @@ __nf_conntrack_confirm(struct sk_buff *s if (CTINFO2DIR(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); + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + repl = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; + + l3proto = __nf_ct_l3proto_find(orig->src.l3num); + if (l3proto->local_hook(hooknum)) { + orig->dst.ctdir |= IP_CT_LOCAL_DST; + repl->dst.ctdir |= IP_CT_LOCAL_SRC; + } + + hash = hash_conntrack(orig); + repl_hash = hash_conntrack(repl); /* We're not in hash table, and we refuse to set up related connections for unconfirmed conns. But packet copies and @@ -359,12 +376,10 @@ __nf_conntrack_confirm(struct sk_buff *s NAT could have grabbed it without realizing, since we're not in the hash. If there is, we lost race. */ hlist_for_each_entry(h, n, &net->ct.hash[hash], hnode) - if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - &h->tuple)) + if (nf_ct_tuple_equal(orig, &h->tuple)) goto out; hlist_for_each_entry(h, n, &net->ct.hash[repl_hash], hnode) - if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, - &h->tuple)) + if (nf_ct_tuple_equal(repl, &h->tuple)) goto out; /* Remove from unconfirmed list */ @@ -619,6 +634,7 @@ static inline struct nf_conn * resolve_normal_ct(struct net *net, struct sk_buff *skb, unsigned int dataoff, + unsigned int hooknum, u_int16_t l3num, u_int8_t protonum, struct nf_conntrack_l3proto *l3proto, @@ -631,7 +647,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *ct; if (!nf_ct_get_tuple(skb, skb_network_offset(skb), - dataoff, l3num, protonum, &tuple, l3proto, + dataoff, hooknum, l3num, protonum, &tuple, l3proto, l4proto)) { pr_debug("resolve_normal_ct: Can't get tuple\n"); return NULL; @@ -717,7 +733,7 @@ nf_conntrack_in(struct net *net, u_int8_ } } - ct = resolve_normal_ct(net, skb, dataoff, pf, protonum, + ct = resolve_normal_ct(net, skb, dataoff, hooknum, pf, protonum, l3proto, l4proto, &set_reply, &ctinfo); if (!ct) { /* Not valid part of a connection */ Index: linux-2.6.x/net/netfilter/nf_conntrack_expect.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/netfilter/nf_conntrack_expect.c,v retrieving revision 1.1.1.8 diff -u -p -r1.1.1.8 nf_conntrack_expect.c --- linux-2.6.x/net/netfilter/nf_conntrack_expect.c 25 Mar 2009 01:16:19 -0000 1.1.1.8 +++ linux-2.6.x/net/netfilter/nf_conntrack_expect.c 26 Jun 2009 06:32:02 -0000 @@ -189,6 +189,7 @@ static inline int expect_clash(const str int count; intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all; + intersect_mask.src.ctdir = a->mask.src.ctdir & b->mask.src.ctdir; for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ intersect_mask.src.u3.all[count] = Index: linux-2.6.x/net/netfilter/nf_conntrack_netlink.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/netfilter/nf_conntrack_netlink.c,v retrieving revision 1.8 diff -u -p -r1.8 nf_conntrack_netlink.c --- linux-2.6.x/net/netfilter/nf_conntrack_netlink.c 25 Mar 2009 06:28:29 -0000 1.8 +++ linux-2.6.x/net/netfilter/nf_conntrack_netlink.c 26 Jun 2009 06:32:02 -0000 @@ -128,6 +128,17 @@ nla_put_failure: } static inline int +ctnetlink_dump_dir(struct sk_buff *skb, const struct nf_conn *ct) +{ + NLA_PUT_U8(skb, CTA_DIR, + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ctdir); + return 0; + +nla_put_failure: + return -1; +} + +static inline int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) { long timeout = (ct->timeout.expires - jiffies) / HZ; @@ -381,6 +392,7 @@ ctnetlink_fill_info(struct sk_buff *skb, nla_nest_end(skb, nest_parms); if (ctnetlink_dump_status(skb, ct) < 0 || + ctnetlink_dump_dir(skb, ct) < 0 || ctnetlink_dump_timeout(skb, ct) < 0 || ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || @@ -476,6 +488,9 @@ static int ctnetlink_conntrack_event(str if (ctnetlink_dump_status(skb, ct) < 0) goto nla_put_failure; + if (ctnetlink_dump_dir(skb, ct) < 0) + goto nla_put_failure; + if (events & IPCT_DESTROY) { if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) @@ -679,10 +694,11 @@ ctnetlink_parse_tuple(struct nlattr *cda /* orig and expect tuples get DIR_ORIGINAL */ if (type == CTA_TUPLE_REPLY) - tuple->dst.dir = IP_CT_DIR_REPLY; + tuple->dst.ctdir = IP_CT_DIR_REPLY; else - tuple->dst.dir = IP_CT_DIR_ORIGINAL; + tuple->dst.ctdir = IP_CT_DIR_ORIGINAL; + /* FIXME: IP_CT_DIR_LOCAL_* */ return 0; } @@ -707,6 +723,7 @@ static const struct nla_policy ct_nla_po [CTA_MARK] = { .type = NLA_U32 }, [CTA_USE] = { .type = NLA_U32 }, [CTA_ID] = { .type = NLA_U32 }, + [CTA_DIR] = { .type = NLA_U8 }, }; static int Index: linux-2.6.x/net/netfilter/nf_conntrack_standalone.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/netfilter/nf_conntrack_standalone.c,v retrieving revision 1.7 diff -u -p -r1.7 nf_conntrack_standalone.c --- linux-2.6.x/net/netfilter/nf_conntrack_standalone.c 25 Mar 2009 06:28:29 -0000 1.7 +++ linux-2.6.x/net/netfilter/nf_conntrack_standalone.c 26 Jun 2009 06:32:02 -0000 @@ -35,6 +35,9 @@ print_tuple(struct seq_file *s, const st const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto) { + if (seq_printf(s, "dir=%u ", tuple->dst.ctdir)) + return -ENOSPC; + return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple); } EXPORT_SYMBOL_GPL(print_tuple); Index: linux-2.6.x/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c,v retrieving revision 1.4 diff -u -p -r1.4 nf_conntrack_l3proto_ipv4.c --- linux-2.6.x/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c 25 Mar 2009 06:28:29 -0000 1.4 +++ linux-2.6.x/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c 26 Jun 2009 06:32:02 -0000 @@ -32,6 +32,11 @@ int (*nf_nat_seq_adjust_hook)(struct sk_ enum ip_conntrack_info ctinfo); EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook); +static bool ipv4_local_hook(unsigned int hooknum) +{ + return hooknum == NF_IP_LOCAL_IN || hooknum == NF_IP_LOCAL_OUT; +} + static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { @@ -125,7 +130,7 @@ static unsigned int ipv4_confirm(unsigne } out: /* We've seen it coming out the other side: confirm it */ - return nf_conntrack_confirm(skb); + return nf_conntrack_confirm(skb, hooknum); } static unsigned int ipv4_conntrack_in(unsigned int hooknum, @@ -340,6 +345,7 @@ struct nf_conntrack_l3proto nf_conntrack .l3proto = PF_INET, .name = "ipv4", .pkt_to_tuple = ipv4_pkt_to_tuple, + .local_hook = ipv4_local_hook, .invert_tuple = ipv4_invert_tuple, .print_tuple = ipv4_print_tuple, .get_l4proto = ipv4_get_l4proto, Index: linux-2.6.x/net/ipv4/netfilter/nf_conntrack_proto_icmp.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/ipv4/netfilter/nf_conntrack_proto_icmp.c,v retrieving revision 1.1.1.13 diff -u -p -r1.1.1.13 nf_conntrack_proto_icmp.c --- linux-2.6.x/net/ipv4/netfilter/nf_conntrack_proto_icmp.c 25 Mar 2009 01:16:17 -0000 1.1.1.13 +++ linux-2.6.x/net/ipv4/netfilter/nf_conntrack_proto_icmp.c 26 Jun 2009 06:32:02 -0000 @@ -137,7 +137,7 @@ icmp_error_message(struct net *net, stru if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb) + ip_hdrlen(skb) + sizeof(struct icmphdr), - PF_INET, &origtuple)) { + hooknum, PF_INET, &origtuple)) { pr_debug("icmp_error_message: failed to get tuple\n"); return -NF_ACCEPT; } Index: linux-2.6.x/net/ipv4/netfilter/nf_nat_core.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/ipv4/netfilter/nf_nat_core.c,v retrieving revision 1.1.1.8 diff -u -p -r1.1.1.8 nf_nat_core.c --- linux-2.6.x/net/ipv4/netfilter/nf_nat_core.c 25 Mar 2009 01:16:17 -0000 1.1.1.8 +++ linux-2.6.x/net/ipv4/netfilter/nf_nat_core.c 26 Jun 2009 06:32:02 -0000 @@ -471,6 +471,7 @@ int nf_nat_icmp_reply_translation(struct ip_hdrlen(skb) + sizeof(struct icmphdr), (ip_hdrlen(skb) + sizeof(struct icmphdr) + inside->ip.ihl * 4), + hooknum, (u_int16_t)AF_INET, inside->ip.protocol, &inner, l3proto, l4proto)) Index: linux-2.6.x/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c =================================================================== RCS file: /cvs/sw/linux-2.6.x/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c,v retrieving revision 1.1.1.13 diff -u -p -r1.1.1.13 nf_conntrack_l3proto_ipv6.c --- linux-2.6.x/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 25 Mar 2009 01:16:12 -0000 1.1.1.13 +++ linux-2.6.x/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 26 Jun 2009 06:32:02 -0000 @@ -27,6 +27,11 @@ #include #include +static bool ipv6_local_hook(unsigned int hooknum) +{ + return hooknum == NF_IP_LOCAL_IN || hooknum == NF_IP_LOCAL_OUT; +} + static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { @@ -179,7 +184,7 @@ static unsigned int ipv6_confirm(unsigne return ret; out: /* We've seen it coming out the other side: confirm it */ - return nf_conntrack_confirm(skb); + return nf_conntrack_confirm(skb, hooknum); } static unsigned int ipv6_defrag(unsigned int hooknum, @@ -346,6 +351,7 @@ static int ipv6_nlattr_to_tuple(struct n struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { .l3proto = PF_INET6, .name = "ipv6", + .local_hook = ipv6_local_hook, .pkt_to_tuple = ipv6_pkt_to_tuple, .invert_tuple = ipv6_invert_tuple, .print_tuple = ipv6_print_tuple,