aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/exthdrs.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2007-04-10 23:50:43 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:24:59 -0400
commitd56f90a7c96da5187f0cdf07ee7434fe6aa78bbc (patch)
tree3b9073cecfbb3b6a1e25ab2b5dd2a22a43aef238 /net/ipv6/exthdrs.c
parentbbe735e4247dba32568a305553b010081c8dea99 (diff)
[SK_BUFF]: Introduce skb_network_header()
For the places where we need a pointer to the network header, it is still legal to touch skb->nh.raw directly if just adding to, subtracting from or setting it to another layer header. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r--net/ipv6/exthdrs.c56
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
51int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) 51int 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);
656static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) 664static 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)
672static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) 681static 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.