1 /* $KAME: ip6_output.c,v 1.94 2000/04/04 14:45:44 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1982, 1986, 1988, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
68 #include "opt_ip6fw.h"
70 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
72 #if __NetBSD__ /*XXX*/
73 #include "opt_ipsec.h"
77 #include <sys/param.h>
78 #include <sys/malloc.h>
80 #include <sys/errno.h>
81 #include <sys/protosw.h>
82 #include <sys/socket.h>
83 #include <sys/socketvar.h>
84 #include <sys/systm.h>
85 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
86 #include <sys/kernel.h>
91 #include <net/route.h>
93 #include <netinet/in.h>
94 #include <netinet/in_var.h>
95 #if defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
96 #include <netinet/in_systm.h>
97 #include <netinet/ip.h>
99 #include <netinet/ip6.h>
100 #include <netinet/icmp6.h>
101 #include <netinet6/ip6_var.h>
102 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802) || defined (__APPLE__)
103 #include <netinet/in_pcb.h>
105 #include <netinet6/in6_pcb.h>
107 #include <netinet6/nd6.h>
110 #include <netinet6/ipsec.h>
111 #include <netkey/key.h>
112 #include <netkey/key_debug.h>
119 #include <net/net_osdep.h>
122 #include <netinet6/ip6_fw.h>
125 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
126 static MALLOC_DEFINE(M_IPMOPTS
, "ip6_moptions", "internet multicast options");
130 struct mbuf
*ip6e_ip6
;
131 struct mbuf
*ip6e_hbh
;
132 struct mbuf
*ip6e_dest1
;
133 struct mbuf
*ip6e_rthdr
;
134 struct mbuf
*ip6e_dest2
;
137 static int ip6_pcbopt
__P((int, u_char
*, int, struct ip6_pktopts
**, int));
138 static int ip6_getpcbopt
__P((struct ip6_pktopts
*, int, void **, int *));
139 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined(__APPLE__)
140 static int ip6_pcbopts
__P((struct ip6_pktopts
**, struct mbuf
*,
141 struct socket
*, struct sockopt
*sopt
));
143 static int ip6_pcbopts
__P((struct ip6_pktopts
**, struct mbuf
*,
146 static int ip6_setmoptions
__P((int, struct ip6_moptions
**, struct mbuf
*));
147 static int ip6_getmoptions
__P((int, struct ip6_moptions
*, struct mbuf
**));
148 static int ip6_copyexthdr
__P((struct mbuf
**, caddr_t
, int));
149 static int ip6_insertfraghdr
__P((struct mbuf
*, struct mbuf
*, int,
150 struct ip6_frag
**));
151 static int ip6_insert_jumboopt
__P((struct ip6_exthdrs
*, u_int32_t
));
152 static int ip6_splithdr
__P((struct mbuf
*, struct ip6_exthdrs
*));
153 #if defined(__bsdi__) || defined(__OpenBSD__)
154 extern struct ifnet loif
;
158 extern struct ifnet
**ifindex2ifnet
;
159 extern struct ifnet loif
[NLOOP
];
163 int (*mip6_output_hook
)(struct mbuf
*m
, struct ip6_pktopts
**opt
);
165 static u_long lo_dl_tag
= 0;
168 * IP6 output. The packet in mbuf chain m contains a skeletal IP6
169 * header (with pri, len, nxt, hlim, src, dst).
170 * This function may modify ver and hlim only.
171 * The mbuf chain containing the packet will be freed.
172 * The mbuf opt, if present, will not be freed.
175 ip6_output(m0
, opt
, ro
, flags
, im6o
, ifpp
)
177 struct ip6_pktopts
*opt
;
178 struct route_in6
*ro
;
180 struct ip6_moptions
*im6o
;
181 struct ifnet
**ifpp
; /* XXX: just for statistics */
183 struct ip6_hdr
*ip6
, *mhip6
;
186 int hlen
, tlen
, len
, off
;
187 struct route_in6 ip6route
;
188 struct sockaddr_in6
*dst
;
190 struct in6_ifaddr
*ia
;
192 u_int32_t optlen
= 0, plen
= 0, unfragpartlen
= 0;
193 struct ip6_exthdrs exthdrs
;
194 struct in6_addr finaldst
;
195 struct route_in6
*ro_pmtu
= NULL
;
201 int needipsectun
= 0;
203 struct secpolicy
*sp
= NULL
;
205 /* for AH processing. stupid to have "socket" variable in IP layer... */
206 so
= ipsec_getsocket(m
);
207 ipsec_setsocket(m
, NULL
);
208 ip6
= mtod(m
, struct ip6_hdr
*);
211 #define MAKE_EXTHDR(hp,mp) \
214 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
215 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
216 ((eh)->ip6e_len + 1) << 3); \
222 bzero(&exthdrs
, sizeof(exthdrs
));
228 * Call Mobile IPv6 to check if there are any Destination Header
231 if (mip6_output_hook
) {
232 error
= (*mip6_output_hook
)(m
, &opt
);
239 /* Hop-by-Hop options header */
240 MAKE_EXTHDR(opt
->ip6po_hbh
, &exthdrs
.ip6e_hbh
);
241 if (opt
->ip6po_rthdr
) {
243 * Destination options header(1st part)
244 * This only makes sence with a routing header.
246 MAKE_EXTHDR(opt
->ip6po_dest1
, &exthdrs
.ip6e_dest1
);
249 MAKE_EXTHDR(opt
->ip6po_rthdr
, &exthdrs
.ip6e_rthdr
);
250 /* Destination options header(2nd part) */
251 MAKE_EXTHDR(opt
->ip6po_dest2
, &exthdrs
.ip6e_dest2
);
255 /* get a security policy for this packet */
257 sp
= ipsec6_getpolicybyaddr(m
, IPSEC_DIR_OUTBOUND
, 0, &error
);
259 sp
= ipsec6_getpolicybysock(m
, IPSEC_DIR_OUTBOUND
, so
, &error
);
262 ipsec6stat
.out_inval
++;
269 switch (sp
->policy
) {
270 case IPSEC_POLICY_DISCARD
:
272 * This packet is just discarded.
274 ipsec6stat
.out_polvio
++;
277 case IPSEC_POLICY_BYPASS
:
278 case IPSEC_POLICY_NONE
:
279 /* no need to do IPsec. */
283 case IPSEC_POLICY_IPSEC
:
284 if (sp
->req
== NULL
) {
285 /* acquire a policy */
286 error
= key_spdacquire(sp
);
292 case IPSEC_POLICY_ENTRUST
:
294 printf("ip6_output: Invalid policy found. %d\n", sp
->policy
);
299 * Calculate the total length of the extension header chain.
300 * Keep the length of the unfragmentable part for fragmentation.
303 if (exthdrs
.ip6e_hbh
) optlen
+= exthdrs
.ip6e_hbh
->m_len
;
304 if (exthdrs
.ip6e_dest1
) optlen
+= exthdrs
.ip6e_dest1
->m_len
;
305 if (exthdrs
.ip6e_rthdr
) optlen
+= exthdrs
.ip6e_rthdr
->m_len
;
306 unfragpartlen
= optlen
+ sizeof(struct ip6_hdr
);
307 /* NOTE: we don't add AH/ESP length here. do that later. */
308 if (exthdrs
.ip6e_dest2
) optlen
+= exthdrs
.ip6e_dest2
->m_len
;
311 * If we need IPsec, or there is at least one extension header,
312 * separate IP6 header from the payload.
314 if ((needipsec
|| optlen
) && !hdrsplit
) {
315 if ((error
= ip6_splithdr(m
, &exthdrs
)) != 0) {
319 m
= exthdrs
.ip6e_ip6
;
324 ip6
= mtod(m
, struct ip6_hdr
*);
326 /* adjust mbuf packet header length */
327 m
->m_pkthdr
.len
+= optlen
;
328 plen
= m
->m_pkthdr
.len
- sizeof(*ip6
);
330 /* If this is a jumbo payload, insert a jumbo payload option. */
331 if (plen
> IPV6_MAXPACKET
) {
333 if ((error
= ip6_splithdr(m
, &exthdrs
)) != 0) {
337 m
= exthdrs
.ip6e_ip6
;
341 ip6
= mtod(m
, struct ip6_hdr
*);
342 if ((error
= ip6_insert_jumboopt(&exthdrs
, plen
)) != 0)
346 ip6
->ip6_plen
= htons(plen
);
349 * Concatenate headers and fill in next header fields.
350 * Here we have, on "m"
352 * and we insert headers accordingly. Finally, we should be getting:
353 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
355 * during the header composing process, "m" points to IPv6 header.
356 * "mprev" points to an extension header prior to esp.
359 u_char
*nexthdrp
= &ip6
->ip6_nxt
;
360 struct mbuf
*mprev
= m
;
363 * we treat dest2 specially. this makes IPsec processing
366 * result: IPv6 dest2 payload
367 * m and mprev will point to IPv6 header.
369 if (exthdrs
.ip6e_dest2
) {
371 panic("assumption failed: hdr not split");
372 exthdrs
.ip6e_dest2
->m_next
= m
->m_next
;
373 m
->m_next
= exthdrs
.ip6e_dest2
;
374 *mtod(exthdrs
.ip6e_dest2
, u_char
*) = ip6
->ip6_nxt
;
375 ip6
->ip6_nxt
= IPPROTO_DSTOPTS
;
378 #define MAKE_CHAIN(m,mp,p,i)\
382 panic("assumption failed: hdr not split"); \
383 *mtod((m), u_char *) = *(p);\
385 p = mtod((m), u_char *);\
386 (m)->m_next = (mp)->m_next;\
392 * result: IPv6 hbh dest1 rthdr dest2 payload
393 * m will point to IPv6 header. mprev will point to the
394 * extension header prior to dest2 (rthdr in the above case).
396 MAKE_CHAIN(exthdrs
.ip6e_hbh
, mprev
,
397 nexthdrp
, IPPROTO_HOPOPTS
);
398 MAKE_CHAIN(exthdrs
.ip6e_dest1
, mprev
,
399 nexthdrp
, IPPROTO_DSTOPTS
);
400 MAKE_CHAIN(exthdrs
.ip6e_rthdr
, mprev
,
401 nexthdrp
, IPPROTO_ROUTING
);
408 * pointers after IPsec headers are not valid any more.
409 * other pointers need a great care too.
410 * (IPsec routines should not mangle mbufs prior to AH/ESP)
412 exthdrs
.ip6e_dest2
= NULL
;
415 struct ip6_rthdr
*rh
= NULL
;
417 struct ipsec_output_state state
;
419 if (exthdrs
.ip6e_rthdr
) {
420 rh
= mtod(exthdrs
.ip6e_rthdr
, struct ip6_rthdr
*);
421 segleft_org
= rh
->ip6r_segleft
;
422 rh
->ip6r_segleft
= 0;
425 bzero(&state
, sizeof(state
));
427 error
= ipsec6_output_trans(&state
, nexthdrp
, mprev
, sp
, flags
,
431 /* mbuf is already reclaimed in ipsec6_output_trans. */
441 printf("ip6_output (ipsec): error code %d\n", error
);
444 /* don't show these error codes to the user */
450 if (exthdrs
.ip6e_rthdr
) {
451 /* ah6_output doesn't modify mbuf chain */
452 rh
->ip6r_segleft
= segleft_org
;
460 * If there is a routing header, replace destination address field
461 * with the first hop of the routing header.
463 if (exthdrs
.ip6e_rthdr
) {
464 struct ip6_rthdr
*rh
=
465 (struct ip6_rthdr
*)(mtod(exthdrs
.ip6e_rthdr
,
466 struct ip6_rthdr
*));
467 struct ip6_rthdr0
*rh0
;
468 struct in6_addr
*addr
;
470 finaldst
= ip6
->ip6_dst
;
471 switch(rh
->ip6r_type
) {
472 case IPV6_RTHDR_TYPE_0
:
473 rh0
= (struct ip6_rthdr0
*)rh
;
474 addr
= (struct in6_addr
*)(rh0
+ 1);
476 ip6
->ip6_dst
= *addr
;
477 bcopy((caddr_t
)(addr
+ 1), (caddr_t
)addr
,
478 sizeof(struct in6_addr
)*(rh0
->ip6r0_segleft
- 1)
480 *(addr
+ rh0
->ip6r0_segleft
- 1) = finaldst
;
482 default: /* is it possible? */
488 /* Source address validation */
489 if (IN6_IS_ADDR_UNSPECIFIED(&ip6
->ip6_src
) &&
490 (flags
& IPV6_DADOUTPUT
) == 0) {
492 ip6stat
.ip6s_badscope
++;
495 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_src
)) {
497 ip6stat
.ip6s_badscope
++;
501 ip6stat
.ip6s_localout
++;
508 bzero((caddr_t
)ro
, sizeof(*ro
));
511 if (opt
&& opt
->ip6po_rthdr
)
512 ro
= &opt
->ip6po_route
;
513 dst
= (struct sockaddr_in6
*)&ro
->ro_dst
;
515 * If there is a cached route,
516 * check that it is to the same destination
517 * and is still up. If not, free it and try again.
519 if (ro
->ro_rt
&& ((ro
->ro_rt
->rt_flags
& RTF_UP
) == 0 ||
520 !IN6_ARE_ADDR_EQUAL(&dst
->sin6_addr
, &ip6
->ip6_dst
))) {
522 ro
->ro_rt
= (struct rtentry
*)0;
524 if (ro
->ro_rt
== 0) {
525 bzero(dst
, sizeof(*dst
));
526 dst
->sin6_family
= AF_INET6
;
527 dst
->sin6_len
= sizeof(struct sockaddr_in6
);
528 dst
->sin6_addr
= ip6
->ip6_dst
;
531 if (needipsec
&& needipsectun
) {
532 struct ipsec_output_state state
;
535 * All the extension headers will become inaccessible
536 * (since they can be encrypted).
537 * Don't panic, we need no more updates to extension headers
538 * on inner IPv6 packet (since they are now encapsulated).
540 * IPv6 [ESP|AH] IPv6 [extension headers] payload
542 bzero(&exthdrs
, sizeof(exthdrs
));
543 exthdrs
.ip6e_ip6
= m
;
545 bzero(&state
, sizeof(state
));
547 state
.ro
= (struct route
*)ro
;
548 state
.dst
= (struct sockaddr
*)dst
;
550 error
= ipsec6_output_tunnel(&state
, sp
, flags
);
553 ro
= (struct route_in6
*)state
.ro
;
554 dst
= (struct sockaddr_in6
*)state
.dst
;
556 /* mbuf is already reclaimed in ipsec6_output_tunnel. */
567 printf("ip6_output (ipsec): error code %d\n", error
);
570 /* don't show these error codes to the user */
577 exthdrs
.ip6e_ip6
= m
;
581 if (!IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
584 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
585 #define sin6tosa(sin6) ((struct sockaddr *)(sin6))
587 * interface selection comes here
588 * if an interface is specified from an upper layer,
591 if (ro
->ro_rt
== 0) {
594 * non-bsdi always clone routes, if parent is
597 rtalloc((struct route
*)ro
);
599 if (ro
== &ip6route
) /* xxx kazu */
600 rtalloc((struct route
*)ro
);
602 rtcalloc((struct route
*)ro
);
605 if (ro
->ro_rt
== 0) {
606 ip6stat
.ip6s_noroute
++;
607 error
= EHOSTUNREACH
;
608 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */
611 ia
= ifatoia6(ro
->ro_rt
->rt_ifa
);
612 ifp
= ro
->ro_rt
->rt_ifp
;
614 if (ro
->ro_rt
->rt_flags
& RTF_GATEWAY
)
615 dst
= (struct sockaddr_in6
*)ro
->ro_rt
->rt_gateway
;
616 m
->m_flags
&= ~(M_BCAST
| M_MCAST
); /* just in case */
618 in6_ifstat_inc(ifp
, ifs6_out_request
);
621 * Check if the outgoing interface conflicts with
622 * the interface specified by ifi6_ifindex (if specified).
623 * Note that loopback interface is always okay.
624 * (this may happen when we are sending a packet to one of
625 * our own addresses.)
627 if (opt
&& opt
->ip6po_pktinfo
628 && opt
->ip6po_pktinfo
->ipi6_ifindex
) {
629 if (!(ifp
->if_flags
& IFF_LOOPBACK
)
630 && ifp
->if_index
!= opt
->ip6po_pktinfo
->ipi6_ifindex
) {
631 ip6stat
.ip6s_noroute
++;
632 in6_ifstat_inc(ifp
, ifs6_out_discard
);
633 error
= EHOSTUNREACH
;
638 if (opt
&& opt
->ip6po_hlim
!= -1)
639 ip6
->ip6_hlim
= opt
->ip6po_hlim
& 0xff;
642 struct in6_multi
*in6m
;
644 m
->m_flags
= (m
->m_flags
& ~M_BCAST
) | M_MCAST
;
647 * See if the caller provided any multicast options
651 ip6
->ip6_hlim
= im6o
->im6o_multicast_hlim
;
652 if (im6o
->im6o_multicast_ifp
!= NULL
)
653 ifp
= im6o
->im6o_multicast_ifp
;
655 ip6
->ip6_hlim
= ip6_defmcasthlim
;
658 * See if the caller provided the outgoing interface
659 * as an ancillary data.
660 * Boundary check for ifindex is assumed to be already done.
662 if (opt
&& opt
->ip6po_pktinfo
&& opt
->ip6po_pktinfo
->ipi6_ifindex
)
663 ifp
= ifindex2ifnet
[opt
->ip6po_pktinfo
->ipi6_ifindex
];
666 * If the destination is a node-local scope multicast,
667 * the packet should be loop-backed only.
669 if (IN6_IS_ADDR_MC_NODELOCAL(&ip6
->ip6_dst
)) {
671 * If the outgoing interface is already specified,
672 * it should be a loopback interface.
674 if (ifp
&& (ifp
->if_flags
& IFF_LOOPBACK
) == 0) {
675 ip6stat
.ip6s_badscope
++;
676 error
= ENETUNREACH
; /* XXX: better error? */
677 /* XXX correct ifp? */
678 in6_ifstat_inc(ifp
, ifs6_out_discard
);
689 if (opt
&& opt
->ip6po_hlim
!= -1)
690 ip6
->ip6_hlim
= opt
->ip6po_hlim
& 0xff;
693 * If caller did not provide an interface lookup a
694 * default in the routing table. This is either a
695 * default for the speicfied group (i.e. a host
696 * route), or a multicast default (a route for the
700 if (ro
->ro_rt
== 0) {
701 ro
->ro_rt
= rtalloc1((struct sockaddr
*)
703 #if __FreeBSD__ || defined (__APPLE__)
708 if (ro
->ro_rt
== 0) {
709 ip6stat
.ip6s_noroute
++;
710 error
= EHOSTUNREACH
;
711 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard) */
714 ia
= ifatoia6(ro
->ro_rt
->rt_ifa
);
715 ifp
= ro
->ro_rt
->rt_ifp
;
719 if ((flags
& IPV6_FORWARDING
) == 0)
720 in6_ifstat_inc(ifp
, ifs6_out_request
);
721 in6_ifstat_inc(ifp
, ifs6_out_mcast
);
724 * Confirm that the outgoing interface supports multicast.
726 if ((ifp
->if_flags
& IFF_MULTICAST
) == 0) {
727 ip6stat
.ip6s_noroute
++;
728 in6_ifstat_inc(ifp
, ifs6_out_discard
);
732 IN6_LOOKUP_MULTI(ip6
->ip6_dst
, ifp
, in6m
);
734 (im6o
== NULL
|| im6o
->im6o_multicast_loop
)) {
736 * If we belong to the destination multicast group
737 * on the outgoing interface, and the caller did not
738 * forbid loopback, loop back a copy.
740 ip6_mloopback(ifp
, m
, dst
);
743 * If we are acting as a multicast router, perform
744 * multicast forwarding as if the packet had just
745 * arrived on the interface to which we are about
746 * to send. The multicast forwarding function
747 * recursively calls this function, using the
748 * IPV6_FORWARDING flag to prevent infinite recursion.
750 * Multicasts that are looped back by ip6_mloopback(),
751 * above, will be forwarded by the ip6_input() routine,
754 if (ip6_mrouter
&& (flags
& IPV6_FORWARDING
) == 0) {
755 if (ip6_mforward(ip6
, ifp
, m
) != NULL
) {
762 * Multicasts with a hoplimit of zero may be looped back,
763 * above, but must not be transmitted on a network.
764 * Also, multicasts addressed to the loopback interface
765 * are not sent -- the above call to ip6_mloopback() will
766 * loop back a copy if this host actually belongs to the
767 * destination group on the loopback interface.
769 if (ip6
->ip6_hlim
== 0 || (ifp
->if_flags
& IFF_LOOPBACK
)) {
776 * Fill the outgoing inteface to tell the upper layer
777 * to increment per-interface statistics.
783 * Upper-layer reachability confirmation
785 if (opt
&& (opt
->ip6po_flags
& IP6PO_REACHCONF
))
786 nd6_nud_hint(ro
->ro_rt
, NULL
);
789 * Determine path MTU.
792 /* The first hop and the final destination may differ. */
793 struct sockaddr_in6
*sin6_fin
=
794 (struct sockaddr_in6
*)&ro_pmtu
->ro_dst
;
795 if (ro_pmtu
->ro_rt
&& ((ro
->ro_rt
->rt_flags
& RTF_UP
) == 0 ||
796 !IN6_ARE_ADDR_EQUAL(&sin6_fin
->sin6_addr
,
798 RTFREE(ro_pmtu
->ro_rt
);
799 ro_pmtu
->ro_rt
= (struct rtentry
*)0;
801 if (ro_pmtu
->ro_rt
== 0) {
802 bzero(sin6_fin
, sizeof(*sin6_fin
));
803 sin6_fin
->sin6_family
= AF_INET6
;
804 sin6_fin
->sin6_len
= sizeof(struct sockaddr_in6
);
805 sin6_fin
->sin6_addr
= finaldst
;
807 #ifdef __bsdi__ /* bsdi needs rtcalloc to clone a route. */
808 rtcalloc((struct route
*)ro_pmtu
);
810 rtalloc((struct route
*)ro_pmtu
);
814 if (ro_pmtu
->ro_rt
!= NULL
) {
815 u_int32_t ifmtu
= nd_ifinfo
[ifp
->if_index
].linkmtu
;
817 mtu
= ro_pmtu
->ro_rt
->rt_rmx
.rmx_mtu
;
820 * The MTU on the route is larger than the MTU on
821 * the interface! This shouldn't happen, unless the
822 * MTU of the interface has been changed after the
823 * interface was brought up. Change the MTU in the
824 * route to match the interface MTU (as long as the
825 * field isn't locked).
828 if ((ro_pmtu
->ro_rt
->rt_rmx
.rmx_locks
& RTV_MTU
) == 0)
829 ro_pmtu
->ro_rt
->rt_rmx
.rmx_mtu
= mtu
; /* XXX */
832 mtu
= nd_ifinfo
[ifp
->if_index
].linkmtu
;
836 * advanced API (IPV6_USE_MIN_MTU) overrides mtu setting
838 if (mtu
> IPV6_MMTU
) {
839 if ((opt
&& (opt
->ip6po_flags
& IP6PO_MINMTU
)) ||
840 (flags
& IPV6_MINMTU
)) {
846 * Fake link-local scope-class addresses
848 if ((ifp
->if_flags
& IFF_LOOPBACK
) == 0) {
849 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_src
))
850 ip6
->ip6_src
.s6_addr16
[1] = 0;
851 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
))
852 ip6
->ip6_dst
.s6_addr16
[1] = 0;
857 * Check with the firewall...
859 if (ip6_fw_chk_ptr
) {
861 /* If ipfw says divert, we have to just drop packet */
862 if ((*ip6_fw_chk_ptr
)(&ip6
, ifp
, &port
, &m
)) {
874 * If the outgoing packet contains a hop-by-hop options header,
875 * it must be examined and processed even by the source node.
876 * (RFC 2460, section 4.)
878 if (exthdrs
.ip6e_hbh
) {
879 struct ip6_hbh
*hbh
= mtod(exthdrs
.ip6e_hbh
,
881 u_int32_t dummy1
; /* XXX unused */
882 u_int32_t dummy2
; /* XXX unused */
885 * XXX: if we have to send an ICMPv6 error to the sender,
886 * we need the M_LOOP flag since icmp6_error() expects
887 * the IPv6 and the hop-by-hop options header are
888 * continuous unless the flag is set.
890 m
->m_flags
|= M_LOOP
;
891 m
->m_pkthdr
.rcvif
= ifp
;
892 if (ip6_process_hopopts(m
,
893 (u_int8_t
*)(hbh
+ 1),
894 ((hbh
->ip6h_len
+ 1) << 3) -
895 sizeof(struct ip6_hbh
),
896 &dummy1
, &dummy2
) < 0) {
897 /* m was already freed at this point */
898 error
= EINVAL
;/* better error? */
901 m
->m_flags
&= ~M_LOOP
; /* XXX */
902 m
->m_pkthdr
.rcvif
= NULL
;
906 * Send the packet to the outgoing interface.
907 * If necessary, do IPv6 fragmentation before sending.
909 tlen
= m
->m_pkthdr
.len
;
913 * On any link that cannot convey a 1280-octet packet in one piece,
914 * link-specific fragmentation and reassembly must be provided at
915 * a layer below IPv6. [RFC 2460, sec.5]
916 * Thus if the interface has ability of link-level fragmentation,
917 * we can just send the packet even if the packet size is
918 * larger than the link's MTU.
919 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet...
922 || ifp
->if_flags
& IFF_FRAGMENTABLE
926 #if defined(__NetBSD__) && defined(IFA_STATS)
928 struct in6_ifaddr
*ia6
;
929 ip6
= mtod(m
, struct ip6_hdr
*);
930 ia6
= in6_ifawithifp(ifp
, &ip6
->ip6_src
);
932 ia
->ia_ifa
.ifa_data
.ifad_outbytes
+=
938 error
= (*ifp
->if_output
)(ifp
, m
, (struct sockaddr
*)dst
,
941 error
= nd6_output(ifp
, m
, dst
, ro
->ro_rt
);
944 } else if (mtu
< IPV6_MMTU
) {
946 * note that path MTU is never less than IPV6_MMTU
950 in6_ifstat_inc(ifp
, ifs6_out_fragfail
);
952 } else if (ip6
->ip6_plen
== 0) { /* jumbo payload cannot be fragmented */
954 in6_ifstat_inc(ifp
, ifs6_out_fragfail
);
957 struct mbuf
**mnext
, *m_frgpart
;
958 struct ip6_frag
*ip6f
;
959 u_int32_t id
= htonl(ip6_id
++);
963 * Too large for the destination or interface;
964 * fragment if possible.
965 * Must be able to put at least 8 bytes per fragment.
967 hlen
= unfragpartlen
;
968 if (mtu
> IPV6_MAXPACKET
)
969 mtu
= IPV6_MAXPACKET
;
970 len
= (mtu
- hlen
- sizeof(struct ip6_frag
)) & ~7;
973 in6_ifstat_inc(ifp
, ifs6_out_fragfail
);
977 mnext
= &m
->m_nextpkt
;
980 * Change the next header field of the last header in the
981 * unfragmentable part.
983 if (exthdrs
.ip6e_rthdr
) {
984 nextproto
= *mtod(exthdrs
.ip6e_rthdr
, u_char
*);
985 *mtod(exthdrs
.ip6e_rthdr
, u_char
*) = IPPROTO_FRAGMENT
;
986 } else if (exthdrs
.ip6e_dest1
) {
987 nextproto
= *mtod(exthdrs
.ip6e_dest1
, u_char
*);
988 *mtod(exthdrs
.ip6e_dest1
, u_char
*) = IPPROTO_FRAGMENT
;
989 } else if (exthdrs
.ip6e_hbh
) {
990 nextproto
= *mtod(exthdrs
.ip6e_hbh
, u_char
*);
991 *mtod(exthdrs
.ip6e_hbh
, u_char
*) = IPPROTO_FRAGMENT
;
993 nextproto
= ip6
->ip6_nxt
;
994 ip6
->ip6_nxt
= IPPROTO_FRAGMENT
;
998 * Loop through length of segment after first fragment,
999 * make new header and copy data of each part and link onto chain.
1002 for (off
= hlen
; off
< tlen
; off
+= len
) {
1003 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
1006 ip6stat
.ip6s_odropped
++;
1009 m
->m_flags
= m0
->m_flags
& M_COPYFLAGS
;
1011 mnext
= &m
->m_nextpkt
;
1012 m
->m_data
+= max_linkhdr
;
1013 mhip6
= mtod(m
, struct ip6_hdr
*);
1015 m
->m_len
= sizeof(*mhip6
);
1016 error
= ip6_insertfraghdr(m0
, m
, hlen
, &ip6f
);
1018 ip6stat
.ip6s_odropped
++;
1021 ip6f
->ip6f_offlg
= htons((u_short
)((off
- hlen
) & ~7));
1022 if (off
+ len
>= tlen
)
1025 ip6f
->ip6f_offlg
|= IP6F_MORE_FRAG
;
1026 mhip6
->ip6_plen
= htons((u_short
)(len
+ hlen
+
1028 sizeof(struct ip6_hdr
)));
1029 if ((m_frgpart
= m_copy(m0
, off
, len
)) == 0) {
1031 ip6stat
.ip6s_odropped
++;
1034 m_cat(m
, m_frgpart
);
1035 m
->m_pkthdr
.len
= len
+ hlen
+ sizeof(*ip6f
);
1036 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
1037 ip6f
->ip6f_reserved
= 0;
1038 ip6f
->ip6f_ident
= id
;
1039 ip6f
->ip6f_nxt
= nextproto
;
1040 ip6stat
.ip6s_ofragments
++;
1041 in6_ifstat_inc(ifp
, ifs6_out_fragcreat
);
1044 in6_ifstat_inc(ifp
, ifs6_out_fragok
);
1048 * Remove leading garbages.
1054 for (m0
= m
; m
; m
= m0
) {
1058 #if defined(__NetBSD__) && defined(IFA_STATS)
1060 struct in6_ifaddr
*ia6
;
1061 ip6
= mtod(m
, struct ip6_hdr
*);
1062 ia6
= in6_ifawithifp(ifp
, &ip6
->ip6_src
);
1064 ia
->ia_ifa
.ifa_data
.ifad_outbytes
+=
1070 error
= (*ifp
->if_output
)(ifp
, m
,
1071 (struct sockaddr
*)dst
,
1074 error
= nd6_output(ifp
, m
, dst
, ro
->ro_rt
);
1081 ip6stat
.ip6s_fragmented
++;
1084 if (ro
== &ip6route
&& ro
->ro_rt
) { /* brace necessary for RTFREE */
1086 } else if (ro_pmtu
== &ip6route
&& ro_pmtu
->ro_rt
) {
1087 RTFREE(ro_pmtu
->ro_rt
);
1098 m_freem(exthdrs
.ip6e_hbh
); /* m_freem will check if mbuf is 0 */
1099 m_freem(exthdrs
.ip6e_dest1
);
1100 m_freem(exthdrs
.ip6e_rthdr
);
1101 m_freem(exthdrs
.ip6e_dest2
);
1109 ip6_copyexthdr(mp
, hdr
, hlen
)
1116 if (hlen
> MCLBYTES
)
1117 return(ENOBUFS
); /* XXX */
1119 MGET(m
, M_DONTWAIT
, MT_DATA
);
1124 MCLGET(m
, M_DONTWAIT
);
1125 if ((m
->m_flags
& M_EXT
) == 0) {
1132 bcopy(hdr
, mtod(m
, caddr_t
), hlen
);
1139 * Insert jumbo payload option.
1142 ip6_insert_jumboopt(exthdrs
, plen
)
1143 struct ip6_exthdrs
*exthdrs
;
1149 #define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */
1152 * If there is no hop-by-hop options header, allocate new one.
1153 * If there is one but it doesn't have enough space to store the
1154 * jumbo payload option, allocate a cluster to store the whole options.
1155 * Otherwise, use it to store the options.
1157 if (exthdrs
->ip6e_hbh
== 0) {
1158 MGET(mopt
, M_DONTWAIT
, MT_DATA
);
1161 mopt
->m_len
= JUMBOOPTLEN
;
1162 optbuf
= mtod(mopt
, u_char
*);
1163 optbuf
[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
1164 exthdrs
->ip6e_hbh
= mopt
;
1166 struct ip6_hbh
*hbh
;
1168 mopt
= exthdrs
->ip6e_hbh
;
1169 if (M_TRAILINGSPACE(mopt
) < JUMBOOPTLEN
) {
1170 caddr_t oldoptp
= mtod(mopt
, caddr_t
);
1171 int oldoptlen
= mopt
->m_len
;
1173 if (mopt
->m_flags
& M_EXT
)
1174 return(ENOBUFS
); /* XXX */
1175 MCLGET(mopt
, M_DONTWAIT
);
1176 if ((mopt
->m_flags
& M_EXT
) == 0)
1179 bcopy(oldoptp
, mtod(mopt
, caddr_t
), oldoptlen
);
1180 optbuf
= mtod(mopt
, caddr_t
) + oldoptlen
;
1181 mopt
->m_len
= oldoptlen
+ JUMBOOPTLEN
;
1183 optbuf
= mtod(mopt
, u_char
*) + mopt
->m_len
;
1184 mopt
->m_len
+= JUMBOOPTLEN
;
1186 optbuf
[0] = IP6OPT_PADN
;
1190 * Adjust the header length according to the pad and
1191 * the jumbo payload option.
1193 hbh
= mtod(mopt
, struct ip6_hbh
*);
1194 hbh
->ip6h_len
+= (JUMBOOPTLEN
>> 3);
1197 /* fill in the option. */
1198 optbuf
[2] = IP6OPT_JUMBO
;
1200 *(u_int32_t
*)&optbuf
[4] = htonl(plen
+ JUMBOOPTLEN
);
1202 /* finally, adjust the packet header length */
1203 exthdrs
->ip6e_ip6
->m_pkthdr
.len
+= JUMBOOPTLEN
;
1210 * Insert fragment header and copy unfragmentable header portions.
1213 ip6_insertfraghdr(m0
, m
, hlen
, frghdrp
)
1214 struct mbuf
*m0
, *m
;
1216 struct ip6_frag
**frghdrp
;
1218 struct mbuf
*n
, *mlast
;
1220 if (hlen
> sizeof(struct ip6_hdr
)) {
1221 n
= m_copym(m0
, sizeof(struct ip6_hdr
),
1222 hlen
- sizeof(struct ip6_hdr
), M_DONTWAIT
);
1229 /* Search for the last mbuf of unfragmentable part. */
1230 for (mlast
= n
; mlast
->m_next
; mlast
= mlast
->m_next
)
1233 if ((mlast
->m_flags
& M_EXT
) == 0 &&
1234 M_TRAILINGSPACE(mlast
) < sizeof(struct ip6_frag
)) {
1235 /* use the trailing space of the last mbuf for the fragment hdr */
1237 (struct ip6_frag
*)(mtod(mlast
, caddr_t
) + mlast
->m_len
);
1238 mlast
->m_len
+= sizeof(struct ip6_frag
);
1239 m
->m_pkthdr
.len
+= sizeof(struct ip6_frag
);
1241 /* allocate a new mbuf for the fragment header */
1244 MGET(mfrg
, M_DONTWAIT
, MT_DATA
);
1247 mfrg
->m_len
= sizeof(struct ip6_frag
);
1248 *frghdrp
= mtod(mfrg
, struct ip6_frag
*);
1249 mlast
->m_next
= mfrg
;
1256 * IP6 socket option processing.
1258 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1260 ip6_ctloutput(so
, sopt
)
1262 struct sockopt
*sopt
;
1265 ip6_ctloutput(op
, so
, level
, optname
, mp
)
1272 int privileged
, optdatalen
;
1274 struct ip6_recvpktopts
*rcvopts
;
1275 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1276 register struct inpcb
*in6p
= sotoinpcb(so
);
1278 int level
, op
, optname
;
1283 level
= sopt
->sopt_level
;
1284 op
= sopt
->sopt_dir
;
1285 optname
= sopt
->sopt_name
;
1286 optlen
= sopt
->sopt_valsize
;
1289 panic("ip6_ctloutput: arg soopt is NULL");
1293 register struct inpcb
*inp
= sotoinpcb(so
);
1295 register struct in6pcb
*in6p
= sotoin6pcb(so
);
1297 register struct mbuf
*m
= *mp
;
1300 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1301 struct proc
*p
= curproc
; /* XXX */
1304 optlen
= m
? m
->m_len
: 0;
1308 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
1309 privileged
= (p
== 0 || suser(p
->p_ucred
, &p
->p_acflag
)) ? 0 : 1;
1312 privileged
= (inp
->inp_socket
->so_state
& SS_PRIV
);
1314 privileged
= (in6p
->in6p_socket
->so_state
& SS_PRIV
);
1318 #if defined(HAVE_NRL_INPCB)
1319 rcvopts
= inp
->inp_inputopts6
;
1321 rcvopts
= in6p
->in6p_inputopts
;
1324 if (level
== IPPROTO_IPV6
) {
1327 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1333 case IPV6_PKTOPTIONS
:
1335 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1338 error
= sooptgetm(sopt
, &m
); /* XXX */
1341 error
= sooptmcopyin(sopt
, m
); /* XXX */
1344 error
= ip6_pcbopts(&in6p
->in6p_outputopts
,
1346 m_freem(m
); /* XXX */
1349 error
= ip6_pcbopts(&inp
->inp_outputopts6
,
1352 error
= ip6_pcbopts(&in6p
->in6p_outputopts
,
1354 #endif /* HAVE_NRL_INPCB */
1355 #endif /* FreeBSD >= 3 */
1359 * Use of some Hop-by-Hop options or some
1360 * Destination options, might require special
1361 * privilege. That is, normal applications
1362 * (without special privilege) might be forbidden
1363 * from setting certain options in outgoing packets,
1364 * and might never see certain options in received
1365 * packets. [RFC 2292 Section 6]
1366 * KAME specific note:
1367 * KAME prevents non-privileged users from sending or
1368 * receiving ANY hbh/dst options in order to avoid
1369 * overhead of parsing options in the kernel.
1371 case IPV6_RECVHOPOPTS
:
1372 case IPV6_RECVDSTOPTS
:
1373 case IPV6_RECVRTHDRDSTOPTS
:
1379 case IPV6_UNICAST_HOPS
:
1384 case IPV6_RECVPKTINFO
:
1385 case IPV6_RECVHOPLIMIT
:
1386 case IPV6_RECVRTHDR
:
1387 case IPV6_USE_MIN_MTU
:
1388 #ifdef notyet /* To be implemented */
1389 case IPV6_RECVPATHMTU
:
1391 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1392 case IPV6_BINDV6ONLY
:
1394 if (optlen
!= sizeof(int))
1397 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1398 error
= sooptcopyin(sopt
, &optval
,
1399 sizeof optval
, sizeof optval
);
1403 optval
= *mtod(m
, int *);
1407 case IPV6_UNICAST_HOPS
:
1408 if (optval
< -1 || optval
>= 256)
1411 /* -1 = kernel default */
1413 inp
->inp_hops
= optval
;
1415 in6p
->in6p_hops
= optval
;
1417 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1418 if ((in6p
->in6p_vflag
&
1420 in6p
->inp_ip_ttl
= optval
;
1426 #define OPTSET(bit) \
1428 inp->inp_flags |= (bit); \
1430 inp->inp_flags &= ~(bit);
1432 #define OPTSET(bit) \
1434 in6p->in6p_flags |= (bit); \
1436 in6p->in6p_flags &= ~(bit);
1439 #define OPTBIT(bit) (inp->inp_flags & (bit) ? 1 : 0)
1441 #define OPTBIT(bit) (in6p->in6p_flags & (bit) ? 1 : 0)
1444 case IPV6_RECVPKTINFO
:
1445 OPTSET(IN6P_PKTINFO
);
1446 if (OPTBIT(IN6P_PKTINFO
) == 0)
1447 ip6_reset_rcvopt(rcvopts
, IPV6_RECVPKTINFO
);
1453 OPTSET(IN6P_HOPLIMIT
);
1454 if (OPTBIT(IN6P_HOPLIMIT
) == 0)
1455 ip6_reset_rcvopt(rcvopts
, IPV6_RECVHOPLIMIT
);
1457 #else /* new advanced API (2292bis) */
1458 struct ip6_pktopts
**optp
;
1460 optp
= &inp
->inp_outputopts6
;
1462 optp
= &in6p
->in6p_outputopts
;
1465 error
= ip6_pcbopt(IPV6_HOPLIMIT
,
1474 case IPV6_RECVHOPLIMIT
:
1475 OPTSET(IN6P_HOPLIMIT
);
1476 if (OPTBIT(IN6P_HOPLIMIT
) == 0)
1477 ip6_reset_rcvopt(rcvopts
, IPV6_RECVHOPLIMIT
);
1480 case IPV6_RECVHOPOPTS
:
1481 OPTSET(IN6P_HOPOPTS
);
1482 if (OPTBIT(IN6P_HOPOPTS
) == 0)
1483 ip6_reset_rcvopt(rcvopts
, IPV6_RECVHOPOPTS
);
1486 case IPV6_RECVDSTOPTS
:
1487 OPTSET(IN6P_DSTOPTS
);
1488 if (OPTBIT(IN6P_DSTOPTS
) == 0)
1489 ip6_reset_rcvopt(rcvopts
, IPV6_RECVDSTOPTS
);
1492 case IPV6_RECVRTHDRDSTOPTS
:
1493 OPTSET(IN6P_RTHDRDSTOPTS
);
1494 if (OPTBIT(IN6P_RTHDRDSTOPTS
) == 0)
1495 ip6_reset_rcvopt(rcvopts
, IPV6_RECVRTHDRDSTOPTS
);
1498 case IPV6_RECVRTHDR
:
1500 if (OPTBIT(IN6P_RTHDR
) == 0)
1501 ip6_reset_rcvopt(rcvopts
, IPV6_RECVRTHDR
);
1506 inp
->inp_csumoffset
= optval
;
1508 in6p
->in6p_cksum
= optval
;
1516 case IPV6_USE_MIN_MTU
:
1517 OPTSET(IN6P_MINMTU
);
1520 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || (defined(__NetBSD__) && !defined(INET6_BINDV6ONLY)) || defined (__APPLE__)
1521 case IPV6_BINDV6ONLY
:
1522 OPTSET(IN6P_BINDV6ONLY
);
1532 case IPV6_RTHDRDSTOPTS
:
1533 if (optlen
== sizeof(int)) {
1535 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1536 error
= sooptcopyin(sopt
, &optval
,
1537 sizeof optval
, sizeof optval
);
1541 optval
= *mtod(m
, int *);
1545 OPTSET(IN6P_PKTINFO
);
1546 if (OPTBIT(IN6P_PKTINFO
) == 0)
1547 ip6_reset_rcvopt(rcvopts
, IPV6_RECVPKTINFO
);
1551 * Check super-user privilege.
1557 OPTSET(IN6P_HOPOPTS
);
1558 if (OPTBIT(IN6P_HOPOPTS
) == 0)
1559 ip6_reset_rcvopt(rcvopts
, IPV6_RECVHOPOPTS
);
1564 OPTSET(IN6P_DSTOPTS
|IN6P_RTHDRDSTOPTS
); /* XXX */
1565 if (OPTBIT(IN6P_DSTOPTS
) == 0) {
1566 ip6_reset_rcvopt(rcvopts
, IPV6_RECVDSTOPTS
);
1567 ip6_reset_rcvopt(rcvopts
, IPV6_RECVRTHDRDSTOPTS
);
1572 if (OPTBIT(IN6P_RTHDR
) == 0)
1573 ip6_reset_rcvopt(rcvopts
, IPV6_RECVRTHDR
);
1578 /* new advanced API (2292bis) */
1581 struct ip6_pktopts
**optp
;
1583 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1584 optbuf
= sopt
->sopt_val
;
1585 optlen
= sopt
->sopt_valsize
;
1587 if (m
&& m
->m_next
) {
1588 error
= EINVAL
; /* XXX */
1592 optbuf
= mtod(m
, u_char
*);
1601 optp
= &inp
->inp_outputopts6
;
1603 optp
= &in6p
->in6p_outputopts
;
1606 error
= ip6_pcbopt(optname
,
1613 case IPV6_MULTICAST_IF
:
1614 case IPV6_MULTICAST_HOPS
:
1615 case IPV6_MULTICAST_LOOP
:
1616 case IPV6_JOIN_GROUP
:
1617 case IPV6_LEAVE_GROUP
:
1618 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1621 if (sopt
->sopt_valsize
> MLEN
) {
1626 MGET(m
, sopt
->sopt_p
? M_WAIT
: M_DONTWAIT
, MT_HEADER
);
1631 m
->m_len
= sopt
->sopt_valsize
;
1632 error
= sooptcopyin(sopt
, mtod(m
, char *),
1633 m
->m_len
, m
->m_len
);
1634 error
= ip6_setmoptions(sopt
->sopt_name
,
1635 &in6p
->in6p_moptions
,
1641 error
= ip6_setmoptions(optname
,
1642 &inp
->inp_moptions6
, m
);
1644 * XXX: setting the flag would be redundant
1645 * except at the first time. Also, we
1646 * actually don't have to reset the flag,
1647 * since ip6_freemoptions() would simply
1648 * return when the inp_moptions6 is NULL.
1650 if (inp
->inp_moptions6
)
1651 inp
->inp_flags
|= INP_IPV6_MCAST
;
1653 inp
->inp_flags
&= ~INP_IPV6_MCAST
;
1655 error
= ip6_setmoptions(optname
,
1656 &in6p
->in6p_moptions
, m
);
1662 case IPV6_PORTRANGE
:
1663 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1664 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
1669 optval
= *mtod(m
, int *);
1674 # define in6p_flags inp_flags
1677 case IPV6_PORTRANGE_DEFAULT
:
1678 in6p
->in6p_flags
&= ~(IN6P_LOWPORT
);
1679 in6p
->in6p_flags
&= ~(IN6P_HIGHPORT
);
1682 case IPV6_PORTRANGE_HIGH
:
1683 in6p
->in6p_flags
&= ~(IN6P_LOWPORT
);
1684 in6p
->in6p_flags
|= IN6P_HIGHPORT
;
1687 case IPV6_PORTRANGE_LOW
:
1688 in6p
->in6p_flags
&= ~(IN6P_HIGHPORT
);
1689 in6p
->in6p_flags
|= IN6P_LOWPORT
;
1704 case IPV6_IPSEC_POLICY
:
1708 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1712 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1713 if (error
= sooptgetm(sopt
, &m
)) /* XXX */
1715 if (error
= sooptmcopyin(sopt
, m
)) /* XXX */
1719 req
= mtod(m
, caddr_t
);
1723 error
= ipsec6_set_policy(inp
, optname
, req
,
1726 error
= ipsec6_set_policy(in6p
, optname
, req
,
1729 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1742 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1744 struct mbuf
**mp
= &m
;
1747 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1748 if (ip6_fw_ctl_ptr
== NULL
)
1750 if (error
= sooptgetm(sopt
, &m
)) /* XXX */
1752 if (error
= sooptmcopyin(sopt
, m
)) /* XXX */
1755 if (ip6_fw_ctl_ptr
== NULL
) {
1756 if (m
) (void)m_free(m
);
1760 error
= (*ip6_fw_ctl_ptr
)(optname
, mp
);
1767 error
= ENOPROTOOPT
;
1770 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
1776 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1783 case IPV6_PKTOPTIONS
:
1784 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1785 if (in6p
->in6p_inputopts
&&
1786 in6p
->in6p_inputopts
->head
) {
1787 error
= sooptmcopyout(sopt
,
1788 in6p
->in6p_inputopts
->head
);
1790 sopt
->sopt_valsize
= 0;
1791 #elif defined(HAVE_NRL_INPCB)
1792 if (inp
->inp_options
) {
1793 *mp
= m_copym(inp
->inp_options
, 0,
1796 *mp
= m_get(M_WAIT
, MT_SOOPTS
);
1800 if (in6p
->in6p_inputopts
&&
1801 in6p
->in6p_inputopts
->head
) {
1802 *mp
= m_copym(in6p
->in6p_inputopts
->head
,
1803 0, M_COPYALL
, M_WAIT
);
1805 *mp
= m_get(M_WAIT
, MT_SOOPTS
);
1811 case IPV6_RECVHOPOPTS
:
1812 case IPV6_RECVDSTOPTS
:
1813 case IPV6_RECVRTHDRDSTOPTS
:
1819 case IPV6_UNICAST_HOPS
:
1822 case IPV6_RECVPKTINFO
:
1823 case IPV6_RECVHOPLIMIT
:
1824 case IPV6_RECVRTHDR
:
1825 case IPV6_USE_MIN_MTU
:
1826 #ifdef notyet /* To be implemented */
1827 case IPV6_RECVPATHMTU
:
1831 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || (defined(__NetBSD__) && !defined(INET6_BINDV6ONLY)) || defined(__APPLE__)
1832 case IPV6_BINDV6ONLY
:
1835 case IPV6_PORTRANGE
:
1839 case IPV6_UNICAST_HOPS
:
1841 optval
= inp
->inp_hops
;
1843 optval
= in6p
->in6p_hops
;
1847 case IPV6_RECVPKTINFO
:
1848 optval
= OPTBIT(IN6P_PKTINFO
);
1851 case IPV6_RECVHOPLIMIT
:
1852 optval
= OPTBIT(IN6P_HOPLIMIT
);
1855 case IPV6_RECVHOPOPTS
:
1856 optval
= OPTBIT(IN6P_HOPOPTS
);
1859 case IPV6_RECVDSTOPTS
:
1860 optval
= OPTBIT(IN6P_DSTOPTS
);
1863 case IPV6_RECVRTHDRDSTOPTS
:
1864 optval
= OPTBIT(IN6P_RTHDRDSTOPTS
);
1869 optval
= inp
->inp_csumoffset
;
1871 optval
= in6p
->in6p_cksum
;
1875 case IPV6_USE_MIN_MTU
:
1876 optval
= OPTBIT(IN6P_MINMTU
);
1880 optval
= OPTBIT(IN6P_FAITH
);
1883 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || (defined(__NetBSD__) && !defined(INET6_BINDV6ONLY)) || defined (__APPLE__)
1884 case IPV6_BINDV6ONLY
:
1885 optval
= OPTBIT(IN6P_BINDV6ONLY
);
1890 case IPV6_PORTRANGE
:
1894 flags
= inp
->inp_flags
;
1896 flags
= in6p
->in6p_flags
;
1898 if (flags
& IN6P_HIGHPORT
)
1899 optval
= IPV6_PORTRANGE_HIGH
;
1900 else if (flags
& IN6P_LOWPORT
)
1901 optval
= IPV6_PORTRANGE_LOW
;
1908 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1909 error
= sooptcopyout(sopt
, &optval
,
1912 *mp
= m
= m_get(M_WAIT
, MT_SOOPTS
);
1913 m
->m_len
= sizeof(int);
1914 *mtod(m
, int *) = optval
;
1922 case IPV6_RTHDRDSTOPTS
:
1924 if (optname
== IPV6_HOPOPTS
||
1925 optname
== IPV6_DSTOPTS
||
1930 optbit
= OPTBIT(IN6P_PKTINFO
);
1933 optval
= OPTBIT(IN6P_HOPLIMIT
);
1936 optbit
= OPTBIT(IN6P_HOPOPTS
);
1939 optbit
= OPTBIT(IN6P_RTHDR
);
1942 optbit
= OPTBIT(IN6P_DSTOPTS
|IN6P_RTHDRDSTOPTS
);
1944 case IPV6_RTHDRDSTOPTS
: /* in 2292bis only */
1947 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1948 error
= sooptcopyout(sopt
, &optval
,
1951 *mp
= m
= m_get(M_WAIT
, MT_SOOPTS
);
1952 m
->m_len
= sizeof(int);
1953 *mtod(m
, int *) = optval
;
1954 #endif /* FreeBSD3 */
1955 #else /* new advanced API */
1958 #define in6p_outputopts inp_outputopts6
1960 error
= ip6_getpcbopt(in6p
->in6p_outputopts
,
1964 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1965 /* note that optdatalen maybe 0 */
1966 error
= sooptcopyout(sopt
, optdata
,
1968 #else /* !FreeBSD3 */
1969 if (optdatalen
> MCLBYTES
)
1970 return(EMSGSIZE
); /* XXX */
1971 *mp
= m
= m_get(M_WAIT
, MT_SOOPTS
);
1972 if (optdatalen
> MLEN
)
1974 m
->m_len
= optdatalen
;
1975 bcopy(optdata
, mtod(m
, void *),
1977 #endif /* FreeBSD3 */
1981 #undef in6p_outputopts
1983 #endif /* COMPAT_RFC2292 */
1986 case IPV6_MULTICAST_IF
:
1987 case IPV6_MULTICAST_HOPS
:
1988 case IPV6_MULTICAST_LOOP
:
1989 case IPV6_JOIN_GROUP
:
1990 case IPV6_LEAVE_GROUP
:
1991 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
1994 error
= ip6_getmoptions(sopt
->sopt_name
,
1995 in6p
->in6p_moptions
, &m
);
1997 error
= sooptcopyout(sopt
,
1998 mtod(m
, char *), m
->m_len
);
2001 #elif defined(HAVE_NRL_INPCB)
2002 error
= ip6_getmoptions(optname
, inp
->inp_moptions6
, mp
);
2004 error
= ip6_getmoptions(optname
, in6p
->in6p_moptions
, mp
);
2009 case IPV6_IPSEC_POLICY
:
2013 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2014 struct mbuf
*m
= NULL
;
2015 struct mbuf
**mp
= &m
;
2017 error
= sooptgetm(sopt
, &m
); /* XXX */
2020 error
= sooptmcopyin(sopt
, m
); /* XXX */
2025 req
= mtod(m
, caddr_t
);
2029 error
= ipsec6_get_policy(inp
, req
, len
, mp
);
2031 error
= ipsec6_get_policy(in6p
, req
, len
, mp
);
2033 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2035 error
= sooptmcopyout(sopt
, m
); /*XXX*/
2045 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2047 struct mbuf
**mp
= &m
;
2050 if (ip6_fw_ctl_ptr
== NULL
)
2052 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
2058 error
= (*ip6_fw_ctl_ptr
)(optname
, mp
);
2059 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2061 error
= sooptmcopyout(sopt
, m
); /* XXX */
2070 error
= ENOPROTOOPT
;
2077 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
2078 if (op
== PRCO_SETOPT
&& *mp
)
2086 * Set up IP6 options in pcb for insertion in output packets or
2087 * specifying behavior of outgoing packets.
2090 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2091 ip6_pcbopts(pktopt
, m
, so
, sopt
)
2093 ip6_pcbopts(pktopt
, m
, so
)
2095 struct ip6_pktopts
**pktopt
;
2096 register struct mbuf
*m
;
2098 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2099 struct sockopt
*sopt
;
2102 register struct ip6_pktopts
*opt
= *pktopt
;
2104 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
2105 struct proc
*p
= sopt
->sopt_p
;
2107 struct proc
*p
= curproc
; /* XXX */
2111 /* turn off any old options. */
2114 if (opt
->ip6po_pktinfo
|| opt
->ip6po_nexthop
||
2115 opt
->ip6po_hbh
|| opt
->ip6po_dest1
|| opt
->ip6po_dest2
||
2116 opt
->ip6po_rhinfo
.ip6po_rhi_rthdr
)
2117 printf("ip6_pcbopts: all specified options are cleared.\n");
2119 ip6_clearpktopts(opt
, 1, -1);
2122 opt
= _MALLOC(sizeof(*opt
), M_IP6OPT
, M_WAITOK
);
2125 if (!m
|| m
->m_len
== 0) {
2127 * Only turning off any previous options.
2130 _FREE(opt
, M_IP6OPT
);
2134 /* set options specified by user. */
2136 if (p
&& !suser(p
->p_ucred
, &p
->p_acflag
))
2139 if ((error
= ip6_setpktoptions(m
, opt
, priv
, 1)) != 0) {
2140 ip6_clearpktopts(opt
, 1, -1); /* XXX: discard all options */
2148 * Set up an IP6 option in pcb for insertion in output packets or
2149 * specifying behavior of outgoing packets.
2150 * XXX: The logic of this function is very similar to ip6_setpktoptions().
2153 ip6_pcbopt(optname
, buf
, len
, pktopt
, priv
)
2154 int optname
, len
, priv
;
2156 struct ip6_pktopts
**pktopt
;
2158 struct ip6_pktopts
*opt
;
2159 struct in6_pktinfo
*pktinfo
;
2161 if (*pktopt
== NULL
) {
2162 *pktopt
= _MALLOC(sizeof(struct ip6_pktopts
), M_IP6OPT
,
2164 bzero(*pktopt
, sizeof(struct ip6_pktopts
));
2165 (*pktopt
)->ip6po_hlim
= -1;
2171 if (len
== 0) { /* just remove the option */
2172 ip6_clearpktopts(opt
, 1, IPV6_PKTINFO
);
2176 if (len
!= sizeof(struct in6_pktinfo
))
2178 pktinfo
= (struct in6_pktinfo
*)buf
;
2181 * An application can clear any sticky IPV6_PKTINFO option by
2182 * doing a "regular" setsockopt with ipi6_addr being
2183 * in6addr_any and ipi6_ifindex being zero.
2184 * [rfc2292bis-01, Section 6]
2185 * XXX: Is this a good feature?? (jinmei@kame.net)
2187 if (pktinfo
->ipi6_ifindex
== 0 &&
2188 IN6_IS_ADDR_UNSPECIFIED(&pktinfo
->ipi6_addr
)) {
2189 ip6_clearpktopts(opt
, 1, IPV6_PKTINFO
);
2193 /* XXX: this overrides the original data space */
2194 if (pktinfo
->ipi6_ifindex
&&
2195 IN6_IS_ADDR_LINKLOCAL(&pktinfo
->ipi6_addr
))
2196 pktinfo
->ipi6_addr
.s6_addr16
[1] =
2197 htons(pktinfo
->ipi6_ifindex
);
2199 if (pktinfo
->ipi6_ifindex
> if_index
||
2200 pktinfo
->ipi6_ifindex
< 0)
2204 * Check if the requested source address is indeed a unicast
2205 * address assigned to the node.
2207 if (!IN6_IS_ADDR_UNSPECIFIED(&pktinfo
->ipi6_addr
)) {
2209 struct sockaddr_in6 sin6
;
2211 bzero(&sin6
, sizeof(sin6
));
2212 sin6
.sin6_len
= sizeof(sin6
);
2213 sin6
.sin6_family
= AF_INET6
;
2214 sin6
.sin6_addr
= pktinfo
->ipi6_addr
;
2215 ia
= ifa_ifwithaddr(sin6tosa(&sin6
));
2217 return(EADDRNOTAVAIL
);
2220 if (opt
->ip6po_pktinfo
== NULL
)
2221 opt
->ip6po_pktinfo
= _MALLOC(sizeof(struct in6_pktinfo
),
2222 M_IP6OPT
, M_WAITOK
);
2223 bcopy(pktinfo
, opt
->ip6po_pktinfo
, sizeof(*pktinfo
));
2230 if (len
!= sizeof(int))
2233 if (*hlimp
< -1 || *hlimp
> 255)
2236 opt
->ip6po_hlim
= *hlimp
;
2243 if (len
== 0) { /* just remove the option */
2244 ip6_clearpktopts(opt
, 1, IPV6_NEXTHOP
);
2248 /* check if cmsg_len is large enough for sa_len */
2249 if (len
< sizeof(u_char
) ||
2253 /* turn off the previous option */
2254 ip6_clearpktopts(opt
, 1, IPV6_NEXTHOP
);
2256 opt
->ip6po_nexthop
= _MALLOC(*buf
, M_IP6OPT
, M_WAITOK
);
2257 bcopy(buf
, opt
->ip6po_nexthop
, *buf
);
2261 struct ip6_hbh
*hbh
;
2265 * XXX: We don't allow a non-privileged user to set ANY HbH
2266 * options, since per-option restriction has too much
2273 ip6_clearpktopts(opt
, 1, IPV6_HOPOPTS
);
2274 break; /* just remove the option */
2277 if (len
< sizeof(struct ip6_hbh
))
2279 hbh
= (struct ip6_hbh
*)buf
;
2280 hbhlen
= (hbh
->ip6h_len
+ 1) << 3;
2284 /* turn off the previous option */
2285 ip6_clearpktopts(opt
, 1, IPV6_HOPOPTS
);
2287 opt
->ip6po_hbh
= _MALLOC(hbhlen
, M_IP6OPT
, M_WAITOK
);
2288 bcopy(buf
, opt
->ip6po_hbh
, hbhlen
);
2293 case IPV6_RTHDRDSTOPTS
:
2295 struct ip6_dest
*dest
, *newdest
;
2298 if (!priv
) /* XXX: see the comment for IPV6_HOPOPTS */
2302 ip6_clearpktopts(opt
, 1, optname
);
2303 break; /* just remove the option */
2306 if (len
< sizeof(struct ip6_dest
))
2308 dest
= (struct ip6_dest
*)buf
;
2309 destlen
= (dest
->ip6d_len
+ 1) << 3;
2313 /* turn off the previous option */
2314 ip6_clearpktopts(opt
, 1, optname
);
2316 newdest
= _MALLOC(destlen
, M_IP6OPT
, M_WAITOK
);
2317 bcopy(buf
, newdest
, destlen
);
2319 if (optname
== IPV6_DSTOPTS
)
2320 opt
->ip6po_dest2
= newdest
;
2322 opt
->ip6po_dest1
= newdest
;
2328 struct ip6_rthdr
*rth
;
2332 ip6_clearpktopts(opt
, 1, IPV6_RTHDR
);
2333 break; /* just remove the option */
2336 if (len
< sizeof(struct ip6_rthdr
))
2338 rth
= (struct ip6_rthdr
*)buf
;
2339 rthlen
= (rth
->ip6r_len
+ 1) << 3;
2343 switch(rth
->ip6r_type
) {
2344 case IPV6_RTHDR_TYPE_0
:
2345 if (rth
->ip6r_len
== 0) /* must contain one addr */
2347 if (rth
->ip6r_len
% 2) /* length must be even */
2349 if (rth
->ip6r_len
/ 2 != rth
->ip6r_segleft
)
2353 return(EINVAL
); /* not supported */
2356 /* turn off the previous option */
2357 ip6_clearpktopts(opt
, 1, IPV6_RTHDR
);
2359 opt
->ip6po_rthdr
= _MALLOC(rthlen
, M_IP6OPT
, M_WAITOK
);
2360 bcopy(buf
, opt
->ip6po_rthdr
, rthlen
);
2365 return(ENOPROTOOPT
);
2366 } /* end of switch */
2372 ip6_getpcbopt(pktopt
, optname
, datap
, datalenp
)
2373 struct ip6_pktopts
*pktopt
;
2374 int optname
, *datalenp
;
2377 void *optdata
= NULL
;
2378 struct ip6_ext
*ip6e
;
2386 if (pktopt
->ip6po_pktinfo
) {
2387 optdata
= (void *)pktopt
->ip6po_pktinfo
;
2388 optdatalen
= sizeof(struct in6_pktinfo
);
2392 optdata
= (void *)&pktopt
->ip6po_hlim
;
2393 optdatalen
= sizeof(int);
2396 if (pktopt
->ip6po_hbh
) {
2397 optdata
= (void *)pktopt
->ip6po_hbh
;
2398 ip6e
= (struct ip6_ext
*)pktopt
->ip6po_hbh
;
2399 optdatalen
= (ip6e
->ip6e_len
+ 1) << 3;
2403 if (pktopt
->ip6po_rthdr
) {
2404 optdata
= (void *)pktopt
->ip6po_rthdr
;
2405 ip6e
= (struct ip6_ext
*)pktopt
->ip6po_rthdr
;
2406 optdatalen
= (ip6e
->ip6e_len
+ 1) << 3;
2409 case IPV6_RTHDRDSTOPTS
:
2410 if (pktopt
->ip6po_dest1
) {
2411 optdata
= (void *)pktopt
->ip6po_dest1
;
2412 ip6e
= (struct ip6_ext
*)pktopt
->ip6po_dest1
;
2413 optdatalen
= (ip6e
->ip6e_len
+ 1) << 3;
2417 if (pktopt
->ip6po_dest2
) {
2418 optdata
= (void *)pktopt
->ip6po_dest2
;
2419 ip6e
= (struct ip6_ext
*)pktopt
->ip6po_dest2
;
2420 optdatalen
= (ip6e
->ip6e_len
+ 1) << 3;
2427 *datalenp
= optdatalen
;
2433 ip6_clearpktopts(pktopt
, needfree
, optname
)
2434 struct ip6_pktopts
*pktopt
;
2435 int needfree
, optname
;
2440 if (optname
== -1 || optname
== IPV6_PKTINFO
) {
2441 if (needfree
&& pktopt
->ip6po_pktinfo
)
2442 _FREE(pktopt
->ip6po_pktinfo
, M_IP6OPT
);
2443 pktopt
->ip6po_pktinfo
= NULL
;
2445 if (optname
== -1 || optname
== IPV6_HOPLIMIT
)
2446 pktopt
->ip6po_hlim
= -1;
2447 if (optname
== -1 || optname
== IPV6_NEXTHOP
) {
2448 if (needfree
&& pktopt
->ip6po_nexthop
)
2449 _FREE(pktopt
->ip6po_nexthop
, M_IP6OPT
);
2450 pktopt
->ip6po_nexthop
= NULL
;
2452 if (optname
== -1 || optname
== IPV6_HOPOPTS
) {
2453 if (needfree
&& pktopt
->ip6po_hbh
)
2454 _FREE(pktopt
->ip6po_hbh
, M_IP6OPT
);
2455 pktopt
->ip6po_hbh
= NULL
;
2457 if (optname
== -1 || optname
== IPV6_RTHDRDSTOPTS
) {
2458 if (needfree
&& pktopt
->ip6po_dest1
)
2459 _FREE(pktopt
->ip6po_dest1
, M_IP6OPT
);
2460 pktopt
->ip6po_dest1
= NULL
;
2462 if (optname
== -1 || optname
== IPV6_RTHDR
) {
2463 if (needfree
&& pktopt
->ip6po_rhinfo
.ip6po_rhi_rthdr
)
2464 _FREE(pktopt
->ip6po_rhinfo
.ip6po_rhi_rthdr
, M_IP6OPT
);
2465 pktopt
->ip6po_rhinfo
.ip6po_rhi_rthdr
= NULL
;
2466 if (pktopt
->ip6po_route
.ro_rt
) {
2467 RTFREE(pktopt
->ip6po_route
.ro_rt
);
2468 pktopt
->ip6po_route
.ro_rt
= NULL
;
2471 if (optname
== -1 || optname
== IPV6_DSTOPTS
) {
2472 if (needfree
&& pktopt
->ip6po_dest2
)
2473 _FREE(pktopt
->ip6po_dest2
, M_IP6OPT
);
2474 pktopt
->ip6po_dest2
= NULL
;
2478 #define PKTOPT_EXTHDRCPY(type) if (src->type) {\
2480 (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
2481 dst->type = _MALLOC(hlen, M_IP6OPT, canwait);\
2482 if (dst->type == NULL && canwait == M_NOWAIT)\
2484 bcopy(src->type, dst->type, hlen);\
2487 struct ip6_pktopts
*
2488 ip6_copypktopts(src
, canwait
)
2489 struct ip6_pktopts
*src
;
2492 struct ip6_pktopts
*dst
;
2495 printf("ip6_clearpktopts: invalid argument\n");
2499 dst
= _MALLOC(sizeof(*dst
), M_IP6OPT
, canwait
);
2500 if (dst
== NULL
&& canwait
== M_NOWAIT
)
2502 bzero(dst
, sizeof(*dst
));
2504 dst
->ip6po_hlim
= src
->ip6po_hlim
;
2505 dst
->ip6po_flags
= src
->ip6po_flags
;
2506 if (src
->ip6po_pktinfo
) {
2507 dst
->ip6po_pktinfo
= _MALLOC(sizeof(*dst
->ip6po_pktinfo
),
2509 if (dst
->ip6po_pktinfo
== NULL
&& canwait
== M_NOWAIT
)
2511 *dst
->ip6po_pktinfo
= *src
->ip6po_pktinfo
;
2513 if (src
->ip6po_nexthop
) {
2514 dst
->ip6po_nexthop
= _MALLOC(src
->ip6po_nexthop
->sa_len
,
2516 if (dst
->ip6po_nexthop
== NULL
&& canwait
== M_NOWAIT
)
2518 bcopy(src
->ip6po_nexthop
, dst
->ip6po_nexthop
,
2519 src
->ip6po_nexthop
->sa_len
);
2521 PKTOPT_EXTHDRCPY(ip6po_hbh
);
2522 PKTOPT_EXTHDRCPY(ip6po_dest1
);
2523 PKTOPT_EXTHDRCPY(ip6po_dest2
);
2524 PKTOPT_EXTHDRCPY(ip6po_rthdr
); /* not copy the cached route */
2528 printf("ip6_copypktopts: copy failed");
2529 if (dst
->ip6po_pktinfo
) _FREE(dst
->ip6po_pktinfo
, M_IP6OPT
);
2530 if (dst
->ip6po_nexthop
) _FREE(dst
->ip6po_nexthop
, M_IP6OPT
);
2531 if (dst
->ip6po_hbh
) _FREE(dst
->ip6po_hbh
, M_IP6OPT
);
2532 if (dst
->ip6po_dest1
) _FREE(dst
->ip6po_dest1
, M_IP6OPT
);
2533 if (dst
->ip6po_dest2
) _FREE(dst
->ip6po_dest2
, M_IP6OPT
);
2534 if (dst
->ip6po_rthdr
) _FREE(dst
->ip6po_rthdr
, M_IP6OPT
);
2537 #undef PKTOPT_EXTHDRCPY
2540 ip6_freepcbopts(pktopt
)
2541 struct ip6_pktopts
*pktopt
;
2546 ip6_clearpktopts(pktopt
, 1, -1);
2548 _FREE(pktopt
, M_IP6OPT
);
2552 * Set the IP6 multicast options in response to user setsockopt().
2555 ip6_setmoptions(optname
, im6op
, m
)
2557 struct ip6_moptions
**im6op
;
2561 u_int loop
, ifindex
;
2562 struct ipv6_mreq
*mreq
;
2564 struct ip6_moptions
*im6o
= *im6op
;
2565 struct route_in6 ro
;
2566 struct sockaddr_in6
*dst
;
2567 struct in6_multi_mship
*imm
;
2569 struct proc
*p
= current_proc(); /* ### */
2573 * No multicast option buffer attached to the pcb;
2574 * allocate one and initialize to default values.
2576 im6o
= (struct ip6_moptions
*)
2577 _MALLOC(sizeof(*im6o
), M_IPMOPTS
, M_WAITOK
);
2582 im6o
->im6o_multicast_ifp
= NULL
;
2583 im6o
->im6o_multicast_hlim
= ip6_defmcasthlim
;
2584 im6o
->im6o_multicast_loop
= IPV6_DEFAULT_MULTICAST_LOOP
;
2585 LIST_INIT(&im6o
->im6o_memberships
);
2590 case IPV6_MULTICAST_IF
:
2592 * Select the interface for outgoing multicast packets.
2594 if (m
== NULL
|| m
->m_len
!= sizeof(u_int
)) {
2598 ifindex
= *(mtod(m
, u_int
*));
2599 if (ifindex
< 0 || if_index
< ifindex
) {
2600 error
= ENXIO
; /* XXX EINVAL? */
2603 ifp
= ifindex2ifnet
[ifindex
];
2604 if (ifp
== NULL
|| (ifp
->if_flags
& IFF_MULTICAST
) == 0) {
2605 error
= EADDRNOTAVAIL
;
2608 im6o
->im6o_multicast_ifp
= ifp
;
2611 case IPV6_MULTICAST_HOPS
:
2614 * Set the IP6 hoplimit for outgoing multicast packets.
2617 if (m
== NULL
|| m
->m_len
!= sizeof(int)) {
2621 optval
= *(mtod(m
, u_int
*));
2622 if (optval
< -1 || optval
>= 256)
2624 else if (optval
== -1)
2625 im6o
->im6o_multicast_hlim
= ip6_defmcasthlim
;
2627 im6o
->im6o_multicast_hlim
= optval
;
2631 case IPV6_MULTICAST_LOOP
:
2633 * Set the loopback flag for outgoing multicast packets.
2634 * Must be zero or one.
2636 if (m
== NULL
|| m
->m_len
!= sizeof(u_int
) ||
2637 (loop
= *(mtod(m
, u_int
*))) > 1) {
2641 im6o
->im6o_multicast_loop
= loop
;
2644 case IPV6_JOIN_GROUP
:
2646 * Add a multicast group membership.
2647 * Group must be a valid IP6 multicast address.
2649 if (m
== NULL
|| m
->m_len
!= sizeof(struct ipv6_mreq
)) {
2653 mreq
= mtod(m
, struct ipv6_mreq
*);
2654 if (IN6_IS_ADDR_UNSPECIFIED(&mreq
->ipv6mr_multiaddr
)) {
2656 * We use the unspecified address to specify to accept
2657 * all multicast addresses. Only super user is allowed
2661 if (suser(p
->p_ucred
, &p
->p_acflag
)) {
2666 } else if (!IN6_IS_ADDR_MULTICAST(&mreq
->ipv6mr_multiaddr
)) {
2672 * If the interface is specified, validate it.
2674 if (mreq
->ipv6mr_interface
< 0
2675 || if_index
< mreq
->ipv6mr_interface
) {
2676 error
= ENXIO
; /* XXX EINVAL? */
2680 * If no interface was explicitly specified, choose an
2681 * appropriate one according to the given multicast address.
2683 if (mreq
->ipv6mr_interface
== 0) {
2685 * If the multicast address is in node-local scope,
2686 * the interface should be a loopback interface.
2687 * Otherwise, look up the routing table for the
2688 * address, and choose the outgoing interface.
2689 * XXX: is it a good approach?
2691 if (IN6_IS_ADDR_MC_NODELOCAL(&mreq
->ipv6mr_multiaddr
)) {
2699 dst
= (struct sockaddr_in6
*)&ro
.ro_dst
;
2700 bzero(dst
, sizeof(*dst
));
2701 dst
->sin6_len
= sizeof(struct sockaddr_in6
);
2702 dst
->sin6_family
= AF_INET6
;
2703 dst
->sin6_addr
= mreq
->ipv6mr_multiaddr
;
2704 rtalloc((struct route
*)&ro
);
2705 if (ro
.ro_rt
== NULL
) {
2706 error
= EADDRNOTAVAIL
;
2709 ifp
= ro
.ro_rt
->rt_ifp
;
2713 ifp
= ifindex2ifnet
[mreq
->ipv6mr_interface
];
2716 * See if we found an interface, and confirm that it
2717 * supports multicast
2719 if (ifp
== NULL
|| (ifp
->if_flags
& IFF_MULTICAST
) == 0) {
2720 error
= EADDRNOTAVAIL
;
2724 * Put interface index into the multicast address,
2725 * if the address has link-local scope.
2727 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq
->ipv6mr_multiaddr
)) {
2728 mreq
->ipv6mr_multiaddr
.s6_addr16
[1]
2729 = htons(mreq
->ipv6mr_interface
);
2732 * See if the membership already exists.
2734 for (imm
= im6o
->im6o_memberships
.lh_first
;
2735 imm
!= NULL
; imm
= imm
->i6mm_chain
.le_next
)
2736 if (imm
->i6mm_maddr
->in6m_ifp
== ifp
&&
2737 IN6_ARE_ADDR_EQUAL(&imm
->i6mm_maddr
->in6m_addr
,
2738 &mreq
->ipv6mr_multiaddr
))
2745 * Everything looks good; add a new record to the multicast
2746 * address list for the given interface.
2748 imm
= _MALLOC(sizeof(*imm
), M_IPMADDR
, M_WAITOK
);
2753 if ((imm
->i6mm_maddr
=
2754 in6_addmulti(&mreq
->ipv6mr_multiaddr
, ifp
, &error
)) == NULL
) {
2755 _FREE(imm
, M_IPMADDR
);
2758 LIST_INSERT_HEAD(&im6o
->im6o_memberships
, imm
, i6mm_chain
);
2761 case IPV6_LEAVE_GROUP
:
2763 * Drop a multicast group membership.
2764 * Group must be a valid IP6 multicast address.
2766 if (m
== NULL
|| m
->m_len
!= sizeof(struct ipv6_mreq
)) {
2770 mreq
= mtod(m
, struct ipv6_mreq
*);
2771 if (IN6_IS_ADDR_UNSPECIFIED(&mreq
->ipv6mr_multiaddr
)) {
2772 if (suser(p
->p_ucred
, &p
->p_acflag
)) {
2776 } else if (!IN6_IS_ADDR_MULTICAST(&mreq
->ipv6mr_multiaddr
)) {
2781 * If an interface address was specified, get a pointer
2782 * to its ifnet structure.
2784 if (mreq
->ipv6mr_interface
< 0
2785 || if_index
< mreq
->ipv6mr_interface
) {
2786 error
= ENXIO
; /* XXX EINVAL? */
2789 ifp
= ifindex2ifnet
[mreq
->ipv6mr_interface
];
2791 * Put interface index into the multicast address,
2792 * if the address has link-local scope.
2794 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq
->ipv6mr_multiaddr
)) {
2795 mreq
->ipv6mr_multiaddr
.s6_addr16
[1]
2796 = htons(mreq
->ipv6mr_interface
);
2799 * Find the membership in the membership list.
2801 for (imm
= im6o
->im6o_memberships
.lh_first
;
2802 imm
!= NULL
; imm
= imm
->i6mm_chain
.le_next
) {
2804 imm
->i6mm_maddr
->in6m_ifp
== ifp
) &&
2805 IN6_ARE_ADDR_EQUAL(&imm
->i6mm_maddr
->in6m_addr
,
2806 &mreq
->ipv6mr_multiaddr
))
2810 /* Unable to resolve interface */
2811 error
= EADDRNOTAVAIL
;
2815 * Give up the multicast address record to which the
2816 * membership points.
2818 LIST_REMOVE(imm
, i6mm_chain
);
2819 in6_delmulti(imm
->i6mm_maddr
);
2820 _FREE(imm
, M_IPMADDR
);
2829 * If all options have default values, no need to keep the mbuf.
2831 if (im6o
->im6o_multicast_ifp
== NULL
&&
2832 im6o
->im6o_multicast_hlim
== ip6_defmcasthlim
&&
2833 im6o
->im6o_multicast_loop
== IPV6_DEFAULT_MULTICAST_LOOP
&&
2834 im6o
->im6o_memberships
.lh_first
== NULL
) {
2835 _FREE(*im6op
, M_IPMOPTS
);
2843 * Return the IP6 multicast options in response to user getsockopt().
2846 ip6_getmoptions(optname
, im6o
, mp
)
2848 register struct ip6_moptions
*im6o
;
2849 register struct mbuf
**mp
;
2851 u_int
*hlim
, *loop
, *ifindex
;
2853 #if __FreeBSD__ || defined (__APPLE__)
2854 *mp
= m_get(M_WAIT
, MT_HEADER
); /*XXX*/
2856 *mp
= m_get(M_WAIT
, MT_SOOPTS
);
2861 case IPV6_MULTICAST_IF
:
2862 ifindex
= mtod(*mp
, u_int
*);
2863 (*mp
)->m_len
= sizeof(u_int
);
2864 if (im6o
== NULL
|| im6o
->im6o_multicast_ifp
== NULL
)
2867 *ifindex
= im6o
->im6o_multicast_ifp
->if_index
;
2870 case IPV6_MULTICAST_HOPS
:
2871 hlim
= mtod(*mp
, u_int
*);
2872 (*mp
)->m_len
= sizeof(u_int
);
2874 *hlim
= ip6_defmcasthlim
;
2876 *hlim
= im6o
->im6o_multicast_hlim
;
2879 case IPV6_MULTICAST_LOOP
:
2880 loop
= mtod(*mp
, u_int
*);
2881 (*mp
)->m_len
= sizeof(u_int
);
2883 *loop
= ip6_defmcasthlim
;
2885 *loop
= im6o
->im6o_multicast_loop
;
2894 * Discard the IP6 multicast options.
2897 ip6_freemoptions(im6o
)
2898 register struct ip6_moptions
*im6o
;
2900 struct in6_multi_mship
*imm
;
2905 while ((imm
= im6o
->im6o_memberships
.lh_first
) != NULL
) {
2906 LIST_REMOVE(imm
, i6mm_chain
);
2907 if (imm
->i6mm_maddr
)
2908 in6_delmulti(imm
->i6mm_maddr
);
2909 _FREE(imm
, M_IPMADDR
);
2911 _FREE(im6o
, M_IPMOPTS
);
2915 * Set IPv6 outgoing packet options based on advanced API.
2918 ip6_setpktoptions(control
, opt
, priv
, needcopy
)
2919 struct mbuf
*control
;
2920 struct ip6_pktopts
*opt
;
2923 register struct cmsghdr
*cm
= 0;
2925 if (control
== 0 || opt
== 0)
2928 bzero(opt
, sizeof(*opt
));
2929 opt
->ip6po_hlim
= -1; /* -1 means to use default hop limit */
2932 * XXX: Currently, we assume all the optional information is stored
2935 if (control
->m_next
)
2938 for (; control
->m_len
; control
->m_data
+= CMSG_ALIGN(cm
->cmsg_len
),
2939 control
->m_len
-= CMSG_ALIGN(cm
->cmsg_len
)) {
2940 cm
= mtod(control
, struct cmsghdr
*);
2941 if (cm
->cmsg_len
== 0 || cm
->cmsg_len
> control
->m_len
)
2943 if (cm
->cmsg_level
!= IPPROTO_IPV6
)
2946 switch(cm
->cmsg_type
) {
2948 if (cm
->cmsg_len
!= CMSG_LEN(sizeof(struct in6_pktinfo
)))
2951 /* XXX: Is it really WAITOK? */
2952 opt
->ip6po_pktinfo
=
2953 _MALLOC(sizeof(struct in6_pktinfo
),
2954 M_IP6OPT
, M_WAITOK
);
2955 *opt
->ip6po_pktinfo
=
2956 *(struct in6_pktinfo
*)CMSG_DATA(cm
);
2958 opt
->ip6po_pktinfo
=
2959 (struct in6_pktinfo
*)CMSG_DATA(cm
);
2960 if (opt
->ip6po_pktinfo
->ipi6_ifindex
&&
2961 IN6_IS_ADDR_LINKLOCAL(&opt
->ip6po_pktinfo
->ipi6_addr
))
2962 opt
->ip6po_pktinfo
->ipi6_addr
.s6_addr16
[1] =
2963 htons(opt
->ip6po_pktinfo
->ipi6_ifindex
);
2965 if (opt
->ip6po_pktinfo
->ipi6_ifindex
> if_index
2966 || opt
->ip6po_pktinfo
->ipi6_ifindex
< 0) {
2971 * Check if the requested source address is indeed a
2972 * unicast address assigned to the node.
2974 if (!IN6_IS_ADDR_UNSPECIFIED(&opt
->ip6po_pktinfo
->ipi6_addr
)) {
2976 struct sockaddr_in6 sin6
;
2978 bzero(&sin6
, sizeof(sin6
));
2979 sin6
.sin6_len
= sizeof(sin6
);
2980 sin6
.sin6_family
= AF_INET6
;
2982 opt
->ip6po_pktinfo
->ipi6_addr
;
2983 ia
= ifa_ifwithaddr(sin6tosa(&sin6
));
2985 return(EADDRNOTAVAIL
);
2990 if (cm
->cmsg_len
!= CMSG_LEN(sizeof(int)))
2993 opt
->ip6po_hlim
= *(int *)CMSG_DATA(cm
);
2994 if (opt
->ip6po_hlim
< -1 || opt
->ip6po_hlim
> 255)
3002 if (cm
->cmsg_len
< sizeof(u_char
) ||
3003 /* check if cmsg_len is large enough for sa_len */
3004 cm
->cmsg_len
< CMSG_LEN(*CMSG_DATA(cm
)))
3008 opt
->ip6po_nexthop
=
3009 _MALLOC(*CMSG_DATA(cm
),
3010 M_IP6OPT
, M_WAITOK
);
3011 bcopy(CMSG_DATA(cm
),
3015 opt
->ip6po_nexthop
=
3016 (struct sockaddr
*)CMSG_DATA(cm
);
3021 struct ip6_hbh
*hbh
;
3024 if (cm
->cmsg_len
< CMSG_LEN(sizeof(struct ip6_hbh
)))
3026 hbh
= (struct ip6_hbh
*)CMSG_DATA(cm
);
3027 hbhlen
= (hbh
->ip6h_len
+ 1) << 3;
3028 if (cm
->cmsg_len
!= CMSG_LEN(hbhlen
))
3033 _MALLOC(hbhlen
, M_IP6OPT
, M_WAITOK
);
3034 bcopy(hbh
, opt
->ip6po_hbh
, hbhlen
);
3036 opt
->ip6po_hbh
= hbh
;
3042 struct ip6_dest
*dest
;
3045 if (cm
->cmsg_len
< CMSG_LEN(sizeof(struct ip6_dest
)))
3047 dest
= (struct ip6_dest
*)CMSG_DATA(cm
);
3048 destlen
= (dest
->ip6d_len
+ 1) << 3;
3049 if (cm
->cmsg_len
!= CMSG_LEN(destlen
))
3053 * If there is no routing header yet, the destination
3054 * options header should be put on the 1st part.
3055 * Otherwise, the header should be on the 2nd part.
3056 * (See RFC 2460, section 4.1)
3058 if (opt
->ip6po_rthdr
== NULL
) {
3061 _MALLOC(destlen
, M_IP6OPT
,
3063 bcopy(dest
, opt
->ip6po_dest1
, destlen
);
3065 opt
->ip6po_dest1
= dest
;
3069 _MALLOC(destlen
, M_IP6OPT
,
3071 bcopy(dest
, opt
->ip6po_dest2
, destlen
);
3073 opt
->ip6po_dest2
= dest
;
3080 struct ip6_rthdr
*rth
;
3083 if (cm
->cmsg_len
< CMSG_LEN(sizeof(struct ip6_rthdr
)))
3085 rth
= (struct ip6_rthdr
*)CMSG_DATA(cm
);
3086 rthlen
= (rth
->ip6r_len
+ 1) << 3;
3087 if (cm
->cmsg_len
!= CMSG_LEN(rthlen
))
3090 switch(rth
->ip6r_type
) {
3091 case IPV6_RTHDR_TYPE_0
:
3092 /* must contain one addr */
3093 if (rth
->ip6r_len
== 0)
3095 /* length must be even */
3096 if (rth
->ip6r_len
% 2)
3098 if (rth
->ip6r_len
/ 2 != rth
->ip6r_segleft
)
3102 return(EINVAL
); /* not supported */
3106 opt
->ip6po_rthdr
= _MALLOC(rthlen
, M_IP6OPT
,
3108 bcopy(rth
, opt
->ip6po_rthdr
, rthlen
);
3110 opt
->ip6po_rthdr
= rth
;
3115 case IPV6_REACHCONF
:
3118 * it looks dangerous to allow IPV6_REACHCONF to
3119 * normal user. it affects the ND state (system state)
3120 * and can affect communication by others - jinmei
3126 if (cm
->cmsg_len
!= CMSG_LEN(0))
3128 opt
->ip6po_flags
|= IP6PO_REACHCONF
;
3131 case IPV6_USE_MIN_MTU
:
3132 if (cm
->cmsg_len
!= CMSG_LEN(0))
3134 opt
->ip6po_flags
|= IP6PO_MINMTU
;
3138 return(ENOPROTOOPT
);
3146 * Routine called from ip6_output() to loop back a copy of an IP6 multicast
3147 * packet to the input queue of a specified interface. Note that this
3148 * calls the output routine of the loopback "driver", but with an interface
3149 * pointer that might NOT be &loif -- easier than replicating that code here.
3152 ip6_mloopback(ifp
, m
, dst
)
3154 register struct mbuf
*m
;
3155 register struct sockaddr_in6
*dst
;
3159 copym
= m_copy(m
, 0, M_COPYALL
);
3160 if (copym
!= NULL
) {
3164 * We need to send all loopback traffic down to dlil in case
3165 * a filter has tapped-in.
3169 dlil_find_dltag(APPLE_IF_FAM_LOOPBACK
, 0, PF_INET6
, &lo_dl_tag
);
3172 dlil_output(lo_dl_tag
, copym
, 0, (struct sockaddr
*) dst
, 0);
3174 printf("Warning: ip6_mloopback call to dlil_find_dltag failed!\n");
3178 (void)if_simloop(ifp
, copym
, (struct sockaddr
*)dst
, NULL
);
3179 (void)looutput(ifp
, copym
, (struct sockaddr
*)dst
, NULL
);
3185 * Chop IPv6 header off from the payload.
3188 ip6_splithdr(m
, exthdrs
)
3190 struct ip6_exthdrs
*exthdrs
;
3193 struct ip6_hdr
*ip6
;
3195 ip6
= mtod(m
, struct ip6_hdr
*);
3196 if (m
->m_len
> sizeof(*ip6
)) {
3197 MGETHDR(mh
, M_DONTWAIT
, MT_HEADER
);
3202 M_COPY_PKTHDR(mh
, m
);
3203 MH_ALIGN(mh
, sizeof(*ip6
));
3204 m
->m_flags
&= ~M_PKTHDR
;
3205 m
->m_len
-= sizeof(*ip6
);
3206 m
->m_data
+= sizeof(*ip6
);
3209 m
->m_len
= sizeof(*ip6
);
3210 bcopy((caddr_t
)ip6
, mtod(m
, caddr_t
), sizeof(*ip6
));
3212 exthdrs
->ip6e_ip6
= m
;
3217 * Compute IPv6 extension header length.
3220 # define in6pcb inpcb
3221 # define in6p_outputopts inp_outputopts6
3225 struct in6pcb
*in6p
;
3229 if (!in6p
->in6p_outputopts
)
3234 (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
3236 len
+= elen(in6p
->in6p_outputopts
->ip6po_hbh
);
3237 if (in6p
->in6p_outputopts
->ip6po_rthdr
)
3238 /* dest1 is valid with rthdr only */
3239 len
+= elen(in6p
->in6p_outputopts
->ip6po_dest1
);
3240 len
+= elen(in6p
->in6p_outputopts
->ip6po_rthdr
);
3241 len
+= elen(in6p
->in6p_outputopts
->ip6po_dest2
);
3247 # undef in6p_outputopts