diff options
| -rw-r--r-- | include/linux/netfilter_ipv4.h | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter.c | 41 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 6 |
3 files changed, 45 insertions, 4 deletions
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index fdc4a9527343..43c09d790b83 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h | |||
| @@ -79,7 +79,7 @@ enum nf_ip_hook_priorities { | |||
| 79 | 79 | ||
| 80 | #ifdef __KERNEL__ | 80 | #ifdef __KERNEL__ |
| 81 | extern int ip_route_me_harder(struct sk_buff **pskb); | 81 | extern int ip_route_me_harder(struct sk_buff **pskb); |
| 82 | 82 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); | |
| 83 | #endif /*__KERNEL__*/ | 83 | #endif /*__KERNEL__*/ |
| 84 | 84 | ||
| 85 | #endif /*__LINUX_IP_NETFILTER_H*/ | 85 | #endif /*__LINUX_IP_NETFILTER_H*/ |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 52a3d7c57907..ed42cdc57cd9 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
| @@ -78,6 +78,47 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
| 78 | } | 78 | } |
| 79 | EXPORT_SYMBOL(ip_route_me_harder); | 79 | EXPORT_SYMBOL(ip_route_me_harder); |
| 80 | 80 | ||
| 81 | #ifdef CONFIG_XFRM | ||
| 82 | int ip_xfrm_me_harder(struct sk_buff **pskb) | ||
| 83 | { | ||
| 84 | struct flowi fl; | ||
| 85 | unsigned int hh_len; | ||
| 86 | struct dst_entry *dst; | ||
| 87 | |||
| 88 | if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) | ||
| 89 | return 0; | ||
| 90 | if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0) | ||
| 91 | return -1; | ||
| 92 | |||
| 93 | dst = (*pskb)->dst; | ||
| 94 | if (dst->xfrm) | ||
| 95 | dst = ((struct xfrm_dst *)dst)->route; | ||
| 96 | dst_hold(dst); | ||
| 97 | |||
| 98 | if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0) | ||
| 99 | return -1; | ||
| 100 | |||
| 101 | dst_release((*pskb)->dst); | ||
| 102 | (*pskb)->dst = dst; | ||
| 103 | |||
| 104 | /* Change in oif may mean change in hh_len. */ | ||
| 105 | hh_len = (*pskb)->dst->dev->hard_header_len; | ||
| 106 | if (skb_headroom(*pskb) < hh_len) { | ||
| 107 | struct sk_buff *nskb; | ||
| 108 | |||
| 109 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
| 110 | if (!nskb) | ||
| 111 | return -1; | ||
| 112 | if ((*pskb)->sk) | ||
| 113 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 114 | kfree_skb(*pskb); | ||
| 115 | *pskb = nskb; | ||
| 116 | } | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | EXPORT_SYMBOL(ip_xfrm_me_harder); | ||
| 120 | #endif | ||
| 121 | |||
| 81 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | 122 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); |
| 82 | EXPORT_SYMBOL(ip_nat_decode_session); | 123 | EXPORT_SYMBOL(ip_nat_decode_session); |
| 83 | 124 | ||
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 92c54999a19d..7c3f7d380240 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
| @@ -235,19 +235,19 @@ ip_nat_out(unsigned int hooknum, | |||
| 235 | return NF_ACCEPT; | 235 | return NF_ACCEPT; |
| 236 | 236 | ||
| 237 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 237 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
| 238 | #ifdef CONFIG_XFRM | ||
| 238 | if (ret != NF_DROP && ret != NF_STOLEN | 239 | if (ret != NF_DROP && ret != NF_STOLEN |
| 239 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | 240 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { |
| 240 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 241 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
| 241 | 242 | ||
| 242 | if (ct->tuplehash[dir].tuple.src.ip != | 243 | if (ct->tuplehash[dir].tuple.src.ip != |
| 243 | ct->tuplehash[!dir].tuple.dst.ip | 244 | ct->tuplehash[!dir].tuple.dst.ip |
| 244 | #ifdef CONFIG_XFRM | ||
| 245 | || ct->tuplehash[dir].tuple.src.u.all != | 245 | || ct->tuplehash[dir].tuple.src.u.all != |
| 246 | ct->tuplehash[!dir].tuple.dst.u.all | 246 | ct->tuplehash[!dir].tuple.dst.u.all |
| 247 | #endif | ||
| 248 | ) | 247 | ) |
| 249 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 248 | return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; |
| 250 | } | 249 | } |
| 250 | #endif | ||
| 251 | return ret; | 251 | return ret; |
| 252 | } | 252 | } |
| 253 | 253 | ||
