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
;
226 struct ipv6_rt_hdr
*hdr
;
227 struct rt0_hdr
*rthdr
;
229 if (!pskb_may_pull(skb
, (skb
->h
.raw
-skb
->data
)+8) ||
230 !pskb_may_pull(skb
, (skb
->h
.raw
-skb
->data
)+((skb
->h
.raw
[1]+1)<<3))) {
231 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
236 hdr
= (struct ipv6_rt_hdr
*) skb
->h
.raw
;
238 if (ipv6_addr_is_multicast(&skb
->nh
.ipv6h
->daddr
) ||
239 skb
->pkt_type
!= PACKET_HOST
) {
240 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS
);
246 if (hdr
->segments_left
== 0) {
247 opt
->lastopt
= skb
->h
.raw
- skb
->nh
.raw
;
248 opt
->srcrt
= skb
->h
.raw
- skb
->nh
.raw
;
249 skb
->h
.raw
+= (hdr
->hdrlen
+ 1) << 3;
250 opt
->dst0
= opt
->dst1
;
252 opt
->nhoff
= (&hdr
->nexthdr
) - skb
->nh
.raw
;
256 if (hdr
->type
!= IPV6_SRCRT_TYPE_0
) {
257 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
258 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, (&hdr
->type
) - skb
->nh
.raw
);
262 if (hdr
->hdrlen
& 0x01) {
263 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
264 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, (&hdr
->hdrlen
) - skb
->nh
.raw
);
269 * This is the routing header forwarding algorithm from
273 n
= hdr
->hdrlen
>> 1;
275 if (hdr
->segments_left
> n
) {
276 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
277 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, (&hdr
->segments_left
) - skb
->nh
.raw
);
281 /* We are about to mangle packet header. Be careful!
282 Do not damage packets queued somewhere.
284 if (skb_cloned(skb
)) {
285 struct sk_buff
*skb2
= skb_copy(skb
, GFP_ATOMIC
);
287 /* the copy is a forwarded packet */
289 IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS
);
294 hdr
= (struct ipv6_rt_hdr
*) skb2
->h
.raw
;
297 if (skb
->ip_summed
== CHECKSUM_HW
)
298 skb
->ip_summed
= CHECKSUM_NONE
;
300 i
= n
- --hdr
->segments_left
;
302 rthdr
= (struct rt0_hdr
*) hdr
;
306 if (ipv6_addr_is_multicast(addr
)) {
307 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS
);
312 ipv6_addr_copy(&daddr
, addr
);
313 ipv6_addr_copy(addr
, &skb
->nh
.ipv6h
->daddr
);
314 ipv6_addr_copy(&skb
->nh
.ipv6h
->daddr
, &daddr
);
316 dst_release(xchg(&skb
->dst
, NULL
));
317 ip6_route_input(skb
);
318 if (skb
->dst
->error
) {
319 skb_push(skb
, skb
->data
- skb
->nh
.raw
);
324 if (skb
->dst
->dev
->flags
&IFF_LOOPBACK
) {
325 if (skb
->nh
.ipv6h
->hop_limit
<= 1) {
326 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
327 icmpv6_send(skb
, ICMPV6_TIME_EXCEED
, ICMPV6_EXC_HOPLIMIT
,
332 skb
->nh
.ipv6h
->hop_limit
--;
336 skb_push(skb
, skb
->data
- skb
->nh
.raw
);
341 static struct inet6_protocol rthdr_protocol
= {
342 .handler
= ipv6_rthdr_rcv
,
343 .flags
= INET6_PROTO_NOPOLICY
,
346 void __init
ipv6_rthdr_init(void)
348 if (inet6_add_protocol(&rthdr_protocol
, IPPROTO_ROUTING
) < 0)
349 printk(KERN_ERR
"ipv6_rthdr_init: Could not register protocol\n");
353 This function inverts received rthdr.
354 NOTE: specs allow to make it automatically only if
355 packet authenticated.
357 I will not discuss it here (though, I am really pissed off at
358 this stupid requirement making rthdr idea useless)
360 Actually, it creates severe problems for us.
361 Embryonic requests has no associated sockets,
362 so that user have no control over it and
363 cannot not only to set reply options, but
364 even to know, that someone wants to connect
367 For now we need to test the engine, so that I created
368 temporary (or permanent) backdoor.
369 If listening socket set IPV6_RTHDR to 2, then we invert header.
373 struct ipv6_txoptions
*
374 ipv6_invert_rthdr(struct sock
*sk
, struct ipv6_rt_hdr
*hdr
)
378 [ H1 -> H2 -> ... H_prev ] daddr=ME
381 [ H_prev -> ... -> H1 ] daddr =sender
383 Note, that IP output engine will rewrite this rthdr
384 by rotating it left by one addr.
388 struct rt0_hdr
*rthdr
= (struct rt0_hdr
*)hdr
;
389 struct rt0_hdr
*irthdr
;
390 struct ipv6_txoptions
*opt
;
391 int hdrlen
= ipv6_optlen(hdr
);
393 if (hdr
->segments_left
||
394 hdr
->type
!= IPV6_SRCRT_TYPE_0
||
398 n
= hdr
->hdrlen
>> 1;
399 opt
= sock_kmalloc(sk
, sizeof(*opt
) + hdrlen
, GFP_ATOMIC
);
402 memset(opt
, 0, sizeof(*opt
));
403 opt
->tot_len
= sizeof(*opt
) + hdrlen
;
404 opt
->srcrt
= (void*)(opt
+1);
405 opt
->opt_nflen
= hdrlen
;
407 memcpy(opt
->srcrt
, hdr
, sizeof(*hdr
));
408 irthdr
= (struct rt0_hdr
*)opt
->srcrt
;
409 irthdr
->reserved
= 0;
410 opt
->srcrt
->segments_left
= n
;
412 memcpy(irthdr
->addr
+i
, rthdr
->addr
+(n
-1-i
), 16);
416 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr
);
418 /**********************************
420 **********************************/
422 /* Router Alert as of RFC 2711 */
424 static int ipv6_hop_ra(struct sk_buff
*skb
, int optoff
)
426 if (skb
->nh
.raw
[optoff
+1] == 2) {
427 IP6CB(skb
)->ra
= optoff
;
430 LIMIT_NETDEBUG(KERN_DEBUG
"ipv6_hop_ra: wrong RA length %d\n",
431 skb
->nh
.raw
[optoff
+1]);
438 static int ipv6_hop_jumbo(struct sk_buff
*skb
, int optoff
)
442 if (skb
->nh
.raw
[optoff
+1] != 4 || (optoff
&3) != 2) {
443 LIMIT_NETDEBUG(KERN_DEBUG
"ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
444 skb
->nh
.raw
[optoff
+1]);
445 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
449 pkt_len
= ntohl(*(u32
*)(skb
->nh
.raw
+optoff
+2));
450 if (pkt_len
<= IPV6_MAXPLEN
) {
451 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
452 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, optoff
+2);
455 if (skb
->nh
.ipv6h
->payload_len
) {
456 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS
);
457 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, optoff
);
461 if (pkt_len
> skb
->len
- sizeof(struct ipv6hdr
)) {
462 IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS
);
466 if (pskb_trim_rcsum(skb
, pkt_len
+ sizeof(struct ipv6hdr
)))
476 static struct tlvtype_proc tlvprochopopt_lst
[] = {
478 .type
= IPV6_TLV_ROUTERALERT
,
482 .type
= IPV6_TLV_JUMBO
,
483 .func
= ipv6_hop_jumbo
,
488 int ipv6_parse_hopopts(struct sk_buff
*skb
)
490 struct inet6_skb_parm
*opt
= IP6CB(skb
);
493 * skb->nh.raw is equal to skb->data, and
494 * skb->h.raw - skb->nh.raw is always equal to
495 * sizeof(struct ipv6hdr) by definition of
496 * hop-by-hop options.
498 if (!pskb_may_pull(skb
, sizeof(struct ipv6hdr
) + 8) ||
499 !pskb_may_pull(skb
, sizeof(struct ipv6hdr
) + ((skb
->h
.raw
[1] + 1) << 3))) {
504 opt
->hop
= sizeof(struct ipv6hdr
);
505 if (ip6_parse_tlv(tlvprochopopt_lst
, skb
)) {
506 skb
->h
.raw
+= (skb
->h
.raw
[1]+1)<<3;
507 opt
->nhoff
= sizeof(struct ipv6hdr
);
514 * Creating outbound headers.
516 * "build" functions work when skb is filled from head to tail (datagram)
517 * "push" functions work when headers are added from tail to head (tcp)
519 * In both cases we assume, that caller reserved enough room
523 static void ipv6_push_rthdr(struct sk_buff
*skb
, u8
*proto
,
524 struct ipv6_rt_hdr
*opt
,
525 struct in6_addr
**addr_p
)
527 struct rt0_hdr
*phdr
, *ihdr
;
530 ihdr
= (struct rt0_hdr
*) opt
;
532 phdr
= (struct rt0_hdr
*) skb_push(skb
, (ihdr
->rt_hdr
.hdrlen
+ 1) << 3);
533 memcpy(phdr
, ihdr
, sizeof(struct rt0_hdr
));
535 hops
= ihdr
->rt_hdr
.hdrlen
>> 1;
538 memcpy(phdr
->addr
, ihdr
->addr
+ 1,
539 (hops
- 1) * sizeof(struct in6_addr
));
541 ipv6_addr_copy(phdr
->addr
+ (hops
- 1), *addr_p
);
542 *addr_p
= ihdr
->addr
;
544 phdr
->rt_hdr
.nexthdr
= *proto
;
545 *proto
= NEXTHDR_ROUTING
;
548 static void ipv6_push_exthdr(struct sk_buff
*skb
, u8
*proto
, u8 type
, struct ipv6_opt_hdr
*opt
)
550 struct ipv6_opt_hdr
*h
= (struct ipv6_opt_hdr
*)skb_push(skb
, ipv6_optlen(opt
));
552 memcpy(h
, opt
, ipv6_optlen(opt
));
557 void ipv6_push_nfrag_opts(struct sk_buff
*skb
, struct ipv6_txoptions
*opt
,
559 struct in6_addr
**daddr
)
562 ipv6_push_rthdr(skb
, proto
, opt
->srcrt
, daddr
);
564 * IPV6_RTHDRDSTOPTS is ignored
565 * unless IPV6_RTHDR is set (RFC3542).
568 ipv6_push_exthdr(skb
, proto
, NEXTHDR_DEST
, opt
->dst0opt
);
571 ipv6_push_exthdr(skb
, proto
, NEXTHDR_HOP
, opt
->hopopt
);
574 void ipv6_push_frag_opts(struct sk_buff
*skb
, struct ipv6_txoptions
*opt
, u8
*proto
)
577 ipv6_push_exthdr(skb
, proto
, NEXTHDR_DEST
, opt
->dst1opt
);
580 struct ipv6_txoptions
*
581 ipv6_dup_options(struct sock
*sk
, struct ipv6_txoptions
*opt
)
583 struct ipv6_txoptions
*opt2
;
585 opt2
= sock_kmalloc(sk
, opt
->tot_len
, GFP_ATOMIC
);
587 long dif
= (char*)opt2
- (char*)opt
;
588 memcpy(opt2
, opt
, opt
->tot_len
);
590 *((char**)&opt2
->hopopt
) += dif
;
592 *((char**)&opt2
->dst0opt
) += dif
;
594 *((char**)&opt2
->dst1opt
) += dif
;
596 *((char**)&opt2
->srcrt
) += dif
;
601 EXPORT_SYMBOL_GPL(ipv6_dup_options
);
603 static int ipv6_renew_option(void *ohdr
,
604 struct ipv6_opt_hdr __user
*newopt
, int newoptlen
,
606 struct ipv6_opt_hdr
**hdr
,
611 memcpy(*p
, ohdr
, ipv6_optlen((struct ipv6_opt_hdr
*)ohdr
));
612 *hdr
= (struct ipv6_opt_hdr
*)*p
;
613 *p
+= CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr
**)hdr
));
617 if (copy_from_user(*p
, newopt
, newoptlen
))
619 *hdr
= (struct ipv6_opt_hdr
*)*p
;
620 if (ipv6_optlen(*(struct ipv6_opt_hdr
**)hdr
) > newoptlen
)
622 *p
+= CMSG_ALIGN(newoptlen
);
628 struct ipv6_txoptions
*
629 ipv6_renew_options(struct sock
*sk
, struct ipv6_txoptions
*opt
,
631 struct ipv6_opt_hdr __user
*newopt
, int newoptlen
)
635 struct ipv6_txoptions
*opt2
;
638 if (newtype
!= IPV6_HOPOPTS
&& opt
->hopopt
)
639 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->hopopt
));
640 if (newtype
!= IPV6_RTHDRDSTOPTS
&& opt
->dst0opt
)
641 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->dst0opt
));
642 if (newtype
!= IPV6_RTHDR
&& opt
->srcrt
)
643 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->srcrt
));
644 if (newtype
!= IPV6_DSTOPTS
&& opt
->dst1opt
)
645 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->dst1opt
));
646 if (newopt
&& newoptlen
)
647 tot_len
+= CMSG_ALIGN(newoptlen
);
652 tot_len
+= sizeof(*opt2
);
653 opt2
= sock_kmalloc(sk
, tot_len
, GFP_ATOMIC
);
655 return ERR_PTR(-ENOBUFS
);
657 memset(opt2
, 0, tot_len
);
659 opt2
->tot_len
= tot_len
;
660 p
= (char *)(opt2
+ 1);
662 err
= ipv6_renew_option(opt
->hopopt
, newopt
, newoptlen
,
663 newtype
!= IPV6_HOPOPTS
,
668 err
= ipv6_renew_option(opt
->dst0opt
, newopt
, newoptlen
,
669 newtype
!= IPV6_RTHDRDSTOPTS
,
674 err
= ipv6_renew_option(opt
->srcrt
, newopt
, newoptlen
,
675 newtype
!= IPV6_RTHDR
,
676 (struct ipv6_opt_hdr
**)opt2
->srcrt
, &p
);
680 err
= ipv6_renew_option(opt
->dst1opt
, newopt
, newoptlen
,
681 newtype
!= IPV6_DSTOPTS
,
686 opt2
->opt_nflen
= (opt2
->hopopt
? ipv6_optlen(opt2
->hopopt
) : 0) +
687 (opt2
->dst0opt
? ipv6_optlen(opt2
->dst0opt
) : 0) +
688 (opt2
->srcrt
? ipv6_optlen(opt2
->srcrt
) : 0);
689 opt2
->opt_flen
= (opt2
->dst1opt
? ipv6_optlen(opt2
->dst1opt
) : 0);
693 sock_kfree_s(sk
, opt2
, opt2
->tot_len
);
697 struct ipv6_txoptions
*ipv6_fixup_options(struct ipv6_txoptions
*opt_space
,
698 struct ipv6_txoptions
*opt
)
701 * ignore the dest before srcrt unless srcrt is being included.
704 if (opt
&& opt
->dst0opt
&& !opt
->srcrt
) {
705 if (opt_space
!= opt
) {
706 memcpy(opt_space
, opt
, sizeof(*opt_space
));
709 opt
->opt_nflen
-= ipv6_optlen(opt
->dst0opt
);