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/net.h>
31 #include <linux/netdevice.h>
32 #include <linux/in6.h>
33 #include <linux/icmpv6.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)
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;
58 if (offset + 2 > packet_len)
60 hdr = (struct ipv6_opt_hdr *)(nh + offset);
61 len = ((hdr->hdrlen + 1) << 3);
63 if (offset + len > packet_len)
70 int opttype = nh[offset];
81 optlen = nh[offset + 1] + 2;
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 {
105 int (*func)(struct sk_buff **skbp, int offset);
108 /*********************
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) {
122 case 1: /* drop packet */
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))
131 case 2: /* send ICMP PARM PROB regardless and drop packet */
132 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
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))
157 int optlen = nh[off + 1] + 2;
167 default: /* Other TLV code so scan list */
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
175 if (curr->func(skbp, off) == 0)
180 if (curr->type < 0) {
181 if (ip6_tlvopt_unknown(skbp, off) == 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;
211 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
214 opt->dsthao = opt->dst1;
217 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
219 if (hao->length != 16) {
221 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
225 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
227 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
231 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
232 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
233 if (unlikely(ret < 0))
236 if (skb_cloned(skb)) {
237 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
238 struct inet6_skb_parm *opt2;
244 memcpy(opt2, opt, sizeof(*opt2));
248 /* update all variable using below by copied skbuff */
250 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
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);
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,
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)
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);
301 opt->lastopt = opt->dst1 = skb_network_header_len(skb);
302 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
306 dst = dst_clone(skb->dst);
307 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
310 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
312 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
315 opt->nhoff = opt->dst1;
320 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
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;
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 /********************************
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;
371 struct ipv6_rt_hdr *hdr;
372 struct rt0_hdr *rthdr;
373 int accept_source_route = ipv6_devconf.accept_source_route;
375 idev = in6_dev_get(skb->dev);
377 if (accept_source_route > idev->cnf.accept_source_route)
378 accept_source_route = idev->cnf.accept_source_route;
382 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
383 !pskb_may_pull(skb, (skb_transport_offset(skb) +
384 ((skb_transport_header(skb)[1] + 1) << 3)))) {
385 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
386 IPSTATS_MIB_INHDRERRORS);
391 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
393 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
394 skb->pkt_type != PACKET_HOST) {
395 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
396 IPSTATS_MIB_INADDRERRORS);
402 if (hdr->segments_left == 0) {
404 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
405 case IPV6_SRCRT_TYPE_2:
406 /* Silently discard type 2 header unless it was
410 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
411 IPSTATS_MIB_INADDRERRORS);
421 opt->lastopt = opt->srcrt = skb_network_header_len(skb);
422 skb->transport_header += (hdr->hdrlen + 1) << 3;
423 opt->dst0 = opt->dst1;
425 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
430 case IPV6_SRCRT_TYPE_0:
431 if (accept_source_route <= 0)
433 if (hdr->hdrlen & 0x01) {
434 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
435 IPSTATS_MIB_INHDRERRORS);
436 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
438 skb_network_header(skb)));
442 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
443 case IPV6_SRCRT_TYPE_2:
444 if (accept_source_route < 0)
446 /* Silently discard invalid RTH type 2 */
447 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
448 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
449 IPSTATS_MIB_INHDRERRORS);
460 * This is the routing header forwarding algorithm from
464 n = hdr->hdrlen >> 1;
466 if (hdr->segments_left > n) {
467 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
468 IPSTATS_MIB_INHDRERRORS);
469 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
470 ((&hdr->segments_left) -
471 skb_network_header(skb)));
475 /* We are about to mangle packet header. Be careful!
476 Do not damage packets queued somewhere.
478 if (skb_cloned(skb)) {
479 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
480 /* the copy is a forwarded packet */
482 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
483 IPSTATS_MIB_OUTDISCARDS);
490 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2);
493 if (skb->ip_summed == CHECKSUM_COMPLETE)
494 skb->ip_summed = CHECKSUM_NONE;
496 i = n - --hdr->segments_left;
498 rthdr = (struct rt0_hdr *) hdr;
503 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
504 case IPV6_SRCRT_TYPE_2:
505 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
506 (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
507 IPPROTO_ROUTING) < 0) {
508 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
509 IPSTATS_MIB_INADDRERRORS);
513 if (!ipv6_chk_home_addr(addr)) {
514 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
515 IPSTATS_MIB_INADDRERRORS);
525 if (ipv6_addr_is_multicast(addr)) {
526 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
527 IPSTATS_MIB_INADDRERRORS);
532 ipv6_addr_copy(&daddr, addr);
533 ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr);
534 ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr);
536 dst_release(xchg(&skb->dst, NULL));
537 ip6_route_input(skb);
538 if (skb->dst->error) {
539 skb_push(skb, skb->data - skb_network_header(skb));
544 if (skb->dst->dev->flags&IFF_LOOPBACK) {
545 if (ipv6_hdr(skb)->hop_limit <= 1) {
546 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
547 IPSTATS_MIB_INHDRERRORS);
548 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
553 ipv6_hdr(skb)->hop_limit--;
557 skb_push(skb, skb->data - skb_network_header(skb));
562 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
563 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
564 (&hdr->type) - skb_network_header(skb));
568 static struct inet6_protocol rthdr_protocol = {
569 .handler = ipv6_rthdr_rcv,
570 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
573 void __init ipv6_rthdr_init(void)
575 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
576 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
580 This function inverts received rthdr.
581 NOTE: specs allow to make it automatically only if
582 packet authenticated.
584 I will not discuss it here (though, I am really pissed off at
585 this stupid requirement making rthdr idea useless)
587 Actually, it creates severe problems for us.
588 Embryonic requests has no associated sockets,
589 so that user have no control over it and
590 cannot not only to set reply options, but
591 even to know, that someone wants to connect
594 For now we need to test the engine, so that I created
595 temporary (or permanent) backdoor.
596 If listening socket set IPV6_RTHDR to 2, then we invert header.
600 struct ipv6_txoptions *
601 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
605 [ H1 -> H2 -> ... H_prev ] daddr=ME
608 [ H_prev -> ... -> H1 ] daddr =sender
610 Note, that IP output engine will rewrite this rthdr
611 by rotating it left by one addr.
615 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
616 struct rt0_hdr *irthdr;
617 struct ipv6_txoptions *opt;
618 int hdrlen = ipv6_optlen(hdr);
620 if (hdr->segments_left ||
621 hdr->type != IPV6_SRCRT_TYPE_0 ||
625 n = hdr->hdrlen >> 1;
626 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
629 memset(opt, 0, sizeof(*opt));
630 opt->tot_len = sizeof(*opt) + hdrlen;
631 opt->srcrt = (void*)(opt+1);
632 opt->opt_nflen = hdrlen;
634 memcpy(opt->srcrt, hdr, sizeof(*hdr));
635 irthdr = (struct rt0_hdr*)opt->srcrt;
636 irthdr->reserved = 0;
637 opt->srcrt->segments_left = n;
639 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
643 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
645 /**********************************
647 **********************************/
650 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
652 static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
654 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
657 /* Router Alert as of RFC 2711 */
659 static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
661 struct sk_buff *skb = *skbp;
662 const unsigned char *nh = skb_network_header(skb);
664 if (nh[optoff + 1] == 2) {
665 IP6CB(skb)->ra = optoff;
668 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
676 static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
678 struct sk_buff *skb = *skbp;
679 const unsigned char *nh = skb_network_header(skb);
682 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
683 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
685 IP6_INC_STATS_BH(ipv6_skb_idev(skb),
686 IPSTATS_MIB_INHDRERRORS);
690 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
691 if (pkt_len <= IPV6_MAXPLEN) {
692 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
693 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
696 if (ipv6_hdr(skb)->payload_len) {
697 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
698 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
702 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
703 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
707 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
717 static struct tlvtype_proc tlvprochopopt_lst[] = {
719 .type = IPV6_TLV_ROUTERALERT,
723 .type = IPV6_TLV_JUMBO,
724 .func = ipv6_hop_jumbo,
729 int ipv6_parse_hopopts(struct sk_buff **skbp)
731 struct sk_buff *skb = *skbp;
732 struct inet6_skb_parm *opt = IP6CB(skb);
735 * skb_network_header(skb) is equal to skb->data, and
736 * skb_network_header_len(skb) is always equal to
737 * sizeof(struct ipv6hdr) by definition of
738 * hop-by-hop options.
740 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
741 !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
742 ((skb_transport_header(skb)[1] + 1) << 3)))) {
747 opt->hop = sizeof(struct ipv6hdr);
748 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
750 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
752 opt->nhoff = sizeof(struct ipv6hdr);
759 * Creating outbound headers.
761 * "build" functions work when skb is filled from head to tail (datagram)
762 * "push" functions work when headers are added from tail to head (tcp)
764 * In both cases we assume, that caller reserved enough room
768 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
769 struct ipv6_rt_hdr *opt,
770 struct in6_addr **addr_p)
772 struct rt0_hdr *phdr, *ihdr;
775 ihdr = (struct rt0_hdr *) opt;
777 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
778 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
780 hops = ihdr->rt_hdr.hdrlen >> 1;
783 memcpy(phdr->addr, ihdr->addr + 1,
784 (hops - 1) * sizeof(struct in6_addr));
786 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
787 *addr_p = ihdr->addr;
789 phdr->rt_hdr.nexthdr = *proto;
790 *proto = NEXTHDR_ROUTING;
793 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
795 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
797 memcpy(h, opt, ipv6_optlen(opt));
802 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
804 struct in6_addr **daddr)
807 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
809 * IPV6_RTHDRDSTOPTS is ignored
810 * unless IPV6_RTHDR is set (RFC3542).
813 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
816 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
819 EXPORT_SYMBOL(ipv6_push_nfrag_opts);
821 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
824 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
827 struct ipv6_txoptions *
828 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
830 struct ipv6_txoptions *opt2;
832 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
834 long dif = (char*)opt2 - (char*)opt;
835 memcpy(opt2, opt, opt->tot_len);
837 *((char**)&opt2->hopopt) += dif;
839 *((char**)&opt2->dst0opt) += dif;
841 *((char**)&opt2->dst1opt) += dif;
843 *((char**)&opt2->srcrt) += dif;
848 EXPORT_SYMBOL_GPL(ipv6_dup_options);
850 static int ipv6_renew_option(void *ohdr,
851 struct ipv6_opt_hdr __user *newopt, int newoptlen,
853 struct ipv6_opt_hdr **hdr,
858 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
859 *hdr = (struct ipv6_opt_hdr *)*p;
860 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
864 if (copy_from_user(*p, newopt, newoptlen))
866 *hdr = (struct ipv6_opt_hdr *)*p;
867 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
869 *p += CMSG_ALIGN(newoptlen);
875 struct ipv6_txoptions *
876 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
878 struct ipv6_opt_hdr __user *newopt, int newoptlen)
882 struct ipv6_txoptions *opt2;
886 if (newtype != IPV6_HOPOPTS && opt->hopopt)
887 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
888 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
889 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
890 if (newtype != IPV6_RTHDR && opt->srcrt)
891 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
892 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
893 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
896 if (newopt && newoptlen)
897 tot_len += CMSG_ALIGN(newoptlen);
902 tot_len += sizeof(*opt2);
903 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
905 return ERR_PTR(-ENOBUFS);
907 memset(opt2, 0, tot_len);
909 opt2->tot_len = tot_len;
910 p = (char *)(opt2 + 1);
912 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
913 newtype != IPV6_HOPOPTS,
918 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
919 newtype != IPV6_RTHDRDSTOPTS,
924 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
925 newtype != IPV6_RTHDR,
926 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
930 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
931 newtype != IPV6_DSTOPTS,
936 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
937 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
938 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
939 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
943 sock_kfree_s(sk, opt2, opt2->tot_len);
947 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
948 struct ipv6_txoptions *opt)
951 * ignore the dest before srcrt unless srcrt is being included.
954 if (opt && opt->dst0opt && !opt->srcrt) {
955 if (opt_space != opt) {
956 memcpy(opt_space, opt, sizeof(*opt_space));
959 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);