aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-14 03:39:18 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-15 15:26:27 -0400
commit37d41879224108d6c24578ba6a3eeafce106ce84 (patch)
tree96eb40eb2be71feef1c675800662084be14b2e96 /net/netfilter
parent7b995651e373d6424f81db23f2ec503306dfd7f0 (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.c38
-rw-r--r--net/netfilter/nfnetlink_queue.c2
-rw-r--r--net/netfilter/xt_DSCP.c4
-rw-r--r--net/netfilter/xt_TCPMSS.c2
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:
196EXPORT_SYMBOL(nf_hook_slow); 196EXPORT_SYMBOL(nf_hook_slow);
197 197
198 198
199int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) 199int 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))
214copy_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}
228EXPORT_SYMBOL(skb_make_writable); 218EXPORT_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;