1 /*
2 * Extension Header handling for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <pedro_m@yahoo.com>
7 * Andi Kleen <ak@muc.de>
8 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
9 *
10 * $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18 /* Changes:
19 * yoshfuji : ensure not to overrun while parsing
20 * tlv options.
21 */
22
23 #include <linux/errno.h>
24 #include <linux/types.h>
25 #include <linux/socket.h>
26 #include <linux/sockios.h>
27 #include <linux/sched.h>
28 #include <linux/net.h>
29 #include <linux/netdevice.h>
30 #include <linux/in6.h>
31 #include <linux/icmpv6.h>
32
33 #include <net/sock.h>
34 #include <net/snmp.h>
35
36 #include <net/ipv6.h>
37 #include <net/protocol.h>
38 #include <net/transp_v6.h>
39 #include <net/rawv6.h>
40 #include <net/ndisc.h>
41 #include <net/ip6_route.h>
42 #include <net/addrconf.h>
43
44 #include <asm/uaccess.h>
45
46 /*
47 * Parsing inbound headers.
48 *
49 * Parsing function "func" returns offset wrt skb->nh of the place,
50 * where next nexthdr value is stored or NULL, if parsing
51 * failed. It should also update skb->h tp point at the next header.
52 */
53
54 struct hdrtype_proc
55 {
56 int type;
57 int (*func) (struct sk_buff **, int offset);
58 };
59
60 /*
61 * Parsing tlv encoded headers.
62 *
63 * Parsing function "func" returns 1, if parsing succeed
64 * and 0, if it failed.
65 * It MUST NOT touch skb->h.
66 */
67
68 struct tlvtype_proc
69 {
70 int type;
71 int (*func) (struct sk_buff *, int offset);
72 };
73
74 /*********************
75 Generic functions
76 *********************/
77
78 /* An unknown option is detected, decide what to do */
79
ip6_tlvopt_unknown(struct sk_buff * skb,int optoff)80 int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
81 {
82 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
83 case 0: /* ignore */
84 return 1;
85
86 case 1: /* drop packet */
87 break;
88
89 case 3: /* Send ICMP if not a multicast address and drop packet */
90 /* Actually, it is redundant check. icmp_send
91 will recheck in any case.
92 */
93 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
94 break;
95 case 2: /* send ICMP PARM PROB regardless and drop packet */
96 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
97 return 0;
98 };
99
100 kfree_skb(skb);
101 return 0;
102 }
103
104 /* Parse tlv encoded option header (hop-by-hop or destination) */
105
ip6_parse_tlv(struct tlvtype_proc * procs,struct sk_buff * skb)106 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
107 {
108 struct tlvtype_proc *curr;
109 int off = skb->h.raw - skb->nh.raw;
110 int len = ((skb->h.raw[1]+1)<<3);
111
112 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
113 goto bad;
114
115 off += 2;
116 len -= 2;
117
118 while (len > 0) {
119 int optlen = skb->nh.raw[off+1]+2;
120
121 switch (skb->nh.raw[off]) {
122 case IPV6_TLV_PAD0:
123 optlen = 1;
124 break;
125
126 case IPV6_TLV_PADN:
127 break;
128
129 default: /* Other TLV code so scan list */
130 if (optlen > len)
131 goto bad;
132 for (curr=procs; curr->type >= 0; curr++) {
133 if (curr->type == skb->nh.raw[off]) {
134 /* type specific length/alignment
135 checks will be perfomed in the
136 func(). */
137 if (curr->func(skb, off) == 0)
138 return 0;
139 break;
140 }
141 }
142 if (curr->type < 0) {
143 if (ip6_tlvopt_unknown(skb, off) == 0)
144 return 0;
145 }
146 break;
147 }
148 off += optlen;
149 len -= optlen;
150 }
151 if (len == 0)
152 return 1;
153 bad:
154 kfree_skb(skb);
155 return 0;
156 }
157
158 /*****************************
159 Destination options header.
160 *****************************/
161
162 struct tlvtype_proc tlvprocdestopt_lst[] = {
163 /* No destination options are defined now */
164 {-1, NULL}
165 };
166
ipv6_dest_opt(struct sk_buff ** skb_ptr,int nhoff)167 static int ipv6_dest_opt(struct sk_buff **skb_ptr, int nhoff)
168 {
169 struct sk_buff *skb=*skb_ptr;
170 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
171
172 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
173 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
174 kfree_skb(skb);
175 return -1;
176 }
177
178 opt->dst1 = skb->h.raw - skb->nh.raw;
179
180 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
181 skb->h.raw += ((skb->h.raw[1]+1)<<3);
182 return opt->dst1;
183 }
184
185 return -1;
186 }
187
188 /********************************
189 NONE header. No data in packet.
190 ********************************/
191
ipv6_nodata(struct sk_buff ** skb_ptr,int nhoff)192 static int ipv6_nodata(struct sk_buff **skb_ptr, int nhoff)
193 {
194 kfree_skb(*skb_ptr);
195 return -1;
196 }
197
198 /********************************
199 Routing header.
200 ********************************/
201
ipv6_routing_header(struct sk_buff ** skb_ptr,int nhoff)202 static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
203 {
204 struct sk_buff *skb = *skb_ptr;
205 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
206 struct in6_addr *addr;
207 struct in6_addr daddr;
208 int addr_type;
209 int n, i;
210
211 struct ipv6_rt_hdr *hdr;
212 struct rt0_hdr *rthdr;
213
214 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
215 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
216 IP6_INC_STATS_BH(Ip6InHdrErrors);
217 kfree_skb(skb);
218 return -1;
219 }
220
221 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
222
223 if ((ipv6_addr_type(&skb->nh.ipv6h->daddr)&IPV6_ADDR_MULTICAST) ||
224 skb->pkt_type != PACKET_HOST) {
225 kfree_skb(skb);
226 return -1;
227 }
228
229 looped_back:
230 if (hdr->segments_left == 0) {
231 opt->srcrt = skb->h.raw - skb->nh.raw;
232 skb->h.raw += (hdr->hdrlen + 1) << 3;
233 opt->dst0 = opt->dst1;
234 opt->dst1 = 0;
235 return (&hdr->nexthdr) - skb->nh.raw;
236 }
237
238 if (hdr->type != IPV6_SRCRT_TYPE_0) {
239 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
240 return -1;
241 }
242
243 if (hdr->hdrlen & 0x01) {
244 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
245 return -1;
246 }
247
248 /*
249 * This is the routing header forwarding algorithm from
250 * RFC 1883, page 17.
251 */
252
253 n = hdr->hdrlen >> 1;
254
255 if (hdr->segments_left > n) {
256 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
257 return -1;
258 }
259
260 /* We are about to mangle packet header. Be careful!
261 Do not damage packets queued somewhere.
262 */
263 if (skb_cloned(skb)) {
264 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
265 kfree_skb(skb);
266 if (skb2 == NULL)
267 return -1;
268 *skb_ptr = skb = skb2;
269 opt = (struct inet6_skb_parm *)skb2->cb;
270 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
271 }
272
273 if (skb->ip_summed == CHECKSUM_HW)
274 skb->ip_summed = CHECKSUM_NONE;
275
276 i = n - --hdr->segments_left;
277
278 rthdr = (struct rt0_hdr *) hdr;
279 addr = rthdr->addr;
280 addr += i - 1;
281
282 addr_type = ipv6_addr_type(addr);
283
284 if (addr_type&IPV6_ADDR_MULTICAST) {
285 kfree_skb(skb);
286 return -1;
287 }
288
289 ipv6_addr_copy(&daddr, addr);
290 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
291 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
292
293 dst_release(xchg(&skb->dst, NULL));
294 ip6_route_input(skb);
295 if (skb->dst->error) {
296 skb_push(skb, skb->data - skb->nh.raw);
297 skb->dst->input(skb);
298 return -1;
299 }
300
301 if (skb->dst->dev->flags&IFF_LOOPBACK) {
302 if (skb->nh.ipv6h->hop_limit <= 1) {
303 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
304 0, skb->dev);
305 kfree_skb(skb);
306 return -1;
307 }
308 skb->nh.ipv6h->hop_limit--;
309 goto looped_back;
310 }
311
312 skb_push(skb, skb->data - skb->nh.raw);
313 skb->dst->input(skb);
314 return -1;
315 }
316
317 /*
318 This function inverts received rthdr.
319 NOTE: specs allow to make it automatically only if
320 packet authenticated.
321
322 I will not discuss it here (though, I am really pissed off at
323 this stupid requirement making rthdr idea useless)
324
325 Actually, it creates severe problems for us.
326 Embrionic requests has no associated sockets,
327 so that user have no control over it and
328 cannot not only to set reply options, but
329 even to know, that someone wants to connect
330 without success. :-(
331
332 For now we need to test the engine, so that I created
333 temporary (or permanent) backdoor.
334 If listening socket set IPV6_RTHDR to 2, then we invert header.
335 --ANK (980729)
336 */
337
338 struct ipv6_txoptions *
ipv6_invert_rthdr(struct sock * sk,struct ipv6_rt_hdr * hdr)339 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
340 {
341 /* Received rthdr:
342
343 [ H1 -> H2 -> ... H_prev ] daddr=ME
344
345 Inverted result:
346 [ H_prev -> ... -> H1 ] daddr =sender
347
348 Note, that IP output engine will rewrire this rthdr
349 by rotating it left by one addr.
350 */
351
352 int n, i;
353 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
354 struct rt0_hdr *irthdr;
355 struct ipv6_txoptions *opt;
356 int hdrlen = ipv6_optlen(hdr);
357
358 if (hdr->segments_left ||
359 hdr->type != IPV6_SRCRT_TYPE_0 ||
360 hdr->hdrlen & 0x01)
361 return NULL;
362
363 n = hdr->hdrlen >> 1;
364 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
365 if (opt == NULL)
366 return NULL;
367 memset(opt, 0, sizeof(*opt));
368 opt->tot_len = sizeof(*opt) + hdrlen;
369 opt->srcrt = (void*)(opt+1);
370 opt->opt_nflen = hdrlen;
371
372 memcpy(opt->srcrt, hdr, sizeof(*hdr));
373 irthdr = (struct rt0_hdr*)opt->srcrt;
374 /* Obsolete field, MBZ, when originated by us */
375 irthdr->bitmap = 0;
376 opt->srcrt->segments_left = n;
377 for (i=0; i<n; i++)
378 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
379 return opt;
380 }
381
382 /********************************
383 AUTH header.
384 ********************************/
385
386 /*
387 rfc1826 said, that if a host does not implement AUTH header
388 it MAY ignore it. We use this hole 8)
389
390 Actually, now we can implement OSPFv6 without kernel IPsec.
391 Authentication for poors may be done in user space with the same success.
392
393 Yes, it means, that we allow application to send/receive
394 raw authentication header. Apparently, we suppose, that it knows
395 what it does and calculates authentication data correctly.
396 Certainly, it is possible only for udp and raw sockets, but not for tcp.
397
398 AUTH header has 4byte granular length, which kills all the idea
399 behind AUTOMATIC 64bit alignment of IPv6. Now we will lose
400 cpu ticks, checking that sender did not something stupid
401 and opt->hdrlen is even. Shit! --ANK (980730)
402 */
403
ipv6_auth_hdr(struct sk_buff ** skb_ptr,int nhoff)404 static int ipv6_auth_hdr(struct sk_buff **skb_ptr, int nhoff)
405 {
406 struct sk_buff *skb=*skb_ptr;
407 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
408 int len;
409
410 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8))
411 goto fail;
412
413 /*
414 * RFC2402 2.2 Payload Length
415 * The 8-bit field specifies the length of AH in 32-bit words
416 * (4-byte units), minus "2".
417 * -- Noriaki Takamiya @USAGI Project
418 */
419 len = (skb->h.raw[1]+2)<<2;
420
421 if (len&7)
422 goto fail;
423
424 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+len))
425 goto fail;
426
427 opt->auth = skb->h.raw - skb->nh.raw;
428 skb->h.raw += len;
429 return opt->auth;
430
431 fail:
432 kfree_skb(skb);
433 return -1;
434 }
435
436 /* This list MUST NOT contain entry for NEXTHDR_HOP.
437 It is parsed immediately after packet received
438 and if it occurs somewhere in another place we must
439 generate error.
440 */
441
442 struct hdrtype_proc hdrproc_lst[] = {
443 {NEXTHDR_FRAGMENT, ipv6_reassembly},
444 {NEXTHDR_ROUTING, ipv6_routing_header},
445 {NEXTHDR_DEST, ipv6_dest_opt},
446 {NEXTHDR_NONE, ipv6_nodata},
447 {NEXTHDR_AUTH, ipv6_auth_hdr},
448 /*
449 {NEXTHDR_ESP, ipv6_esp_hdr},
450 */
451 {-1, NULL}
452 };
453
ipv6_parse_exthdrs(struct sk_buff ** skb_in,int nhoff)454 int ipv6_parse_exthdrs(struct sk_buff **skb_in, int nhoff)
455 {
456 struct hdrtype_proc *hdrt;
457 u8 nexthdr = (*skb_in)->nh.raw[nhoff];
458
459 restart:
460 for (hdrt=hdrproc_lst; hdrt->type >= 0; hdrt++) {
461 if (hdrt->type == nexthdr) {
462 if ((nhoff = hdrt->func(skb_in, nhoff)) >= 0) {
463 nexthdr = (*skb_in)->nh.raw[nhoff];
464 goto restart;
465 }
466 return -1;
467 }
468 }
469 return nhoff;
470 }
471
472
473 /**********************************
474 Hop-by-hop options.
475 **********************************/
476
477 /* Router Alert as of draft-ietf-ipngwg-ipv6router-alert-04 */
478
ipv6_hop_ra(struct sk_buff * skb,int optoff)479 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
480 {
481 if (skb->nh.raw[optoff+1] == 2) {
482 ((struct inet6_skb_parm*)skb->cb)->ra = optoff;
483 return 1;
484 }
485 if (net_ratelimit())
486 printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1]);
487 kfree_skb(skb);
488 return 0;
489 }
490
491 /* Jumbo payload */
492
ipv6_hop_jumbo(struct sk_buff * skb,int optoff)493 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
494 {
495 u32 pkt_len;
496
497 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
498 if (net_ratelimit())
499 printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]);
500 goto drop;
501 }
502
503 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
504 if (pkt_len < 0x10000) {
505 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
506 return 0;
507 }
508 if (skb->nh.ipv6h->payload_len) {
509 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
510 return 0;
511 }
512
513 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
514 IP6_INC_STATS_BH(Ip6InTruncatedPkts);
515 goto drop;
516 }
517 if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
518 __pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr));
519 if (skb->ip_summed == CHECKSUM_HW)
520 skb->ip_summed = CHECKSUM_NONE;
521 }
522 return 1;
523
524 drop:
525 kfree_skb(skb);
526 return 0;
527 }
528
529 struct tlvtype_proc tlvprochopopt_lst[] = {
530 {IPV6_TLV_ROUTERALERT, ipv6_hop_ra},
531 {IPV6_TLV_JUMBO, ipv6_hop_jumbo},
532 {-1, NULL}
533 };
534
ipv6_parse_hopopts(struct sk_buff * skb,int nhoff)535 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
536 {
537 ((struct inet6_skb_parm*)skb->cb)->hop = sizeof(struct ipv6hdr);
538 if (ip6_parse_tlv(tlvprochopopt_lst, skb))
539 return sizeof(struct ipv6hdr);
540 return -1;
541 }
542
543 /*
544 * Creating outbound headers.
545 *
546 * "build" functions work when skb is filled from head to tail (datagram)
547 * "push" functions work when headers are added from tail to head (tcp)
548 *
549 * In both cases we assume, that caller reserved enough room
550 * for headers.
551 */
552
ipv6_build_rthdr(struct sk_buff * skb,u8 * prev_hdr,struct ipv6_rt_hdr * opt,struct in6_addr * addr)553 u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr,
554 struct ipv6_rt_hdr *opt, struct in6_addr *addr)
555 {
556 struct rt0_hdr *phdr, *ihdr;
557 int hops;
558
559 ihdr = (struct rt0_hdr *) opt;
560
561 phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
562 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
563
564 hops = ihdr->rt_hdr.hdrlen >> 1;
565
566 if (hops > 1)
567 memcpy(phdr->addr, ihdr->addr + 1,
568 (hops - 1) * sizeof(struct in6_addr));
569
570 ipv6_addr_copy(phdr->addr + (hops - 1), addr);
571
572 phdr->rt_hdr.nexthdr = *prev_hdr;
573 *prev_hdr = NEXTHDR_ROUTING;
574 return &phdr->rt_hdr.nexthdr;
575 }
576
ipv6_build_exthdr(struct sk_buff * skb,u8 * prev_hdr,u8 type,struct ipv6_opt_hdr * opt)577 static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt)
578 {
579 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt));
580
581 memcpy(h, opt, ipv6_optlen(opt));
582 h->nexthdr = *prev_hdr;
583 *prev_hdr = type;
584 return &h->nexthdr;
585 }
586
ipv6_build_authhdr(struct sk_buff * skb,u8 * prev_hdr,struct ipv6_opt_hdr * opt)587 static u8 *ipv6_build_authhdr(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_opt_hdr *opt)
588 {
589 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, (opt->hdrlen+2)<<2);
590
591 memcpy(h, opt, (opt->hdrlen+2)<<2);
592 h->nexthdr = *prev_hdr;
593 *prev_hdr = NEXTHDR_AUTH;
594 return &h->nexthdr;
595 }
596
597
ipv6_build_nfrag_opts(struct sk_buff * skb,u8 * prev_hdr,struct ipv6_txoptions * opt,struct in6_addr * daddr,u32 jumbolen)598 u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt,
599 struct in6_addr *daddr, u32 jumbolen)
600 {
601 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data;
602
603 if (opt && opt->hopopt)
604 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt);
605
606 if (jumbolen) {
607 u8 *jumboopt = (u8 *)skb_put(skb, 8);
608
609 if (opt && opt->hopopt) {
610 *jumboopt++ = IPV6_TLV_PADN;
611 *jumboopt++ = 0;
612 h->hdrlen++;
613 } else {
614 h = (struct ipv6_opt_hdr *)jumboopt;
615 h->nexthdr = *prev_hdr;
616 h->hdrlen = 0;
617 jumboopt += 2;
618 *prev_hdr = NEXTHDR_HOP;
619 prev_hdr = &h->nexthdr;
620 }
621 jumboopt[0] = IPV6_TLV_JUMBO;
622 jumboopt[1] = 4;
623 *(u32*)(jumboopt+2) = htonl(jumbolen);
624 }
625 if (opt) {
626 if (opt->dst0opt)
627 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);
628 if (opt->srcrt)
629 prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
630 }
631 return prev_hdr;
632 }
633
ipv6_build_frag_opts(struct sk_buff * skb,u8 * prev_hdr,struct ipv6_txoptions * opt)634 u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt)
635 {
636 if (opt->auth)
637 prev_hdr = ipv6_build_authhdr(skb, prev_hdr, opt->auth);
638 if (opt->dst1opt)
639 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt);
640 return prev_hdr;
641 }
642
ipv6_push_rthdr(struct sk_buff * skb,u8 * proto,struct ipv6_rt_hdr * opt,struct in6_addr ** addr_p)643 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
644 struct ipv6_rt_hdr *opt,
645 struct in6_addr **addr_p)
646 {
647 struct rt0_hdr *phdr, *ihdr;
648 int hops;
649
650 ihdr = (struct rt0_hdr *) opt;
651
652 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
653 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
654
655 hops = ihdr->rt_hdr.hdrlen >> 1;
656
657 if (hops > 1)
658 memcpy(phdr->addr, ihdr->addr + 1,
659 (hops - 1) * sizeof(struct in6_addr));
660
661 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
662 *addr_p = ihdr->addr;
663
664 phdr->rt_hdr.nexthdr = *proto;
665 *proto = NEXTHDR_ROUTING;
666 }
667
ipv6_push_exthdr(struct sk_buff * skb,u8 * proto,u8 type,struct ipv6_opt_hdr * opt)668 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
669 {
670 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
671
672 memcpy(h, opt, ipv6_optlen(opt));
673 h->nexthdr = *proto;
674 *proto = type;
675 }
676
ipv6_push_authhdr(struct sk_buff * skb,u8 * proto,struct ipv6_opt_hdr * opt)677 static void ipv6_push_authhdr(struct sk_buff *skb, u8 *proto, struct ipv6_opt_hdr *opt)
678 {
679 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, (opt->hdrlen+2)<<2);
680
681 memcpy(h, opt, (opt->hdrlen+2)<<2);
682 h->nexthdr = *proto;
683 *proto = NEXTHDR_AUTH;
684 }
685
ipv6_push_nfrag_opts(struct sk_buff * skb,struct ipv6_txoptions * opt,u8 * proto,struct in6_addr ** daddr)686 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
687 u8 *proto,
688 struct in6_addr **daddr)
689 {
690 if (opt->srcrt)
691 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
692 if (opt->dst0opt)
693 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
694 if (opt->hopopt)
695 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
696 }
697
ipv6_push_frag_opts(struct sk_buff * skb,struct ipv6_txoptions * opt,u8 * proto)698 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
699 {
700 if (opt->dst1opt)
701 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
702 if (opt->auth)
703 ipv6_push_authhdr(skb, proto, opt->auth);
704 }
705
706 struct ipv6_txoptions *
ipv6_dup_options(struct sock * sk,struct ipv6_txoptions * opt)707 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
708 {
709 struct ipv6_txoptions *opt2;
710
711 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
712 if (opt2) {
713 long dif = (char*)opt2 - (char*)opt;
714 memcpy(opt2, opt, opt->tot_len);
715 if (opt2->hopopt)
716 *((char**)&opt2->hopopt) += dif;
717 if (opt2->dst0opt)
718 *((char**)&opt2->dst0opt) += dif;
719 if (opt2->dst1opt)
720 *((char**)&opt2->dst1opt) += dif;
721 if (opt2->auth)
722 *((char**)&opt2->auth) += dif;
723 if (opt2->srcrt)
724 *((char**)&opt2->srcrt) += dif;
725 }
726 return opt2;
727 }
728
729
730 /*
731 * find out if nexthdr is a well-known extension header or a protocol
732 */
733
ipv6_ext_hdr(u8 nexthdr)734 int ipv6_ext_hdr(u8 nexthdr)
735 {
736 /*
737 * find out if nexthdr is an extension header or a protocol
738 */
739 return ( (nexthdr == NEXTHDR_HOP) ||
740 (nexthdr == NEXTHDR_ROUTING) ||
741 (nexthdr == NEXTHDR_FRAGMENT) ||
742 (nexthdr == NEXTHDR_AUTH) ||
743 (nexthdr == NEXTHDR_NONE) ||
744 (nexthdr == NEXTHDR_DEST) );
745 }
746
747 /*
748 * Skip any extension headers. This is used by the ICMP module.
749 *
750 * Note that strictly speaking this conflicts with RFC1883 4.0:
751 * ...The contents and semantics of each extension header determine whether
752 * or not to proceed to the next header. Therefore, extension headers must
753 * be processed strictly in the order they appear in the packet; a
754 * receiver must not, for example, scan through a packet looking for a
755 * particular kind of extension header and process that header prior to
756 * processing all preceding ones.
757 *
758 * We do exactly this. This is a protocol bug. We can't decide after a
759 * seeing an unknown discard-with-error flavour TLV option if it's a
760 * ICMP error message or not (errors should never be send in reply to
761 * ICMP error messages).
762 *
763 * But I see no other way to do this. This might need to be reexamined
764 * when Linux implements ESP (and maybe AUTH) headers.
765 * --AK
766 *
767 * This function parses (probably truncated) exthdr set "hdr"
768 * of length "len". "nexthdrp" initially points to some place,
769 * where type of the first header can be found.
770 *
771 * It skips all well-known exthdrs, and returns pointer to the start
772 * of unparsable area i.e. the first header with unknown type.
773 * If it is not NULL *nexthdr is updated by type/protocol of this header.
774 *
775 * NOTES: - if packet terminated with NEXTHDR_NONE it returns NULL.
776 * - it may return pointer pointing beyond end of packet,
777 * if the last recognized header is truncated in the middle.
778 * - if packet is truncated, so that all parsed headers are skipped,
779 * it returns NULL.
780 * - First fragment header is skipped, not-first ones
781 * are considered as unparsable.
782 * - ESP is unparsable for now and considered like
783 * normal payload protocol.
784 * - Note also special handling of AUTH header. Thanks to IPsec wizards.
785 *
786 * --ANK (980726)
787 */
788
ipv6_skip_exthdr(const struct sk_buff * skb,int start,u8 * nexthdrp,int len)789 int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
790 {
791 u8 nexthdr = *nexthdrp;
792
793 while (ipv6_ext_hdr(nexthdr)) {
794 struct ipv6_opt_hdr hdr;
795 int hdrlen;
796
797 if (len < (int)sizeof(struct ipv6_opt_hdr))
798 return -1;
799 if (nexthdr == NEXTHDR_NONE)
800 return -1;
801 if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
802 BUG();
803 if (nexthdr == NEXTHDR_FRAGMENT) {
804 unsigned short frag_off;
805 if (skb_copy_bits(skb,
806 start+offsetof(struct frag_hdr,
807 frag_off),
808 &frag_off,
809 sizeof(frag_off))) {
810 return -1;
811 }
812
813 if (ntohs(frag_off) & ~0x7)
814 break;
815 hdrlen = 8;
816 } else if (nexthdr == NEXTHDR_AUTH)
817 hdrlen = (hdr.hdrlen+2)<<2;
818 else
819 hdrlen = ipv6_optlen(&hdr);
820
821 nexthdr = hdr.nexthdr;
822 len -= hdrlen;
823 start += hdrlen;
824 }
825
826 *nexthdrp = nexthdr;
827 return start;
828 }
829
830