# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/04/14 02:58:21+02:00 kaber@trash.net # [NETFILTER]: Make policy checks locate correct policy after NAT # # net/xfrm/xfrm_policy.c # 2004/04/14 02:58:11+02:00 kaber@trash.net +2 -0 # [NETFILTER]: Make policy checks locate correct policy after NAT # # net/ipv4/udp.c # 2004/04/14 02:58:11+02:00 kaber@trash.net +2 -0 # [NETFILTER]: Make policy checks locate correct policy after NAT # # net/ipv4/tcp_ipv4.c # 2004/04/14 02:58:11+02:00 kaber@trash.net +1 -0 # [NETFILTER]: Make policy checks locate correct policy after NAT # # net/ipv4/raw.c # 2004/04/14 02:58:11+02:00 kaber@trash.net +1 -0 # [NETFILTER]: Make policy checks locate correct policy after NAT # # net/ipv4/ip_input.c # 2004/04/14 02:58:11+02:00 kaber@trash.net +6 -8 # [NETFILTER]: Make policy checks locate correct policy after NAT # # net/core/netfilter.c # 2004/04/14 02:58:11+02:00 kaber@trash.net +43 -0 # [NETFILTER]: Make policy checks locate correct policy after NAT # # include/linux/netfilter.h # 2004/04/14 02:58:11+02:00 kaber@trash.net +16 -0 # [NETFILTER]: Make policy checks locate correct policy after NAT # diff -Nru a/include/linux/netfilter.h b/include/linux/netfilter.h --- a/include/linux/netfilter.h Wed Apr 14 03:03:46 2004 +++ b/include/linux/netfilter.h Wed Apr 14 03:03:46 2004 @@ -171,5 +171,21 @@ #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) #endif /*CONFIG_NETFILTER*/ +#ifdef CONFIG_XFRM +#ifdef CONFIG_IP_NF_NAT_NEEDED +struct flowi; +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl); + +static inline void +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) +{ + if (family == AF_INET) + nf_nat_decode_session4(skb, fl); +} +#else /* CONFIG_IP_NF_NAT_NEEDED */ +#define nf_nat_decode_session(skb,fl,family) +#endif /* CONFIG_IP_NF_NAT_NEEDED */ +#endif /* CONFIG_XFRM */ + #endif /*__KERNEL__*/ #endif /*__LINUX_NETFILTER_H*/ diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c --- a/net/core/netfilter.c Wed Apr 14 03:03:46 2004 +++ b/net/core/netfilter.c Wed Apr 14 03:03:46 2004 @@ -715,6 +715,49 @@ } return nf_rcv_postxfrm_nonlocal(skb); } + +#ifdef CONFIG_IP_NF_NAT_NEEDED +#include +#include + +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl) +{ + struct ip_conntrack *ct; + struct ip_conntrack_tuple *t; + struct ip_nat_info_manip *m; + unsigned int i; + + if (skb->nfct == NULL) + return; + ct = (struct ip_conntrack *)skb->nfct->master; + + for (i = 0; i < ct->nat.info.num_manips; i++) { + m = &ct->nat.info.manips[i]; + t = &ct->tuplehash[m->direction].tuple; + + switch (m->hooknum) { + case NF_IP_PRE_ROUTING: + if (m->maniptype != IP_NAT_MANIP_DST) + break; + fl->fl4_dst = t->dst.ip; + if (t->dst.protonum == IPPROTO_TCP || + t->dst.protonum == IPPROTO_UDP) + fl->fl_ip_dport = t->dst.u.tcp.port; + break; +#ifdef CONFIG_IP_NF_NAT_LOCAL + case NF_IP_LOCAL_IN: + if (m->maniptype != IP_NAT_MANIP_SRC) + break; + fl->fl4_src = t->src.ip; + if (t->dst.protonum == IPPROTO_TCP || + t->dst.protonum == IPPROTO_UDP) + fl->fl_ip_sport = t->src.u.tcp.port; + break; +#endif + } + } +} +#endif /* CONFIG_IP_NF_NAT_NEEDED */ #endif int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len) diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c --- a/net/ipv4/ip_input.c Wed Apr 14 03:03:45 2004 +++ b/net/ipv4/ip_input.c Wed Apr 14 03:03:45 2004 @@ -206,10 +206,6 @@ __skb_pull(skb, ihl); - /* Free reference early: we don't need it any more, and it may - hold ip_conntrack module loaded indefinitely. */ - nf_reset(skb); - /* Point into the IP datagram, just past the header. */ skb->h.raw = skb->data; @@ -241,10 +237,12 @@ if (ipprot != NULL) { int ret; - if (!ipprot->no_policy && - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { - kfree_skb(skb); - goto out; + if (!ipprot->no_policy) { + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { + kfree_skb(skb); + goto out; + } + nf_reset(skb); } ret = ipprot->handler(skb); if (ret < 0) { diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c --- a/net/ipv4/raw.c Wed Apr 14 03:03:46 2004 +++ b/net/ipv4/raw.c Wed Apr 14 03:03:46 2004 @@ -249,6 +249,7 @@ kfree_skb(skb); return NET_RX_DROP; } + nf_reset(skb); skb_push(skb, skb->data - skb->nh.raw); diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c --- a/net/ipv4/tcp_ipv4.c Wed Apr 14 03:03:45 2004 +++ b/net/ipv4/tcp_ipv4.c Wed Apr 14 03:03:46 2004 @@ -1785,6 +1785,7 @@ if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; + nf_reset(skb); if (sk_filter(sk, skb, 0)) goto discard_and_relse; diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c --- a/net/ipv4/udp.c Wed Apr 14 03:03:45 2004 +++ b/net/ipv4/udp.c Wed Apr 14 03:03:45 2004 @@ -1030,6 +1030,7 @@ kfree_skb(skb); return -1; } + nf_reset(skb); if (up->encap_type) { /* @@ -1195,6 +1196,7 @@ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) goto drop; + nf_reset(skb); /* No socket. Drop packet silently, if checksum is wrong */ if (udp_checksum_complete(skb)) diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c --- a/net/xfrm/xfrm_policy.c Wed Apr 14 03:03:46 2004 +++ b/net/xfrm/xfrm_policy.c Wed Apr 14 03:03:46 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -908,6 +909,7 @@ if (_decode_session(skb, &fl, family) < 0) return 0; + nf_nat_decode_session(skb, &fl, family); /* First, check used SA against their selectors. */ if (skb->sp) {