diff options
author | davem <davem> | 2002-01-14 06:31:03 +0000 |
---|---|---|
committer | davem <davem> | 2002-01-14 06:31:03 +0000 |
commit | 2db8d017f219b32cb65e7a4437ca9e8cf833ab65 (patch) | |
tree | 8bbeb86de346fe1e12d67cc2bb0bc75d95e40f2e | |
parent | b81564ebc32812209399d2befb9a27d154ba9712 (diff) | |
download | netdev-vger-cvs-2db8d017f219b32cb65e7a4437ca9e8cf833ab65.tar.gz |
When output interface changes, so does
hh_len, realloc if necessary. From Paul Russell.
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index f6e13323d..50c679e63 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -166,19 +166,16 @@ ip_nat_out(unsigned int hooknum, return ip_nat_fn(hooknum, pskb, in, out, okfn); } -/* FIXME: change in oif may mean change in hh_len. Check and realloc - --RR */ -static int -route_me_harder(struct sk_buff *skb) +static int route_me_harder(struct sk_buff **pskb) { - struct iphdr *iph = skb->nh.iph; + struct iphdr *iph = (*pskb)->nh.iph; struct rtable *rt; struct rt_key key = { dst:iph->daddr, src:iph->saddr, - oif:skb->sk ? skb->sk->bound_dev_if : 0, + oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, tos:RT_TOS(iph->tos)|RTO_CONN, #ifdef CONFIG_IP_ROUTE_FWMARK - fwmark:skb->nfmark + fwmark:(*pskb)->nfmark #endif }; @@ -188,9 +185,24 @@ route_me_harder(struct sk_buff *skb) } /* Drop old route. */ - dst_release(skb->dst); - - skb->dst = &rt->u.dst; + dst_release((*pskb)->dst); + + (*pskb)->dst = &rt->u.dst; + + /* Change in oif may mean change in hh_len. */ + if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) { + struct sk_buff *nskb; + + nskb = skb_realloc_headroom(*pskb, + (*pskb)->dst->dev + ->hard_header_len); + if (!nskb) + return -ENOMEM; + if ((*pskb)->sk) + skb_set_owner_w(nskb, (*pskb)->sk); + kfree_skb(*pskb); + *pskb = nskb; + } return 0; } @@ -216,7 +228,7 @@ ip_nat_local_fn(unsigned int hooknum, if (ret != NF_DROP && ret != NF_STOLEN && ((*pskb)->nh.iph->saddr != saddr || (*pskb)->nh.iph->daddr != daddr)) - return route_me_harder(*pskb) == 0 ? ret : NF_DROP; + return route_me_harder(pskb) == 0 ? ret : NF_DROP; return ret; } |