diff options
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r-- | net/ipv6/exthdrs.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 50ff49e518bc..1cdd0f0b5d34 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -102,7 +102,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | |||
102 | 102 | ||
103 | struct tlvtype_proc { | 103 | struct tlvtype_proc { |
104 | int type; | 104 | int type; |
105 | int (*func)(struct sk_buff *skb, int offset); | 105 | int (*func)(struct sk_buff **skbp, int offset); |
106 | }; | 106 | }; |
107 | 107 | ||
108 | /********************* | 108 | /********************* |
@@ -111,8 +111,10 @@ 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 *skb, int optoff) | 114 | static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) |
115 | { | 115 | { |
116 | struct sk_buff *skb = *skbp; | ||
117 | |||
116 | switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { | 118 | switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { |
117 | case 0: /* ignore */ | 119 | case 0: /* ignore */ |
118 | return 1; | 120 | return 1; |
@@ -137,8 +139,9 @@ static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) | |||
137 | 139 | ||
138 | /* Parse tlv encoded option header (hop-by-hop or destination) */ | 140 | /* Parse tlv encoded option header (hop-by-hop or destination) */ |
139 | 141 | ||
140 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) | 142 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) |
141 | { | 143 | { |
144 | struct sk_buff *skb = *skbp; | ||
142 | struct tlvtype_proc *curr; | 145 | struct tlvtype_proc *curr; |
143 | int off = skb->h.raw - skb->nh.raw; | 146 | int off = skb->h.raw - skb->nh.raw; |
144 | int len = ((skb->h.raw[1]+1)<<3); | 147 | int len = ((skb->h.raw[1]+1)<<3); |
@@ -168,13 +171,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) | |||
168 | /* type specific length/alignment | 171 | /* type specific length/alignment |
169 | checks will be performed in the | 172 | checks will be performed in the |
170 | func(). */ | 173 | func(). */ |
171 | if (curr->func(skb, off) == 0) | 174 | if (curr->func(skbp, off) == 0) |
172 | return 0; | 175 | return 0; |
173 | break; | 176 | break; |
174 | } | 177 | } |
175 | } | 178 | } |
176 | if (curr->type < 0) { | 179 | if (curr->type < 0) { |
177 | if (ip6_tlvopt_unknown(skb, off) == 0) | 180 | if (ip6_tlvopt_unknown(skbp, off) == 0) |
178 | return 0; | 181 | return 0; |
179 | } | 182 | } |
180 | break; | 183 | break; |
@@ -213,7 +216,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
213 | opt->lastopt = skb->h.raw - skb->nh.raw; | 216 | opt->lastopt = skb->h.raw - skb->nh.raw; |
214 | opt->dst1 = skb->h.raw - skb->nh.raw; | 217 | opt->dst1 = skb->h.raw - skb->nh.raw; |
215 | 218 | ||
216 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { | 219 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { |
220 | skb = *skbp; | ||
217 | skb->h.raw += ((skb->h.raw[1]+1)<<3); | 221 | skb->h.raw += ((skb->h.raw[1]+1)<<3); |
218 | opt->nhoff = opt->dst1; | 222 | opt->nhoff = opt->dst1; |
219 | return 1; | 223 | return 1; |
@@ -517,8 +521,10 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); | |||
517 | 521 | ||
518 | /* Router Alert as of RFC 2711 */ | 522 | /* Router Alert as of RFC 2711 */ |
519 | 523 | ||
520 | static int ipv6_hop_ra(struct sk_buff *skb, int optoff) | 524 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) |
521 | { | 525 | { |
526 | struct sk_buff *skb = *skbp; | ||
527 | |||
522 | if (skb->nh.raw[optoff+1] == 2) { | 528 | if (skb->nh.raw[optoff+1] == 2) { |
523 | IP6CB(skb)->ra = optoff; | 529 | IP6CB(skb)->ra = optoff; |
524 | return 1; | 530 | return 1; |
@@ -531,8 +537,9 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) | |||
531 | 537 | ||
532 | /* Jumbo payload */ | 538 | /* Jumbo payload */ |
533 | 539 | ||
534 | static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) | 540 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) |
535 | { | 541 | { |
542 | struct sk_buff *skb = *skbp; | ||
536 | u32 pkt_len; | 543 | u32 pkt_len; |
537 | 544 | ||
538 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { | 545 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { |
@@ -581,8 +588,9 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { | |||
581 | { -1, } | 588 | { -1, } |
582 | }; | 589 | }; |
583 | 590 | ||
584 | int ipv6_parse_hopopts(struct sk_buff *skb) | 591 | int ipv6_parse_hopopts(struct sk_buff **skbp) |
585 | { | 592 | { |
593 | struct sk_buff *skb = *skbp; | ||
586 | struct inet6_skb_parm *opt = IP6CB(skb); | 594 | struct inet6_skb_parm *opt = IP6CB(skb); |
587 | 595 | ||
588 | /* | 596 | /* |
@@ -598,7 +606,8 @@ int ipv6_parse_hopopts(struct sk_buff *skb) | |||
598 | } | 606 | } |
599 | 607 | ||
600 | opt->hop = sizeof(struct ipv6hdr); | 608 | opt->hop = sizeof(struct ipv6hdr); |
601 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { | 609 | if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { |
610 | skb = *skbp; | ||
602 | skb->h.raw += (skb->h.raw[1]+1)<<3; | 611 | skb->h.raw += (skb->h.raw[1]+1)<<3; |
603 | opt->nhoff = sizeof(struct ipv6hdr); | 612 | opt->nhoff = sizeof(struct ipv6hdr); |
604 | return 1; | 613 | return 1; |