diff options
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r-- | net/ipv6/exthdrs.c | 64 |
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 | ||
103 | struct tlvtype_proc { | 103 | struct 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 | ||
114 | static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | 114 | static 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 | ||
142 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | 140 | static 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) |
201 | static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | 198 | static 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 | ||
283 | static int ipv6_destopt_rcv(struct sk_buff **skbp) | 270 | static 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 | ||
340 | static int ipv6_nodata_rcv(struct sk_buff **skbp) | 325 | static 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 | ||
363 | static int ipv6_rthdr_rcv(struct sk_buff **skbp) | 346 | static 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 | ||
581 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | 559 | static 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 | ||
598 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | 575 | static 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 | ||
651 | int ipv6_parse_hopopts(struct sk_buff **skbp) | 627 | int 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); |