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 int packet_len
= skb
->tail
- skb
->nh
.raw
;
54 struct ipv6_opt_hdr
*hdr
;
57 if (offset
+ 2 > packet_len
)
59 hdr
= (struct ipv6_opt_hdr
*)(skb
->nh
.raw
+ offset
);
60 len
= ((hdr
->hdrlen
+ 1) << 3);
62 if (offset
+ len
> packet_len
)
69 int opttype
= skb
->nh
.raw
[offset
];
80 optlen
= skb
->nh
.raw
[offset
+ 1] + 2;
94 * Parsing tlv encoded headers.
96 * Parsing function "func" returns 1, if parsing succeed
97 * and 0, if it failed.
98 * It MUST NOT touch skb->h.
101 struct tlvtype_proc
{
103 int (*func
)(struct sk_buff
**skbp
, int offset
);
106 /*********************
108 *********************/
110 /* An unknown option is detected, decide what to do */
112 static int ip6_tlvopt_unknown(struct sk_buff
**skbp
, int optoff
)
114 struct sk_buff
*skb
= *skbp
;
116 switch ((skb
->nh
.raw
[optoff
] & 0xC0) >> 6) {
120 case 1: /* drop packet */
123 case 3: /* Send ICMP if not a multicast address and drop packet */
124 /* Actually, it is redundant check. icmp_send
125 will recheck in any case.
127 if (ipv6_addr_is_multicast(&skb
->nh
.ipv6h
->daddr
))
129 case 2: /* send ICMP PARM PROB regardless and drop packet */
130 icmpv6_param_prob(skb
, ICMPV6_UNK_OPTION
, optoff
);
138 /* Parse tlv encoded option header (hop-by-hop or destination) */
140 static int ip6_parse_tlv(struct tlvtype_proc
*procs
, struct sk_buff
**skbp
)
142 struct sk_buff
*skb
= *skbp
;
143 struct tlvtype_proc
*curr
;
144 int off
= skb
->h
.raw
- skb
->nh
.raw
;
145 int len
= ((skb
->h
.raw
[1]+1)<<3);
147 if ((skb
->h
.raw
+ len
) - skb
->data
> skb_headlen(skb
))
154 int optlen
= skb
->nh
.raw
[off
+1]+2;
156 switch (skb
->nh
.raw
[off
]) {
164 default: /* Other TLV code so scan list */
167 for (curr
=procs
; curr
->type
>= 0; curr
++) {
168 if (curr
->type
== skb
->nh
.raw
[off
]) {
169 /* type specific length/alignment
170 checks will be performed in the
172 if (curr
->func(skbp
, off
) == 0)
177 if (curr
->type
< 0) {
178 if (ip6_tlvopt_unknown(skbp
, off
) == 0)
193 /*****************************
194 Destination options header.
195 *****************************/
197 #ifdef CONFIG_IPV6_MIP6
198 static int ipv6_dest_hao(struct sk_buff
**skbp
, int optoff
)
200 struct sk_buff
*skb
= *skbp
;
201 struct ipv6_destopt_hao
*hao
;
202 struct inet6_skb_parm
*opt
= IP6CB(skb
);
203 struct ipv6hdr
*ipv6h
= (struct ipv6hdr
*)skb
->nh
.raw
;
204 struct in6_addr tmp_addr
;
208 LIMIT_NETDEBUG(KERN_DEBUG
"hao duplicated\n");
211 opt
->dsthao
= opt
->dst1
;
214 hao
= (struct ipv6_destopt_hao
*)(skb
->nh
.raw
+ optoff
);
216 if (hao
->length
!= 16) {
218 KERN_DEBUG
"hao invalid option length = %d\n", hao
->length
);
222 if (!(ipv6_addr_type(&hao
->addr
) & IPV6_ADDR_UNICAST
)) {
224 KERN_DEBUG
"hao is not an unicast addr: " NIP6_FMT
"\n", NIP6(hao
->addr
));
228 ret
= xfrm6_input_addr(skb
, (xfrm_address_t
*)&ipv6h
->daddr
,
229 (xfrm_address_t
*)&hao
->addr
, IPPROTO_DSTOPTS
);
230 if (unlikely(ret
< 0))
233 if (skb_cloned(skb
)) {
234 struct sk_buff
*skb2
= skb_copy(skb
, GFP_ATOMIC
);
235 struct inet6_skb_parm
*opt2
;
241 memcpy(opt2
, opt
, sizeof(*opt2
));
245 /* update all variable using below by copied skbuff */
247 hao
= (struct ipv6_destopt_hao
*)(skb2
->nh
.raw
+ optoff
);
248 ipv6h
= (struct ipv6hdr
*)skb2
->nh
.raw
;
251 if (skb
->ip_summed
== CHECKSUM_COMPLETE
)
252 skb
->ip_summed
= CHECKSUM_NONE
;
254 ipv6_addr_copy(&tmp_addr
, &ipv6h
->saddr
);
255 ipv6_addr_copy(&ipv6h
->saddr
, &hao
->addr
);
256 ipv6_addr_copy(&hao
->addr
, &tmp_addr
);
258 if (skb
->tstamp
.off_sec
== 0)
259 __net_timestamp(skb
);
269 static struct tlvtype_proc tlvprocdestopt_lst
[] = {
270 #ifdef CONFIG_IPV6_MIP6
272 .type
= IPV6_TLV_HAO
,
273 .func
= ipv6_dest_hao
,
279 static int ipv6_destopt_rcv(struct sk_buff
**skbp
)
281 struct sk_buff
*skb
= *skbp
;
282 struct inet6_skb_parm
*opt
= IP6CB(skb
);
283 #ifdef CONFIG_IPV6_MIP6
286 struct dst_entry
*dst
;
288 if (!pskb_may_pull(skb
, (skb
->h
.raw
-skb
->data
)+8) ||
289 !pskb_may_pull(skb
, (skb
->h
.raw
-skb
->data
)+((skb
->h
.raw
[1]+1)<<3))) {
290 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
291 IPSTATS_MIB_INHDRERRORS
);
296 opt
->lastopt
= skb
->h
.raw
- skb
->nh
.raw
;
297 opt
->dst1
= skb
->h
.raw
- skb
->nh
.raw
;
298 #ifdef CONFIG_IPV6_MIP6
302 dst
= dst_clone(skb
->dst
);
303 if (ip6_parse_tlv(tlvprocdestopt_lst
, skbp
)) {
306 skb
->h
.raw
+= ((skb
->h
.raw
[1]+1)<<3);
308 #ifdef CONFIG_IPV6_MIP6
311 opt
->nhoff
= opt
->dst1
;
316 IP6_INC_STATS_BH(ip6_dst_idev(dst
), IPSTATS_MIB_INHDRERRORS
);
321 static struct inet6_protocol destopt_protocol
= {
322 .handler
= ipv6_destopt_rcv
,
323 .flags
= INET6_PROTO_NOPOLICY
| INET6_PROTO_GSO_EXTHDR
,
326 void __init
ipv6_destopt_init(void)
328 if (inet6_add_protocol(&destopt_protocol
, IPPROTO_DSTOPTS
) < 0)
329 printk(KERN_ERR
"ipv6_destopt_init: Could not register protocol\n");
332 /********************************
333 NONE header. No data in packet.
334 ********************************/
336 static int ipv6_nodata_rcv(struct sk_buff
**skbp
)
338 struct sk_buff
*skb
= *skbp
;
344 static struct inet6_protocol nodata_protocol
= {
345 .handler
= ipv6_nodata_rcv
,
346 .flags
= INET6_PROTO_NOPOLICY
,
349 void __init
ipv6_nodata_init(void)
351 if (inet6_add_protocol(&nodata_protocol
, IPPROTO_NONE
) < 0)
352 printk(KERN_ERR
"ipv6_nodata_init: Could not register protocol\n");
355 /********************************
357 ********************************/
359 static int ipv6_rthdr_rcv(struct sk_buff
**skbp
)
361 struct sk_buff
*skb
= *skbp
;
362 struct inet6_skb_parm
*opt
= IP6CB(skb
);
363 struct in6_addr
*addr
= NULL
;
364 struct in6_addr daddr
;
367 struct ipv6_rt_hdr
*hdr
;
368 struct rt0_hdr
*rthdr
;
370 if (!pskb_may_pull(skb
, (skb
->h
.raw
-skb
->data
)+8) ||
371 !pskb_may_pull(skb
, (skb
->h
.raw
-skb
->data
)+((skb
->h
.raw
[1]+1)<<3))) {
372 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
373 IPSTATS_MIB_INHDRERRORS
);
378 hdr
= (struct ipv6_rt_hdr
*) skb
->h
.raw
;
380 if (ipv6_addr_is_multicast(&skb
->nh
.ipv6h
->daddr
) ||
381 skb
->pkt_type
!= PACKET_HOST
) {
382 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
383 IPSTATS_MIB_INADDRERRORS
);
389 if (hdr
->segments_left
== 0) {
391 #ifdef CONFIG_IPV6_MIP6
392 case IPV6_SRCRT_TYPE_2
:
393 /* Silently discard type 2 header unless it was
397 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
398 IPSTATS_MIB_INADDRERRORS
);
408 opt
->lastopt
= skb
->h
.raw
- skb
->nh
.raw
;
409 opt
->srcrt
= skb
->h
.raw
- skb
->nh
.raw
;
410 skb
->h
.raw
+= (hdr
->hdrlen
+ 1) << 3;
411 opt
->dst0
= opt
->dst1
;
413 opt
->nhoff
= (&hdr
->nexthdr
) - skb
->nh
.raw
;
418 case IPV6_SRCRT_TYPE_0
:
419 if (hdr
->hdrlen
& 0x01) {
420 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
421 IPSTATS_MIB_INHDRERRORS
);
422 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, (&hdr
->hdrlen
) - skb
->nh
.raw
);
426 #ifdef CONFIG_IPV6_MIP6
427 case IPV6_SRCRT_TYPE_2
:
428 /* Silently discard invalid RTH type 2 */
429 if (hdr
->hdrlen
!= 2 || hdr
->segments_left
!= 1) {
430 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
431 IPSTATS_MIB_INHDRERRORS
);
438 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
439 IPSTATS_MIB_INHDRERRORS
);
440 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, (&hdr
->type
) - skb
->nh
.raw
);
445 * This is the routing header forwarding algorithm from
449 n
= hdr
->hdrlen
>> 1;
451 if (hdr
->segments_left
> n
) {
452 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
453 IPSTATS_MIB_INHDRERRORS
);
454 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, (&hdr
->segments_left
) - skb
->nh
.raw
);
458 /* We are about to mangle packet header. Be careful!
459 Do not damage packets queued somewhere.
461 if (skb_cloned(skb
)) {
462 struct sk_buff
*skb2
= skb_copy(skb
, GFP_ATOMIC
);
463 /* the copy is a forwarded packet */
465 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
466 IPSTATS_MIB_OUTDISCARDS
);
473 hdr
= (struct ipv6_rt_hdr
*) skb2
->h
.raw
;
476 if (skb
->ip_summed
== CHECKSUM_COMPLETE
)
477 skb
->ip_summed
= CHECKSUM_NONE
;
479 i
= n
- --hdr
->segments_left
;
481 rthdr
= (struct rt0_hdr
*) hdr
;
486 #ifdef CONFIG_IPV6_MIP6
487 case IPV6_SRCRT_TYPE_2
:
488 if (xfrm6_input_addr(skb
, (xfrm_address_t
*)addr
,
489 (xfrm_address_t
*)&skb
->nh
.ipv6h
->saddr
,
490 IPPROTO_ROUTING
) < 0) {
491 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
492 IPSTATS_MIB_INADDRERRORS
);
496 if (!ipv6_chk_home_addr(addr
)) {
497 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
498 IPSTATS_MIB_INADDRERRORS
);
508 if (ipv6_addr_is_multicast(addr
)) {
509 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
510 IPSTATS_MIB_INADDRERRORS
);
515 ipv6_addr_copy(&daddr
, addr
);
516 ipv6_addr_copy(addr
, &skb
->nh
.ipv6h
->daddr
);
517 ipv6_addr_copy(&skb
->nh
.ipv6h
->daddr
, &daddr
);
519 dst_release(xchg(&skb
->dst
, NULL
));
520 ip6_route_input(skb
);
521 if (skb
->dst
->error
) {
522 skb_push(skb
, skb
->data
- skb
->nh
.raw
);
527 if (skb
->dst
->dev
->flags
&IFF_LOOPBACK
) {
528 if (skb
->nh
.ipv6h
->hop_limit
<= 1) {
529 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
530 IPSTATS_MIB_INHDRERRORS
);
531 icmpv6_send(skb
, ICMPV6_TIME_EXCEED
, ICMPV6_EXC_HOPLIMIT
,
536 skb
->nh
.ipv6h
->hop_limit
--;
540 skb_push(skb
, skb
->data
- skb
->nh
.raw
);
545 static struct inet6_protocol rthdr_protocol
= {
546 .handler
= ipv6_rthdr_rcv
,
547 .flags
= INET6_PROTO_NOPOLICY
| INET6_PROTO_GSO_EXTHDR
,
550 void __init
ipv6_rthdr_init(void)
552 if (inet6_add_protocol(&rthdr_protocol
, IPPROTO_ROUTING
) < 0)
553 printk(KERN_ERR
"ipv6_rthdr_init: Could not register protocol\n");
557 This function inverts received rthdr.
558 NOTE: specs allow to make it automatically only if
559 packet authenticated.
561 I will not discuss it here (though, I am really pissed off at
562 this stupid requirement making rthdr idea useless)
564 Actually, it creates severe problems for us.
565 Embryonic requests has no associated sockets,
566 so that user have no control over it and
567 cannot not only to set reply options, but
568 even to know, that someone wants to connect
571 For now we need to test the engine, so that I created
572 temporary (or permanent) backdoor.
573 If listening socket set IPV6_RTHDR to 2, then we invert header.
577 struct ipv6_txoptions
*
578 ipv6_invert_rthdr(struct sock
*sk
, struct ipv6_rt_hdr
*hdr
)
582 [ H1 -> H2 -> ... H_prev ] daddr=ME
585 [ H_prev -> ... -> H1 ] daddr =sender
587 Note, that IP output engine will rewrite this rthdr
588 by rotating it left by one addr.
592 struct rt0_hdr
*rthdr
= (struct rt0_hdr
*)hdr
;
593 struct rt0_hdr
*irthdr
;
594 struct ipv6_txoptions
*opt
;
595 int hdrlen
= ipv6_optlen(hdr
);
597 if (hdr
->segments_left
||
598 hdr
->type
!= IPV6_SRCRT_TYPE_0
||
602 n
= hdr
->hdrlen
>> 1;
603 opt
= sock_kmalloc(sk
, sizeof(*opt
) + hdrlen
, GFP_ATOMIC
);
606 memset(opt
, 0, sizeof(*opt
));
607 opt
->tot_len
= sizeof(*opt
) + hdrlen
;
608 opt
->srcrt
= (void*)(opt
+1);
609 opt
->opt_nflen
= hdrlen
;
611 memcpy(opt
->srcrt
, hdr
, sizeof(*hdr
));
612 irthdr
= (struct rt0_hdr
*)opt
->srcrt
;
613 irthdr
->reserved
= 0;
614 opt
->srcrt
->segments_left
= n
;
616 memcpy(irthdr
->addr
+i
, rthdr
->addr
+(n
-1-i
), 16);
620 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr
);
622 /**********************************
624 **********************************/
626 /* Router Alert as of RFC 2711 */
628 static int ipv6_hop_ra(struct sk_buff
**skbp
, int optoff
)
630 struct sk_buff
*skb
= *skbp
;
632 if (skb
->nh
.raw
[optoff
+1] == 2) {
633 IP6CB(skb
)->ra
= optoff
;
636 LIMIT_NETDEBUG(KERN_DEBUG
"ipv6_hop_ra: wrong RA length %d\n",
637 skb
->nh
.raw
[optoff
+1]);
644 static int ipv6_hop_jumbo(struct sk_buff
**skbp
, int optoff
)
646 struct sk_buff
*skb
= *skbp
;
649 if (skb
->nh
.raw
[optoff
+1] != 4 || (optoff
&3) != 2) {
650 LIMIT_NETDEBUG(KERN_DEBUG
"ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
651 skb
->nh
.raw
[optoff
+1]);
652 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
),
653 IPSTATS_MIB_INHDRERRORS
);
657 pkt_len
= ntohl(*(__be32
*)(skb
->nh
.raw
+optoff
+2));
658 if (pkt_len
<= IPV6_MAXPLEN
) {
659 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
), IPSTATS_MIB_INHDRERRORS
);
660 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, optoff
+2);
663 if (skb
->nh
.ipv6h
->payload_len
) {
664 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
), IPSTATS_MIB_INHDRERRORS
);
665 icmpv6_param_prob(skb
, ICMPV6_HDR_FIELD
, optoff
);
669 if (pkt_len
> skb
->len
- sizeof(struct ipv6hdr
)) {
670 IP6_INC_STATS_BH(ip6_dst_idev(skb
->dst
), IPSTATS_MIB_INTRUNCATEDPKTS
);
674 if (pskb_trim_rcsum(skb
, pkt_len
+ sizeof(struct ipv6hdr
)))
684 static struct tlvtype_proc tlvprochopopt_lst
[] = {
686 .type
= IPV6_TLV_ROUTERALERT
,
690 .type
= IPV6_TLV_JUMBO
,
691 .func
= ipv6_hop_jumbo
,
696 int ipv6_parse_hopopts(struct sk_buff
**skbp
)
698 struct sk_buff
*skb
= *skbp
;
699 struct inet6_skb_parm
*opt
= IP6CB(skb
);
702 * skb->nh.raw is equal to skb->data, and
703 * skb->h.raw - skb->nh.raw is always equal to
704 * sizeof(struct ipv6hdr) by definition of
705 * hop-by-hop options.
707 if (!pskb_may_pull(skb
, sizeof(struct ipv6hdr
) + 8) ||
708 !pskb_may_pull(skb
, sizeof(struct ipv6hdr
) + ((skb
->h
.raw
[1] + 1) << 3))) {
713 opt
->hop
= sizeof(struct ipv6hdr
);
714 if (ip6_parse_tlv(tlvprochopopt_lst
, skbp
)) {
716 skb
->h
.raw
+= (skb
->h
.raw
[1]+1)<<3;
718 opt
->nhoff
= sizeof(struct ipv6hdr
);
725 * Creating outbound headers.
727 * "build" functions work when skb is filled from head to tail (datagram)
728 * "push" functions work when headers are added from tail to head (tcp)
730 * In both cases we assume, that caller reserved enough room
734 static void ipv6_push_rthdr(struct sk_buff
*skb
, u8
*proto
,
735 struct ipv6_rt_hdr
*opt
,
736 struct in6_addr
**addr_p
)
738 struct rt0_hdr
*phdr
, *ihdr
;
741 ihdr
= (struct rt0_hdr
*) opt
;
743 phdr
= (struct rt0_hdr
*) skb_push(skb
, (ihdr
->rt_hdr
.hdrlen
+ 1) << 3);
744 memcpy(phdr
, ihdr
, sizeof(struct rt0_hdr
));
746 hops
= ihdr
->rt_hdr
.hdrlen
>> 1;
749 memcpy(phdr
->addr
, ihdr
->addr
+ 1,
750 (hops
- 1) * sizeof(struct in6_addr
));
752 ipv6_addr_copy(phdr
->addr
+ (hops
- 1), *addr_p
);
753 *addr_p
= ihdr
->addr
;
755 phdr
->rt_hdr
.nexthdr
= *proto
;
756 *proto
= NEXTHDR_ROUTING
;
759 static void ipv6_push_exthdr(struct sk_buff
*skb
, u8
*proto
, u8 type
, struct ipv6_opt_hdr
*opt
)
761 struct ipv6_opt_hdr
*h
= (struct ipv6_opt_hdr
*)skb_push(skb
, ipv6_optlen(opt
));
763 memcpy(h
, opt
, ipv6_optlen(opt
));
768 void ipv6_push_nfrag_opts(struct sk_buff
*skb
, struct ipv6_txoptions
*opt
,
770 struct in6_addr
**daddr
)
773 ipv6_push_rthdr(skb
, proto
, opt
->srcrt
, daddr
);
775 * IPV6_RTHDRDSTOPTS is ignored
776 * unless IPV6_RTHDR is set (RFC3542).
779 ipv6_push_exthdr(skb
, proto
, NEXTHDR_DEST
, opt
->dst0opt
);
782 ipv6_push_exthdr(skb
, proto
, NEXTHDR_HOP
, opt
->hopopt
);
785 void ipv6_push_frag_opts(struct sk_buff
*skb
, struct ipv6_txoptions
*opt
, u8
*proto
)
788 ipv6_push_exthdr(skb
, proto
, NEXTHDR_DEST
, opt
->dst1opt
);
791 struct ipv6_txoptions
*
792 ipv6_dup_options(struct sock
*sk
, struct ipv6_txoptions
*opt
)
794 struct ipv6_txoptions
*opt2
;
796 opt2
= sock_kmalloc(sk
, opt
->tot_len
, GFP_ATOMIC
);
798 long dif
= (char*)opt2
- (char*)opt
;
799 memcpy(opt2
, opt
, opt
->tot_len
);
801 *((char**)&opt2
->hopopt
) += dif
;
803 *((char**)&opt2
->dst0opt
) += dif
;
805 *((char**)&opt2
->dst1opt
) += dif
;
807 *((char**)&opt2
->srcrt
) += dif
;
812 EXPORT_SYMBOL_GPL(ipv6_dup_options
);
814 static int ipv6_renew_option(void *ohdr
,
815 struct ipv6_opt_hdr __user
*newopt
, int newoptlen
,
817 struct ipv6_opt_hdr
**hdr
,
822 memcpy(*p
, ohdr
, ipv6_optlen((struct ipv6_opt_hdr
*)ohdr
));
823 *hdr
= (struct ipv6_opt_hdr
*)*p
;
824 *p
+= CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr
**)hdr
));
828 if (copy_from_user(*p
, newopt
, newoptlen
))
830 *hdr
= (struct ipv6_opt_hdr
*)*p
;
831 if (ipv6_optlen(*(struct ipv6_opt_hdr
**)hdr
) > newoptlen
)
833 *p
+= CMSG_ALIGN(newoptlen
);
839 struct ipv6_txoptions
*
840 ipv6_renew_options(struct sock
*sk
, struct ipv6_txoptions
*opt
,
842 struct ipv6_opt_hdr __user
*newopt
, int newoptlen
)
846 struct ipv6_txoptions
*opt2
;
850 if (newtype
!= IPV6_HOPOPTS
&& opt
->hopopt
)
851 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->hopopt
));
852 if (newtype
!= IPV6_RTHDRDSTOPTS
&& opt
->dst0opt
)
853 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->dst0opt
));
854 if (newtype
!= IPV6_RTHDR
&& opt
->srcrt
)
855 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->srcrt
));
856 if (newtype
!= IPV6_DSTOPTS
&& opt
->dst1opt
)
857 tot_len
+= CMSG_ALIGN(ipv6_optlen(opt
->dst1opt
));
860 if (newopt
&& newoptlen
)
861 tot_len
+= CMSG_ALIGN(newoptlen
);
866 tot_len
+= sizeof(*opt2
);
867 opt2
= sock_kmalloc(sk
, tot_len
, GFP_ATOMIC
);
869 return ERR_PTR(-ENOBUFS
);
871 memset(opt2
, 0, tot_len
);
873 opt2
->tot_len
= tot_len
;
874 p
= (char *)(opt2
+ 1);
876 err
= ipv6_renew_option(opt
? opt
->hopopt
: NULL
, newopt
, newoptlen
,
877 newtype
!= IPV6_HOPOPTS
,
882 err
= ipv6_renew_option(opt
? opt
->dst0opt
: NULL
, newopt
, newoptlen
,
883 newtype
!= IPV6_RTHDRDSTOPTS
,
888 err
= ipv6_renew_option(opt
? opt
->srcrt
: NULL
, newopt
, newoptlen
,
889 newtype
!= IPV6_RTHDR
,
890 (struct ipv6_opt_hdr
**)&opt2
->srcrt
, &p
);
894 err
= ipv6_renew_option(opt
? opt
->dst1opt
: NULL
, newopt
, newoptlen
,
895 newtype
!= IPV6_DSTOPTS
,
900 opt2
->opt_nflen
= (opt2
->hopopt
? ipv6_optlen(opt2
->hopopt
) : 0) +
901 (opt2
->dst0opt
? ipv6_optlen(opt2
->dst0opt
) : 0) +
902 (opt2
->srcrt
? ipv6_optlen(opt2
->srcrt
) : 0);
903 opt2
->opt_flen
= (opt2
->dst1opt
? ipv6_optlen(opt2
->dst1opt
) : 0);
907 sock_kfree_s(sk
, opt2
, opt2
->tot_len
);
911 struct ipv6_txoptions
*ipv6_fixup_options(struct ipv6_txoptions
*opt_space
,
912 struct ipv6_txoptions
*opt
)
915 * ignore the dest before srcrt unless srcrt is being included.
918 if (opt
&& opt
->dst0opt
&& !opt
->srcrt
) {
919 if (opt_space
!= opt
) {
920 memcpy(opt_space
, opt
, sizeof(*opt_space
));
923 opt
->opt_nflen
-= ipv6_optlen(opt
->dst0opt
);