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 #ifdef CONFIG_IPV6_MIP6
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 - nh;
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;
95 * Parsing tlv encoded headers.
97 * Parsing function "func" returns 1, if parsing succeed
98 * and 0, if it failed.
99 * It MUST NOT touch skb->h.
102 struct tlvtype_proc {
104 int (*func)(struct sk_buff **skbp, int offset);
107 /*********************
109 *********************/
111 /* An unknown option is detected, decide what to do */
113 static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
115 struct sk_buff *skb = *skbp;
117 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
121 case 1: /* drop packet */
124 case 3: /* Send ICMP if not a multicast address and drop packet */
125 /* Actually, it is redundant check. icmp_send
126 will recheck in any case.
128 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
130 case 2: /* send ICMP PARM PROB regardless and drop packet */
131 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
139 /* Parse tlv encoded option header (hop-by-hop or destination) */
141 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
143 struct sk_buff *skb = *skbp;
144 struct tlvtype_proc *curr;
145 const unsigned char *nh = skb_network_header(skb);
146 int off = skb->h.raw - skb->nh.raw;
147 int len = ((skb->h.raw[1]+1)<<3);
149 if (skb_transport_offset(skb) + len > skb_headlen(skb))
156 int optlen = nh[off + 1] + 2;
166 default: /* Other TLV code so scan list */
169 for (curr=procs; curr->type >= 0; curr++) {
170 if (curr->type == nh[off]) {
171 /* type specific length/alignment
172 checks will be performed in the
174 if (curr->func(skbp, off) == 0)
179 if (curr->type < 0) {
180 if (ip6_tlvopt_unknown(skbp, off) == 0)
195 /*****************************
196 Destination options header.
197 *****************************/
199 #ifdef CONFIG_IPV6_MIP6
200 static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
202 struct sk_buff *skb = *skbp;
203 struct ipv6_destopt_hao *hao;
204 struct inet6_skb_parm *opt = IP6CB(skb);
205 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
206 struct in6_addr tmp_addr;
210 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
213 opt->dsthao = opt->dst1;
216 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
218 if (hao->length != 16) {
220 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
224 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
226 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
230 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
231 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
232 if (unlikely(ret < 0))
235 if (skb_cloned(skb)) {
236 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
237 struct inet6_skb_parm *opt2;
243 memcpy(opt2, opt, sizeof(*opt2));
247 /* update all variable using below by copied skbuff */
249 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
251 ipv6h = ipv6_hdr(skb2);
254 if (skb->ip_summed == CHECKSUM_COMPLETE)
255 skb->ip_summed = CHECKSUM_NONE;
257 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
258 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
259 ipv6_addr_copy(&hao->addr, &tmp_addr);
261 if (skb->tstamp.tv64 == 0)
262 __net_timestamp(skb);
272 static struct tlvtype_proc tlvprocdestopt_lst[] = {
273 #ifdef CONFIG_IPV6_MIP6
275 .type = IPV6_TLV_HAO,
276 .func = ipv6_dest_hao,
282 static int ipv6_destopt_rcv(struct sk_buff **skbp)
284 struct sk_buff *skb = *skbp;
285 struct inet6_skb_parm *opt = IP6CB(skb);
286 #ifdef CONFIG_IPV6_MIP6
289 struct dst_entry *dst;
291 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
292 !pskb_may_pull(skb, (skb_transport_offset(skb) +
293 ((skb->h.raw[1] + 1) << 3)))) {
294 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
295 IPSTATS_MIB_INHDRERRORS);
300 opt->lastopt = skb->h.raw - skb->nh.raw;
301 opt->dst1 = skb->h.raw - skb->nh.raw;
302 #ifdef CONFIG_IPV6_MIP6
306 dst = dst_clone(skb->dst);
307 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
310 skb->h.raw += ((skb->h.raw[1]+1)<<3);
312 #ifdef CONFIG_IPV6_MIP6
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 if (accept_source_route < 0 ||
376 ((idev = in6_dev_get(skb->dev)) == NULL)) {
380 if (idev->cnf.accept_source_route < 0) {
386 if (accept_source_route > idev->cnf.accept_source_route)
387 accept_source_route = idev->cnf.accept_source_route;
391 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
392 !pskb_may_pull(skb, (skb_transport_offset(skb) +
393 ((skb->h.raw[1] + 1) << 3)))) {
394 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
395 IPSTATS_MIB_INHDRERRORS);
400 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
403 #ifdef CONFIG_IPV6_MIP6
406 case IPV6_SRCRT_TYPE_0:
407 if (accept_source_route > 0)
412 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
413 IPSTATS_MIB_INHDRERRORS);
414 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
415 (&hdr->type) - skb_network_header(skb));
419 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
420 skb->pkt_type != PACKET_HOST) {
421 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
422 IPSTATS_MIB_INADDRERRORS);
428 if (hdr->segments_left == 0) {
430 #ifdef CONFIG_IPV6_MIP6
431 case IPV6_SRCRT_TYPE_2:
432 /* Silently discard type 2 header unless it was
436 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
437 IPSTATS_MIB_INADDRERRORS);
447 opt->lastopt = skb->h.raw - skb->nh.raw;
448 opt->srcrt = skb->h.raw - skb->nh.raw;
449 skb->h.raw += (hdr->hdrlen + 1) << 3;
450 opt->dst0 = opt->dst1;
452 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
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,
463 skb_network_header(skb)));
467 #ifdef CONFIG_IPV6_MIP6
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);
481 * This is the routing header forwarding algorithm from
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)));
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 */
503 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
504 IPSTATS_MIB_OUTDISCARDS);
511 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
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;
524 #ifdef CONFIG_IPV6_MIP6
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);
534 if (!ipv6_chk_home_addr(addr)) {
535 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
536 IPSTATS_MIB_INADDRERRORS);
546 if (ipv6_addr_is_multicast(addr)) {
547 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
548 IPSTATS_MIB_INADDRERRORS);
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));
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,
574 ipv6_hdr(skb)->hop_limit--;
578 skb_push(skb, skb->data - skb_network_header(skb));
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
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.
615 struct ipv6_txoptions *
616 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
620 [ H1 -> H2 -> ... H_prev ] daddr=ME
623 [ H_prev -> ... -> H1 ] daddr =sender
625 Note, that IP output engine will rewrite this rthdr
626 by rotating it left by one addr.
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 ||
640 n = hdr->hdrlen >> 1;
641 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
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;
654 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
658 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
660 /**********************************
662 **********************************/
664 /* Router Alert as of RFC 2711 */
666 static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
668 struct sk_buff *skb = *skbp;
669 const unsigned char *nh = skb_network_header(skb);
671 if (nh[optoff + 1] == 2) {
672 IP6CB(skb)->ra = optoff;
675 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
683 static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
685 struct sk_buff *skb = *skbp;
686 const unsigned char *nh = skb_network_header(skb);
689 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
690 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
692 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
693 IPSTATS_MIB_INHDRERRORS);
697 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
698 if (pkt_len <= IPV6_MAXPLEN) {
699 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
700 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
703 if (ipv6_hdr(skb)->payload_len) {
704 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
705 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
709 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
710 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
714 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
724 static struct tlvtype_proc tlvprochopopt_lst[] = {
726 .type = IPV6_TLV_ROUTERALERT,
730 .type = IPV6_TLV_JUMBO,
731 .func = ipv6_hop_jumbo,
736 int ipv6_parse_hopopts(struct sk_buff **skbp)
738 struct sk_buff *skb = *skbp;
739 struct inet6_skb_parm *opt = IP6CB(skb);
742 * skb_network_header(skb) is equal to skb->data, and
743 * skb->h.raw - skb->nh.raw is always equal to
744 * sizeof(struct ipv6hdr) by definition of
745 * hop-by-hop options.
747 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
748 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
753 opt->hop = sizeof(struct ipv6hdr);
754 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
756 skb->h.raw += (skb->h.raw[1]+1)<<3;
758 opt->nhoff = sizeof(struct ipv6hdr);
765 * Creating outbound headers.
767 * "build" functions work when skb is filled from head to tail (datagram)
768 * "push" functions work when headers are added from tail to head (tcp)
770 * In both cases we assume, that caller reserved enough room
774 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
775 struct ipv6_rt_hdr *opt,
776 struct in6_addr **addr_p)
778 struct rt0_hdr *phdr, *ihdr;
781 ihdr = (struct rt0_hdr *) opt;
783 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
784 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
786 hops = ihdr->rt_hdr.hdrlen >> 1;
789 memcpy(phdr->addr, ihdr->addr + 1,
790 (hops - 1) * sizeof(struct in6_addr));
792 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
793 *addr_p = ihdr->addr;
795 phdr->rt_hdr.nexthdr = *proto;
796 *proto = NEXTHDR_ROUTING;
799 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
801 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
803 memcpy(h, opt, ipv6_optlen(opt));
808 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
810 struct in6_addr **daddr)
813 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
815 * IPV6_RTHDRDSTOPTS is ignored
816 * unless IPV6_RTHDR is set (RFC3542).
819 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
822 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
825 EXPORT_SYMBOL(ipv6_push_nfrag_opts);
827 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
830 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
833 struct ipv6_txoptions *
834 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
836 struct ipv6_txoptions *opt2;
838 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
840 long dif = (char*)opt2 - (char*)opt;
841 memcpy(opt2, opt, opt->tot_len);
843 *((char**)&opt2->hopopt) += dif;
845 *((char**)&opt2->dst0opt) += dif;
847 *((char**)&opt2->dst1opt) += dif;
849 *((char**)&opt2->srcrt) += dif;
854 EXPORT_SYMBOL_GPL(ipv6_dup_options);
856 static int ipv6_renew_option(void *ohdr,
857 struct ipv6_opt_hdr __user *newopt, int newoptlen,
859 struct ipv6_opt_hdr **hdr,
864 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
865 *hdr = (struct ipv6_opt_hdr *)*p;
866 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
870 if (copy_from_user(*p, newopt, newoptlen))
872 *hdr = (struct ipv6_opt_hdr *)*p;
873 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
875 *p += CMSG_ALIGN(newoptlen);
881 struct ipv6_txoptions *
882 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
884 struct ipv6_opt_hdr __user *newopt, int newoptlen)
888 struct ipv6_txoptions *opt2;
892 if (newtype != IPV6_HOPOPTS && opt->hopopt)
893 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
894 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
895 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
896 if (newtype != IPV6_RTHDR && opt->srcrt)
897 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
898 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
899 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
902 if (newopt && newoptlen)
903 tot_len += CMSG_ALIGN(newoptlen);
908 tot_len += sizeof(*opt2);
909 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
911 return ERR_PTR(-ENOBUFS);
913 memset(opt2, 0, tot_len);
915 opt2->tot_len = tot_len;
916 p = (char *)(opt2 + 1);
918 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
919 newtype != IPV6_HOPOPTS,
924 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
925 newtype != IPV6_RTHDRDSTOPTS,
930 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
931 newtype != IPV6_RTHDR,
932 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
936 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
937 newtype != IPV6_DSTOPTS,
942 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
943 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
944 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
945 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
949 sock_kfree_s(sk, opt2, opt2->tot_len);
953 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
954 struct ipv6_txoptions *opt)
957 * ignore the dest before srcrt unless srcrt is being included.
960 if (opt && opt->dst0opt && !opt->srcrt) {
961 if (opt_space != opt) {
962 memcpy(opt_space, opt, sizeof(*opt_space));
965 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);