aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/exthdrs.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r--net/ipv6/exthdrs.c29
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
103struct tlvtype_proc { 103struct 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
114static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) 114static 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
140static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) 142static 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
520static int ipv6_hop_ra(struct sk_buff *skb, int optoff) 524static 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
534static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) 540static 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
584int ipv6_parse_hopopts(struct sk_buff *skb) 591int 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;