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 <asm/uaccess.h>
50 * Parsing tlv encoded headers.
52 * Parsing function "func" returns 1, if parsing succeed
53 * and 0, if it failed.
54 * It MUST NOT touch skb->h.
59 int (*func)(struct sk_buff *skb, int offset);
62 /*********************
64 *********************/
66 /* An unknown option is detected, decide what to do */
68 static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
70 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
74 case 1: /* drop packet */
77 case 3: /* Send ICMP if not a multicast address and drop packet */
78 /* Actually, it is redundant check. icmp_send
79 will recheck in any case.
81 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
83 case 2: /* send ICMP PARM PROB regardless and drop packet */
84 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
92 /* Parse tlv encoded option header (hop-by-hop or destination) */
94 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
96 struct tlvtype_proc *curr;
97 int off = skb->h.raw - skb->nh.raw;
98 int len = ((skb->h.raw[1]+1)<<3);
100 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
107 int optlen = skb->nh.raw[off+1]+2;
109 switch (skb->nh.raw[off]) {
117 default: /* Other TLV code so scan list */
120 for (curr=procs; curr->type >= 0; curr++) {
121 if (curr->type == skb->nh.raw[off]) {
122 /* type specific length/alignment
123 checks will be performed in the
125 if (curr->func(skb, off) == 0)
130 if (curr->type < 0) {
131 if (ip6_tlvopt_unknown(skb, off) == 0)
146 /*****************************
147 Destination options header.
148 *****************************/
150 static struct tlvtype_proc tlvprocdestopt_lst[] = {
151 /* No destination options are defined now */
155 static int ipv6_destopt_rcv(struct sk_buff **skbp)
157 struct sk_buff *skb = *skbp;
158 struct inet6_skb_parm *opt = IP6CB(skb);
160 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
161 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
162 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
167 opt->lastopt = skb->h.raw - skb->nh.raw;
168 opt->dst1 = skb->h.raw - skb->nh.raw;
170 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
171 skb->h.raw += ((skb->h.raw[1]+1)<<3);
172 opt->nhoff = opt->dst1;
176 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
180 static struct inet6_protocol destopt_protocol = {
181 .handler = ipv6_destopt_rcv,
182 .flags = INET6_PROTO_NOPOLICY,
185 void __init ipv6_destopt_init(void)
187 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
188 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
191 /********************************
192 NONE header. No data in packet.
193 ********************************/
195 static int ipv6_nodata_rcv(struct sk_buff **skbp)
197 struct sk_buff *skb = *skbp;
203 static struct inet6_protocol nodata_protocol = {
204 .handler = ipv6_nodata_rcv,
205 .flags = INET6_PROTO_NOPOLICY,
208 void __init ipv6_nodata_init(void)
210 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
211 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
214 /********************************
216 ********************************/
218 static int ipv6_rthdr_rcv(struct sk_buff **skbp)
220 struct sk_buff *skb = *skbp;
221 struct inet6_skb_parm *opt = IP6CB(skb);
222 struct in6_addr *addr;
223 struct in6_addr daddr;
224 struct inet6_dev *idev;
226 struct ipv6_rt_hdr *hdr;
227 struct rt0_hdr *rthdr;
228 int accept_source_route = ipv6_devconf.accept_source_route;
230 if (accept_source_route < 0 ||
231 ((idev = in6_dev_get(skb->dev)) == NULL)) {
235 if (idev->cnf.accept_source_route < 0) {
241 if (accept_source_route > idev->cnf.accept_source_route)
242 accept_source_route = idev->cnf.accept_source_route;
246 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
247 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
248 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
253 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
256 case IPV6_SRCRT_TYPE_0:
257 if (accept_source_route > 0)
262 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
263 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
267 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
268 skb->pkt_type != PACKET_HOST) {
269 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
275 if (hdr->segments_left == 0) {
276 opt->lastopt = skb->h.raw - skb->nh.raw;
277 opt->srcrt = skb->h.raw - skb->nh.raw;
278 skb->h.raw += (hdr->hdrlen + 1) << 3;
279 opt->dst0 = opt->dst1;
281 opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
285 if (hdr->hdrlen & 0x01) {
286 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
287 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
292 * This is the routing header forwarding algorithm from
296 n = hdr->hdrlen >> 1;
298 if (hdr->segments_left > n) {
299 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
300 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
304 /* We are about to mangle packet header. Be careful!
305 Do not damage packets queued somewhere.
307 if (skb_cloned(skb)) {
308 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
310 /* the copy is a forwarded packet */
312 IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS);
317 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
320 if (skb->ip_summed == CHECKSUM_HW)
321 skb->ip_summed = CHECKSUM_NONE;
323 i = n - --hdr->segments_left;
325 rthdr = (struct rt0_hdr *) hdr;
329 if (ipv6_addr_is_multicast(addr)) {
330 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
335 ipv6_addr_copy(&daddr, addr);
336 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
337 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
339 dst_release(xchg(&skb->dst, NULL));
340 ip6_route_input(skb);
341 if (skb->dst->error) {
342 skb_push(skb, skb->data - skb->nh.raw);
347 if (skb->dst->dev->flags&IFF_LOOPBACK) {
348 if (skb->nh.ipv6h->hop_limit <= 1) {
349 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
350 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
355 skb->nh.ipv6h->hop_limit--;
359 skb_push(skb, skb->data - skb->nh.raw);
364 static struct inet6_protocol rthdr_protocol = {
365 .handler = ipv6_rthdr_rcv,
366 .flags = INET6_PROTO_NOPOLICY,
369 void __init ipv6_rthdr_init(void)
371 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
372 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
376 This function inverts received rthdr.
377 NOTE: specs allow to make it automatically only if
378 packet authenticated.
380 I will not discuss it here (though, I am really pissed off at
381 this stupid requirement making rthdr idea useless)
383 Actually, it creates severe problems for us.
384 Embryonic requests has no associated sockets,
385 so that user have no control over it and
386 cannot not only to set reply options, but
387 even to know, that someone wants to connect
390 For now we need to test the engine, so that I created
391 temporary (or permanent) backdoor.
392 If listening socket set IPV6_RTHDR to 2, then we invert header.
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->segments_left ||
417 hdr->type != IPV6_SRCRT_TYPE_0 ||
421 n = hdr->hdrlen >> 1;
422 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
425 memset(opt, 0, sizeof(*opt));
426 opt->tot_len = sizeof(*opt) + hdrlen;
427 opt->srcrt = (void*)(opt+1);
428 opt->opt_nflen = hdrlen;
430 memcpy(opt->srcrt, hdr, sizeof(*hdr));
431 irthdr = (struct rt0_hdr*)opt->srcrt;
432 irthdr->reserved = 0;
433 opt->srcrt->segments_left = n;
435 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
439 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
441 /**********************************
443 **********************************/
445 /* Router Alert as of RFC 2711 */
447 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
449 if (skb->nh.raw[optoff+1] == 2) {
450 IP6CB(skb)->ra = optoff;
453 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
454 skb->nh.raw[optoff+1]);
461 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
465 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
466 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
467 skb->nh.raw[optoff+1]);
468 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
472 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
473 if (pkt_len <= IPV6_MAXPLEN) {
474 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
475 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
478 if (skb->nh.ipv6h->payload_len) {
479 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
480 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
484 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
485 IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
489 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
499 static struct tlvtype_proc tlvprochopopt_lst[] = {
501 .type = IPV6_TLV_ROUTERALERT,
505 .type = IPV6_TLV_JUMBO,
506 .func = ipv6_hop_jumbo,
511 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
513 struct inet6_skb_parm *opt = IP6CB(skb);
516 * skb->nh.raw is equal to skb->data, and
517 * skb->h.raw - skb->nh.raw is always equal to
518 * sizeof(struct ipv6hdr) by definition of
519 * hop-by-hop options.
521 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
522 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
527 opt->hop = sizeof(struct ipv6hdr);
528 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
529 skb->h.raw += (skb->h.raw[1]+1)<<3;
530 opt->nhoff = sizeof(struct ipv6hdr);
531 return sizeof(struct ipv6hdr);
537 * Creating outbound headers.
539 * "build" functions work when skb is filled from head to tail (datagram)
540 * "push" functions work when headers are added from tail to head (tcp)
542 * In both cases we assume, that caller reserved enough room
546 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
547 struct ipv6_rt_hdr *opt,
548 struct in6_addr **addr_p)
550 struct rt0_hdr *phdr, *ihdr;
553 ihdr = (struct rt0_hdr *) opt;
555 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
556 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
558 hops = ihdr->rt_hdr.hdrlen >> 1;
561 memcpy(phdr->addr, ihdr->addr + 1,
562 (hops - 1) * sizeof(struct in6_addr));
564 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
565 *addr_p = ihdr->addr;
567 phdr->rt_hdr.nexthdr = *proto;
568 *proto = NEXTHDR_ROUTING;
571 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
573 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
575 memcpy(h, opt, ipv6_optlen(opt));
580 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
582 struct in6_addr **daddr)
585 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
587 * IPV6_RTHDRDSTOPTS is ignored
588 * unless IPV6_RTHDR is set (RFC3542).
591 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
594 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
597 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
600 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
603 struct ipv6_txoptions *
604 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
606 struct ipv6_txoptions *opt2;
608 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
610 long dif = (char*)opt2 - (char*)opt;
611 memcpy(opt2, opt, opt->tot_len);
613 *((char**)&opt2->hopopt) += dif;
615 *((char**)&opt2->dst0opt) += dif;
617 *((char**)&opt2->dst1opt) += dif;
619 *((char**)&opt2->srcrt) += dif;
624 EXPORT_SYMBOL_GPL(ipv6_dup_options);
626 static int ipv6_renew_option(void *ohdr,
627 struct ipv6_opt_hdr __user *newopt, int newoptlen,
629 struct ipv6_opt_hdr **hdr,
634 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
635 *hdr = (struct ipv6_opt_hdr *)*p;
636 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
640 if (copy_from_user(*p, newopt, newoptlen))
642 *hdr = (struct ipv6_opt_hdr *)*p;
643 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
645 *p += CMSG_ALIGN(newoptlen);
651 struct ipv6_txoptions *
652 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
654 struct ipv6_opt_hdr __user *newopt, int newoptlen)
658 struct ipv6_txoptions *opt2;
662 if (newtype != IPV6_HOPOPTS && opt->hopopt)
663 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
664 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
665 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
666 if (newtype != IPV6_RTHDR && opt->srcrt)
667 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
668 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
669 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
672 if (newopt && newoptlen)
673 tot_len += CMSG_ALIGN(newoptlen);
678 tot_len += sizeof(*opt2);
679 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
681 return ERR_PTR(-ENOBUFS);
683 memset(opt2, 0, tot_len);
685 opt2->tot_len = tot_len;
686 p = (char *)(opt2 + 1);
688 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
689 newtype != IPV6_HOPOPTS,
694 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
695 newtype != IPV6_RTHDRDSTOPTS,
700 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
701 newtype != IPV6_RTHDR,
702 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
706 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
707 newtype != IPV6_DSTOPTS,
712 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
713 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
714 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
715 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
719 sock_kfree_s(sk, opt2, opt2->tot_len);
723 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
724 struct ipv6_txoptions *opt)
727 * ignore the dest before srcrt unless srcrt is being included.
730 if (opt && opt->dst0opt && !opt->srcrt) {
731 if (opt_space != opt) {
732 memcpy(opt_space, opt, sizeof(*opt_space));
735 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);