diff options
Diffstat (limited to 'net/ipv6/exthdrs.c')
| -rw-r--r-- | net/ipv6/exthdrs.c | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index fce5abde554f..9ebf120ba6d3 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -50,13 +50,14 @@ | |||
| 50 | 50 | ||
| 51 | int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | 51 | int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) |
| 52 | { | 52 | { |
| 53 | int packet_len = skb->tail - skb->nh.raw; | 53 | const unsigned char *nh = skb_network_header(skb); |
| 54 | int packet_len = skb->tail - nh; | ||
| 54 | struct ipv6_opt_hdr *hdr; | 55 | struct ipv6_opt_hdr *hdr; |
| 55 | int len; | 56 | int len; |
| 56 | 57 | ||
| 57 | if (offset + 2 > packet_len) | 58 | if (offset + 2 > packet_len) |
| 58 | goto bad; | 59 | goto bad; |
| 59 | hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 60 | hdr = (struct ipv6_opt_hdr *)(nh + offset); |
| 60 | len = ((hdr->hdrlen + 1) << 3); | 61 | len = ((hdr->hdrlen + 1) << 3); |
| 61 | 62 | ||
| 62 | if (offset + len > packet_len) | 63 | if (offset + len > packet_len) |
| @@ -66,7 +67,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | |||
| 66 | len -= 2; | 67 | len -= 2; |
| 67 | 68 | ||
| 68 | while (len > 0) { | 69 | while (len > 0) { |
| 69 | int opttype = skb->nh.raw[offset]; | 70 | int opttype = nh[offset]; |
| 70 | int optlen; | 71 | int optlen; |
| 71 | 72 | ||
| 72 | if (opttype == type) | 73 | if (opttype == type) |
| @@ -77,7 +78,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | |||
| 77 | optlen = 1; | 78 | optlen = 1; |
| 78 | break; | 79 | break; |
| 79 | default: | 80 | default: |
| 80 | optlen = skb->nh.raw[offset + 1] + 2; | 81 | optlen = nh[offset + 1] + 2; |
| 81 | if (optlen > len) | 82 | if (optlen > len) |
| 82 | goto bad; | 83 | goto bad; |
| 83 | break; | 84 | break; |
| @@ -113,7 +114,7 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | |||
| 113 | { | 114 | { |
| 114 | struct sk_buff *skb = *skbp; | 115 | struct sk_buff *skb = *skbp; |
| 115 | 116 | ||
| 116 | switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { | 117 | switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { |
| 117 | case 0: /* ignore */ | 118 | case 0: /* ignore */ |
| 118 | return 1; | 119 | return 1; |
| 119 | 120 | ||
| @@ -141,6 +142,7 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
| 141 | { | 142 | { |
| 142 | struct sk_buff *skb = *skbp; | 143 | struct sk_buff *skb = *skbp; |
| 143 | struct tlvtype_proc *curr; | 144 | struct tlvtype_proc *curr; |
| 145 | const unsigned char *nh = skb_network_header(skb); | ||
| 144 | int off = skb->h.raw - skb->nh.raw; | 146 | int off = skb->h.raw - skb->nh.raw; |
| 145 | int len = ((skb->h.raw[1]+1)<<3); | 147 | int len = ((skb->h.raw[1]+1)<<3); |
| 146 | 148 | ||
| @@ -151,9 +153,9 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
| 151 | len -= 2; | 153 | len -= 2; |
| 152 | 154 | ||
| 153 | while (len > 0) { | 155 | while (len > 0) { |
| 154 | int optlen = skb->nh.raw[off+1]+2; | 156 | int optlen = nh[off + 1] + 2; |
| 155 | 157 | ||
| 156 | switch (skb->nh.raw[off]) { | 158 | switch (nh[off]) { |
| 157 | case IPV6_TLV_PAD0: | 159 | case IPV6_TLV_PAD0: |
| 158 | optlen = 1; | 160 | optlen = 1; |
| 159 | break; | 161 | break; |
| @@ -165,7 +167,7 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
| 165 | if (optlen > len) | 167 | if (optlen > len) |
| 166 | goto bad; | 168 | goto bad; |
| 167 | for (curr=procs; curr->type >= 0; curr++) { | 169 | for (curr=procs; curr->type >= 0; curr++) { |
| 168 | if (curr->type == skb->nh.raw[off]) { | 170 | if (curr->type == nh[off]) { |
| 169 | /* type specific length/alignment | 171 | /* type specific length/alignment |
| 170 | checks will be performed in the | 172 | checks will be performed in the |
| 171 | func(). */ | 173 | func(). */ |
| @@ -211,7 +213,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
| 211 | opt->dsthao = opt->dst1; | 213 | opt->dsthao = opt->dst1; |
| 212 | opt->dst1 = 0; | 214 | opt->dst1 = 0; |
| 213 | 215 | ||
| 214 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff); | 216 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff); |
| 215 | 217 | ||
| 216 | if (hao->length != 16) { | 218 | if (hao->length != 16) { |
| 217 | LIMIT_NETDEBUG( | 219 | LIMIT_NETDEBUG( |
| @@ -244,8 +246,9 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
| 244 | 246 | ||
| 245 | /* update all variable using below by copied skbuff */ | 247 | /* update all variable using below by copied skbuff */ |
| 246 | *skbp = skb = skb2; | 248 | *skbp = skb = skb2; |
| 247 | hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff); | 249 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) + |
| 248 | ipv6h = (struct ipv6hdr *)skb2->nh.raw; | 250 | optoff); |
| 251 | ipv6h = skb2->nh.ipv6h; | ||
| 249 | } | 252 | } |
| 250 | 253 | ||
| 251 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 254 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| @@ -406,7 +409,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
| 406 | default: | 409 | default: |
| 407 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 410 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 408 | IPSTATS_MIB_INHDRERRORS); | 411 | IPSTATS_MIB_INHDRERRORS); |
| 409 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | 412 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
| 413 | (&hdr->type) - skb_network_header(skb)); | ||
| 410 | return -1; | 414 | return -1; |
| 411 | } | 415 | } |
| 412 | 416 | ||
| @@ -443,7 +447,7 @@ looped_back: | |||
| 443 | skb->h.raw += (hdr->hdrlen + 1) << 3; | 447 | skb->h.raw += (hdr->hdrlen + 1) << 3; |
| 444 | opt->dst0 = opt->dst1; | 448 | opt->dst0 = opt->dst1; |
| 445 | opt->dst1 = 0; | 449 | opt->dst1 = 0; |
| 446 | opt->nhoff = (&hdr->nexthdr) - skb->nh.raw; | 450 | opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb); |
| 447 | return 1; | 451 | return 1; |
| 448 | } | 452 | } |
| 449 | 453 | ||
| @@ -452,7 +456,9 @@ looped_back: | |||
| 452 | if (hdr->hdrlen & 0x01) { | 456 | if (hdr->hdrlen & 0x01) { |
| 453 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 457 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 454 | IPSTATS_MIB_INHDRERRORS); | 458 | IPSTATS_MIB_INHDRERRORS); |
| 455 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); | 459 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
| 460 | ((&hdr->hdrlen) - | ||
| 461 | skb_network_header(skb))); | ||
| 456 | return -1; | 462 | return -1; |
| 457 | } | 463 | } |
| 458 | break; | 464 | break; |
| @@ -479,7 +485,9 @@ looped_back: | |||
| 479 | if (hdr->segments_left > n) { | 485 | if (hdr->segments_left > n) { |
| 480 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 486 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 481 | IPSTATS_MIB_INHDRERRORS); | 487 | IPSTATS_MIB_INHDRERRORS); |
| 482 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); | 488 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
| 489 | ((&hdr->segments_left) - | ||
| 490 | skb_network_header(skb))); | ||
| 483 | return -1; | 491 | return -1; |
| 484 | } | 492 | } |
| 485 | 493 | ||
| @@ -547,7 +555,7 @@ looped_back: | |||
| 547 | dst_release(xchg(&skb->dst, NULL)); | 555 | dst_release(xchg(&skb->dst, NULL)); |
| 548 | ip6_route_input(skb); | 556 | ip6_route_input(skb); |
| 549 | if (skb->dst->error) { | 557 | if (skb->dst->error) { |
| 550 | skb_push(skb, skb->data - skb->nh.raw); | 558 | skb_push(skb, skb->data - skb_network_header(skb)); |
| 551 | dst_input(skb); | 559 | dst_input(skb); |
| 552 | return -1; | 560 | return -1; |
| 553 | } | 561 | } |
| @@ -565,7 +573,7 @@ looped_back: | |||
| 565 | goto looped_back; | 573 | goto looped_back; |
| 566 | } | 574 | } |
| 567 | 575 | ||
| 568 | skb_push(skb, skb->data - skb->nh.raw); | 576 | skb_push(skb, skb->data - skb_network_header(skb)); |
| 569 | dst_input(skb); | 577 | dst_input(skb); |
| 570 | return -1; | 578 | return -1; |
| 571 | } | 579 | } |
| @@ -656,13 +664,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); | |||
| 656 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | 664 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) |
| 657 | { | 665 | { |
| 658 | struct sk_buff *skb = *skbp; | 666 | struct sk_buff *skb = *skbp; |
| 667 | const unsigned char *nh = skb_network_header(skb); | ||
| 659 | 668 | ||
| 660 | if (skb->nh.raw[optoff+1] == 2) { | 669 | if (nh[optoff + 1] == 2) { |
| 661 | IP6CB(skb)->ra = optoff; | 670 | IP6CB(skb)->ra = optoff; |
| 662 | return 1; | 671 | return 1; |
| 663 | } | 672 | } |
| 664 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", | 673 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", |
| 665 | skb->nh.raw[optoff+1]); | 674 | nh[optoff + 1]); |
| 666 | kfree_skb(skb); | 675 | kfree_skb(skb); |
| 667 | return 0; | 676 | return 0; |
| 668 | } | 677 | } |
| @@ -672,17 +681,18 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | |||
| 672 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | 681 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) |
| 673 | { | 682 | { |
| 674 | struct sk_buff *skb = *skbp; | 683 | struct sk_buff *skb = *skbp; |
| 684 | const unsigned char *nh = skb_network_header(skb); | ||
| 675 | u32 pkt_len; | 685 | u32 pkt_len; |
| 676 | 686 | ||
| 677 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { | 687 | if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { |
| 678 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", | 688 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", |
| 679 | skb->nh.raw[optoff+1]); | 689 | nh[optoff+1]); |
| 680 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 690 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 681 | IPSTATS_MIB_INHDRERRORS); | 691 | IPSTATS_MIB_INHDRERRORS); |
| 682 | goto drop; | 692 | goto drop; |
| 683 | } | 693 | } |
| 684 | 694 | ||
| 685 | pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2)); | 695 | pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); |
| 686 | if (pkt_len <= IPV6_MAXPLEN) { | 696 | if (pkt_len <= IPV6_MAXPLEN) { |
| 687 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); | 697 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
| 688 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); | 698 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); |
| @@ -727,7 +737,7 @@ int ipv6_parse_hopopts(struct sk_buff **skbp) | |||
| 727 | struct inet6_skb_parm *opt = IP6CB(skb); | 737 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 728 | 738 | ||
| 729 | /* | 739 | /* |
| 730 | * skb->nh.raw is equal to skb->data, and | 740 | * skb_network_header(skb) is equal to skb->data, and |
| 731 | * skb->h.raw - skb->nh.raw is always equal to | 741 | * skb->h.raw - skb->nh.raw is always equal to |
| 732 | * sizeof(struct ipv6hdr) by definition of | 742 | * sizeof(struct ipv6hdr) by definition of |
| 733 | * hop-by-hop options. | 743 | * hop-by-hop options. |
