aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/exthdrs.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r--net/ipv6/exthdrs.c64
1 files changed, 19 insertions, 45 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index c82d4d49f71f..1e89efd38a0c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv);
102 102
103struct tlvtype_proc { 103struct tlvtype_proc {
104 int type; 104 int type;
105 int (*func)(struct sk_buff **skbp, int offset); 105 int (*func)(struct sk_buff *skb, int offset);
106}; 106};
107 107
108/********************* 108/*********************
@@ -111,10 +111,8 @@ struct tlvtype_proc {
111 111
112/* An unknown option is detected, decide what to do */ 112/* An unknown option is detected, decide what to do */
113 113
114static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) 114static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
115{ 115{
116 struct sk_buff *skb = *skbp;
117
118 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { 116 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
119 case 0: /* ignore */ 117 case 0: /* ignore */
120 return 1; 118 return 1;
@@ -139,9 +137,8 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
139 137
140/* Parse tlv encoded option header (hop-by-hop or destination) */ 138/* Parse tlv encoded option header (hop-by-hop or destination) */
141 139
142static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) 140static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
143{ 141{
144 struct sk_buff *skb = *skbp;
145 struct tlvtype_proc *curr; 142 struct tlvtype_proc *curr;
146 const unsigned char *nh = skb_network_header(skb); 143 const unsigned char *nh = skb_network_header(skb);
147 int off = skb_network_header_len(skb); 144 int off = skb_network_header_len(skb);
@@ -172,13 +169,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
172 /* type specific length/alignment 169 /* type specific length/alignment
173 checks will be performed in the 170 checks will be performed in the
174 func(). */ 171 func(). */
175 if (curr->func(skbp, off) == 0) 172 if (curr->func(skb, off) == 0)
176 return 0; 173 return 0;
177 break; 174 break;
178 } 175 }
179 } 176 }
180 if (curr->type < 0) { 177 if (curr->type < 0) {
181 if (ip6_tlvopt_unknown(skbp, off) == 0) 178 if (ip6_tlvopt_unknown(skb, off) == 0)
182 return 0; 179 return 0;
183 } 180 }
184 break; 181 break;
@@ -198,9 +195,8 @@ bad:
198 *****************************/ 195 *****************************/
199 196
200#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 197#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
201static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) 198static int ipv6_dest_hao(struct sk_buff *skb, int optoff)
202{ 199{
203 struct sk_buff *skb = *skbp;
204 struct ipv6_destopt_hao *hao; 200 struct ipv6_destopt_hao *hao;
205 struct inet6_skb_parm *opt = IP6CB(skb); 201 struct inet6_skb_parm *opt = IP6CB(skb);
206 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 202 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
@@ -234,22 +230,13 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
234 goto discard; 230 goto discard;
235 231
236 if (skb_cloned(skb)) { 232 if (skb_cloned(skb)) {
237 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); 233 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
238 struct inet6_skb_parm *opt2;
239
240 if (skb2 == NULL)
241 goto discard; 234 goto discard;
242 235
243 opt2 = IP6CB(skb2);
244 memcpy(opt2, opt, sizeof(*opt2));
245
246 kfree_skb(skb);
247
248 /* update all variable using below by copied skbuff */ 236 /* update all variable using below by copied skbuff */
249 *skbp = skb = skb2; 237 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) +
250 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
251 optoff); 238 optoff);
252 ipv6h = ipv6_hdr(skb2); 239 ipv6h = ipv6_hdr(skb);
253 } 240 }
254 241
255 if (skb->ip_summed == CHECKSUM_COMPLETE) 242 if (skb->ip_summed == CHECKSUM_COMPLETE)
@@ -280,9 +267,8 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
280 {-1, NULL} 267 {-1, NULL}
281}; 268};
282 269
283static int ipv6_destopt_rcv(struct sk_buff **skbp) 270static int ipv6_destopt_rcv(struct sk_buff *skb)
284{ 271{
285 struct sk_buff *skb = *skbp;
286 struct inet6_skb_parm *opt = IP6CB(skb); 272 struct inet6_skb_parm *opt = IP6CB(skb);
287#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 273#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
288 __u16 dstbuf; 274 __u16 dstbuf;
@@ -304,9 +290,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
304#endif 290#endif
305 291
306 dst = dst_clone(skb->dst); 292 dst = dst_clone(skb->dst);
307 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { 293 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
308 dst_release(dst); 294 dst_release(dst);
309 skb = *skbp;
310 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; 295 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
311 opt = IP6CB(skb); 296 opt = IP6CB(skb);
312#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 297#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
@@ -337,10 +322,8 @@ void __init ipv6_destopt_init(void)
337 NONE header. No data in packet. 322 NONE header. No data in packet.
338 ********************************/ 323 ********************************/
339 324
340static int ipv6_nodata_rcv(struct sk_buff **skbp) 325static int ipv6_nodata_rcv(struct sk_buff *skb)
341{ 326{
342 struct sk_buff *skb = *skbp;
343
344 kfree_skb(skb); 327 kfree_skb(skb);
345 return 0; 328 return 0;
346} 329}
@@ -360,9 +343,8 @@ void __init ipv6_nodata_init(void)
360 Routing header. 343 Routing header.
361 ********************************/ 344 ********************************/
362 345
363static int ipv6_rthdr_rcv(struct sk_buff **skbp) 346static int ipv6_rthdr_rcv(struct sk_buff *skb)
364{ 347{
365 struct sk_buff *skb = *skbp;
366 struct inet6_skb_parm *opt = IP6CB(skb); 348 struct inet6_skb_parm *opt = IP6CB(skb);
367 struct in6_addr *addr = NULL; 349 struct in6_addr *addr = NULL;
368 struct in6_addr daddr; 350 struct in6_addr daddr;
@@ -464,18 +446,14 @@ looped_back:
464 Do not damage packets queued somewhere. 446 Do not damage packets queued somewhere.
465 */ 447 */
466 if (skb_cloned(skb)) { 448 if (skb_cloned(skb)) {
467 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
468 /* the copy is a forwarded packet */ 449 /* the copy is a forwarded packet */
469 if (skb2 == NULL) { 450 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
470 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 451 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
471 IPSTATS_MIB_OUTDISCARDS); 452 IPSTATS_MIB_OUTDISCARDS);
472 kfree_skb(skb); 453 kfree_skb(skb);
473 return -1; 454 return -1;
474 } 455 }
475 kfree_skb(skb); 456 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
476 *skbp = skb = skb2;
477 opt = IP6CB(skb2);
478 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2);
479 } 457 }
480 458
481 if (skb->ip_summed == CHECKSUM_COMPLETE) 459 if (skb->ip_summed == CHECKSUM_COMPLETE)
@@ -578,9 +556,8 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
578 556
579/* Router Alert as of RFC 2711 */ 557/* Router Alert as of RFC 2711 */
580 558
581static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) 559static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
582{ 560{
583 struct sk_buff *skb = *skbp;
584 const unsigned char *nh = skb_network_header(skb); 561 const unsigned char *nh = skb_network_header(skb);
585 562
586 if (nh[optoff + 1] == 2) { 563 if (nh[optoff + 1] == 2) {
@@ -595,9 +572,8 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
595 572
596/* Jumbo payload */ 573/* Jumbo payload */
597 574
598static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) 575static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
599{ 576{
600 struct sk_buff *skb = *skbp;
601 const unsigned char *nh = skb_network_header(skb); 577 const unsigned char *nh = skb_network_header(skb);
602 u32 pkt_len; 578 u32 pkt_len;
603 579
@@ -648,9 +624,8 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
648 { -1, } 624 { -1, }
649}; 625};
650 626
651int ipv6_parse_hopopts(struct sk_buff **skbp) 627int ipv6_parse_hopopts(struct sk_buff *skb)
652{ 628{
653 struct sk_buff *skb = *skbp;
654 struct inet6_skb_parm *opt = IP6CB(skb); 629 struct inet6_skb_parm *opt = IP6CB(skb);
655 630
656 /* 631 /*
@@ -667,8 +642,7 @@ int ipv6_parse_hopopts(struct sk_buff **skbp)
667 } 642 }
668 643
669 opt->hop = sizeof(struct ipv6hdr); 644 opt->hop = sizeof(struct ipv6hdr);
670 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { 645 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
671 skb = *skbp;
672 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; 646 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
673 opt = IP6CB(skb); 647 opt = IP6CB(skb);
674 opt->nhoff = sizeof(struct ipv6hdr); 648 opt->nhoff = sizeof(struct ipv6hdr);