2 * Extension Header handling for IPv6
3 * Linux INET6 implementation
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Andi Kleen <ak@muc.de>
8 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
10 * $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
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.
19 * yoshfuji : ensure not to overrun while parsing
21 * Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
22 * YOSHIFUJI Hideaki @USAGI Register inbound extension header
23 * handlers as inet6_protocol{}.
26 #include <linux/errno.h>
27 #include <linux/types.h>
28 #include <linux/socket.h>
29 #include <linux/sockios.h>
30 #include <linux/sched.h>
31 #include <linux/net.h>
32 #include <linux/netdevice.h>
33 #include <linux/in6.h>
34 #include <linux/icmpv6.h>
40 #include <net/protocol.h>
41 #include <net/transp_v6.h>
42 #include <net/rawv6.h>
43 #include <net/ndisc.h>
44 #include <net/ip6_route.h>
45 #include <net/addrconf.h>
47 #include <net/mipglue.h>
48 #include <net/mipv6.h>
50 #include <asm/uaccess.h>
53 * Parsing tlv encoded headers.
55 * Parsing function "func" returns 1, if parsing succeed
56 * and 0, if it failed.
57 * It MUST NOT touch skb->h.
62 int (*func)(struct sk_buff *skb, int offset);
65 /*********************
67 *********************/
69 /* An unknown option is detected, decide what to do */
71 int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
73 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
77 case 1: /* drop packet */
80 case 3: /* Send ICMP if not a multicast address and drop packet */
81 /* Actually, it is redundant check. icmp_send
82 will recheck in any case.
84 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
86 case 2: /* send ICMP PARM PROB regardless and drop packet */
87 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
95 /* Parse tlv encoded option header (hop-by-hop or destination) */
97 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
99 struct tlvtype_proc *curr;
100 int off = skb->h.raw - skb->nh.raw;
101 int len = ((skb->h.raw[1]+1)<<3);
103 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
110 int optlen = skb->nh.raw[off+1]+2;
112 switch (skb->nh.raw[off]) {
120 default: /* Other TLV code so scan list */
123 for (curr=procs; curr->type >= 0; curr++) {
124 if (curr->type == skb->nh.raw[off]) {
125 /* type specific length/alignment
126 checks will be performed in the
128 if (curr->func(skb, off) == 0)
133 if (curr->type < 0) {
134 if (ip6_tlvopt_unknown(skb, off) == 0)
149 /*****************************
150 Destination options header.
151 *****************************/
153 static struct tlvtype_proc tlvprocdestopt_lst[] = {
154 /* Mobility Support destination options */
155 {MIPV6_TLV_HOMEADDR, mipv6_handle_dstopt},
159 static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
161 struct sk_buff *skb = *skbp;
162 struct inet6_skb_parm *opt = IP6CB(skb);
164 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
165 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
166 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
171 opt->dst1 = skb->h.raw - skb->nh.raw;
173 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
174 skb->h.raw += ((skb->h.raw[1]+1)<<3);
179 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
183 static struct inet6_protocol destopt_protocol = {
184 .handler = ipv6_destopt_rcv,
185 .flags = INET6_PROTO_NOPOLICY,
188 void __init ipv6_destopt_init(void)
190 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
191 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
194 /********************************
195 NONE header. No data in packet.
196 ********************************/
198 static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
200 struct sk_buff *skb = *skbp;
206 static struct inet6_protocol nodata_protocol = {
207 .handler = ipv6_nodata_rcv,
208 .flags = INET6_PROTO_NOPOLICY,
211 void __init ipv6_nodata_init(void)
213 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
214 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
217 /********************************
219 ********************************/
221 static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
223 struct sk_buff *skb = *skbp;
224 struct inet6_skb_parm *opt = IP6CB(skb);
225 struct in6_addr *addr;
226 struct in6_addr daddr;
229 struct ipv6_rt_hdr *hdr;
230 struct rt0_hdr *rthdr;
231 struct rt2_hdr *rt2hdr;
233 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
234 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
235 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
240 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
242 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
243 skb->pkt_type != PACKET_HOST) {
244 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
250 if (hdr->segments_left == 0) {
251 if (hdr->type == IPV6_SRCRT_TYPE_0)
252 opt->srcrt = skb->h.raw - skb->nh.raw;
253 else if (hdr->type == IPV6_SRCRT_TYPE_2)
254 opt->srcrt2 = skb->h.raw - skb->nh.raw;
255 skb->h.raw += (hdr->hdrlen + 1) << 3;
256 opt->dst0 = opt->dst1;
258 *nhoffp = (&hdr->nexthdr) - skb->nh.raw;
262 if (hdr->type != IPV6_SRCRT_TYPE_0 && hdr->type != IPV6_SRCRT_TYPE_2) {
263 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
264 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
268 if (hdr->hdrlen & 0x01) {
269 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
270 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
275 * This is the routing header forwarding algorithm from
279 n = hdr->hdrlen >> 1;
281 if (hdr->segments_left > n) {
282 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
283 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
287 /* We are about to mangle packet header. Be careful!
288 Do not damage packets queued somewhere.
290 if (skb_cloned(skb)) {
291 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
293 /* the copy is a forwarded packet */
295 IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS);
300 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
303 if (skb->ip_summed == CHECKSUM_HW)
304 skb->ip_summed = CHECKSUM_NONE;
306 i = n - --hdr->segments_left;
308 if (hdr->type == IPV6_SRCRT_TYPE_0) {
309 rthdr = (struct rt0_hdr *) hdr;
313 if (hdr->hdrlen != 2 || hdr->segments_left != 0) {
314 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
315 hdr->hdrlen != 2 ? 1 : 3);
318 /* check that address is this node's home address */
319 rt2hdr = (struct rt2_hdr *) hdr;
320 addr = &rt2hdr->addr;
321 if (!ipv6_chk_addr(addr, NULL, 0) ||
322 !ipv6_chk_mip_home_addr(addr)) {
328 if (ipv6_addr_is_multicast(addr)) {
329 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
334 ipv6_addr_copy(&daddr, addr);
335 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
336 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
338 dst_release(xchg(&skb->dst, NULL));
339 ip6_route_input(skb);
340 if (skb->dst->error) {
344 if (skb->dst->dev->flags&IFF_LOOPBACK) {
345 if (skb->nh.ipv6h->hop_limit <= 1) {
346 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
347 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
352 skb->nh.ipv6h->hop_limit--;
360 static struct inet6_protocol rthdr_protocol = {
361 .handler = ipv6_rthdr_rcv,
362 .flags = INET6_PROTO_NOPOLICY,
365 void __init ipv6_rthdr_init(void)
367 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
368 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
372 This function inverts received rthdr.
373 NOTE: specs allow to make it automatically only if
374 packet authenticated.
376 I will not discuss it here (though, I am really pissed off at
377 this stupid requirement making rthdr idea useless)
379 Actually, it creates severe problems for us.
380 Embryonic requests has no associated sockets,
381 so that user have no control over it and
382 cannot not only to set reply options, but
383 even to know, that someone wants to connect
386 For now we need to test the engine, so that I created
387 temporary (or permanent) backdoor.
388 If listening socket set IPV6_RTHDR to 2, then we invert header.
391 By the Mobile IPv6 specification Type 2 routing header MUST NOT be
396 struct ipv6_txoptions *
397 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
401 [ H1 -> H2 -> ... H_prev ] daddr=ME
404 [ H_prev -> ... -> H1 ] daddr =sender
406 Note, that IP output engine will rewrite this rthdr
407 by rotating it left by one addr.
411 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
412 struct rt0_hdr *irthdr;
413 struct ipv6_txoptions *opt;
414 int hdrlen = ipv6_optlen(hdr);
416 if (hdr->type == IPV6_SRCRT_TYPE_2) {
417 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
420 memset(opt, 0, sizeof(*opt));
421 opt->tot_len = sizeof(*opt) + hdrlen;
422 opt->srcrt = (void*)(opt+1);
423 opt->opt_nflen = hdrlen;
424 memcpy(opt->srcrt, hdr, sizeof(struct rt2_hdr));
428 if (hdr->segments_left ||
429 hdr->type != IPV6_SRCRT_TYPE_0 ||
433 n = hdr->hdrlen >> 1;
434 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
437 memset(opt, 0, sizeof(*opt));
438 opt->tot_len = sizeof(*opt) + hdrlen;
439 opt->srcrt = (void*)(opt+1);
440 opt->opt_nflen = hdrlen;
442 memcpy(opt->srcrt, hdr, sizeof(*hdr));
443 irthdr = (struct rt0_hdr*)opt->srcrt;
444 /* Obsolete field, MBZ, when originated by us */
446 opt->srcrt->segments_left = n;
448 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
452 /**********************************
454 **********************************/
456 /* Router Alert as of RFC 2711 */
458 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
460 if (skb->nh.raw[optoff+1] == 2) {
461 IP6CB(skb)->ra = optoff;
465 printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1]));
472 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
476 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
478 printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]));
479 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
483 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
484 if (pkt_len <= IPV6_MAXPLEN) {
485 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
486 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
489 if (skb->nh.ipv6h->payload_len) {
490 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
491 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
495 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
496 IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
499 if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
500 __pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr));
501 if (skb->ip_summed == CHECKSUM_HW)
502 skb->ip_summed = CHECKSUM_NONE;
511 static struct tlvtype_proc tlvprochopopt_lst[] = {
513 .type = IPV6_TLV_ROUTERALERT,
517 .type = IPV6_TLV_JUMBO,
518 .func = ipv6_hop_jumbo,
523 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
525 IP6CB(skb)->hop = sizeof(struct ipv6hdr);
526 if (ip6_parse_tlv(tlvprochopopt_lst, skb))
527 return sizeof(struct ipv6hdr);
532 * Creating outbound headers.
534 * "build" functions work when skb is filled from head to tail (datagram)
535 * "push" functions work when headers are added from tail to head (tcp)
537 * In both cases we assume, that caller reserved enough room
541 static u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr,
542 struct ipv6_rt_hdr *opt, struct in6_addr *addr)
544 struct rt0_hdr *phdr, *ihdr;
547 ihdr = (struct rt0_hdr *) opt;
549 phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
550 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
552 hops = ihdr->rt_hdr.hdrlen >> 1;
555 memcpy(phdr->addr, ihdr->addr + 1,
556 (hops - 1) * sizeof(struct in6_addr));
558 ipv6_addr_copy(phdr->addr + (hops - 1), addr);
560 phdr->rt_hdr.nexthdr = *prev_hdr;
561 *prev_hdr = NEXTHDR_ROUTING;
562 return &phdr->rt_hdr.nexthdr;
565 static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt)
567 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt));
569 memcpy(h, opt, ipv6_optlen(opt));
570 h->nexthdr = *prev_hdr;
575 u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt,
576 struct in6_addr *daddr, u32 jumbolen)
578 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data;
580 if (opt && opt->hopopt)
581 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt);
584 u8 *jumboopt = (u8 *)skb_put(skb, 8);
586 if (opt && opt->hopopt) {
587 *jumboopt++ = IPV6_TLV_PADN;
591 h = (struct ipv6_opt_hdr *)jumboopt;
592 h->nexthdr = *prev_hdr;
595 *prev_hdr = NEXTHDR_HOP;
596 prev_hdr = &h->nexthdr;
598 jumboopt[0] = IPV6_TLV_JUMBO;
600 *(u32*)(jumboopt+2) = htonl(jumbolen);
604 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);
607 struct in6_addr *rt2_hop = &((struct rt2_hdr *)opt->srcrt2)->addr;
608 prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, rt2_hop);
610 prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
613 prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt2, daddr);
618 u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt)
621 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt);
625 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
626 struct ipv6_rt_hdr *opt,
627 struct in6_addr **addr_p)
629 struct rt0_hdr *phdr, *ihdr;
632 ihdr = (struct rt0_hdr *) opt;
634 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
635 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
637 hops = ihdr->rt_hdr.hdrlen >> 1;
640 memcpy(phdr->addr, ihdr->addr + 1,
641 (hops - 1) * sizeof(struct in6_addr));
643 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
644 *addr_p = ihdr->addr;
646 phdr->rt_hdr.nexthdr = *proto;
647 *proto = NEXTHDR_ROUTING;
650 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
652 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
654 memcpy(h, opt, ipv6_optlen(opt));
659 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
661 struct in6_addr **daddr)
664 ipv6_push_rthdr(skb, proto, opt->srcrt2, daddr);
666 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
668 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
670 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
673 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
676 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
679 struct ipv6_txoptions *
680 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
682 struct ipv6_txoptions *opt2;
684 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
686 long dif = (char*)opt2 - (char*)opt;
687 memcpy(opt2, opt, opt->tot_len);
689 *((char**)&opt2->hopopt) += dif;
691 *((char**)&opt2->dst0opt) += dif;
693 *((char**)&opt2->dst1opt) += dif;
695 *((char**)&opt2->srcrt) += dif;
697 *((char**)&opt2->srcrt2) += dif;
702 EXPORT_SYMBOL(ip6_tlvopt_unknown);