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); |
