2 * Copyright (c) 2000-2020 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 /* $FreeBSD: src/sys/netinet6/udp6_usrreq.c,v 1.6.2.6 2001/07/29 19:32:40 ume Exp $ */
30 /* $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $ */
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * 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. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * Copyright (c) 1982, 1986, 1989, 1993
63 * The Regents of the University of California. All rights reserved.
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
68 * 1. Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in the
72 * documentation and/or other materials provided with the distribution.
73 * 3. All advertising materials mentioning features or use of this software
74 * must display the following acknowledgement:
75 * This product includes software developed by the University of
76 * California, Berkeley and its contributors.
77 * 4. Neither the name of the University nor the names of its contributors
78 * may be used to endorse or promote products derived from this software
79 * without specific prior written permission.
81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
93 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
95 #include <sys/kernel.h>
96 #include <sys/malloc.h>
98 #include <sys/param.h>
99 #include <sys/protosw.h>
100 #include <sys/socket.h>
101 #include <sys/socketvar.h>
102 #include <sys/sysctl.h>
103 #include <sys/errno.h>
104 #include <sys/stat.h>
105 #include <sys/systm.h>
106 #include <sys/syslog.h>
107 #include <sys/proc.h>
108 #include <sys/kauth.h>
111 #include <net/route.h>
112 #include <net/if_types.h>
113 #include <net/ntstat.h>
114 #include <net/dlil.h>
115 #include <net/net_api_stats.h>
117 #include <netinet/in.h>
118 #include <netinet/in_systm.h>
119 #include <netinet/ip.h>
120 #include <netinet/in_pcb.h>
121 #include <netinet/in_var.h>
122 #include <netinet/ip_var.h>
123 #include <netinet/udp.h>
124 #include <netinet/udp_var.h>
125 #include <netinet/ip6.h>
126 #include <netinet6/ip6_var.h>
127 #include <netinet6/in6_pcb.h>
128 #include <netinet/icmp6.h>
129 #include <netinet6/udp6_var.h>
130 #include <netinet6/ip6protosw.h>
133 #include <netinet6/ipsec.h>
134 #include <netinet6/ipsec6.h>
135 #include <netinet6/esp6.h>
136 #include <netkey/key.h>
137 extern int ipsec_bypass
;
138 extern int esp_udp_encap_port
;
142 #include <net/necp.h>
146 #include <netinet/flow_divert.h>
147 #endif /* FLOW_DIVERT */
150 #include <net/content_filter.h>
151 #endif /* CONTENT_FILTER */
154 * UDP protocol inplementation.
155 * Per RFC 768, August, 1980.
158 static int udp6_abort(struct socket
*);
159 static int udp6_attach(struct socket
*, int, struct proc
*);
160 static int udp6_bind(struct socket
*, struct sockaddr
*, struct proc
*);
161 static int udp6_connectx(struct socket
*, struct sockaddr
*,
162 struct sockaddr
*, struct proc
*, uint32_t, sae_associd_t
,
163 sae_connid_t
*, uint32_t, void *, uint32_t, struct uio
*, user_ssize_t
*);
164 static int udp6_detach(struct socket
*);
165 static int udp6_disconnect(struct socket
*);
166 static int udp6_disconnectx(struct socket
*, sae_associd_t
, sae_connid_t
);
167 static int udp6_send(struct socket
*, int, struct mbuf
*, struct sockaddr
*,
168 struct mbuf
*, struct proc
*);
169 static void udp6_append(struct inpcb
*, struct ip6_hdr
*,
170 struct sockaddr_in6
*, struct mbuf
*, int, struct ifnet
*);
171 static int udp6_input_checksum(struct mbuf
*, struct udphdr
*, int, int);
173 struct pr_usrreqs udp6_usrreqs
= {
174 .pru_abort
= udp6_abort
,
175 .pru_attach
= udp6_attach
,
176 .pru_bind
= udp6_bind
,
177 .pru_connect
= udp6_connect
,
178 .pru_connectx
= udp6_connectx
,
179 .pru_control
= in6_control
,
180 .pru_detach
= udp6_detach
,
181 .pru_disconnect
= udp6_disconnect
,
182 .pru_disconnectx
= udp6_disconnectx
,
183 .pru_peeraddr
= in6_mapped_peeraddr
,
184 .pru_send
= udp6_send
,
185 .pru_shutdown
= udp_shutdown
,
186 .pru_sockaddr
= in6_mapped_sockaddr
,
187 .pru_sosend
= sosend
,
188 .pru_soreceive
= soreceive
,
189 .pru_soreceive_list
= soreceive_list
,
193 * subroutine of udp6_input(), mainly for source code readability.
196 udp6_append(struct inpcb
*last
, struct ip6_hdr
*ip6
,
197 struct sockaddr_in6
*udp_in6
, struct mbuf
*n
, int off
, struct ifnet
*ifp
)
200 struct mbuf
*opts
= NULL
;
202 boolean_t cell
= IFNET_IS_CELLULAR(ifp
);
203 boolean_t wifi
= (!cell
&& IFNET_IS_WIFI(ifp
));
204 boolean_t wired
= (!wifi
&& IFNET_IS_WIRED(ifp
));
206 if ((last
->in6p_flags
& INP_CONTROLOPTS
) != 0 ||
208 /* Content Filter needs to see local address */
209 (last
->in6p_socket
->so_cfil_db
!= NULL
) ||
211 (last
->in6p_socket
->so_options
& SO_TIMESTAMP
) != 0 ||
212 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_MONOTONIC
) != 0 ||
213 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_CONTINUOUS
) != 0) {
214 ret
= ip6_savecontrol(last
, n
, &opts
);
223 INP_ADD_STAT(last
, cell
, wifi
, wired
, rxpackets
, 1);
224 INP_ADD_STAT(last
, cell
, wifi
, wired
, rxbytes
, n
->m_pkthdr
.len
);
225 inp_set_activity_bitmap(last
);
227 so_recv_data_stat(last
->in6p_socket
, n
, 0);
228 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
229 (struct sockaddr
*)udp_in6
, n
, opts
, NULL
) == 0) {
230 udpstat
.udps_fullsock
++;
232 sorwakeup(last
->in6p_socket
);
237 udp6_input(struct mbuf
**mp
, int *offp
, int proto
)
239 #pragma unused(proto)
240 struct mbuf
*m
= *mp
;
245 struct mbuf
*opts
= NULL
;
247 int plen
, ulen
, ret
= 0;
248 boolean_t cell
, wifi
, wired
;
249 struct sockaddr_in6 udp_in6
;
250 struct inpcbinfo
*pcbinfo
= &udbinfo
;
251 struct sockaddr_in6 fromsa
;
252 u_int16_t pf_tag
= 0;
254 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct udphdr
), return IPPROTO_DONE
);
256 /* Expect 32-bit aligned data pointer on strict-align platforms */
257 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
259 ifp
= m
->m_pkthdr
.rcvif
;
260 ip6
= mtod(m
, struct ip6_hdr
*);
261 cell
= IFNET_IS_CELLULAR(ifp
);
262 wifi
= (!cell
&& IFNET_IS_WIFI(ifp
));
263 wired
= (!wifi
&& IFNET_IS_WIRED(ifp
));
265 if (m
->m_flags
& M_PKTHDR
) {
266 pf_tag
= m_pftag(m
)->pftag_tag
;
269 udpstat
.udps_ipackets
++;
271 plen
= ntohs(ip6
->ip6_plen
) - off
+ sizeof(*ip6
);
272 uh
= (struct udphdr
*)(void *)((caddr_t
)ip6
+ off
);
273 ulen
= ntohs((u_short
)uh
->uh_ulen
);
276 udpstat
.udps_badlen
++;
277 IF_UDP_STATINC(ifp
, badlength
);
281 /* destination port of 0 is illegal, based on RFC768. */
282 if (uh
->uh_dport
== 0) {
283 IF_UDP_STATINC(ifp
, port0
);
288 * Checksum extended UDP header and data.
290 if (udp6_input_checksum(m
, uh
, off
, ulen
)) {
295 * Construct sockaddr format source address.
297 init_sin6(&fromsa
, m
);
298 fromsa
.sin6_port
= uh
->uh_sport
;
300 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
301 int reuse_sock
= 0, mcast_delivered
= 0;
302 struct ip6_moptions
*imo
;
305 * Deliver a multicast datagram to all sockets
306 * for which the local and remote addresses and ports match
307 * those of the incoming datagram. This allows more than
308 * one process to receive multicasts on the same port.
309 * (This really ought to be done for unicast datagrams as
310 * well, but that would cause problems with existing
311 * applications that open both address-specific sockets and
312 * a wildcard socket listening to the same port -- they would
313 * end up receiving duplicates of every unicast datagram.
314 * Those applications open the multiple sockets to overcome an
315 * inadequacy of the UDP socket interface, but for backwards
316 * compatibility we avoid the problem here rather than
317 * fixing the interface. Maybe 4.5BSD will remedy this?)
321 * In a case that laddr should be set to the link-local
322 * address (this happens in RIPng), the multicast address
323 * specified in the received packet does not match with
324 * laddr. To cure this situation, the matching is relaxed
325 * if the receiving interface is the same as one specified
326 * in the socket and if the destination multicast address
327 * matches one of the multicast groups specified in the socket.
331 * Construct sockaddr format source address.
333 init_sin6(&udp_in6
, m
); /* general init */
334 udp_in6
.sin6_port
= uh
->uh_sport
;
336 * KAME note: usually we drop udphdr from mbuf here.
337 * We need udphdr for IPsec processing so we do that later.
341 * Locate pcb(s) for datagram.
342 * (Algorithm copied from raw_intr().)
344 lck_rw_lock_shared(pcbinfo
->ipi_lock
);
346 LIST_FOREACH(in6p
, &udb
, inp_list
) {
351 if ((in6p
->inp_vflag
& INP_IPV6
) == 0) {
355 if (inp_restricted_recv(in6p
, ifp
)) {
359 if (in_pcb_checkstate(in6p
, WNT_ACQUIRE
, 0) ==
364 udp_lock(in6p
->in6p_socket
, 1, 0);
366 if (in_pcb_checkstate(in6p
, WNT_RELEASE
, 1) ==
368 udp_unlock(in6p
->in6p_socket
, 1, 0);
371 if (in6p
->in6p_lport
!= uh
->uh_dport
) {
372 udp_unlock(in6p
->in6p_socket
, 1, 0);
377 * Handle socket delivery policy for any-source
378 * and source-specific multicast. [RFC3678]
380 imo
= in6p
->in6p_moptions
;
381 if (imo
&& IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
382 struct sockaddr_in6 mcaddr
;
386 bzero(&mcaddr
, sizeof(struct sockaddr_in6
));
387 mcaddr
.sin6_len
= sizeof(struct sockaddr_in6
);
388 mcaddr
.sin6_family
= AF_INET6
;
389 mcaddr
.sin6_addr
= ip6
->ip6_dst
;
391 blocked
= im6o_mc_filter(imo
, ifp
,
394 if (blocked
!= MCAST_PASS
) {
395 udp_unlock(in6p
->in6p_socket
, 1, 0);
396 if (blocked
== MCAST_NOTSMEMBER
||
397 blocked
== MCAST_MUTED
) {
398 udpstat
.udps_filtermcast
++;
403 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
404 (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
,
406 in6p
->in6p_fport
!= uh
->uh_sport
)) {
407 udp_unlock(in6p
->in6p_socket
, 1, 0);
411 reuse_sock
= in6p
->inp_socket
->so_options
&
412 (SO_REUSEPORT
| SO_REUSEADDR
);
416 if (!necp_socket_is_allowed_to_send_recv_v6(in6p
,
417 uh
->uh_dport
, uh
->uh_sport
, &ip6
->ip6_dst
,
418 &ip6
->ip6_src
, ifp
, pf_tag
, NULL
, NULL
, NULL
, NULL
)) {
419 /* do not inject data to pcb */
425 struct mbuf
*n
= NULL
;
428 * m_copy(m, offset, ...) below.
429 * sbappendaddr() expects M_PKTHDR,
430 * and m_copy() will copy M_PKTHDR
431 * only if offset is 0.
434 n
= m_copy(m
, 0, M_COPYALL
);
436 udp6_append(in6p
, ip6
, &udp_in6
, m
,
437 off
+ sizeof(struct udphdr
), ifp
);
441 udp_unlock(in6p
->in6p_socket
, 1, 0);
444 * Don't look for additional matches if this one does
445 * not have either the SO_REUSEPORT or SO_REUSEADDR
446 * socket options set. This heuristic avoids searching
447 * through all pcbs in the common case of a non-shared
448 * port. It assumes that an application will never
449 * clear these options after setting them.
451 if (reuse_sock
== 0 || m
== NULL
) {
456 * Expect 32-bit aligned data pointer on strict-align
459 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
462 * Recompute IP and UDP header pointers for new mbuf
464 ip6
= mtod(m
, struct ip6_hdr
*);
465 uh
= (struct udphdr
*)(void *)((caddr_t
)ip6
+ off
);
467 lck_rw_done(pcbinfo
->ipi_lock
);
469 if (mcast_delivered
== 0) {
471 * No matching pcb found; discard datagram.
472 * (No need to send an ICMP Port Unreachable
473 * for a broadcast or multicast datgram.)
475 udpstat
.udps_noport
++;
476 udpstat
.udps_noportmcast
++;
477 IF_UDP_STATINC(ifp
, port_unreach
);
481 /* free the extra copy of mbuf or skipped by NECP */
490 * UDP to port 4500 with a payload where the first four bytes are
491 * not zero is a UDP encapsulated IPsec packet. Packets where
492 * the payload is one byte and that byte is 0xFF are NAT keepalive
493 * packets. Decapsulate the ESP packet and carry on with IPsec input
494 * or discard the NAT keep-alive.
496 if (ipsec_bypass
== 0 && (esp_udp_encap_port
& 0xFFFF) != 0 &&
497 (uh
->uh_dport
== ntohs((u_short
)esp_udp_encap_port
) ||
498 uh
->uh_sport
== ntohs((u_short
)esp_udp_encap_port
))) {
500 * Check if ESP or keepalive:
501 * 1. If the destination port of the incoming packet is 4500.
502 * 2. If the source port of the incoming packet is 4500,
503 * then check the SADB to match IP address and port.
505 bool check_esp
= true;
506 if (uh
->uh_dport
!= ntohs((u_short
)esp_udp_encap_port
)) {
507 check_esp
= key_checksa_present(AF_INET6
, (caddr_t
)&ip6
->ip6_dst
,
508 (caddr_t
)&ip6
->ip6_src
, uh
->uh_dport
,
513 int payload_len
= ulen
- sizeof(struct udphdr
) > 4 ? 4 :
514 ulen
- sizeof(struct udphdr
);
516 if (m
->m_len
< off
+ sizeof(struct udphdr
) + payload_len
) {
517 if ((m
= m_pullup(m
, off
+ sizeof(struct udphdr
) +
518 payload_len
)) == NULL
) {
519 udpstat
.udps_hdrops
++;
523 * Expect 32-bit aligned data pointer on strict-align
526 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
528 ip6
= mtod(m
, struct ip6_hdr
*);
529 uh
= (struct udphdr
*)(void *)((caddr_t
)ip6
+ off
);
531 /* Check for NAT keepalive packet */
532 if (payload_len
== 1 && *(u_int8_t
*)
533 ((caddr_t
)uh
+ sizeof(struct udphdr
)) == 0xFF) {
535 } else if (payload_len
== 4 && *(u_int32_t
*)(void *)
536 ((caddr_t
)uh
+ sizeof(struct udphdr
)) != 0) {
537 /* UDP encapsulated IPsec packet to pass through NAT */
538 /* preserve the udp header */
539 *offp
= off
+ sizeof(struct udphdr
);
540 return esp6_input(mp
, offp
, IPPROTO_UDP
);
547 * Locate pcb for datagram.
549 in6p
= in6_pcblookup_hash(&udbinfo
, &ip6
->ip6_src
, uh
->uh_sport
,
550 &ip6
->ip6_dst
, uh
->uh_dport
, 1, m
->m_pkthdr
.rcvif
);
552 IF_UDP_STATINC(ifp
, port_unreach
);
554 if (udp_log_in_vain
) {
555 char buf
[INET6_ADDRSTRLEN
];
557 strlcpy(buf
, ip6_sprintf(&ip6
->ip6_dst
), sizeof(buf
));
558 if (udp_log_in_vain
< 3) {
559 log(LOG_INFO
, "Connection attempt to UDP "
560 "%s:%d from %s:%d\n", buf
,
562 ip6_sprintf(&ip6
->ip6_src
),
563 ntohs(uh
->uh_sport
));
564 } else if (!(m
->m_flags
& (M_BCAST
| M_MCAST
)) &&
565 !IN6_ARE_ADDR_EQUAL(&ip6
->ip6_dst
, &ip6
->ip6_src
)) {
566 log(LOG_INFO
, "Connection attempt "
567 "to UDP %s:%d from %s:%d\n", buf
,
569 ip6_sprintf(&ip6
->ip6_src
),
570 ntohs(uh
->uh_sport
));
573 udpstat
.udps_noport
++;
574 if (m
->m_flags
& M_MCAST
) {
575 printf("UDP6: M_MCAST is set in a unicast packet.\n");
576 udpstat
.udps_noportmcast
++;
577 IF_UDP_STATINC(ifp
, badmcast
);
580 icmp6_error(m
, ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
, 0);
584 if (!necp_socket_is_allowed_to_send_recv_v6(in6p
, uh
->uh_dport
,
585 uh
->uh_sport
, &ip6
->ip6_dst
, &ip6
->ip6_src
, ifp
, pf_tag
, NULL
, NULL
, NULL
, NULL
)) {
586 in_pcb_checkstate(in6p
, WNT_RELEASE
, 0);
587 IF_UDP_STATINC(ifp
, badipsec
);
593 * Construct sockaddr format source address.
594 * Stuff source address and datagram in user buffer.
596 udp_lock(in6p
->in6p_socket
, 1, 0);
598 if (in_pcb_checkstate(in6p
, WNT_RELEASE
, 1) == WNT_STOPUSING
) {
599 udp_unlock(in6p
->in6p_socket
, 1, 0);
600 IF_UDP_STATINC(ifp
, cleanup
);
604 init_sin6(&udp_in6
, m
); /* general init */
605 udp_in6
.sin6_port
= uh
->uh_sport
;
606 if ((in6p
->in6p_flags
& INP_CONTROLOPTS
) != 0 ||
608 /* Content Filter needs to see local address */
609 (in6p
->in6p_socket
->so_cfil_db
!= NULL
) ||
611 (in6p
->in6p_socket
->so_options
& SO_TIMESTAMP
) != 0 ||
612 (in6p
->in6p_socket
->so_options
& SO_TIMESTAMP_MONOTONIC
) != 0 ||
613 (in6p
->in6p_socket
->so_options
& SO_TIMESTAMP_CONTINUOUS
) != 0) {
614 ret
= ip6_savecontrol(in6p
, m
, &opts
);
616 udp_unlock(in6p
->in6p_socket
, 1, 0);
620 m_adj(m
, off
+ sizeof(struct udphdr
));
622 INP_ADD_STAT(in6p
, cell
, wifi
, wired
, rxpackets
, 1);
623 INP_ADD_STAT(in6p
, cell
, wifi
, wired
, rxbytes
, m
->m_pkthdr
.len
);
624 inp_set_activity_bitmap(in6p
);
626 so_recv_data_stat(in6p
->in6p_socket
, m
, 0);
627 if (sbappendaddr(&in6p
->in6p_socket
->so_rcv
,
628 (struct sockaddr
*)&udp_in6
, m
, opts
, NULL
) == 0) {
631 udpstat
.udps_fullsock
++;
632 udp_unlock(in6p
->in6p_socket
, 1, 0);
635 sorwakeup(in6p
->in6p_socket
);
636 udp_unlock(in6p
->in6p_socket
, 1, 0);
649 udp6_ctlinput(int cmd
, struct sockaddr
*sa
, void *d
, __unused
struct ifnet
*ifp
)
655 struct ip6ctlparam
*ip6cp
= NULL
;
656 struct icmp6_hdr
*icmp6
= NULL
;
657 const struct sockaddr_in6
*sa6_src
= NULL
;
659 void (*notify
)(struct inpcb
*, int) = udp_notify
;
661 struct udp_portonly
{
666 if (sa
->sa_family
!= AF_INET6
||
667 sa
->sa_len
!= sizeof(struct sockaddr_in6
)) {
671 if ((unsigned)cmd
>= PRC_NCMDS
) {
674 if (PRC_IS_REDIRECT(cmd
)) {
675 notify
= in6_rtchange
;
677 } else if (cmd
== PRC_HOSTDEAD
) {
679 } else if (inet6ctlerrmap
[cmd
] == 0) {
683 /* if the parameter is from icmp6, decode it. */
685 ip6cp
= (struct ip6ctlparam
*)d
;
686 icmp6
= ip6cp
->ip6c_icmp6
;
688 ip6
= ip6cp
->ip6c_ip6
;
689 off
= ip6cp
->ip6c_off
;
690 cmdarg
= ip6cp
->ip6c_cmdarg
;
691 sa6_src
= ip6cp
->ip6c_src
;
701 * XXX: We assume that when IPV6 is non NULL,
702 * M and OFF are valid.
704 /* check if we can safely examine src and dst ports */
705 if (m
->m_pkthdr
.len
< off
+ sizeof(*uhp
)) {
709 bzero(&uh
, sizeof(uh
));
710 m_copydata(m
, off
, sizeof(*uhp
), (caddr_t
)&uh
);
712 in6p
= in6_pcblookup_hash(&udbinfo
, &ip6
->ip6_dst
, uh
.uh_dport
,
713 &ip6
->ip6_src
, uh
.uh_sport
, 0, NULL
);
714 if (cmd
== PRC_MSGSIZE
&& in6p
!= NULL
&& !uuid_is_null(in6p
->necp_client_uuid
)) {
716 uuid_clear(null_uuid
);
717 necp_update_flow_protoctl_event(null_uuid
, in6p
->necp_client_uuid
,
718 PRC_MSGSIZE
, ntohl(icmp6
->icmp6_mtu
), 0);
721 (void) in6_pcbnotify(&udbinfo
, sa
, uh
.uh_dport
,
722 (struct sockaddr
*)ip6cp
->ip6c_src
, uh
.uh_sport
,
723 cmd
, cmdarg
, notify
);
726 * XXX The else condition here was broken for a long time.
727 * Fixing it made us deliver notification correctly but broke
728 * some frameworks that didn't handle it well.
729 * For now we have removed it and will revisit it later.
734 udp6_abort(struct socket
*so
)
740 panic("%s: so=%p null inp\n", __func__
, so
);
743 soisdisconnected(so
);
749 udp6_attach(struct socket
*so
, int proto
, struct proc
*p
)
751 #pragma unused(proto)
760 error
= in_pcballoc(so
, &udbinfo
, p
);
765 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0) {
766 error
= soreserve(so
, udp_sendspace
, udp_recvspace
);
771 inp
= (struct inpcb
*)so
->so_pcb
;
772 inp
->inp_vflag
|= INP_IPV6
;
773 if (ip6_mapped_addr_on
) {
774 inp
->inp_vflag
|= INP_IPV4
;
776 inp
->in6p_hops
= -1; /* use kernel default */
777 inp
->in6p_cksum
= -1; /* just to be sure */
780 * IPv4 TTL initialization is necessary for an IPv6 socket as well,
781 * because the socket may be bound to an IPv6 wildcard address,
782 * which may match an IPv4-mapped IPv6 address.
784 inp
->inp_ip_ttl
= (u_char
)ip_defttl
;
786 nstat_udp_new_pcb(inp
);
792 udp6_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
802 inp
->inp_vflag
&= ~INP_IPV4
;
803 inp
->inp_vflag
|= INP_IPV6
;
804 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
805 struct sockaddr_in6
*sin6_p
;
807 sin6_p
= (struct sockaddr_in6
*)(void *)nam
;
809 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p
->sin6_addr
)) {
810 inp
->inp_vflag
|= INP_IPV4
;
811 } else if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
812 struct sockaddr_in sin
;
814 in6_sin6_2_sin(&sin
, sin6_p
);
815 inp
->inp_vflag
|= INP_IPV4
;
816 inp
->inp_vflag
&= ~INP_IPV6
;
817 error
= in_pcbbind(inp
, (struct sockaddr
*)&sin
, p
);
822 error
= in6_pcbbind(inp
, nam
, p
);
827 udp6_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
831 #if defined(NECP) && defined(FLOW_DIVERT)
832 int should_use_flow_divert
= 0;
833 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
840 #if defined(NECP) && defined(FLOW_DIVERT)
841 should_use_flow_divert
= necp_socket_should_use_flow_divert(inp
);
842 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
844 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
845 struct sockaddr_in6
*sin6_p
;
847 sin6_p
= (struct sockaddr_in6
*)(void *)nam
;
848 if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
849 struct sockaddr_in sin
;
851 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
) {
855 if (!(so
->so_flags1
& SOF1_CONNECT_COUNTED
)) {
856 so
->so_flags1
|= SOF1_CONNECT_COUNTED
;
857 INC_ATOMIC_INT64_LIM(net_api_stats
.nas_socket_inet_dgram_connected
);
860 in6_sin6_2_sin(&sin
, sin6_p
);
861 #if defined(NECP) && defined(FLOW_DIVERT)
862 if (should_use_flow_divert
) {
865 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
866 error
= in_pcbconnect(inp
, (struct sockaddr
*)&sin
,
867 p
, IFSCOPE_NONE
, NULL
);
870 /* Update NECP client with connected five-tuple */
871 if (!uuid_is_null(inp
->necp_client_uuid
)) {
872 socket_unlock(so
, 0);
873 necp_client_assign_from_socket(so
->last_pid
, inp
->necp_client_uuid
, inp
);
877 inp
->inp_vflag
|= INP_IPV4
;
878 inp
->inp_vflag
&= ~INP_IPV6
;
885 if (!IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
)) {
889 if (!(so
->so_flags1
& SOF1_CONNECT_COUNTED
)) {
890 so
->so_flags1
|= SOF1_CONNECT_COUNTED
;
891 INC_ATOMIC_INT64_LIM(net_api_stats
.nas_socket_inet6_dgram_connected
);
894 #if defined(NECP) && defined(FLOW_DIVERT)
896 if (should_use_flow_divert
) {
897 error
= flow_divert_pcb_init(so
);
899 error
= flow_divert_connect_out(so
, nam
, p
);
903 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
905 error
= in6_pcbconnect(inp
, nam
, p
);
907 /* should be non mapped addr */
908 if (ip6_mapped_addr_on
||
909 (inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
910 inp
->inp_vflag
&= ~INP_IPV4
;
911 inp
->inp_vflag
|= INP_IPV6
;
914 /* Update NECP client with connected five-tuple */
915 if (!uuid_is_null(inp
->necp_client_uuid
)) {
916 socket_unlock(so
, 0);
917 necp_client_assign_from_socket(so
->last_pid
, inp
->necp_client_uuid
, inp
);
922 if (inp
->inp_flowhash
== 0) {
923 inp
->inp_flowhash
= inp_calc_flowhash(inp
);
925 /* update flowinfo - RFC 6437 */
926 if (inp
->inp_flow
== 0 &&
927 inp
->in6p_flags
& IN6P_AUTOFLOWLABEL
) {
928 inp
->inp_flow
&= ~IPV6_FLOWLABEL_MASK
;
930 (htonl(inp
->inp_flowhash
) & IPV6_FLOWLABEL_MASK
);
937 udp6_connectx(struct socket
*so
, struct sockaddr
*src
,
938 struct sockaddr
*dst
, struct proc
*p
, uint32_t ifscope
,
939 sae_associd_t aid
, sae_connid_t
*pcid
, uint32_t flags
, void *arg
,
940 uint32_t arglen
, struct uio
*uio
, user_ssize_t
*bytes_written
)
942 return udp_connectx_common(so
, AF_INET6
, src
, dst
,
943 p
, ifscope
, aid
, pcid
, flags
, arg
, arglen
, uio
, bytes_written
);
947 udp6_detach(struct socket
*so
)
960 udp6_disconnect(struct socket
*so
)
967 || (necp_socket_should_use_flow_divert(inp
))
970 return inp
== NULL
? EINVAL
: EPROTOTYPE
;
973 if (inp
->inp_vflag
& INP_IPV4
) {
974 struct pr_usrreqs
*pru
;
976 pru
= ip_protox
[IPPROTO_UDP
]->pr_usrreqs
;
977 return (*pru
->pru_disconnect
)(so
);
980 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
)) {
984 in6_pcbdisconnect(inp
);
986 /* reset flow-controlled state, just in case */
987 inp_reset_fc_state(inp
);
989 inp
->in6p_laddr
= in6addr_any
;
990 inp
->in6p_last_outifp
= NULL
;
992 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
997 udp6_disconnectx(struct socket
*so
, sae_associd_t aid
, sae_connid_t cid
)
1000 if (aid
!= SAE_ASSOCID_ANY
&& aid
!= SAE_ASSOCID_ALL
) {
1004 return udp6_disconnect(so
);
1008 udp6_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
1009 struct mbuf
*control
, struct proc
*p
)
1013 #if defined(NECP) && defined(FLOW_DIVERT)
1014 int should_use_flow_divert
= 0;
1015 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
1017 struct m_tag
*cfil_tag
= NULL
;
1018 struct sockaddr
*cfil_faddr
= NULL
;
1021 inp
= sotoinpcb(so
);
1028 //If socket is subject to UDP Content Filter and unconnected, get addr from tag.
1029 if (so
->so_cfil_db
&& !addr
&& IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
)) {
1030 cfil_tag
= cfil_dgram_get_socket_state(m
, NULL
, NULL
, &cfil_faddr
, NULL
);
1032 addr
= (struct sockaddr
*)cfil_faddr
;
1037 #if defined(NECP) && defined(FLOW_DIVERT)
1038 should_use_flow_divert
= necp_socket_should_use_flow_divert(inp
);
1039 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
1042 if (addr
->sa_len
!= sizeof(struct sockaddr_in6
)) {
1046 if (addr
->sa_family
!= AF_INET6
) {
1047 error
= EAFNOSUPPORT
;
1052 if (ip6_mapped_addr_on
|| (inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
1054 struct sockaddr_in6
*sin6
= NULL
;
1057 hasv4addr
= (inp
->inp_vflag
& INP_IPV4
);
1059 sin6
= (struct sockaddr_in6
*)(void *)addr
;
1061 IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
) ? 1 : 0;
1064 struct pr_usrreqs
*pru
;
1067 in6_sin6_2_sin_in_sock(addr
);
1069 #if defined(NECP) && defined(FLOW_DIVERT)
1070 if (should_use_flow_divert
) {
1071 goto do_flow_divert
;
1073 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
1074 pru
= ip_protox
[IPPROTO_UDP
]->pr_usrreqs
;
1075 error
= ((*pru
->pru_send
)(so
, flags
, m
, addr
,
1079 m_tag_free(cfil_tag
);
1082 /* addr will just be freed in sendit(). */
1087 #if defined(NECP) && defined(FLOW_DIVERT)
1089 if (should_use_flow_divert
) {
1090 /* Implicit connect */
1091 error
= flow_divert_implicit_data_out(so
, flags
, m
, addr
, control
, p
);
1094 m_tag_free(cfil_tag
);
1099 #endif /* defined(NECP) && defined(FLOW_DIVERT) */
1101 error
= udp6_output(inp
, m
, addr
, control
, p
);
1104 m_tag_free(cfil_tag
);
1115 if (control
!= NULL
) {
1120 m_tag_free(cfil_tag
);
1127 * Checksum extended UDP header and data.
1130 udp6_input_checksum(struct mbuf
*m
, struct udphdr
*uh
, int off
, int ulen
)
1132 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
1133 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
1135 if (!(m
->m_pkthdr
.csum_flags
& CSUM_DATA_VALID
) &&
1137 /* UDP/IPv6 checksum is mandatory (RFC2460) */
1140 * If checksum was already validated, ignore this check.
1141 * This is necessary for transport-mode ESP, which may be
1142 * getting UDP payloads without checksums when the network
1145 udpstat
.udps_nosum
++;
1149 if ((hwcksum_rx
|| (ifp
->if_flags
& IFF_LOOPBACK
) ||
1150 (m
->m_pkthdr
.pkt_flags
& PKTF_LOOP
)) &&
1151 (m
->m_pkthdr
.csum_flags
& CSUM_DATA_VALID
)) {
1152 if (m
->m_pkthdr
.csum_flags
& CSUM_PSEUDO_HDR
) {
1153 uh
->uh_sum
= m
->m_pkthdr
.csum_rx_val
;
1155 uint32_t sum
= m
->m_pkthdr
.csum_rx_val
;
1156 uint32_t start
= m
->m_pkthdr
.csum_rx_start
;
1157 int32_t trailer
= (m_pktlen(m
) - (off
+ ulen
));
1160 * Perform 1's complement adjustment of octets
1161 * that got included/excluded in the hardware-
1162 * calculated checksum value. Also take care
1163 * of any trailing bytes and subtract out
1164 * their partial sum.
1166 ASSERT(trailer
>= 0);
1167 if ((m
->m_pkthdr
.csum_flags
& CSUM_PARTIAL
) &&
1168 (start
!= off
|| trailer
!= 0)) {
1169 uint32_t swbytes
= (uint32_t)trailer
;
1170 uint16_t s
= 0, d
= 0;
1172 if (IN6_IS_SCOPE_EMBED(&ip6
->ip6_src
)) {
1173 s
= ip6
->ip6_src
.s6_addr16
[1];
1174 ip6
->ip6_src
.s6_addr16
[1] = 0;
1176 if (IN6_IS_SCOPE_EMBED(&ip6
->ip6_dst
)) {
1177 d
= ip6
->ip6_dst
.s6_addr16
[1];
1178 ip6
->ip6_dst
.s6_addr16
[1] = 0;
1181 /* callee folds in sum */
1182 sum
= m_adj_sum16(m
, start
, off
, ulen
, sum
);
1184 swbytes
+= (off
- start
);
1186 swbytes
+= (start
- off
);
1189 if (IN6_IS_SCOPE_EMBED(&ip6
->ip6_src
)) {
1190 ip6
->ip6_src
.s6_addr16
[1] = s
;
1192 if (IN6_IS_SCOPE_EMBED(&ip6
->ip6_dst
)) {
1193 ip6
->ip6_dst
.s6_addr16
[1] = d
;
1197 udp_in_cksum_stats(swbytes
);
1204 uh
->uh_sum
= in6_pseudo(&ip6
->ip6_src
, &ip6
->ip6_dst
,
1205 sum
+ htonl(ulen
+ IPPROTO_UDP
));
1207 uh
->uh_sum
^= 0xffff;
1209 udp_in6_cksum_stats(ulen
);
1210 uh
->uh_sum
= in6_cksum(m
, IPPROTO_UDP
, off
, ulen
);
1213 if (uh
->uh_sum
!= 0) {
1215 udpstat
.udps_badsum
++;
1216 IF_UDP_STATINC(ifp
, badchksum
);