[NETFILTER]: x_tables: switch xt_match->match to bool
[linux-2.6/kvm.git] / net / ipv6 / exthdrs.c
blob173a4bb52255d57a9e7f2b105b95a52c32f1cda2
1 /*
2 * Extension Header handling for IPv6
3 * Linux INET6 implementation
5 * Authors:
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.
18 /* Changes:
19 * yoshfuji : ensure not to overrun while parsing
20 * tlv options.
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/net.h>
31 #include <linux/netdevice.h>
32 #include <linux/in6.h>
33 #include <linux/icmpv6.h>
35 #include <net/sock.h>
36 #include <net/snmp.h>
38 #include <net/ipv6.h>
39 #include <net/protocol.h>
40 #include <net/transp_v6.h>
41 #include <net/rawv6.h>
42 #include <net/ndisc.h>
43 #include <net/ip6_route.h>
44 #include <net/addrconf.h>
45 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
46 #include <net/xfrm.h>
47 #endif
49 #include <asm/uaccess.h>
51 int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
53 const unsigned char *nh = skb_network_header(skb);
54 int packet_len = skb->tail - skb->network_header;
55 struct ipv6_opt_hdr *hdr;
56 int len;
58 if (offset + 2 > packet_len)
59 goto bad;
60 hdr = (struct ipv6_opt_hdr *)(nh + offset);
61 len = ((hdr->hdrlen + 1) << 3);
63 if (offset + len > packet_len)
64 goto bad;
66 offset += 2;
67 len -= 2;
69 while (len > 0) {
70 int opttype = nh[offset];
71 int optlen;
73 if (opttype == type)
74 return offset;
76 switch (opttype) {
77 case IPV6_TLV_PAD0:
78 optlen = 1;
79 break;
80 default:
81 optlen = nh[offset + 1] + 2;
82 if (optlen > len)
83 goto bad;
84 break;
86 offset += optlen;
87 len -= optlen;
89 /* not_found */
90 bad:
91 return -1;
93 EXPORT_SYMBOL_GPL(ipv6_find_tlv);
96 * Parsing tlv encoded headers.
98 * Parsing function "func" returns 1, if parsing succeed
99 * and 0, if it failed.
100 * It MUST NOT touch skb->h.
103 struct tlvtype_proc {
104 int type;
105 int (*func)(struct sk_buff **skbp, int offset);
108 /*********************
109 Generic functions
110 *********************/
112 /* An unknown option is detected, decide what to do */
114 static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
116 struct sk_buff *skb = *skbp;
118 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
119 case 0: /* ignore */
120 return 1;
122 case 1: /* drop packet */
123 break;
125 case 3: /* Send ICMP if not a multicast address and drop packet */
126 /* Actually, it is redundant check. icmp_send
127 will recheck in any case.
129 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
130 break;
131 case 2: /* send ICMP PARM PROB regardless and drop packet */
132 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
133 return 0;
136 kfree_skb(skb);
137 return 0;
140 /* Parse tlv encoded option header (hop-by-hop or destination) */
142 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
144 struct sk_buff *skb = *skbp;
145 struct tlvtype_proc *curr;
146 const unsigned char *nh = skb_network_header(skb);
147 int off = skb_network_header_len(skb);
148 int len = (skb_transport_header(skb)[1] + 1) << 3;
150 if (skb_transport_offset(skb) + len > skb_headlen(skb))
151 goto bad;
153 off += 2;
154 len -= 2;
156 while (len > 0) {
157 int optlen = nh[off + 1] + 2;
159 switch (nh[off]) {
160 case IPV6_TLV_PAD0:
161 optlen = 1;
162 break;
164 case IPV6_TLV_PADN:
165 break;
167 default: /* Other TLV code so scan list */
168 if (optlen > len)
169 goto bad;
170 for (curr=procs; curr->type >= 0; curr++) {
171 if (curr->type == nh[off]) {
172 /* type specific length/alignment
173 checks will be performed in the
174 func(). */
175 if (curr->func(skbp, off) == 0)
176 return 0;
177 break;
180 if (curr->type < 0) {
181 if (ip6_tlvopt_unknown(skbp, off) == 0)
182 return 0;
184 break;
186 off += optlen;
187 len -= optlen;
189 if (len == 0)
190 return 1;
191 bad:
192 kfree_skb(skb);
193 return 0;
196 /*****************************
197 Destination options header.
198 *****************************/
200 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
201 static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
203 struct sk_buff *skb = *skbp;
204 struct ipv6_destopt_hao *hao;
205 struct inet6_skb_parm *opt = IP6CB(skb);
206 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
207 struct in6_addr tmp_addr;
208 int ret;
210 if (opt->dsthao) {
211 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
212 goto discard;
214 opt->dsthao = opt->dst1;
215 opt->dst1 = 0;
217 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
219 if (hao->length != 16) {
220 LIMIT_NETDEBUG(
221 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
222 goto discard;
225 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
226 LIMIT_NETDEBUG(
227 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
228 goto discard;
231 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
232 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
233 if (unlikely(ret < 0))
234 goto discard;
236 if (skb_cloned(skb)) {
237 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
238 struct inet6_skb_parm *opt2;
240 if (skb2 == NULL)
241 goto discard;
243 opt2 = IP6CB(skb2);
244 memcpy(opt2, opt, sizeof(*opt2));
246 kfree_skb(skb);
248 /* update all variable using below by copied skbuff */
249 *skbp = skb = skb2;
250 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
251 optoff);
252 ipv6h = ipv6_hdr(skb2);
255 if (skb->ip_summed == CHECKSUM_COMPLETE)
256 skb->ip_summed = CHECKSUM_NONE;
258 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
259 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
260 ipv6_addr_copy(&hao->addr, &tmp_addr);
262 if (skb->tstamp.tv64 == 0)
263 __net_timestamp(skb);
265 return 1;
267 discard:
268 kfree_skb(skb);
269 return 0;
271 #endif
273 static struct tlvtype_proc tlvprocdestopt_lst[] = {
274 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
276 .type = IPV6_TLV_HAO,
277 .func = ipv6_dest_hao,
279 #endif
280 {-1, NULL}
283 static int ipv6_destopt_rcv(struct sk_buff **skbp)
285 struct sk_buff *skb = *skbp;
286 struct inet6_skb_parm *opt = IP6CB(skb);
287 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
288 __u16 dstbuf;
289 #endif
290 struct dst_entry *dst;
292 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
293 !pskb_may_pull(skb, (skb_transport_offset(skb) +
294 ((skb_transport_header(skb)[1] + 1) << 3)))) {
295 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
296 IPSTATS_MIB_INHDRERRORS);
297 kfree_skb(skb);
298 return -1;
301 opt->lastopt = opt->dst1 = skb_network_header_len(skb);
302 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
303 dstbuf = opt->dst1;
304 #endif
306 dst = dst_clone(skb->dst);
307 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
308 dst_release(dst);
309 skb = *skbp;
310 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
311 opt = IP6CB(skb);
312 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
313 opt->nhoff = dstbuf;
314 #else
315 opt->nhoff = opt->dst1;
316 #endif
317 return 1;
320 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
321 dst_release(dst);
322 return -1;
325 static struct inet6_protocol destopt_protocol = {
326 .handler = ipv6_destopt_rcv,
327 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
330 void __init ipv6_destopt_init(void)
332 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
333 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
336 /********************************
337 NONE header. No data in packet.
338 ********************************/
340 static int ipv6_nodata_rcv(struct sk_buff **skbp)
342 struct sk_buff *skb = *skbp;
344 kfree_skb(skb);
345 return 0;
348 static struct inet6_protocol nodata_protocol = {
349 .handler = ipv6_nodata_rcv,
350 .flags = INET6_PROTO_NOPOLICY,
353 void __init ipv6_nodata_init(void)
355 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
356 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
359 /********************************
360 Routing header.
361 ********************************/
363 static int ipv6_rthdr_rcv(struct sk_buff **skbp)
365 struct sk_buff *skb = *skbp;
366 struct inet6_skb_parm *opt = IP6CB(skb);
367 struct in6_addr *addr = NULL;
368 struct in6_addr daddr;
369 struct inet6_dev *idev;
370 int n, i;
371 struct ipv6_rt_hdr *hdr;
372 struct rt0_hdr *rthdr;
373 int accept_source_route = ipv6_devconf.accept_source_route;
375 if (accept_source_route < 0 ||
376 ((idev = in6_dev_get(skb->dev)) == NULL)) {
377 kfree_skb(skb);
378 return -1;
380 if (idev->cnf.accept_source_route < 0) {
381 in6_dev_put(idev);
382 kfree_skb(skb);
383 return -1;
386 if (accept_source_route > idev->cnf.accept_source_route)
387 accept_source_route = idev->cnf.accept_source_route;
389 in6_dev_put(idev);
391 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
392 !pskb_may_pull(skb, (skb_transport_offset(skb) +
393 ((skb_transport_header(skb)[1] + 1) << 3)))) {
394 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
395 IPSTATS_MIB_INHDRERRORS);
396 kfree_skb(skb);
397 return -1;
400 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
402 switch (hdr->type) {
403 #ifdef CONFIG_IPV6_MIP6
404 case IPV6_SRCRT_TYPE_2:
405 break;
406 #endif
407 case IPV6_SRCRT_TYPE_0:
408 if (accept_source_route > 0)
409 break;
410 kfree_skb(skb);
411 return -1;
412 default:
413 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
414 IPSTATS_MIB_INHDRERRORS);
415 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
416 (&hdr->type) - skb_network_header(skb));
417 return -1;
420 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
421 skb->pkt_type != PACKET_HOST) {
422 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
423 IPSTATS_MIB_INADDRERRORS);
424 kfree_skb(skb);
425 return -1;
428 looped_back:
429 if (hdr->segments_left == 0) {
430 switch (hdr->type) {
431 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
432 case IPV6_SRCRT_TYPE_2:
433 /* Silently discard type 2 header unless it was
434 * processed by own
436 if (!addr) {
437 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
438 IPSTATS_MIB_INADDRERRORS);
439 kfree_skb(skb);
440 return -1;
442 break;
443 #endif
444 default:
445 break;
448 opt->lastopt = opt->srcrt = skb_network_header_len(skb);
449 skb->transport_header += (hdr->hdrlen + 1) << 3;
450 opt->dst0 = opt->dst1;
451 opt->dst1 = 0;
452 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
453 return 1;
456 switch (hdr->type) {
457 case IPV6_SRCRT_TYPE_0:
458 if (hdr->hdrlen & 0x01) {
459 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
460 IPSTATS_MIB_INHDRERRORS);
461 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
462 ((&hdr->hdrlen) -
463 skb_network_header(skb)));
464 return -1;
466 break;
467 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
468 case IPV6_SRCRT_TYPE_2:
469 /* Silently discard invalid RTH type 2 */
470 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
471 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
472 IPSTATS_MIB_INHDRERRORS);
473 kfree_skb(skb);
474 return -1;
476 break;
477 #endif
481 * This is the routing header forwarding algorithm from
482 * RFC 2460, page 16.
485 n = hdr->hdrlen >> 1;
487 if (hdr->segments_left > n) {
488 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
489 IPSTATS_MIB_INHDRERRORS);
490 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
491 ((&hdr->segments_left) -
492 skb_network_header(skb)));
493 return -1;
496 /* We are about to mangle packet header. Be careful!
497 Do not damage packets queued somewhere.
499 if (skb_cloned(skb)) {
500 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
501 /* the copy is a forwarded packet */
502 if (skb2 == NULL) {
503 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
504 IPSTATS_MIB_OUTDISCARDS);
505 kfree_skb(skb);
506 return -1;
508 kfree_skb(skb);
509 *skbp = skb = skb2;
510 opt = IP6CB(skb2);
511 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2);
514 if (skb->ip_summed == CHECKSUM_COMPLETE)
515 skb->ip_summed = CHECKSUM_NONE;
517 i = n - --hdr->segments_left;
519 rthdr = (struct rt0_hdr *) hdr;
520 addr = rthdr->addr;
521 addr += i - 1;
523 switch (hdr->type) {
524 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
525 case IPV6_SRCRT_TYPE_2:
526 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
527 (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
528 IPPROTO_ROUTING) < 0) {
529 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
530 IPSTATS_MIB_INADDRERRORS);
531 kfree_skb(skb);
532 return -1;
534 if (!ipv6_chk_home_addr(addr)) {
535 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
536 IPSTATS_MIB_INADDRERRORS);
537 kfree_skb(skb);
538 return -1;
540 break;
541 #endif
542 default:
543 break;
546 if (ipv6_addr_is_multicast(addr)) {
547 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
548 IPSTATS_MIB_INADDRERRORS);
549 kfree_skb(skb);
550 return -1;
553 ipv6_addr_copy(&daddr, addr);
554 ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr);
555 ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr);
557 dst_release(xchg(&skb->dst, NULL));
558 ip6_route_input(skb);
559 if (skb->dst->error) {
560 skb_push(skb, skb->data - skb_network_header(skb));
561 dst_input(skb);
562 return -1;
565 if (skb->dst->dev->flags&IFF_LOOPBACK) {
566 if (ipv6_hdr(skb)->hop_limit <= 1) {
567 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
568 IPSTATS_MIB_INHDRERRORS);
569 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
570 0, skb->dev);
571 kfree_skb(skb);
572 return -1;
574 ipv6_hdr(skb)->hop_limit--;
575 goto looped_back;
578 skb_push(skb, skb->data - skb_network_header(skb));
579 dst_input(skb);
580 return -1;
583 static struct inet6_protocol rthdr_protocol = {
584 .handler = ipv6_rthdr_rcv,
585 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
588 void __init ipv6_rthdr_init(void)
590 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
591 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
595 This function inverts received rthdr.
596 NOTE: specs allow to make it automatically only if
597 packet authenticated.
599 I will not discuss it here (though, I am really pissed off at
600 this stupid requirement making rthdr idea useless)
602 Actually, it creates severe problems for us.
603 Embryonic requests has no associated sockets,
604 so that user have no control over it and
605 cannot not only to set reply options, but
606 even to know, that someone wants to connect
607 without success. :-(
609 For now we need to test the engine, so that I created
610 temporary (or permanent) backdoor.
611 If listening socket set IPV6_RTHDR to 2, then we invert header.
612 --ANK (980729)
615 struct ipv6_txoptions *
616 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
618 /* Received rthdr:
620 [ H1 -> H2 -> ... H_prev ] daddr=ME
622 Inverted result:
623 [ H_prev -> ... -> H1 ] daddr =sender
625 Note, that IP output engine will rewrite this rthdr
626 by rotating it left by one addr.
629 int n, i;
630 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
631 struct rt0_hdr *irthdr;
632 struct ipv6_txoptions *opt;
633 int hdrlen = ipv6_optlen(hdr);
635 if (hdr->segments_left ||
636 hdr->type != IPV6_SRCRT_TYPE_0 ||
637 hdr->hdrlen & 0x01)
638 return NULL;
640 n = hdr->hdrlen >> 1;
641 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
642 if (opt == NULL)
643 return NULL;
644 memset(opt, 0, sizeof(*opt));
645 opt->tot_len = sizeof(*opt) + hdrlen;
646 opt->srcrt = (void*)(opt+1);
647 opt->opt_nflen = hdrlen;
649 memcpy(opt->srcrt, hdr, sizeof(*hdr));
650 irthdr = (struct rt0_hdr*)opt->srcrt;
651 irthdr->reserved = 0;
652 opt->srcrt->segments_left = n;
653 for (i=0; i<n; i++)
654 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
655 return opt;
658 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
660 /**********************************
661 Hop-by-hop options.
662 **********************************/
665 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
667 static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
669 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
672 /* Router Alert as of RFC 2711 */
674 static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
676 struct sk_buff *skb = *skbp;
677 const unsigned char *nh = skb_network_header(skb);
679 if (nh[optoff + 1] == 2) {
680 IP6CB(skb)->ra = optoff;
681 return 1;
683 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
684 nh[optoff + 1]);
685 kfree_skb(skb);
686 return 0;
689 /* Jumbo payload */
691 static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
693 struct sk_buff *skb = *skbp;
694 const unsigned char *nh = skb_network_header(skb);
695 u32 pkt_len;
697 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
698 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
699 nh[optoff+1]);
700 IP6_INC_STATS_BH(ipv6_skb_idev(skb),
701 IPSTATS_MIB_INHDRERRORS);
702 goto drop;
705 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
706 if (pkt_len <= IPV6_MAXPLEN) {
707 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
708 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
709 return 0;
711 if (ipv6_hdr(skb)->payload_len) {
712 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
713 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
714 return 0;
717 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
718 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
719 goto drop;
722 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
723 goto drop;
725 return 1;
727 drop:
728 kfree_skb(skb);
729 return 0;
732 static struct tlvtype_proc tlvprochopopt_lst[] = {
734 .type = IPV6_TLV_ROUTERALERT,
735 .func = ipv6_hop_ra,
738 .type = IPV6_TLV_JUMBO,
739 .func = ipv6_hop_jumbo,
741 { -1, }
744 int ipv6_parse_hopopts(struct sk_buff **skbp)
746 struct sk_buff *skb = *skbp;
747 struct inet6_skb_parm *opt = IP6CB(skb);
750 * skb_network_header(skb) is equal to skb->data, and
751 * skb_network_header_len(skb) is always equal to
752 * sizeof(struct ipv6hdr) by definition of
753 * hop-by-hop options.
755 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
756 !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
757 ((skb_transport_header(skb)[1] + 1) << 3)))) {
758 kfree_skb(skb);
759 return -1;
762 opt->hop = sizeof(struct ipv6hdr);
763 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
764 skb = *skbp;
765 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
766 opt = IP6CB(skb);
767 opt->nhoff = sizeof(struct ipv6hdr);
768 return 1;
770 return -1;
774 * Creating outbound headers.
776 * "build" functions work when skb is filled from head to tail (datagram)
777 * "push" functions work when headers are added from tail to head (tcp)
779 * In both cases we assume, that caller reserved enough room
780 * for headers.
783 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
784 struct ipv6_rt_hdr *opt,
785 struct in6_addr **addr_p)
787 struct rt0_hdr *phdr, *ihdr;
788 int hops;
790 ihdr = (struct rt0_hdr *) opt;
792 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
793 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
795 hops = ihdr->rt_hdr.hdrlen >> 1;
797 if (hops > 1)
798 memcpy(phdr->addr, ihdr->addr + 1,
799 (hops - 1) * sizeof(struct in6_addr));
801 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
802 *addr_p = ihdr->addr;
804 phdr->rt_hdr.nexthdr = *proto;
805 *proto = NEXTHDR_ROUTING;
808 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
810 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
812 memcpy(h, opt, ipv6_optlen(opt));
813 h->nexthdr = *proto;
814 *proto = type;
817 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
818 u8 *proto,
819 struct in6_addr **daddr)
821 if (opt->srcrt) {
822 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
824 * IPV6_RTHDRDSTOPTS is ignored
825 * unless IPV6_RTHDR is set (RFC3542).
827 if (opt->dst0opt)
828 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
830 if (opt->hopopt)
831 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
834 EXPORT_SYMBOL(ipv6_push_nfrag_opts);
836 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
838 if (opt->dst1opt)
839 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
842 struct ipv6_txoptions *
843 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
845 struct ipv6_txoptions *opt2;
847 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
848 if (opt2) {
849 long dif = (char*)opt2 - (char*)opt;
850 memcpy(opt2, opt, opt->tot_len);
851 if (opt2->hopopt)
852 *((char**)&opt2->hopopt) += dif;
853 if (opt2->dst0opt)
854 *((char**)&opt2->dst0opt) += dif;
855 if (opt2->dst1opt)
856 *((char**)&opt2->dst1opt) += dif;
857 if (opt2->srcrt)
858 *((char**)&opt2->srcrt) += dif;
860 return opt2;
863 EXPORT_SYMBOL_GPL(ipv6_dup_options);
865 static int ipv6_renew_option(void *ohdr,
866 struct ipv6_opt_hdr __user *newopt, int newoptlen,
867 int inherit,
868 struct ipv6_opt_hdr **hdr,
869 char **p)
871 if (inherit) {
872 if (ohdr) {
873 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
874 *hdr = (struct ipv6_opt_hdr *)*p;
875 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
877 } else {
878 if (newopt) {
879 if (copy_from_user(*p, newopt, newoptlen))
880 return -EFAULT;
881 *hdr = (struct ipv6_opt_hdr *)*p;
882 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
883 return -EINVAL;
884 *p += CMSG_ALIGN(newoptlen);
887 return 0;
890 struct ipv6_txoptions *
891 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
892 int newtype,
893 struct ipv6_opt_hdr __user *newopt, int newoptlen)
895 int tot_len = 0;
896 char *p;
897 struct ipv6_txoptions *opt2;
898 int err;
900 if (opt) {
901 if (newtype != IPV6_HOPOPTS && opt->hopopt)
902 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
903 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
904 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
905 if (newtype != IPV6_RTHDR && opt->srcrt)
906 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
907 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
908 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
911 if (newopt && newoptlen)
912 tot_len += CMSG_ALIGN(newoptlen);
914 if (!tot_len)
915 return NULL;
917 tot_len += sizeof(*opt2);
918 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
919 if (!opt2)
920 return ERR_PTR(-ENOBUFS);
922 memset(opt2, 0, tot_len);
924 opt2->tot_len = tot_len;
925 p = (char *)(opt2 + 1);
927 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
928 newtype != IPV6_HOPOPTS,
929 &opt2->hopopt, &p);
930 if (err)
931 goto out;
933 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
934 newtype != IPV6_RTHDRDSTOPTS,
935 &opt2->dst0opt, &p);
936 if (err)
937 goto out;
939 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
940 newtype != IPV6_RTHDR,
941 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
942 if (err)
943 goto out;
945 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
946 newtype != IPV6_DSTOPTS,
947 &opt2->dst1opt, &p);
948 if (err)
949 goto out;
951 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
952 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
953 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
954 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
956 return opt2;
957 out:
958 sock_kfree_s(sk, opt2, opt2->tot_len);
959 return ERR_PTR(err);
962 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
963 struct ipv6_txoptions *opt)
966 * ignore the dest before srcrt unless srcrt is being included.
967 * --yoshfuji
969 if (opt && opt->dst0opt && !opt->srcrt) {
970 if (opt_space != opt) {
971 memcpy(opt_space, opt, sizeof(*opt_space));
972 opt = opt_space;
974 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
975 opt->dst0opt = NULL;
978 return opt;