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. |