summaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-14 00:39:55 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-15 12:26:28 -0700
commit2ca7b0ac022aa0158599178fe1056b1ba9ec8b97 (patch)
tree6eece25447f0ec3b5d5f5533e49e10fde4d59f35 /net/ipv4
parentaf1e1cf073e3d038b7aac417a20585ecdcab7de6 (diff)
downloadlinux-3.10-2ca7b0ac022aa0158599178fe1056b1ba9ec8b97.tar.gz
linux-3.10-2ca7b0ac022aa0158599178fe1056b1ba9ec8b97.tar.bz2
linux-3.10-2ca7b0ac022aa0158599178fe1056b1ba9ec8b97.zip
[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.c31
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c14
-rw-r--r--net/ipv4/netfilter/ip_queue.c22
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c10
4 files changed, 21 insertions, 56 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b44192924f9..d1e3012d891 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -3,6 +3,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
+#include <linux/skbuff.h>
#include <net/route.h>
#include <net/xfrm.h>
#include <net/ip.h>
@@ -66,17 +67,10 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
/* Change in oif may mean change in hh_len. */
hh_len = (*pskb)->dst->dev->hard_header_len;
- if (skb_headroom(*pskb) < hh_len) {
- struct sk_buff *nskb;
-
- nskb = skb_realloc_headroom(*pskb, hh_len);
- if (!nskb)
- return -1;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
+ if (skb_headroom(*pskb) < hh_len &&
+ pskb_expand_head(*pskb, hh_len - skb_headroom(*pskb), 0,
+ GFP_ATOMIC))
+ return -1;
return 0;
}
@@ -107,17 +101,10 @@ int ip_xfrm_me_harder(struct sk_buff **pskb)
/* Change in oif may mean change in hh_len. */
hh_len = (*pskb)->dst->dev->hard_header_len;
- if (skb_headroom(*pskb) < hh_len) {
- struct sk_buff *nskb;
-
- nskb = skb_realloc_headroom(*pskb, hh_len);
- if (!nskb)
- return -1;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
+ if (skb_headroom(*pskb) < hh_len &&
+ pskb_expand_head(*pskb, hh_len - skb_headroom(*pskb), 0,
+ GFP_ATOMIC))
+ return -1;
return 0;
}
EXPORT_SYMBOL(ip_xfrm_me_harder);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index c4bdab47597..0181f919a79 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -1,5 +1,6 @@
/* module that allows mangling of the arp payload */
#include <linux/module.h>
+#include <linux/netfilter.h>
#include <linux/netfilter_arp/arpt_mangle.h>
#include <net/sock.h>
@@ -18,17 +19,8 @@ target(struct sk_buff **pskb,
unsigned char *arpptr;
int pln, hln;
- if (skb_shared(*pskb) || skb_cloned(*pskb)) {
- struct sk_buff *nskb;
-
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return NF_DROP;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
+ if (skb_make_writable(*pskb, (*pskb)->len))
+ return NF_DROP;
arp = arp_hdr(*pskb);
arpptr = skb_network_header(*pskb) + sizeof(*arp);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 62d8867ca7d..10a2ce09fd8 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -335,6 +335,7 @@ static int
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
{
int diff;
+ int err;
struct iphdr *user_iph = (struct iphdr *)v->payload;
if (v->data_len < sizeof(*user_iph))
@@ -347,21 +348,14 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
if (v->data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
- struct sk_buff *newskb;
-
- newskb = skb_copy_expand(e->skb,
- skb_headroom(e->skb),
- diff,
- GFP_ATOMIC);
- if (newskb == NULL) {
- printk(KERN_WARNING "ip_queue: OOM "
- "in mangle, dropping packet\n");
- return -ENOMEM;
+ err = pskb_expand_head(e->skb, 0,
+ diff - skb_tailroom(e->skb),
+ GFP_ATOMIC);
+ if (err) {
+ printk(KERN_WARNING "ip_queue: error "
+ "in mangle, dropping packet: %d\n", -err);
+ return err;
}
- if (e->skb->sk)
- skb_set_owner_w(newskb, e->skb->sk);
- kfree_skb(e->skb);
- e->skb = newskb;
}
skb_put(e->skb, diff);
}
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 6e81f7612b7..40b429e4540 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,
/* Unusual, but possible case. */
static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
{
- struct sk_buff *nskb;
-
if ((*pskb)->len + extra > 65535)
return 0;
- nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
- if (!nskb)
+ if (pskb_expand_head(*pskb, 0, extra - skb_tailroom(*pskb), GFP_ATOMIC))
return 0;
- /* Transfer socket to new skb. */
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
return 1;
}