aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
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 @@
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}
123EXPORT_SYMBOL(ip_xfrm_me_harder); 110EXPORT_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 @@
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 62d8867ca7d..10a2ce09fd8 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -335,6 +335,7 @@ static int
335ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) 335ipq_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 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,
113/* Unusual, but possible case. */ 113/* Unusual, but possible case. */
114static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) 114static 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