2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. Neither the name of the project nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.7.2.4 2001/07/29 19:32:40 ume Exp $
60 * Copyright (c) 1982, 1986, 1988, 1993
61 * The Regents of the University of California. All rights reserved.
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
66 * 1. Redistributions of source code must retain the above copyright
67 * notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in the
70 * documentation and/or other materials provided with the distribution.
71 * 3. All advertising materials mentioning features or use of this software
72 * must display the following acknowledgement:
73 * This product includes software developed by the University of
74 * California, Berkeley and its contributors.
75 * 4. Neither the name of the University nor the names of its contributors
76 * may be used to endorse or promote products derived from this software
77 * without specific prior written permission.
79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
93 #include <sys/param.h>
94 #include <sys/malloc.h>
96 #include <sys/mcache.h>
98 #include <sys/socket.h>
99 #include <sys/protosw.h>
100 #include <sys/socketvar.h>
101 #include <sys/errno.h>
102 #include <sys/systm.h>
105 #include <net/net_api_stats.h>
106 #include <net/route.h>
107 #include <net/if_types.h>
108 #include <net/content_filter.h>
110 #include <netinet/in.h>
111 #include <netinet/in_var.h>
112 #include <netinet/in_systm.h>
113 #include <netinet/in_tclass.h>
114 #include <netinet/ip6.h>
115 #include <netinet6/ip6_var.h>
116 #include <netinet/icmp6.h>
117 #include <netinet/in_pcb.h>
118 #include <netinet6/in6_pcb.h>
119 #include <netinet6/nd6.h>
120 #include <netinet6/ip6protosw.h>
121 #include <netinet6/scope6_var.h>
122 #include <netinet6/raw_ip6.h>
125 #include <netinet6/ipsec.h>
126 #include <netinet6/ipsec6.h>
130 #include <net/necp.h>
134 * Raw interface to IP6 protocol.
137 extern struct inpcbhead ripcb
;
138 extern struct inpcbinfo ripcbinfo
;
139 extern u_int32_t rip_sendspace
;
140 extern u_int32_t rip_recvspace
;
142 struct rip6stat rip6stat
;
145 * Setup generic address and protocol structures
146 * for raw_input routine, then pass them along with
155 struct mbuf
*m
= *mp
;
156 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
158 struct inpcb
*last
= 0;
159 struct mbuf
*opts
= NULL
;
160 struct sockaddr_in6 rip6src
;
162 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
164 /* Expect 32-bit aligned data pointer on strict-align platforms */
165 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
167 rip6stat
.rip6s_ipackets
++;
169 init_sin6(&rip6src
, m
); /* general init */
171 lck_rw_lock_shared(ripcbinfo
.ipi_lock
);
172 LIST_FOREACH(in6p
, &ripcb
, inp_list
) {
173 if ((in6p
->in6p_vflag
& INP_IPV6
) == 0) {
176 if (in6p
->in6p_ip6_nxt
&&
177 in6p
->in6p_ip6_nxt
!= proto
) {
180 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
181 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
)) {
184 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
185 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
)) {
189 if (inp_restricted_recv(in6p
, ifp
)) {
193 if (proto
== IPPROTO_ICMPV6
|| in6p
->in6p_cksum
!= -1) {
194 rip6stat
.rip6s_isum
++;
195 if (in6_cksum(m
, ip6
->ip6_nxt
, *offp
,
196 m
->m_pkthdr
.len
- *offp
)) {
197 rip6stat
.rip6s_badsum
++;
202 struct mbuf
*n
= m_copy(m
, 0, (int)M_COPYALL
);
205 if (n
&& !necp_socket_is_allowed_to_send_recv_v6(in6p
, 0, 0,
206 &ip6
->ip6_dst
, &ip6
->ip6_src
, ifp
, 0, NULL
, NULL
, NULL
, NULL
)) {
208 /* do not inject data into pcb */
212 if ((last
->in6p_flags
& INP_CONTROLOPTS
) != 0 ||
214 /* Content Filter needs to see local address */
215 (last
->in6p_socket
->so_cfil_db
!= NULL
) ||
217 (last
->in6p_socket
->so_options
& SO_TIMESTAMP
) != 0 ||
218 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_MONOTONIC
) != 0 ||
219 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_CONTINUOUS
) != 0) {
220 ret
= ip6_savecontrol(last
, n
, &opts
);
228 /* strip intermediate headers */
230 so_recv_data_stat(last
->in6p_socket
, m
, 0);
231 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
232 (struct sockaddr
*)&rip6src
,
233 n
, opts
, NULL
) == 0) {
234 rip6stat
.rip6s_fullsock
++;
236 sorwakeup(last
->in6p_socket
);
245 if (last
&& !necp_socket_is_allowed_to_send_recv_v6(in6p
, 0, 0,
246 &ip6
->ip6_dst
, &ip6
->ip6_src
, ifp
, 0, NULL
, NULL
, NULL
, NULL
)) {
248 ip6stat
.ip6s_delivered
--;
249 /* do not inject data into pcb */
253 if ((last
->in6p_flags
& INP_CONTROLOPTS
) != 0 ||
255 /* Content Filter needs to see local address */
256 (last
->in6p_socket
->so_cfil_db
!= NULL
) ||
258 (last
->in6p_socket
->so_options
& SO_TIMESTAMP
) != 0 ||
259 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_MONOTONIC
) != 0 ||
260 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_CONTINUOUS
) != 0) {
261 ret
= ip6_savecontrol(last
, m
, &opts
);
265 ip6stat
.ip6s_delivered
--;
269 /* strip intermediate headers */
271 so_recv_data_stat(last
->in6p_socket
, m
, 0);
272 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
273 (struct sockaddr
*)&rip6src
, m
, opts
, NULL
) == 0) {
274 rip6stat
.rip6s_fullsock
++;
276 sorwakeup(last
->in6p_socket
);
279 rip6stat
.rip6s_nosock
++;
280 if (m
->m_flags
& M_MCAST
) {
281 rip6stat
.rip6s_nosockmcast
++;
283 if (proto
== IPPROTO_NONE
) {
286 char *prvnxtp
= ip6_get_prevhdr(m
, *offp
); /* XXX */
287 icmp6_error(m
, ICMP6_PARAM_PROB
,
288 ICMP6_PARAMPROB_NEXTHEADER
,
289 (int)(prvnxtp
- mtod(m
, char *)));
291 ip6stat
.ip6s_delivered
--;
295 lck_rw_done(ripcbinfo
.ipi_lock
);
305 __unused
struct ifnet
*ifp
)
307 struct ip6_hdr
*ip6
= NULL
;
308 struct mbuf
*m
= NULL
;
311 struct ip6ctlparam
*ip6cp
= NULL
;
312 const struct sockaddr_in6
*sa6_src
= NULL
;
313 void (*notify
)(struct inpcb
*, int) = in6_rtchange
;
315 if (sa
->sa_family
!= AF_INET6
||
316 sa
->sa_len
!= sizeof(struct sockaddr_in6
)) {
320 if ((unsigned)cmd
>= PRC_NCMDS
) {
323 if (PRC_IS_REDIRECT(cmd
)) {
324 notify
= in6_rtchange
;
326 } else if (cmd
== PRC_HOSTDEAD
) {
328 } else if (inet6ctlerrmap
[cmd
] == 0) {
332 /* if the parameter is from icmp6, decode it. */
334 ip6cp
= (struct ip6ctlparam
*)d
;
336 ip6
= ip6cp
->ip6c_ip6
;
337 off
= ip6cp
->ip6c_off
;
338 cmdarg
= ip6cp
->ip6c_cmdarg
;
339 sa6_src
= ip6cp
->ip6c_src
;
347 (void) in6_pcbnotify(&ripcbinfo
, sa
, 0, (const struct sockaddr
*)sa6_src
,
348 0, cmd
, cmdarg
, notify
);
352 * Generate IPv6 header and pass packet to ip6_output.
353 * Tack on options user may have setup with control call.
359 struct sockaddr_in6
*dstsock
,
360 struct mbuf
*control
,
363 struct in6_addr
*dst
;
366 u_int plen
= m
->m_pkthdr
.len
;
368 struct ip6_pktopts opt
, *optp
= NULL
;
369 struct ip6_moptions
*im6o
= NULL
;
370 struct ifnet
*oifp
= NULL
;
371 int type
= 0, code
= 0; /* for ICMPv6 output statistics only */
372 int sotc
= SO_TC_UNSPEC
;
373 int netsvctype
= _NET_SERVICE_TYPE_UNSPEC
;
374 struct ip6_out_args ip6oa
;
375 int flags
= IPV6_OUTARGS
;
376 struct sockaddr_in6 tmp
;
378 struct m_tag
*cfil_tag
= NULL
;
379 bool cfil_faddr_use
= false;
380 uint32_t cfil_so_state_change_cnt
= 0;
381 uint32_t cfil_so_options
= 0;
382 struct sockaddr
*cfil_faddr
= NULL
;
383 struct sockaddr_in6
*cfil_sin6
= NULL
;
386 in6p
= sotoin6pcb(so
);
394 * If socket is subject to Content Filter and no addr is passed in,
395 * retrieve CFIL saved state from mbuf and use it if necessary.
397 if (so
->so_cfil_db
&& !dstsock
) {
398 cfil_tag
= cfil_dgram_get_socket_state(m
, &cfil_so_state_change_cnt
, &cfil_so_options
, &cfil_faddr
, NULL
);
400 cfil_sin6
= SIN6(cfil_faddr
);
401 if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
403 * Socket is unconnected, simply use the saved faddr as 'addr' to go through
404 * the connect/disconnect logic.
407 } else if ((so
->so_state_change_cnt
!= cfil_so_state_change_cnt
) &&
408 (in6p
->in6p_fport
!= cfil_sin6
->sin6_port
||
409 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &cfil_sin6
->sin6_addr
))) {
411 * Socket is connected but socket state and dest addr/port changed.
412 * We need to use the saved faddr and socket options.
414 cfil_faddr_use
= true;
420 /* always copy sockaddr to avoid overwrites */
421 if (so
->so_state
& SS_ISCONNECTED
) {
422 if (dstsock
!= NULL
) {
427 bzero(&tmp
, sizeof(tmp
));
428 tmp
.sin6_family
= AF_INET6
;
429 tmp
.sin6_len
= sizeof(struct sockaddr_in6
);
432 cfil_faddr_use
? &cfil_sin6
->sin6_addr
:
434 &in6p
->in6p_faddr
, &tmp
.sin6_addr
, sizeof(struct in6_addr
));
437 if (dstsock
== NULL
) {
445 #if ENABLE_DEFAULT_SCOPE
446 if (dstsock
->sin6_scope_id
== 0) { /* not change if specified */
447 dstsock
->sin6_scope_id
= scope6_addr2default(&dstsock
->sin6_addr
);
451 bzero(&ip6oa
, sizeof(ip6oa
));
452 ip6oa
.ip6oa_boundif
= IFSCOPE_NONE
;
453 ip6oa
.ip6oa_flags
= IP6OAF_SELECT_SRCIF
;
457 || (necp_socket_should_use_flow_divert(in6p
))
467 if (dstsock
!= NULL
&& IN6_IS_ADDR_V4MAPPED(&dstsock
->sin6_addr
)) {
472 if (in6p
->inp_flags
& INP_BOUND_IF
) {
473 ip6oa
.ip6oa_boundif
= in6p
->inp_boundifp
->if_index
;
474 ip6oa
.ip6oa_flags
|= IP6OAF_BOUND_IF
;
476 if (INP_NO_CELLULAR(in6p
)) {
477 ip6oa
.ip6oa_flags
|= IP6OAF_NO_CELLULAR
;
479 if (INP_NO_EXPENSIVE(in6p
)) {
480 ip6oa
.ip6oa_flags
|= IP6OAF_NO_EXPENSIVE
;
482 if (INP_NO_CONSTRAINED(in6p
)) {
483 ip6oa
.ip6oa_flags
|= IP6OAF_NO_CONSTRAINED
;
485 if (INP_AWDL_UNRESTRICTED(in6p
)) {
486 ip6oa
.ip6oa_flags
|= IP6OAF_AWDL_UNRESTRICTED
;
488 if (INP_INTCOPROC_ALLOWED(in6p
)) {
489 ip6oa
.ip6oa_flags
|= IP6OAF_INTCOPROC_ALLOWED
;
492 dst
= &dstsock
->sin6_addr
;
494 sotc
= so_tc_from_control(control
, &netsvctype
);
496 if ((error
= ip6_setpktopts(control
, &opt
, NULL
,
497 SOCK_PROTO(so
))) != 0) {
502 optp
= in6p
->in6p_outputopts
;
504 if (sotc
== SO_TC_UNSPEC
) {
505 sotc
= so
->so_traffic_class
;
506 netsvctype
= so
->so_netsvctype
;
508 ip6oa
.ip6oa_sotc
= sotc
;
509 ip6oa
.ip6oa_netsvctype
= netsvctype
;
512 * For an ICMPv6 packet, we should know its type and code
513 * to update statistics.
515 if (SOCK_PROTO(so
) == IPPROTO_ICMPV6
) {
516 struct icmp6_hdr
*icmp6
;
517 if (m
->m_len
< sizeof(struct icmp6_hdr
) &&
518 (m
= m_pullup(m
, sizeof(struct icmp6_hdr
))) == NULL
) {
522 icmp6
= mtod(m
, struct icmp6_hdr
*);
523 type
= icmp6
->icmp6_type
;
524 code
= icmp6
->icmp6_code
;
527 if (in6p
->inp_flowhash
== 0) {
528 in6p
->inp_flowhash
= inp_calc_flowhash(in6p
);
530 /* update flowinfo - RFC 6437 */
531 if (in6p
->inp_flow
== 0 && in6p
->in6p_flags
& IN6P_AUTOFLOWLABEL
) {
532 in6p
->inp_flow
&= ~IPV6_FLOWLABEL_MASK
;
534 (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK
);
537 M_PREPEND(m
, sizeof(*ip6
), M_WAIT
, 1);
542 ip6
= mtod(m
, struct ip6_hdr
*);
545 * Next header might not be ICMP6 but use its pseudo header anyway.
549 im6o
= in6p
->in6p_moptions
;
552 * If the scope of the destination is link-local, embed the interface
553 * index in the address.
555 * XXX advanced-api value overrides sin6_scope_id
557 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
)) {
558 struct in6_pktinfo
*pi
;
559 struct ifnet
*im6o_multicast_ifp
= NULL
;
561 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) && im6o
!= NULL
) {
563 im6o_multicast_ifp
= im6o
->im6o_multicast_ifp
;
567 * XXX Boundary check is assumed to be already done in
568 * ip6_setpktoptions().
570 ifnet_head_lock_shared();
571 if (optp
&& (pi
= optp
->ip6po_pktinfo
) && pi
->ipi6_ifindex
) {
572 ip6
->ip6_dst
.s6_addr16
[1] = htons((uint16_t)pi
->ipi6_ifindex
);
573 oifp
= ifindex2ifnet
[pi
->ipi6_ifindex
];
575 ifnet_reference(oifp
);
577 } else if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) &&
578 im6o
!= NULL
&& im6o_multicast_ifp
!= NULL
) {
579 oifp
= im6o_multicast_ifp
;
580 ifnet_reference(oifp
);
581 ip6
->ip6_dst
.s6_addr16
[1] = htons(oifp
->if_index
);
582 } else if (dstsock
->sin6_scope_id
) {
586 * Sinced stsock->sin6_scope_id is unsigned, we don't
587 * need to check if it's < 0
589 if (if_index
< dstsock
->sin6_scope_id
) {
590 error
= ENXIO
; /* XXX EINVAL? */
594 ip6
->ip6_dst
.s6_addr16
[1]
595 = htons(dstsock
->sin6_scope_id
& 0xffff);/*XXX*/
601 * Source address selection.
604 struct in6_addr
*in6a
;
605 struct in6_addr storage
;
608 if (israw
!= 0 && optp
&& optp
->ip6po_pktinfo
&& !IN6_IS_ADDR_UNSPECIFIED(&optp
->ip6po_pktinfo
->ipi6_addr
)) {
609 in6a
= &optp
->ip6po_pktinfo
->ipi6_addr
;
610 flags
|= IPV6_FLAG_NOSRCIFSEL
;
611 } else if ((in6a
= in6_selectsrc(dstsock
, optp
, in6p
,
612 &in6p
->in6p_route
, NULL
, &storage
, ip6oa
.ip6oa_boundif
,
615 error
= EADDRNOTAVAIL
;
619 ip6oa
.ip6oa_flags
|= IP6OAF_BOUND_SRCADDR
;
621 ip6
->ip6_src
= *in6a
;
622 if (in6p
->in6p_route
.ro_rt
!= NULL
) {
623 RT_LOCK(in6p
->in6p_route
.ro_rt
);
624 if (in6p
->in6p_route
.ro_rt
->rt_ifp
!= NULL
) {
625 index
= in6p
->in6p_route
.ro_rt
->rt_ifp
->if_index
;
627 RT_UNLOCK(in6p
->in6p_route
.ro_rt
);
631 ifnet_head_lock_shared();
632 if (index
== 0 || if_index
< index
) {
633 panic("bad if_index on interface from route");
635 oifp
= ifindex2ifnet
[index
];
637 ifnet_reference(oifp
);
642 ip6
->ip6_flow
= (ip6
->ip6_flow
& ~IPV6_FLOWINFO_MASK
) |
643 (in6p
->inp_flow
& IPV6_FLOWINFO_MASK
);
644 ip6
->ip6_vfc
= (ip6
->ip6_vfc
& ~IPV6_VERSION_MASK
) |
645 (IPV6_VERSION
& IPV6_VERSION_MASK
);
646 /* ip6_plen will be filled in ip6_output, so not fill it here. */
647 ip6
->ip6_nxt
= in6p
->in6p_ip6_nxt
;
648 ip6
->ip6_hlim
= in6_selecthlim(in6p
, oifp
);
650 if (SOCK_PROTO(so
) == IPPROTO_ICMPV6
|| in6p
->in6p_cksum
!= -1) {
655 /* compute checksum */
656 if (SOCK_PROTO(so
) == IPPROTO_ICMPV6
) {
657 off
= offsetof(struct icmp6_hdr
, icmp6_cksum
);
659 off
= in6p
->in6p_cksum
;
661 if (plen
< (unsigned int)(off
+ 1)) {
665 off
+= sizeof(struct ip6_hdr
);
668 while (n
&& n
->m_len
<= off
) {
675 p
= (u_int16_t
*)(void *)(mtod(n
, caddr_t
) + off
);
677 *p
= in6_cksum(m
, ip6
->ip6_nxt
, sizeof(*ip6
), plen
);
682 necp_kernel_policy_id policy_id
;
683 necp_kernel_policy_id skip_policy_id
;
684 u_int32_t route_rule_id
;
685 u_int32_t pass_flags
;
688 * We need a route to perform NECP route rule checks
690 if ((net_qos_policy_restricted
!= 0 &&
691 ROUTE_UNUSABLE(&in6p
->in6p_route
))
696 struct sockaddr_in6 to
;
697 struct sockaddr_in6 from
;
699 ROUTE_RELEASE(&in6p
->in6p_route
);
701 bzero(&from
, sizeof(struct sockaddr_in6
));
702 from
.sin6_family
= AF_INET6
;
703 from
.sin6_len
= sizeof(struct sockaddr_in6
);
704 from
.sin6_addr
= ip6
->ip6_src
;
706 bzero(&to
, sizeof(struct sockaddr_in6
));
707 to
.sin6_family
= AF_INET6
;
708 to
.sin6_len
= sizeof(struct sockaddr_in6
);
709 to
.sin6_addr
= ip6
->ip6_dst
;
711 in6p
->in6p_route
.ro_dst
.sin6_family
= AF_INET6
;
712 in6p
->in6p_route
.ro_dst
.sin6_len
= sizeof(struct sockaddr_in6
);
713 ((struct sockaddr_in6
*)(void *)&in6p
->in6p_route
.ro_dst
)->sin6_addr
=
716 rtalloc_scoped((struct route
*)&in6p
->in6p_route
, ip6oa
.ip6oa_boundif
);
718 inp_update_necp_policy(in6p
, (struct sockaddr
*)&from
,
719 (struct sockaddr
*)&to
, ip6oa
.ip6oa_boundif
);
720 in6p
->inp_policyresult
.results
.qos_marking_gencount
= 0;
723 if (!necp_socket_is_allowed_to_send_recv_v6(in6p
, 0, 0,
724 &ip6
->ip6_src
, &ip6
->ip6_dst
, NULL
, 0, &policy_id
, &route_rule_id
, &skip_policy_id
, &pass_flags
)) {
725 error
= EHOSTUNREACH
;
729 necp_mark_packet_from_socket(m
, in6p
, policy_id
, route_rule_id
, skip_policy_id
, pass_flags
);
731 if (net_qos_policy_restricted
!= 0) {
732 necp_socket_update_qos_marking(in6p
, in6p
->in6p_route
.ro_rt
, route_rule_id
);
736 if ((so
->so_flags1
& SOF1_QOSMARKING_ALLOWED
)) {
737 ip6oa
.ip6oa_flags
|= IP6OAF_QOSMARKING_ALLOWED
;
741 if (in6p
->in6p_sp
!= NULL
&& ipsec_setsocket(m
, so
) != 0) {
747 if (ROUTE_UNUSABLE(&in6p
->in6p_route
)) {
748 ROUTE_RELEASE(&in6p
->in6p_route
);
756 set_packet_service_class(m
, so
, sotc
, PKT_SCF_IPV6
);
757 m
->m_pkthdr
.pkt_flowsrc
= FLOWSRC_INPCB
;
758 m
->m_pkthdr
.pkt_flowid
= in6p
->inp_flowhash
;
759 m
->m_pkthdr
.pkt_flags
|= (PKTF_FLOW_ID
| PKTF_FLOW_LOCALSRC
|
761 m
->m_pkthdr
.pkt_proto
= in6p
->in6p_ip6_nxt
;
762 m
->m_pkthdr
.tx_rawip_pid
= so
->last_pid
;
763 if (so
->so_flags
& SOF_DELEGATED
) {
764 m
->m_pkthdr
.tx_rawip_e_pid
= so
->e_pid
;
766 m
->m_pkthdr
.tx_rawip_e_pid
= 0;
773 error
= ip6_output(m
, optp
, &in6p
->in6p_route
, flags
, im6o
,
780 if (in6p
->in6p_route
.ro_rt
!= NULL
) {
781 struct rtentry
*rt
= in6p
->in6p_route
.ro_rt
;
784 if ((rt
->rt_flags
& RTF_MULTICAST
) ||
785 in6p
->in6p_socket
== NULL
||
787 /* Discard temporary route for cfil case */
790 !(in6p
->in6p_socket
->so_state
& SS_ISCONNECTED
)) {
791 rt
= NULL
; /* unusable */
794 * Always discard the cached route for unconnected
795 * socket or if it is a multicast route.
798 ROUTE_RELEASE(&in6p
->in6p_route
);
802 * If this is a connected socket and the destination
803 * route is not multicast, update outif with that of
804 * the route interface index used by IP.
808 * When an NECP IP tunnel policy forces the outbound interface,
809 * ip6_output_list() informs the transport layer what is the actual
812 if (ip6oa
.ip6oa_flags
& IP6OAF_BOUND_IF
) {
813 outif
= ifindex2ifnet
[ip6oa
.ip6oa_boundif
];
818 in6p
->in6p_last_outifp
= outif
;
822 ROUTE_RELEASE(&in6p
->in6p_route
);
826 * If output interface was cellular/expensive, and this socket is
827 * denied access to it, generate an event.
829 if (error
!= 0 && (ip6oa
.ip6oa_retflags
& IP6OARF_IFDENIED
) &&
830 (INP_NO_CELLULAR(in6p
) || INP_NO_EXPENSIVE(in6p
) || INP_NO_CONSTRAINED(in6p
))) {
831 soevent(in6p
->inp_socket
, (SO_FILT_HINT_LOCKED
|
832 SO_FILT_HINT_IFDENIED
));
835 if (SOCK_PROTO(so
) == IPPROTO_ICMPV6
) {
837 icmp6_ifoutstat_inc(oifp
, type
, code
);
839 icmp6stat
.icp6s_outhist
[type
]++;
841 rip6stat
.rip6s_opackets
++;
852 if (optp
== &opt
&& optp
->ip6po_rthdr
) {
853 ROUTE_RELEASE(&optp
->ip6po_route
);
856 if (control
!= NULL
) {
858 ip6_clearpktopts(optp
, -1);
867 m_tag_free(cfil_tag
);
875 * Raw IPv6 socket option processing.
880 struct sockopt
*sopt
)
884 /* Allow <SOL_SOCKET,SO_FLUSH> at this level */
885 if (sopt
->sopt_level
== IPPROTO_ICMPV6
) {
887 * XXX: is it better to call icmp6_ctloutput() directly
890 return icmp6_ctloutput(so
, sopt
);
891 } else if (sopt
->sopt_level
!= IPPROTO_IPV6
&&
892 !(sopt
->sopt_level
== SOL_SOCKET
&& sopt
->sopt_name
== SO_FLUSH
)) {
898 switch (sopt
->sopt_dir
) {
900 switch (sopt
->sopt_name
) {
902 error
= ip6_raw_ctloutput(so
, sopt
);
905 error
= ip6_ctloutput(so
, sopt
);
911 switch (sopt
->sopt_name
) {
913 error
= ip6_raw_ctloutput(so
, sopt
);
917 if ((error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
918 sizeof(optval
))) != 0) {
922 error
= inp_flush(sotoinpcb(so
), optval
);
926 error
= ip6_ctloutput(so
, sopt
);
936 rip6_attach(struct socket
*so
, int proto
, struct proc
*p
)
943 panic("rip6_attach");
945 if ((error
= proc_suser(p
)) != 0) {
949 error
= soreserve(so
, rip_sendspace
, rip_recvspace
);
953 error
= in_pcballoc(so
, &ripcbinfo
, p
);
957 inp
= (struct inpcb
*)so
->so_pcb
;
958 inp
->inp_vflag
|= INP_IPV6
;
959 inp
->in6p_ip6_nxt
= (char)proto
;
960 inp
->in6p_hops
= -1; /* use kernel default */
961 inp
->in6p_cksum
= -1;
962 MALLOC(inp
->in6p_icmp6filt
, struct icmp6_filter
*,
963 sizeof(struct icmp6_filter
), M_PCB
, M_WAITOK
);
964 if (inp
->in6p_icmp6filt
== NULL
) {
967 ICMP6_FILTER_SETPASSALL(inp
->in6p_icmp6filt
);
972 rip6_detach(struct socket
*so
)
978 panic("rip6_detach");
981 if (inp
->in6p_icmp6filt
) {
982 FREE(inp
->in6p_icmp6filt
, M_PCB
);
983 inp
->in6p_icmp6filt
= NULL
;
990 rip6_abort(struct socket
*so
)
992 soisdisconnected(so
);
993 return rip6_detach(so
);
997 rip6_disconnect(struct socket
*so
)
999 struct inpcb
*inp
= sotoinpcb(so
);
1001 if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
1004 inp
->in6p_faddr
= in6addr_any
;
1005 return rip6_abort(so
);
1009 rip6_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
1012 struct inpcb
*inp
= sotoinpcb(so
);
1013 struct sockaddr_in6 sin6
;
1014 struct ifaddr
*ifa
= NULL
;
1015 struct ifnet
*outif
= NULL
;
1020 || (necp_socket_should_use_flow_divert(inp
))
1023 return inp
== NULL
? EINVAL
: EPROTOTYPE
;
1026 if (nam
->sa_len
!= sizeof(struct sockaddr_in6
)) {
1030 if (TAILQ_EMPTY(&ifnet_head
) || SIN6(nam
)->sin6_family
!= AF_INET6
) {
1031 return EADDRNOTAVAIL
;
1034 bzero(&sin6
, sizeof(sin6
));
1035 *(&sin6
) = *SIN6(nam
);
1037 if ((error
= sa6_embedscope(&sin6
, ip6_use_defzone
)) != 0) {
1041 /* Sanitize local copy for address searches */
1042 sin6
.sin6_flowinfo
= 0;
1043 sin6
.sin6_scope_id
= 0;
1046 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6
.sin6_addr
) &&
1047 (ifa
= ifa_ifwithaddr(SA(&sin6
))) == 0) {
1048 return EADDRNOTAVAIL
;
1052 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
&
1053 (IN6_IFF_ANYCAST
| IN6_IFF_NOTREADY
| IN6_IFF_CLAT46
|
1054 IN6_IFF_DETACHED
| IN6_IFF_DEPRECATED
)) {
1057 return EADDRNOTAVAIL
;
1059 outif
= ifa
->ifa_ifp
;
1063 inp
->in6p_laddr
= sin6
.sin6_addr
;
1064 inp
->in6p_last_outifp
= outif
;
1070 rip6_connect(struct socket
*so
, struct sockaddr
*nam
, __unused
struct proc
*p
)
1072 struct inpcb
*inp
= sotoinpcb(so
);
1073 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)(void *)nam
;
1074 struct in6_addr
*in6a
= NULL
;
1075 struct in6_addr storage
;
1077 #if ENABLE_DEFAULT_SCOPE
1078 struct sockaddr_in6 tmp
;
1080 unsigned int ifscope
;
1081 struct ifnet
*outif
= NULL
;
1085 || (necp_socket_should_use_flow_divert(inp
))
1088 return inp
== NULL
? EINVAL
: EPROTOTYPE
;
1090 if (nam
->sa_len
!= sizeof(*addr
)) {
1093 if (TAILQ_EMPTY(&ifnet_head
)) {
1094 return EADDRNOTAVAIL
;
1096 if (addr
->sin6_family
!= AF_INET6
) {
1097 return EAFNOSUPPORT
;
1100 if (!(so
->so_flags1
& SOF1_CONNECT_COUNTED
)) {
1101 so
->so_flags1
|= SOF1_CONNECT_COUNTED
;
1102 INC_ATOMIC_INT64_LIM(net_api_stats
.nas_socket_inet6_dgram_connected
);
1105 #if ENABLE_DEFAULT_SCOPE
1106 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
1107 /* avoid overwrites */
1110 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
1114 /* KAME hack: embed scopeid */
1115 if (in6_embedscope(&SIN6(nam
)->sin6_addr
, SIN6(nam
), inp
, NULL
, NULL
) != 0) {
1119 ifscope
= (inp
->inp_flags
& INP_BOUND_IF
) ?
1120 inp
->inp_boundifp
->if_index
: IFSCOPE_NONE
;
1122 /* Source address selection. XXX: need pcblookup? */
1123 in6a
= in6_selectsrc(addr
, inp
->in6p_outputopts
, inp
, &inp
->in6p_route
,
1124 NULL
, &storage
, ifscope
, &error
);
1126 return error
? error
: EADDRNOTAVAIL
;
1128 inp
->in6p_laddr
= *in6a
;
1129 inp
->in6p_faddr
= addr
->sin6_addr
;
1130 if (inp
->in6p_route
.ro_rt
!= NULL
) {
1131 outif
= inp
->in6p_route
.ro_rt
->rt_ifp
;
1133 inp
->in6p_last_outifp
= outif
;
1140 rip6_shutdown(struct socket
*so
)
1147 rip6_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
1148 struct mbuf
*control
, struct proc
*p
)
1150 #pragma unused(flags, p)
1151 struct inpcb
*inp
= sotoinpcb(so
);
1156 || (necp_socket_should_use_flow_divert(inp
))
1167 return rip6_output(m
, so
, SIN6(nam
), control
, 1);
1175 if (control
!= NULL
) {
1182 struct pr_usrreqs rip6_usrreqs
= {
1183 .pru_abort
= rip6_abort
,
1184 .pru_attach
= rip6_attach
,
1185 .pru_bind
= rip6_bind
,
1186 .pru_connect
= rip6_connect
,
1187 .pru_control
= in6_control
,
1188 .pru_detach
= rip6_detach
,
1189 .pru_disconnect
= rip6_disconnect
,
1190 .pru_peeraddr
= in6_getpeeraddr
,
1191 .pru_send
= rip6_send
,
1192 .pru_shutdown
= rip6_shutdown
,
1193 .pru_sockaddr
= in6_getsockaddr
,
1194 .pru_sosend
= sosend
,
1195 .pru_soreceive
= soreceive
,
1198 __private_extern__
struct pr_usrreqs icmp6_dgram_usrreqs
= {
1199 .pru_abort
= rip6_abort
,
1200 .pru_attach
= icmp6_dgram_attach
,
1201 .pru_bind
= rip6_bind
,
1202 .pru_connect
= rip6_connect
,
1203 .pru_control
= in6_control
,
1204 .pru_detach
= rip6_detach
,
1205 .pru_disconnect
= rip6_disconnect
,
1206 .pru_peeraddr
= in6_getpeeraddr
,
1207 .pru_send
= icmp6_dgram_send
,
1208 .pru_shutdown
= rip6_shutdown
,
1209 .pru_sockaddr
= in6_getsockaddr
,
1210 .pru_sosend
= sosend
,
1211 .pru_soreceive
= soreceive
,