diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-10-14 03:39:55 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-15 15:26:28 -0400 |
commit | 2ca7b0ac022aa0158599178fe1056b1ba9ec8b97 (patch) | |
tree | 6eece25447f0ec3b5d5f5533e49e10fde4d59f35 /net/ipv4 | |
parent | af1e1cf073e3d038b7aac417a20585ecdcab7de6 (diff) |
[NETFILTER]: Avoid skb_copy/pskb_copy/skb_realloc_headroom
This patch replaces unnecessary uses of skb_copy, pskb_copy and
skb_realloc_headroom by functions such as skb_make_writable and
pskb_expand_head.
This allows us to remove the double pointers later.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter.c | 31 | ||||
-rw-r--r-- | net/ipv4/netfilter/arpt_mangle.c | 14 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 22 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 10 |
4 files changed, 21 insertions, 56 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b44192924f95..d1e3012d891f 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/netfilter.h> | 3 | #include <linux/netfilter.h> |
4 | #include <linux/netfilter_ipv4.h> | 4 | #include <linux/netfilter_ipv4.h> |
5 | #include <linux/ip.h> | 5 | #include <linux/ip.h> |
6 | #include <linux/skbuff.h> | ||
6 | #include <net/route.h> | 7 | #include <net/route.h> |
7 | #include <net/xfrm.h> | 8 | #include <net/xfrm.h> |
8 | #include <net/ip.h> | 9 | #include <net/ip.h> |
@@ -66,17 +67,10 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
66 | 67 | ||
67 | /* Change in oif may mean change in hh_len. */ | 68 | /* Change in oif may mean change in hh_len. */ |
68 | hh_len = (*pskb)->dst->dev->hard_header_len; | 69 | hh_len = (*pskb)->dst->dev->hard_header_len; |
69 | if (skb_headroom(*pskb) < hh_len) { | 70 | if (skb_headroom(*pskb) < hh_len && |
70 | struct sk_buff *nskb; | 71 | pskb_expand_head(*pskb, hh_len - skb_headroom(*pskb), 0, |
71 | 72 | GFP_ATOMIC)) | |
72 | nskb = skb_realloc_headroom(*pskb, hh_len); | 73 | return -1; |
73 | if (!nskb) | ||
74 | return -1; | ||
75 | if ((*pskb)->sk) | ||
76 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
77 | kfree_skb(*pskb); | ||
78 | *pskb = nskb; | ||
79 | } | ||
80 | 74 | ||
81 | return 0; | 75 | return 0; |
82 | } | 76 | } |
@@ -107,17 +101,10 @@ int ip_xfrm_me_harder(struct sk_buff **pskb) | |||
107 | 101 | ||
108 | /* Change in oif may mean change in hh_len. */ | 102 | /* Change in oif may mean change in hh_len. */ |
109 | hh_len = (*pskb)->dst->dev->hard_header_len; | 103 | hh_len = (*pskb)->dst->dev->hard_header_len; |
110 | if (skb_headroom(*pskb) < hh_len) { | 104 | if (skb_headroom(*pskb) < hh_len && |
111 | struct sk_buff *nskb; | 105 | pskb_expand_head(*pskb, hh_len - skb_headroom(*pskb), 0, |
112 | 106 | GFP_ATOMIC)) | |
113 | nskb = skb_realloc_headroom(*pskb, hh_len); | 107 | return -1; |
114 | if (!nskb) | ||
115 | return -1; | ||
116 | if ((*pskb)->sk) | ||
117 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
118 | kfree_skb(*pskb); | ||
119 | *pskb = nskb; | ||
120 | } | ||
121 | return 0; | 108 | return 0; |
122 | } | 109 | } |
123 | EXPORT_SYMBOL(ip_xfrm_me_harder); | 110 | EXPORT_SYMBOL(ip_xfrm_me_harder); |
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index c4bdab47597f..0181f919a79c 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* module that allows mangling of the arp payload */ | 1 | /* module that allows mangling of the arp payload */ |
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/netfilter.h> | ||
3 | #include <linux/netfilter_arp/arpt_mangle.h> | 4 | #include <linux/netfilter_arp/arpt_mangle.h> |
4 | #include <net/sock.h> | 5 | #include <net/sock.h> |
5 | 6 | ||
@@ -18,17 +19,8 @@ target(struct sk_buff **pskb, | |||
18 | unsigned char *arpptr; | 19 | unsigned char *arpptr; |
19 | int pln, hln; | 20 | int pln, hln; |
20 | 21 | ||
21 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 22 | if (skb_make_writable(*pskb, (*pskb)->len)) |
22 | struct sk_buff *nskb; | 23 | return NF_DROP; |
23 | |||
24 | nskb = skb_copy(*pskb, GFP_ATOMIC); | ||
25 | if (!nskb) | ||
26 | return NF_DROP; | ||
27 | if ((*pskb)->sk) | ||
28 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
29 | kfree_skb(*pskb); | ||
30 | *pskb = nskb; | ||
31 | } | ||
32 | 24 | ||
33 | arp = arp_hdr(*pskb); | 25 | arp = arp_hdr(*pskb); |
34 | arpptr = skb_network_header(*pskb) + sizeof(*arp); | 26 | arpptr = skb_network_header(*pskb) + sizeof(*arp); |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 62d8867ca7d0..10a2ce09fd8e 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -335,6 +335,7 @@ static int | |||
335 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | 335 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) |
336 | { | 336 | { |
337 | int diff; | 337 | int diff; |
338 | int err; | ||
338 | struct iphdr *user_iph = (struct iphdr *)v->payload; | 339 | struct iphdr *user_iph = (struct iphdr *)v->payload; |
339 | 340 | ||
340 | if (v->data_len < sizeof(*user_iph)) | 341 | if (v->data_len < sizeof(*user_iph)) |
@@ -347,21 +348,14 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
347 | if (v->data_len > 0xFFFF) | 348 | if (v->data_len > 0xFFFF) |
348 | return -EINVAL; | 349 | return -EINVAL; |
349 | if (diff > skb_tailroom(e->skb)) { | 350 | if (diff > skb_tailroom(e->skb)) { |
350 | struct sk_buff *newskb; | 351 | err = pskb_expand_head(e->skb, 0, |
351 | 352 | diff - skb_tailroom(e->skb), | |
352 | newskb = skb_copy_expand(e->skb, | 353 | GFP_ATOMIC); |
353 | skb_headroom(e->skb), | 354 | if (err) { |
354 | diff, | 355 | printk(KERN_WARNING "ip_queue: error " |
355 | GFP_ATOMIC); | 356 | "in mangle, dropping packet: %d\n", -err); |
356 | if (newskb == NULL) { | 357 | return err; |
357 | printk(KERN_WARNING "ip_queue: OOM " | ||
358 | "in mangle, dropping packet\n"); | ||
359 | return -ENOMEM; | ||
360 | } | 358 | } |
361 | if (e->skb->sk) | ||
362 | skb_set_owner_w(newskb, e->skb->sk); | ||
363 | kfree_skb(e->skb); | ||
364 | e->skb = newskb; | ||
365 | } | 359 | } |
366 | skb_put(e->skb, diff); | 360 | skb_put(e->skb, diff); |
367 | } | 361 | } |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 6e81f7612b71..40b429e4540d 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -113,20 +113,12 @@ static void mangle_contents(struct sk_buff *skb, | |||
113 | /* Unusual, but possible case. */ | 113 | /* Unusual, but possible case. */ |
114 | static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) | 114 | static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) |
115 | { | 115 | { |
116 | struct sk_buff *nskb; | ||
117 | |||
118 | if ((*pskb)->len + extra > 65535) | 116 | if ((*pskb)->len + extra > 65535) |
119 | return 0; | 117 | return 0; |
120 | 118 | ||
121 | nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC); | 119 | if (pskb_expand_head(*pskb, 0, extra - skb_tailroom(*pskb), GFP_ATOMIC)) |
122 | if (!nskb) | ||
123 | return 0; | 120 | return 0; |
124 | 121 | ||
125 | /* Transfer socket to new skb. */ | ||
126 | if ((*pskb)->sk) | ||
127 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
128 | kfree_skb(*pskb); | ||
129 | *pskb = nskb; | ||
130 | return 1; | 122 | return 1; |
131 | } | 123 | } |
132 | 124 | ||