diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-10-14 03:39:18 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-15 15:26:27 -0400 |
commit | 37d41879224108d6c24578ba6a3eeafce106ce84 (patch) | |
tree | 96eb40eb2be71feef1c675800662084be14b2e96 /net/netfilter | |
parent | 7b995651e373d6424f81db23f2ec503306dfd7f0 (diff) |
[NETFILTER]: Do not copy skb in skb_make_writable
Now that all callers of netfilter can guarantee that the skb is not shared,
we no longer have to copy the skb in skb_make_writable.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/core.c | 38 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 2 | ||||
-rw-r--r-- | net/netfilter/xt_DSCP.c | 4 | ||||
-rw-r--r-- | net/netfilter/xt_TCPMSS.c | 2 |
4 files changed, 18 insertions, 28 deletions
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index a523fa4136ed..2c9e8e3652d0 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -196,34 +196,24 @@ unlock: | |||
196 | EXPORT_SYMBOL(nf_hook_slow); | 196 | EXPORT_SYMBOL(nf_hook_slow); |
197 | 197 | ||
198 | 198 | ||
199 | int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) | 199 | int skb_make_writable(struct sk_buff *skb, unsigned int writable_len) |
200 | { | 200 | { |
201 | struct sk_buff *nskb; | 201 | if (writable_len > skb->len) |
202 | |||
203 | if (writable_len > (*pskb)->len) | ||
204 | return 0; | 202 | return 0; |
205 | 203 | ||
206 | /* Not exclusive use of packet? Must copy. */ | 204 | /* Not exclusive use of packet? Must copy. */ |
207 | if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len)) | 205 | if (!skb_cloned(skb)) { |
208 | goto copy_skb; | 206 | if (writable_len <= skb_headlen(skb)) |
209 | if (skb_shared(*pskb)) | 207 | return 1; |
210 | goto copy_skb; | 208 | } else if (skb_clone_writable(skb, writable_len)) |
211 | 209 | return 1; | |
212 | return pskb_may_pull(*pskb, writable_len); | 210 | |
213 | 211 | if (writable_len <= skb_headlen(skb)) | |
214 | copy_skb: | 212 | writable_len = 0; |
215 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 213 | else |
216 | if (!nskb) | 214 | writable_len -= skb_headlen(skb); |
217 | return 0; | 215 | |
218 | BUG_ON(skb_is_nonlinear(nskb)); | 216 | return !!__pskb_pull_tail(skb, writable_len); |
219 | |||
220 | /* Rest of kernel will get very unhappy if we pass it a | ||
221 | suddenly-orphaned skbuff */ | ||
222 | if ((*pskb)->sk) | ||
223 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
224 | kfree_skb(*pskb); | ||
225 | *pskb = nskb; | ||
226 | return 1; | ||
227 | } | 217 | } |
228 | EXPORT_SYMBOL(skb_make_writable); | 218 | EXPORT_SYMBOL(skb_make_writable); |
229 | 219 | ||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 49f0480afe09..6ba98acdd7a2 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -644,7 +644,7 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) | |||
644 | } | 644 | } |
645 | skb_put(e->skb, diff); | 645 | skb_put(e->skb, diff); |
646 | } | 646 | } |
647 | if (!skb_make_writable(&e->skb, data_len)) | 647 | if (!skb_make_writable(e->skb, data_len)) |
648 | return -ENOMEM; | 648 | return -ENOMEM; |
649 | skb_copy_to_linear_data(e->skb, data, data_len); | 649 | skb_copy_to_linear_data(e->skb, data, data_len); |
650 | e->skb->ip_summed = CHECKSUM_NONE; | 650 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 798ab731009d..170661674388 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
@@ -36,7 +36,7 @@ static unsigned int target(struct sk_buff **pskb, | |||
36 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT; | 36 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT; |
37 | 37 | ||
38 | if (dscp != dinfo->dscp) { | 38 | if (dscp != dinfo->dscp) { |
39 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 39 | if (!skb_make_writable(*pskb, sizeof(struct iphdr))) |
40 | return NF_DROP; | 40 | return NF_DROP; |
41 | 41 | ||
42 | ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK), | 42 | ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK), |
@@ -57,7 +57,7 @@ static unsigned int target6(struct sk_buff **pskb, | |||
57 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT; | 57 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT; |
58 | 58 | ||
59 | if (dscp != dinfo->dscp) { | 59 | if (dscp != dinfo->dscp) { |
60 | if (!skb_make_writable(pskb, sizeof(struct ipv6hdr))) | 60 | if (!skb_make_writable(*pskb, sizeof(struct ipv6hdr))) |
61 | return NF_DROP; | 61 | return NF_DROP; |
62 | 62 | ||
63 | ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK), | 63 | ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK), |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index d40f7e4b1289..31b6f9d09822 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -50,7 +50,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
50 | u16 newmss; | 50 | u16 newmss; |
51 | u8 *opt; | 51 | u8 *opt; |
52 | 52 | ||
53 | if (!skb_make_writable(pskb, (*pskb)->len)) | 53 | if (!skb_make_writable(*pskb, (*pskb)->len)) |
54 | return -1; | 54 | return -1; |
55 | 55 | ||
56 | tcplen = (*pskb)->len - tcphoff; | 56 | tcplen = (*pskb)->len - tcphoff; |