aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip_vs.h1
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c5
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c42
-rw-r--r--net/ipv4/ipvs/ip_vs_ftp.c5
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c5
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c5
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c4
7 files changed, 16 insertions, 51 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 672564e5a81d..5da3b4a40aa2 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -984,7 +984,6 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
984 return fwd; 984 return fwd;
985} 985}
986 986
987extern int ip_vs_make_skb_writable(struct sk_buff **pskb, int len);
988extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, 987extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
989 struct ip_vs_conn *cp, int dir); 988 struct ip_vs_conn *cp, int dir);
990 989
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 341474eefa55..8ca5f4806a63 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -25,6 +25,7 @@
25#include <linux/skbuff.h> 25#include <linux/skbuff.h>
26#include <linux/in.h> 26#include <linux/in.h>
27#include <linux/ip.h> 27#include <linux/ip.h>
28#include <linux/netfilter.h>
28#include <net/net_namespace.h> 29#include <net/net_namespace.h>
29#include <net/protocol.h> 30#include <net/protocol.h>
30#include <net/tcp.h> 31#include <net/tcp.h>
@@ -336,7 +337,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
336 struct tcphdr *th; 337 struct tcphdr *th;
337 __u32 seq; 338 __u32 seq;
338 339
339 if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th))) 340 if (!skb_make_writable(*pskb, tcp_offset + sizeof(*th)))
340 return 0; 341 return 0;
341 342
342 th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset); 343 th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset);
@@ -411,7 +412,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
411 struct tcphdr *th; 412 struct tcphdr *th;
412 __u32 seq; 413 __u32 seq;
413 414
414 if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th))) 415 if (!skb_make_writable(*pskb, tcp_offset + sizeof(*th)))
415 return 0; 416 return 0;
416 417
417 th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset); 418 th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset);
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 3487337192c6..09cac38580fe 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -58,7 +58,6 @@ EXPORT_SYMBOL(ip_vs_conn_put);
58#ifdef CONFIG_IP_VS_DEBUG 58#ifdef CONFIG_IP_VS_DEBUG
59EXPORT_SYMBOL(ip_vs_get_debug_level); 59EXPORT_SYMBOL(ip_vs_get_debug_level);
60#endif 60#endif
61EXPORT_SYMBOL(ip_vs_make_skb_writable);
62 61
63 62
64/* ID used in ICMP lookups */ 63/* ID used in ICMP lookups */
@@ -163,42 +162,6 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction,
163} 162}
164 163
165 164
166int ip_vs_make_skb_writable(struct sk_buff **pskb, int writable_len)
167{
168 struct sk_buff *skb = *pskb;
169
170 /* skb is already used, better copy skb and its payload */
171 if (unlikely(skb_shared(skb) || skb->sk))
172 goto copy_skb;
173
174 /* skb data is already used, copy it */
175 if (unlikely(skb_cloned(skb)))
176 goto copy_data;
177
178 return pskb_may_pull(skb, writable_len);
179
180 copy_data:
181 if (unlikely(writable_len > skb->len))
182 return 0;
183 return !pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
184
185 copy_skb:
186 if (unlikely(writable_len > skb->len))
187 return 0;
188 skb = skb_copy(skb, GFP_ATOMIC);
189 if (!skb)
190 return 0;
191 BUG_ON(skb_is_nonlinear(skb));
192
193 /* Rest of kernel will get very unhappy if we pass it a
194 suddenly-orphaned skbuff */
195 if ((*pskb)->sk)
196 skb_set_owner_w(skb, (*pskb)->sk);
197 kfree_skb(*pskb);
198 *pskb = skb;
199 return 1;
200}
201
202/* 165/*
203 * IPVS persistent scheduling function 166 * IPVS persistent scheduling function
204 * It creates a connection entry according to its template if exists, 167 * It creates a connection entry according to its template if exists,
@@ -689,9 +652,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
689 652
690 if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) 653 if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
691 offset += 2 * sizeof(__u16); 654 offset += 2 * sizeof(__u16);
692 if (!ip_vs_make_skb_writable(pskb, offset)) 655 if (!skb_make_writable(skb, offset))
693 goto out; 656 goto out;
694 skb = *pskb;
695 657
696 ip_vs_nat_icmp(skb, pp, cp, 1); 658 ip_vs_nat_icmp(skb, pp, cp, 1);
697 659
@@ -799,7 +761,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
799 761
800 IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); 762 IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
801 763
802 if (!ip_vs_make_skb_writable(pskb, ihl)) 764 if (!skb_make_writable(skb, ihl))
803 goto drop; 765 goto drop;
804 766
805 /* mangle the packet */ 767 /* mangle the packet */
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index 344ddbbdc756..4167d419b666 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -30,6 +30,7 @@
30#include <linux/skbuff.h> 30#include <linux/skbuff.h>
31#include <linux/in.h> 31#include <linux/in.h>
32#include <linux/ip.h> 32#include <linux/ip.h>
33#include <linux/netfilter.h>
33#include <net/protocol.h> 34#include <net/protocol.h>
34#include <net/tcp.h> 35#include <net/tcp.h>
35#include <asm/unaligned.h> 36#include <asm/unaligned.h>
@@ -155,7 +156,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
155 return 1; 156 return 1;
156 157
157 /* Linear packets are much easier to deal with. */ 158 /* Linear packets are much easier to deal with. */
158 if (!ip_vs_make_skb_writable(pskb, (*pskb)->len)) 159 if (!skb_make_writable(*pskb, (*pskb)->len))
159 return 0; 160 return 0;
160 161
161 if (cp->app_data == &ip_vs_ftp_pasv) { 162 if (cp->app_data == &ip_vs_ftp_pasv) {
@@ -256,7 +257,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
256 return 1; 257 return 1;
257 258
258 /* Linear packets are much easier to deal with. */ 259 /* Linear packets are much easier to deal with. */
259 if (!ip_vs_make_skb_writable(pskb, (*pskb)->len)) 260 if (!skb_make_writable(*pskb, (*pskb)->len))
260 return 0; 261 return 0;
261 262
262 /* 263 /*
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index e65577a77006..b65b1a352ba3 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -20,6 +20,7 @@
20#include <linux/tcp.h> /* for tcphdr */ 20#include <linux/tcp.h> /* for tcphdr */
21#include <net/ip.h> 21#include <net/ip.h>
22#include <net/tcp.h> /* for csum_tcpudp_magic */ 22#include <net/tcp.h> /* for csum_tcpudp_magic */
23#include <linux/netfilter.h>
23#include <linux/netfilter_ipv4.h> 24#include <linux/netfilter_ipv4.h>
24 25
25#include <net/ip_vs.h> 26#include <net/ip_vs.h>
@@ -129,7 +130,7 @@ tcp_snat_handler(struct sk_buff **pskb,
129 const unsigned int tcphoff = ip_hdrlen(*pskb); 130 const unsigned int tcphoff = ip_hdrlen(*pskb);
130 131
131 /* csum_check requires unshared skb */ 132 /* csum_check requires unshared skb */
132 if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph))) 133 if (!skb_make_writable(*pskb, tcphoff+sizeof(*tcph)))
133 return 0; 134 return 0;
134 135
135 if (unlikely(cp->app != NULL)) { 136 if (unlikely(cp->app != NULL)) {
@@ -177,7 +178,7 @@ tcp_dnat_handler(struct sk_buff **pskb,
177 const unsigned int tcphoff = ip_hdrlen(*pskb); 178 const unsigned int tcphoff = ip_hdrlen(*pskb);
178 179
179 /* csum_check requires unshared skb */ 180 /* csum_check requires unshared skb */
180 if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph))) 181 if (!skb_make_writable(*pskb, tcphoff+sizeof(*tcph)))
181 return 0; 182 return 0;
182 183
183 if (unlikely(cp->app != NULL)) { 184 if (unlikely(cp->app != NULL)) {
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 8ee5fe6a101d..c70aa40e2c9d 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -18,6 +18,7 @@
18#include <linux/in.h> 18#include <linux/in.h>
19#include <linux/ip.h> 19#include <linux/ip.h>
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/netfilter.h>
21#include <linux/netfilter_ipv4.h> 22#include <linux/netfilter_ipv4.h>
22#include <linux/udp.h> 23#include <linux/udp.h>
23 24
@@ -136,7 +137,7 @@ udp_snat_handler(struct sk_buff **pskb,
136 const unsigned int udphoff = ip_hdrlen(*pskb); 137 const unsigned int udphoff = ip_hdrlen(*pskb);
137 138
138 /* csum_check requires unshared skb */ 139 /* csum_check requires unshared skb */
139 if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph))) 140 if (!skb_make_writable(*pskb, udphoff+sizeof(*udph)))
140 return 0; 141 return 0;
141 142
142 if (unlikely(cp->app != NULL)) { 143 if (unlikely(cp->app != NULL)) {
@@ -190,7 +191,7 @@ udp_dnat_handler(struct sk_buff **pskb,
190 unsigned int udphoff = ip_hdrlen(*pskb); 191 unsigned int udphoff = ip_hdrlen(*pskb);
191 192
192 /* csum_check requires unshared skb */ 193 /* csum_check requires unshared skb */
193 if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph))) 194 if (!skb_make_writable(*pskb, udphoff+sizeof(*udph)))
194 return 0; 195 return 0;
195 196
196 if (unlikely(cp->app != NULL)) { 197 if (unlikely(cp->app != NULL)) {
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 666e080a74a3..afd90d4d7399 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -253,7 +253,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
253 } 253 }
254 254
255 /* copy-on-write the packet before mangling it */ 255 /* copy-on-write the packet before mangling it */
256 if (!ip_vs_make_skb_writable(&skb, sizeof(struct iphdr))) 256 if (!skb_make_writable(skb, sizeof(struct iphdr)))
257 goto tx_error_put; 257 goto tx_error_put;
258 258
259 if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) 259 if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
@@ -529,7 +529,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
529 } 529 }
530 530
531 /* copy-on-write the packet before mangling it */ 531 /* copy-on-write the packet before mangling it */
532 if (!ip_vs_make_skb_writable(&skb, offset)) 532 if (!skb_make_writable(skb, offset))
533 goto tx_error_put; 533 goto tx_error_put;
534 534
535 if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) 535 if (skb_cow(skb, rt->u.dst.dev->hard_header_len))