aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2002-01-14 06:31:03 +0000
committerdavem <davem>2002-01-14 06:31:03 +0000
commit2db8d017f219b32cb65e7a4437ca9e8cf833ab65 (patch)
tree8bbeb86de346fe1e12d67cc2bb0bc75d95e40f2e
parentb81564ebc32812209399d2befb9a27d154ba9712 (diff)
downloadnetdev-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.c34
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;
}