]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/udp6_usrreq.c
xnu-3248.40.184.tar.gz
[apple/xnu.git] / bsd / netinet6 / udp6_usrreq.c
CommitLineData
6d2010ae 1/*
3e170ce0 2 * Copyright (c) 2000-2015 Apple Inc. All rights reserved.
6d2010ae
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
9bccf70c
A
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 $ */
1c79356b
A
31
32/*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
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.
47 *
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
58 * SUCH DAMAGE.
59 */
60
61/*
62 * Copyright (c) 1982, 1986, 1989, 1993
63 * The Regents of the University of California. All rights reserved.
64 *
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
67 * are met:
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.
80 *
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
91 * SUCH DAMAGE.
92 *
93 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
94 */
1c79356b
A
95
96#include <sys/param.h>
97#include <sys/kernel.h>
98#include <sys/malloc.h>
99#include <sys/mbuf.h>
100#include <sys/protosw.h>
101#include <sys/socket.h>
102#include <sys/socketvar.h>
103#include <sys/sysctl.h>
104#include <sys/errno.h>
105#include <sys/stat.h>
106#include <sys/systm.h>
107#include <sys/syslog.h>
108#include <sys/proc.h>
91447636 109#include <sys/kauth.h>
1c79356b
A
110
111#include <net/if.h>
112#include <net/route.h>
113#include <net/if_types.h>
6d2010ae 114#include <net/ntstat.h>
39236c6e 115#include <net/dlil.h>
1c79356b
A
116
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>
131
132#if IPSEC
133#include <netinet6/ipsec.h>
9bccf70c 134#include <netinet6/ipsec6.h>
3e170ce0
A
135#include <netinet6/esp6.h>
136extern int ipsec_bypass;
137extern int esp_udp_encap_port;
39236c6e 138#endif /* IPSEC */
1c79356b 139
fe8ab488
A
140#if NECP
141#include <net/necp.h>
142#endif /* NECP */
143
3e170ce0
A
144#if FLOW_DIVERT
145#include <netinet/flow_divert.h>
146#endif /* FLOW_DIVERT */
147
1c79356b
A
148/*
149 * UDP protocol inplementation.
150 * Per RFC 768, August, 1980.
151 */
152
39236c6e
A
153static int udp6_abort(struct socket *);
154static int udp6_attach(struct socket *, int, struct proc *);
155static int udp6_bind(struct socket *, struct sockaddr *, struct proc *);
156static int udp6_connectx(struct socket *, struct sockaddr_list **,
3e170ce0
A
157 struct sockaddr_list **, struct proc *, uint32_t, sae_associd_t,
158 sae_connid_t *, uint32_t, void *, uint32_t, struct uio *, user_ssize_t *);
39236c6e
A
159static int udp6_detach(struct socket *);
160static int udp6_disconnect(struct socket *);
3e170ce0 161static int udp6_disconnectx(struct socket *, sae_associd_t, sae_connid_t);
39236c6e
A
162static int udp6_send(struct socket *, int, struct mbuf *, struct sockaddr *,
163 struct mbuf *, struct proc *);
2d21ac55 164static void udp6_append(struct inpcb *, struct ip6_hdr *,
39236c6e
A
165 struct sockaddr_in6 *, struct mbuf *, int, struct ifnet *);
166static int udp6_input_checksum(struct mbuf *, struct udphdr *, int, int);
91447636 167
2d21ac55 168#if IPFIREWALL
39236c6e
A
169extern int fw_verbose;
170extern void ipfwsyslog( int level, const char *format,...);
171extern void ipfw_stealth_stats_incr_udpv6(void);
172
173/* Apple logging, log to ipfw.log */
174#define log_in_vain_log(a) { \
175 if ((udp_log_in_vain == 3) && (fw_verbose == 2)) { \
176 ipfwsyslog a; \
177 } else if ((udp_log_in_vain == 4) && (fw_verbose == 2)) { \
178 ipfw_stealth_stats_incr_udpv6(); \
179 } else { \
180 log a; \
181 } \
91447636 182}
39236c6e 183#else /* !IPFIREWALL */
2d21ac55 184#define log_in_vain_log( a ) { log a; }
39236c6e
A
185#endif /* !IPFIREWALL */
186
187struct pr_usrreqs udp6_usrreqs = {
188 .pru_abort = udp6_abort,
189 .pru_attach = udp6_attach,
190 .pru_bind = udp6_bind,
191 .pru_connect = udp6_connect,
192 .pru_connectx = udp6_connectx,
193 .pru_control = in6_control,
194 .pru_detach = udp6_detach,
195 .pru_disconnect = udp6_disconnect,
196 .pru_disconnectx = udp6_disconnectx,
197 .pru_peeraddr = in6_mapped_peeraddr,
198 .pru_send = udp6_send,
199 .pru_shutdown = udp_shutdown,
200 .pru_sockaddr = in6_mapped_sockaddr,
201 .pru_sosend = sosend,
202 .pru_soreceive = soreceive,
3e170ce0 203 .pru_soreceive_list = soreceive_list,
39236c6e 204};
1c79356b 205
2d21ac55
A
206/*
207 * subroutine of udp6_input(), mainly for source code readability.
208 */
209static void
39236c6e
A
210udp6_append(struct inpcb *last, struct ip6_hdr *ip6,
211 struct sockaddr_in6 *udp_in6, struct mbuf *n, int off, struct ifnet *ifp)
2d21ac55 212{
39236c6e 213#pragma unused(ip6)
2d21ac55 214 struct mbuf *opts = NULL;
6d2010ae 215 int ret = 0;
39236c6e
A
216 boolean_t cell = IFNET_IS_CELLULAR(ifp);
217 boolean_t wifi = (!cell && IFNET_IS_WIFI(ifp));
fe8ab488 218 boolean_t wired = (!wifi && IFNET_IS_WIRED(ifp));
39236c6e 219
2d21ac55
A
220#if CONFIG_MACF_NET
221 if (mac_inpcb_check_deliver(last, n, AF_INET6, SOCK_DGRAM) != 0) {
222 m_freem(n);
223 return;
224 }
39236c6e
A
225#endif /* CONFIG_MACF_NET */
226 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
6d2010ae
A
227 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
228 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) {
229 ret = ip6_savecontrol(last, n, &opts);
230 if (ret != 0) {
231 m_freem(n);
232 m_freem(opts);
233 return;
234 }
235 }
2d21ac55 236 m_adj(n, off);
6d2010ae 237 if (nstat_collect) {
fe8ab488
A
238 INP_ADD_STAT(last, cell, wifi, wired, rxpackets, 1);
239 INP_ADD_STAT(last, cell, wifi, wired, rxbytes, n->m_pkthdr.len);
6d2010ae
A
240 }
241 so_recv_data_stat(last->in6p_socket, n, 0);
2d21ac55
A
242 if (sbappendaddr(&last->in6p_socket->so_rcv,
243 (struct sockaddr *)udp_in6, n, opts, NULL) == 0)
244 udpstat.udps_fullsock++;
245 else
246 sorwakeup(last->in6p_socket);
247}
248
1c79356b 249int
39236c6e 250udp6_input(struct mbuf **mp, int *offp, int proto)
1c79356b 251{
6d2010ae 252#pragma unused(proto)
1c79356b 253 struct mbuf *m = *mp;
6d2010ae 254 struct ifnet *ifp;
39236c6e
A
255 struct ip6_hdr *ip6;
256 struct udphdr *uh;
257 struct inpcb *in6p;
9bccf70c 258 struct mbuf *opts = NULL;
1c79356b 259 int off = *offp;
6d2010ae 260 int plen, ulen, ret = 0;
fe8ab488 261 boolean_t cell, wifi, wired;
1c79356b 262 struct sockaddr_in6 udp_in6;
91447636 263 struct inpcbinfo *pcbinfo = &udbinfo;
6d2010ae 264 struct sockaddr_in6 fromsa;
1c79356b 265
39236c6e 266 IP6_EXTHDR_CHECK(m, off, sizeof (struct udphdr), return IPPROTO_DONE);
9bccf70c 267
316670eb
A
268 /* Expect 32-bit aligned data pointer on strict-align platforms */
269 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
270
6d2010ae 271 ifp = m->m_pkthdr.rcvif;
9bccf70c 272 ip6 = mtod(m, struct ip6_hdr *);
39236c6e
A
273 cell = IFNET_IS_CELLULAR(ifp);
274 wifi = (!cell && IFNET_IS_WIFI(ifp));
fe8ab488 275 wired = (!wifi && IFNET_IS_WIRED(ifp));
9bccf70c 276
9bccf70c 277 udpstat.udps_ipackets++;
1c79356b 278
39236c6e 279 plen = ntohs(ip6->ip6_plen) - off + sizeof (*ip6);
316670eb 280 uh = (struct udphdr *)(void *)((caddr_t)ip6 + off);
1c79356b
A
281 ulen = ntohs((u_short)uh->uh_ulen);
282
283 if (plen != ulen) {
284 udpstat.udps_badlen++;
39236c6e 285 IF_UDP_STATINC(ifp, badlength);
1c79356b
A
286 goto bad;
287 }
288
6d2010ae 289 /* destination port of 0 is illegal, based on RFC768. */
316670eb 290 if (uh->uh_dport == 0) {
39236c6e 291 IF_UDP_STATINC(ifp, port0);
6d2010ae 292 goto bad;
316670eb 293 }
6d2010ae 294
1c79356b
A
295 /*
296 * Checksum extended UDP header and data.
297 */
39236c6e
A
298 if (udp6_input_checksum(m, uh, off, ulen))
299 goto bad;
6d2010ae
A
300
301 /*
302 * Construct sockaddr format source address.
303 */
304 init_sin6(&fromsa, m);
305 fromsa.sin6_port = uh->uh_sport;
306
1c79356b 307 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
2d21ac55 308 int reuse_sock = 0, mcast_delivered = 0;
6d2010ae 309 struct ip6_moptions *imo;
1c79356b
A
310
311 /*
312 * Deliver a multicast datagram to all sockets
313 * for which the local and remote addresses and ports match
314 * those of the incoming datagram. This allows more than
315 * one process to receive multicasts on the same port.
316 * (This really ought to be done for unicast datagrams as
317 * well, but that would cause problems with existing
318 * applications that open both address-specific sockets and
319 * a wildcard socket listening to the same port -- they would
320 * end up receiving duplicates of every unicast datagram.
321 * Those applications open the multiple sockets to overcome an
322 * inadequacy of the UDP socket interface, but for backwards
323 * compatibility we avoid the problem here rather than
324 * fixing the interface. Maybe 4.5BSD will remedy this?)
325 */
326
327 /*
328 * In a case that laddr should be set to the link-local
329 * address (this happens in RIPng), the multicast address
330 * specified in the received packet does not match with
331 * laddr. To cure this situation, the matching is relaxed
332 * if the receiving interface is the same as one specified
333 * in the socket and if the destination multicast address
334 * matches one of the multicast groups specified in the socket.
335 */
336
337 /*
338 * Construct sockaddr format source address.
339 */
340 init_sin6(&udp_in6, m); /* general init */
341 udp_in6.sin6_port = uh->uh_sport;
342 /*
343 * KAME note: usually we drop udphdr from mbuf here.
344 * We need udphdr for IPsec processing so we do that later.
345 */
346
347 /*
348 * Locate pcb(s) for datagram.
349 * (Algorithm copied from raw_intr().)
350 */
39236c6e 351 lck_rw_lock_shared(pcbinfo->ipi_lock);
91447636 352
1c79356b 353 LIST_FOREACH(in6p, &udb, inp_list) {
39236c6e
A
354#if IPSEC
355 int skipit;
356#endif /* IPSEC */
91447636 357
1c79356b
A
358 if ((in6p->inp_vflag & INP_IPV6) == 0)
359 continue;
91447636 360
fe8ab488 361 if (inp_restricted_recv(in6p, ifp))
316670eb
A
362 continue;
363
39236c6e
A
364 if (in_pcb_checkstate(in6p, WNT_ACQUIRE, 0) ==
365 WNT_STOPUSING)
91447636
A
366 continue;
367
316670eb 368 udp_lock(in6p->in6p_socket, 1, 0);
91447636 369
39236c6e
A
370 if (in_pcb_checkstate(in6p, WNT_RELEASE, 1) ==
371 WNT_STOPUSING) {
91447636
A
372 udp_unlock(in6p->in6p_socket, 1, 0);
373 continue;
374 }
375 if (in6p->in6p_lport != uh->uh_dport) {
376 udp_unlock(in6p->in6p_socket, 1, 0);
1c79356b 377 continue;
91447636 378 }
6d2010ae
A
379
380 /*
381 * Handle socket delivery policy for any-source
382 * and source-specific multicast. [RFC3678]
383 */
384 imo = in6p->in6p_moptions;
385 if (imo && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
39236c6e
A
386 struct sockaddr_in6 mcaddr;
387 int blocked;
6d2010ae 388
316670eb 389 IM6O_LOCK(imo);
39236c6e
A
390 bzero(&mcaddr, sizeof (struct sockaddr_in6));
391 mcaddr.sin6_len = sizeof (struct sockaddr_in6);
6d2010ae
A
392 mcaddr.sin6_family = AF_INET6;
393 mcaddr.sin6_addr = ip6->ip6_dst;
394
395 blocked = im6o_mc_filter(imo, ifp,
39236c6e
A
396 (struct sockaddr *)&mcaddr,
397 (struct sockaddr *)&fromsa);
316670eb 398 IM6O_UNLOCK(imo);
6d2010ae 399 if (blocked != MCAST_PASS) {
91447636 400 udp_unlock(in6p->in6p_socket, 1, 0);
39236c6e
A
401 if (blocked == MCAST_NOTSMEMBER ||
402 blocked == MCAST_MUTED)
403 udpstat.udps_filtermcast++;
1c79356b 404 continue;
91447636 405 }
1c79356b 406 }
39236c6e
A
407 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
408 (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
409 &ip6->ip6_src) ||
410 in6p->in6p_fport != uh->uh_sport)) {
411 udp_unlock(in6p->in6p_socket, 1, 0);
412 continue;
1c79356b
A
413 }
414
2d21ac55
A
415 reuse_sock = in6p->inp_socket->so_options &
416 (SO_REUSEPORT | SO_REUSEADDR);
1c79356b 417
fe8ab488 418#if NECP
39236c6e 419 skipit = 0;
fe8ab488
A
420 if (!necp_socket_is_allowed_to_send_recv_v6(in6p,
421 uh->uh_dport, uh->uh_sport, &ip6->ip6_dst,
3e170ce0 422 &ip6->ip6_src, ifp, NULL, NULL)) {
39236c6e
A
423 /* do not inject data to pcb */
424 skipit = 1;
425 }
426 if (skipit == 0)
fe8ab488 427#endif /* NECP */
39236c6e 428 {
fe8ab488 429 struct mbuf *n = NULL;
39236c6e
A
430 /*
431 * KAME NOTE: do not
432 * m_copy(m, offset, ...) below.
433 * sbappendaddr() expects M_PKTHDR,
434 * and m_copy() will copy M_PKTHDR
435 * only if offset is 0.
436 */
437 if (reuse_sock)
438 n = m_copy(m, 0, M_COPYALL);
439 udp6_append(in6p, ip6, &udp_in6, m,
440 off + sizeof (struct udphdr), ifp);
441 mcast_delivered++;
fe8ab488 442 m = n;
1c79356b 443 }
39236c6e
A
444 udp_unlock(in6p->in6p_socket, 1, 0);
445
1c79356b
A
446 /*
447 * Don't look for additional matches if this one does
448 * not have either the SO_REUSEPORT or SO_REUSEADDR
449 * socket options set. This heuristic avoids searching
450 * through all pcbs in the common case of a non-shared
451 * port. It assumes that an application will never
452 * clear these options after setting them.
453 */
fe8ab488 454 if (reuse_sock == 0 || m == NULL)
1c79356b 455 break;
316670eb
A
456
457 /*
458 * Expect 32-bit aligned data pointer on strict-align
459 * platforms.
460 */
461 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
462
b0d623f7
A
463 /*
464 * Recompute IP and UDP header pointers for new mbuf
465 */
466 ip6 = mtod(m, struct ip6_hdr *);
316670eb 467 uh = (struct udphdr *)(void *)((caddr_t)ip6 + off);
1c79356b 468 }
39236c6e 469 lck_rw_done(pcbinfo->ipi_lock);
1c79356b 470
2d21ac55 471 if (mcast_delivered == 0) {
1c79356b
A
472 /*
473 * No matching pcb found; discard datagram.
474 * (No need to send an ICMP Port Unreachable
475 * for a broadcast or multicast datgram.)
476 */
477 udpstat.udps_noport++;
9bccf70c 478 udpstat.udps_noportmcast++;
39236c6e 479 IF_UDP_STATINC(ifp, port_unreach);
1c79356b
A
480 goto bad;
481 }
2d21ac55 482
fe8ab488
A
483 /* free the extra copy of mbuf or skipped by NECP */
484 if (m != NULL)
2d21ac55 485 m_freem(m);
39236c6e 486 return (IPPROTO_DONE);
1c79356b 487 }
3e170ce0
A
488
489#if IPSEC
490 /*
491 * UDP to port 4500 with a payload where the first four bytes are
492 * not zero is a UDP encapsulated IPSec packet. Packets where
493 * the payload is one byte and that byte is 0xFF are NAT keepalive
494 * packets. Decapsulate the ESP packet and carry on with IPSec input
495 * or discard the NAT keep-alive.
496 */
497 if (ipsec_bypass == 0 && (esp_udp_encap_port & 0xFFFF) != 0 &&
498 uh->uh_dport == ntohs((u_short)esp_udp_encap_port)) {
499 int payload_len = ulen - sizeof (struct udphdr) > 4 ? 4 :
500 ulen - sizeof (struct udphdr);
501
502 if (m->m_len < off + sizeof (struct udphdr) + payload_len) {
503 if ((m = m_pullup(m, off + sizeof (struct udphdr) +
504 payload_len)) == NULL) {
505 udpstat.udps_hdrops++;
506 goto bad;
507 }
508 /*
509 * Expect 32-bit aligned data pointer on strict-align
510 * platforms.
511 */
512 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
513
514 ip6 = mtod(m, struct ip6_hdr *);
515 uh = (struct udphdr *)(void *)((caddr_t)ip6 + off);
516 }
517 /* Check for NAT keepalive packet */
518 if (payload_len == 1 && *(u_int8_t*)
519 ((caddr_t)uh + sizeof (struct udphdr)) == 0xFF) {
520 goto bad;
521 } else if (payload_len == 4 && *(u_int32_t*)(void *)
522 ((caddr_t)uh + sizeof (struct udphdr)) != 0) {
523 /* UDP encapsulated IPSec packet to pass through NAT */
524 /* preserve the udp header */
525 *offp = off + sizeof (struct udphdr);
526 return (esp6_input(mp, offp, IPPROTO_UDP));
527 }
528 }
529#endif /* IPSEC */
530
1c79356b
A
531 /*
532 * Locate pcb for datagram.
533 */
534 in6p = in6_pcblookup_hash(&udbinfo, &ip6->ip6_src, uh->uh_sport,
39236c6e 535 &ip6->ip6_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
316670eb 536 if (in6p == NULL) {
39236c6e 537 IF_UDP_STATINC(ifp, port_unreach);
316670eb 538
39236c6e 539 if (udp_log_in_vain) {
1c79356b
A
540 char buf[INET6_ADDRSTRLEN];
541
39236c6e
A
542 strlcpy(buf, ip6_sprintf(&ip6->ip6_dst), sizeof (buf));
543 if (udp_log_in_vain < 3) {
544 log(LOG_INFO, "Connection attempt to UDP "
545 "%s:%d from %s:%d\n", buf,
546 ntohs(uh->uh_dport),
547 ip6_sprintf(&ip6->ip6_src),
548 ntohs(uh->uh_sport));
549 } else if (!(m->m_flags & (M_BCAST | M_MCAST)) &&
550 !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ip6->ip6_src)) {
551 log_in_vain_log((LOG_INFO, "Connection attempt "
552 "to UDP %s:%d from %s:%d\n", buf,
553 ntohs(uh->uh_dport),
554 ip6_sprintf(&ip6->ip6_src),
555 ntohs(uh->uh_sport)));
556 }
1c79356b
A
557 }
558 udpstat.udps_noport++;
559 if (m->m_flags & M_MCAST) {
560 printf("UDP6: M_MCAST is set in a unicast packet.\n");
9bccf70c 561 udpstat.udps_noportmcast++;
39236c6e 562 IF_UDP_STATINC(ifp, badmcast);
1c79356b
A
563 goto bad;
564 }
565 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
39236c6e 566 return (IPPROTO_DONE);
1c79356b 567 }
fe8ab488
A
568#if NECP
569 if (!necp_socket_is_allowed_to_send_recv_v6(in6p, uh->uh_dport,
3e170ce0 570 uh->uh_sport, &ip6->ip6_dst, &ip6->ip6_src, ifp, NULL, NULL)) {
fe8ab488
A
571 in_pcb_checkstate(in6p, WNT_RELEASE, 0);
572 IF_UDP_STATINC(ifp, badipsec);
573 goto bad;
1c79356b 574 }
fe8ab488 575#endif /* NECP */
1c79356b
A
576
577 /*
578 * Construct sockaddr format source address.
579 * Stuff source address and datagram in user buffer.
580 */
91447636
A
581 udp_lock(in6p->in6p_socket, 1, 0);
582
583 if (in_pcb_checkstate(in6p, WNT_RELEASE, 1) == WNT_STOPUSING) {
584 udp_unlock(in6p->in6p_socket, 1, 0);
39236c6e 585 IF_UDP_STATINC(ifp, cleanup);
91447636
A
586 goto bad;
587 }
316670eb 588
1c79356b
A
589 init_sin6(&udp_in6, m); /* general init */
590 udp_in6.sin6_port = uh->uh_sport;
39236c6e
A
591 if ((in6p->in6p_flags & INP_CONTROLOPTS) != 0 ||
592 (in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
593 (in6p->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) {
6d2010ae
A
594 ret = ip6_savecontrol(in6p, m, &opts);
595 if (ret != 0) {
596 udp_unlock(in6p->in6p_socket, 1, 0);
597 goto bad;
598 }
599 }
39236c6e 600 m_adj(m, off + sizeof (struct udphdr));
6d2010ae 601 if (nstat_collect) {
fe8ab488
A
602 INP_ADD_STAT(in6p, cell, wifi, wired, rxpackets, 1);
603 INP_ADD_STAT(in6p, cell, wifi, wired, rxbytes, m->m_pkthdr.len);
6d2010ae
A
604 }
605 so_recv_data_stat(in6p->in6p_socket, m, 0);
1c79356b 606 if (sbappendaddr(&in6p->in6p_socket->so_rcv,
39236c6e 607 (struct sockaddr *)&udp_in6, m, opts, NULL) == 0) {
91447636
A
608 m = NULL;
609 opts = NULL;
1c79356b 610 udpstat.udps_fullsock++;
91447636 611 udp_unlock(in6p->in6p_socket, 1, 0);
1c79356b
A
612 goto bad;
613 }
614 sorwakeup(in6p->in6p_socket);
91447636 615 udp_unlock(in6p->in6p_socket, 1, 0);
39236c6e 616 return (IPPROTO_DONE);
1c79356b 617bad:
39236c6e 618 if (m != NULL)
1c79356b 619 m_freem(m);
39236c6e 620 if (opts != NULL)
9bccf70c 621 m_freem(opts);
39236c6e 622 return (IPPROTO_DONE);
1c79356b
A
623}
624
625void
39236c6e 626udp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
1c79356b 627{
1c79356b 628 struct udphdr uh;
1c79356b
A
629 struct ip6_hdr *ip6;
630 struct mbuf *m;
631 int off = 0;
9bccf70c
A
632 struct ip6ctlparam *ip6cp = NULL;
633 const struct sockaddr_in6 *sa6_src = NULL;
91447636 634 void (*notify)(struct inpcb *, int) = udp_notify;
9bccf70c
A
635 struct udp_portonly {
636 u_int16_t uh_sport;
637 u_int16_t uh_dport;
638 } *uhp;
1c79356b
A
639
640 if (sa->sa_family != AF_INET6 ||
39236c6e 641 sa->sa_len != sizeof (struct sockaddr_in6))
1c79356b
A
642 return;
643
644 if ((unsigned)cmd >= PRC_NCMDS)
645 return;
646 if (PRC_IS_REDIRECT(cmd))
647 notify = in6_rtchange, d = NULL;
648 else if (cmd == PRC_HOSTDEAD)
649 d = NULL;
650 else if (inet6ctlerrmap[cmd] == 0)
651 return;
652
653 /* if the parameter is from icmp6, decode it. */
654 if (d != NULL) {
9bccf70c 655 ip6cp = (struct ip6ctlparam *)d;
1c79356b
A
656 m = ip6cp->ip6c_m;
657 ip6 = ip6cp->ip6c_ip6;
658 off = ip6cp->ip6c_off;
9bccf70c 659 sa6_src = ip6cp->ip6c_src;
1c79356b
A
660 } else {
661 m = NULL;
662 ip6 = NULL;
9bccf70c 663 sa6_src = &sa6_any;
1c79356b
A
664 }
665
39236c6e 666 if (ip6 != NULL) {
1c79356b
A
667 /*
668 * XXX: We assume that when IPV6 is non NULL,
669 * M and OFF are valid.
670 */
1c79356b 671
9bccf70c 672 /* check if we can safely examine src and dst ports */
39236c6e 673 if (m->m_pkthdr.len < off + sizeof (*uhp))
9bccf70c 674 return;
1c79356b 675
39236c6e
A
676 bzero(&uh, sizeof (uh));
677 m_copydata(m, off, sizeof (*uhp), (caddr_t)&uh);
9bccf70c 678
91447636 679 (void) in6_pcbnotify(&udbinfo, sa, uh.uh_dport,
39236c6e
A
680 (struct sockaddr*)ip6cp->ip6c_src, uh.uh_sport,
681 cmd, NULL, notify);
682 } else {
683 (void) in6_pcbnotify(&udbinfo, sa, 0,
684 (struct sockaddr *)&sa6_src, 0, cmd, NULL, notify);
1c79356b 685 }
1c79356b
A
686}
687
1c79356b
A
688static int
689udp6_abort(struct socket *so)
690{
691 struct inpcb *inp;
1c79356b
A
692
693 inp = sotoinpcb(so);
39236c6e
A
694 if (inp == NULL) {
695 panic("%s: so=%p null inp\n", __func__, so);
696 /* NOTREACHED */
697 }
1c79356b 698 soisdisconnected(so);
1c79356b 699 in6_pcbdetach(inp);
39236c6e 700 return (0);
1c79356b
A
701}
702
703static int
39236c6e 704udp6_attach(struct socket *so, int proto, struct proc *p)
1c79356b 705{
39236c6e 706#pragma unused(proto)
1c79356b 707 struct inpcb *inp;
91447636 708 int error;
1c79356b
A
709
710 inp = sotoinpcb(so);
39236c6e
A
711 if (inp != NULL)
712 return (EINVAL);
1c79356b 713
91447636
A
714 error = in_pcballoc(so, &udbinfo, p);
715 if (error)
39236c6e 716 return (error);
91447636 717
1c79356b
A
718 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
719 error = soreserve(so, udp_sendspace, udp_recvspace);
720 if (error)
39236c6e 721 return (error);
1c79356b 722 }
1c79356b
A
723 inp = (struct inpcb *)so->so_pcb;
724 inp->inp_vflag |= INP_IPV6;
55e303ae
A
725 if (ip6_mapped_addr_on)
726 inp->inp_vflag |= INP_IPV4;
1c79356b
A
727 inp->in6p_hops = -1; /* use kernel default */
728 inp->in6p_cksum = -1; /* just to be sure */
9bccf70c
A
729 /*
730 * XXX: ugly!!
731 * IPv4 TTL initialization is necessary for an IPv6 socket as well,
732 * because the socket may be bound to an IPv6 wildcard address,
733 * which may match an IPv4-mapped IPv6 address.
734 */
735 inp->inp_ip_ttl = ip_defttl;
316670eb
A
736 if (nstat_collect)
737 nstat_udp_new_pcb(inp);
39236c6e 738 return (0);
1c79356b
A
739}
740
741static int
742udp6_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
743{
744 struct inpcb *inp;
91447636 745 int error;
1c79356b
A
746
747 inp = sotoinpcb(so);
3e170ce0
A
748 if (inp == NULL)
749 return (EINVAL);
1c79356b
A
750
751 inp->inp_vflag &= ~INP_IPV4;
752 inp->inp_vflag |= INP_IPV6;
9bccf70c 753 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
1c79356b
A
754 struct sockaddr_in6 *sin6_p;
755
316670eb 756 sin6_p = (struct sockaddr_in6 *)(void *)nam;
1c79356b 757
39236c6e 758 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
1c79356b 759 inp->inp_vflag |= INP_IPV4;
39236c6e 760 } else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
1c79356b
A
761 struct sockaddr_in sin;
762
763 in6_sin6_2_sin(&sin, sin6_p);
764 inp->inp_vflag |= INP_IPV4;
765 inp->inp_vflag &= ~INP_IPV6;
1c79356b 766 error = in_pcbbind(inp, (struct sockaddr *)&sin, p);
39236c6e 767 return (error);
1c79356b
A
768 }
769 }
770
1c79356b 771 error = in6_pcbbind(inp, nam, p);
39236c6e 772 return (error);
1c79356b
A
773}
774
39236c6e 775int
1c79356b
A
776udp6_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
777{
778 struct inpcb *inp;
91447636 779 int error;
3e170ce0
A
780#if defined(NECP) && defined(FLOW_DIVERT)
781 int should_use_flow_divert = 0;
782#endif /* defined(NECP) && defined(FLOW_DIVERT) */
1c79356b
A
783
784 inp = sotoinpcb(so);
3e170ce0
A
785 if (inp == NULL)
786 return (EINVAL);
787
788#if defined(NECP) && defined(FLOW_DIVERT)
789 should_use_flow_divert = necp_socket_should_use_flow_divert(inp);
790#endif /* defined(NECP) && defined(FLOW_DIVERT) */
1c79356b 791
9bccf70c 792 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
1c79356b
A
793 struct sockaddr_in6 *sin6_p;
794
316670eb 795 sin6_p = (struct sockaddr_in6 *)(void *)nam;
1c79356b
A
796 if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
797 struct sockaddr_in sin;
798
799 if (inp->inp_faddr.s_addr != INADDR_ANY)
39236c6e 800 return (EISCONN);
1c79356b 801 in6_sin6_2_sin(&sin, sin6_p);
3e170ce0
A
802#if defined(NECP) && defined(FLOW_DIVERT)
803 if (should_use_flow_divert) {
804 goto do_flow_divert;
805 }
806#endif /* defined(NECP) && defined(FLOW_DIVERT) */
39236c6e
A
807 error = in_pcbconnect(inp, (struct sockaddr *)&sin,
808 p, IFSCOPE_NONE, NULL);
1c79356b
A
809 if (error == 0) {
810 inp->inp_vflag |= INP_IPV4;
811 inp->inp_vflag &= ~INP_IPV6;
812 soisconnected(so);
813 }
39236c6e 814 return (error);
1c79356b
A
815 }
816 }
817
818 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
39236c6e 819 return (EISCONN);
3e170ce0
A
820
821#if defined(NECP) && defined(FLOW_DIVERT)
822do_flow_divert:
823 if (should_use_flow_divert) {
824 uint32_t fd_ctl_unit = necp_socket_get_flow_divert_control_unit(inp);
825 if (fd_ctl_unit > 0) {
826 error = flow_divert_pcb_init(so, fd_ctl_unit);
827 if (error == 0) {
828 error = flow_divert_connect_out(so, nam, p);
829 }
830 } else {
831 error = ENETDOWN;
832 }
833 return (error);
834 }
835#endif /* defined(NECP) && defined(FLOW_DIVERT) */
836
1c79356b 837 error = in6_pcbconnect(inp, nam, p);
1c79356b 838 if (error == 0) {
39236c6e
A
839 /* should be non mapped addr */
840 if (ip6_mapped_addr_on ||
841 (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
1c79356b
A
842 inp->inp_vflag &= ~INP_IPV4;
843 inp->inp_vflag |= INP_IPV6;
844 }
845 soisconnected(so);
316670eb
A
846 if (inp->inp_flowhash == 0)
847 inp->inp_flowhash = inp_calc_flowhash(inp);
39236c6e
A
848 /* update flowinfo - RFC 6437 */
849 if (inp->inp_flow == 0 &&
850 inp->in6p_flags & IN6P_AUTOFLOWLABEL) {
851 inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
852 inp->inp_flow |=
853 (htonl(inp->inp_flowhash) & IPV6_FLOWLABEL_MASK);
854 }
1c79356b 855 }
39236c6e
A
856 return (error);
857}
858
859static int
860udp6_connectx(struct socket *so, struct sockaddr_list **src_sl,
861 struct sockaddr_list **dst_sl, struct proc *p, uint32_t ifscope,
3e170ce0
A
862 sae_associd_t aid, sae_connid_t *pcid, uint32_t flags, void *arg,
863 uint32_t arglen, struct uio *uio, user_ssize_t *bytes_written)
39236c6e
A
864{
865 return (udp_connectx_common(so, AF_INET6, src_sl, dst_sl,
3e170ce0 866 p, ifscope, aid, pcid, flags, arg, arglen, uio, bytes_written));
1c79356b
A
867}
868
869static int
870udp6_detach(struct socket *so)
871{
872 struct inpcb *inp;
1c79356b
A
873
874 inp = sotoinpcb(so);
39236c6e
A
875 if (inp == NULL)
876 return (EINVAL);
1c79356b 877 in6_pcbdetach(inp);
39236c6e 878 return (0);
1c79356b
A
879}
880
881static int
882udp6_disconnect(struct socket *so)
883{
884 struct inpcb *inp;
1c79356b
A
885
886 inp = sotoinpcb(so);
fe8ab488
A
887 if (inp == NULL
888#if NECP
889 || (necp_socket_should_use_flow_divert(inp))
890#endif /* NECP */
891 )
39236c6e 892 return (inp == NULL ? EINVAL : EPROTOTYPE);
1c79356b
A
893
894 if (inp->inp_vflag & INP_IPV4) {
895 struct pr_usrreqs *pru;
896
897 pru = ip_protox[IPPROTO_UDP]->pr_usrreqs;
898 return ((*pru->pru_disconnect)(so));
899 }
900
901 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
39236c6e 902 return (ENOTCONN);
1c79356b 903
1c79356b 904 in6_pcbdisconnect(inp);
316670eb
A
905
906 /* reset flow-controlled state, just in case */
907 inp_reset_fc_state(inp);
908
1c79356b 909 inp->in6p_laddr = in6addr_any;
316670eb 910 inp->in6p_last_outifp = NULL;
1c79356b 911 so->so_state &= ~SS_ISCONNECTED; /* XXX */
39236c6e
A
912 return (0);
913}
914
915static int
3e170ce0 916udp6_disconnectx(struct socket *so, sae_associd_t aid, sae_connid_t cid)
39236c6e
A
917{
918#pragma unused(cid)
3e170ce0 919 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL)
39236c6e
A
920 return (EINVAL);
921
922 return (udp6_disconnect(so));
1c79356b
A
923}
924
925static int
926udp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
39236c6e 927 struct mbuf *control, struct proc *p)
1c79356b
A
928{
929 struct inpcb *inp;
9bccf70c 930 int error = 0;
3e170ce0
A
931#if defined(NECP) && defined(FLOW_DIVERT)
932 int should_use_flow_divert = 0;
933#endif /* defined(NECP) && defined(FLOW_DIVERT) */
1c79356b
A
934
935 inp = sotoinpcb(so);
3e170ce0
A
936 if (inp == NULL) {
937 error = EINVAL;
9bccf70c
A
938 goto bad;
939 }
940
3e170ce0
A
941#if defined(NECP) && defined(FLOW_DIVERT)
942 should_use_flow_divert = necp_socket_should_use_flow_divert(inp);
943#endif /* defined(NECP) && defined(FLOW_DIVERT) */
944
39236c6e
A
945 if (addr != NULL) {
946 if (addr->sa_len != sizeof (struct sockaddr_in6)) {
9bccf70c
A
947 error = EINVAL;
948 goto bad;
949 }
950 if (addr->sa_family != AF_INET6) {
951 error = EAFNOSUPPORT;
952 goto bad;
953 }
1c79356b
A
954 }
955
55e303ae 956 if (ip6_mapped_addr_on || (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
1c79356b 957 int hasv4addr;
39236c6e 958 struct sockaddr_in6 *sin6 = NULL;
1c79356b 959
39236c6e 960 if (addr == NULL) {
1c79356b 961 hasv4addr = (inp->inp_vflag & INP_IPV4);
39236c6e 962 } else {
316670eb 963 sin6 = (struct sockaddr_in6 *)(void *)addr;
39236c6e
A
964 hasv4addr =
965 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ? 1 : 0;
1c79356b
A
966 }
967 if (hasv4addr) {
968 struct pr_usrreqs *pru;
1c79356b 969
39236c6e 970 if (sin6 != NULL)
1c79356b 971 in6_sin6_2_sin_in_sock(addr);
3e170ce0
A
972#if defined(NECP) && defined(FLOW_DIVERT)
973 if (should_use_flow_divert) {
974 goto do_flow_divert;
975 }
976#endif /* defined(NECP) && defined(FLOW_DIVERT) */
1c79356b 977 pru = ip_protox[IPPROTO_UDP]->pr_usrreqs;
39236c6e
A
978 error = ((*pru->pru_send)(so, flags, m, addr,
979 control, p));
1c79356b 980 /* addr will just be freed in sendit(). */
39236c6e 981 return (error);
1c79356b
A
982 }
983 }
3e170ce0
A
984
985#if defined(NECP) && defined(FLOW_DIVERT)
986do_flow_divert:
987 if (should_use_flow_divert) {
988 /* Implicit connect */
989 return (flow_divert_implicit_data_out(so, flags, m, addr, control, p));
990 }
991#endif /* defined(NECP) && defined(FLOW_DIVERT) */
992
39236c6e
A
993 return (udp6_output(inp, m, addr, control, p));
994
995bad:
996 VERIFY(error != 0);
1c79356b 997
39236c6e
A
998 if (m != NULL)
999 m_freem(m);
1000 if (control != NULL)
1001 m_freem(control);
9bccf70c 1002
39236c6e 1003 return (error);
1c79356b
A
1004}
1005
39236c6e
A
1006/*
1007 * Checksum extended UDP header and data.
1008 */
1009static int
1010udp6_input_checksum(struct mbuf *m, struct udphdr *uh, int off, int ulen)
1011{
1012 struct ifnet *ifp = m->m_pkthdr.rcvif;
1013 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1014
490019cf
A
1015 if (!(m->m_pkthdr.csum_flags & CSUM_DATA_VALID) &&
1016 uh->uh_sum == 0) {
39236c6e 1017 /* UDP/IPv6 checksum is mandatory (RFC2460) */
490019cf
A
1018
1019 /*
1020 * If checksum was already validated, ignore this check.
1021 * This is necessary for transport-mode ESP, which may be
1022 * getting UDP payloads without checksums when the network
1023 * has a NAT64.
1024 */
39236c6e
A
1025 udpstat.udps_nosum++;
1026 goto badsum;
1027 }
1028
1029 if ((hwcksum_rx || (ifp->if_flags & IFF_LOOPBACK) ||
1030 (m->m_pkthdr.pkt_flags & PKTF_LOOP)) &&
1031 (m->m_pkthdr.csum_flags & CSUM_DATA_VALID)) {
1032 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
1033 uh->uh_sum = m->m_pkthdr.csum_rx_val;
1034 } else {
1035 uint16_t sum = m->m_pkthdr.csum_rx_val;
1036 uint16_t start = m->m_pkthdr.csum_rx_start;
1037
1038 /*
1039 * Perform 1's complement adjustment of octets
1040 * that got included/excluded in the hardware-
1041 * calculated checksum value.
1042 */
1043 if ((m->m_pkthdr.csum_flags & CSUM_PARTIAL) &&
1044 start != off) {
1045 uint16_t s, d;
1046
1047 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) {
1048 s = ip6->ip6_src.s6_addr16[1];
1049 ip6->ip6_src.s6_addr16[1] = 0 ;
1050 }
1051 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) {
1052 d = ip6->ip6_dst.s6_addr16[1];
1053 ip6->ip6_dst.s6_addr16[1] = 0;
1054 }
1055
1056 /* callee folds in sum */
1057 sum = m_adj_sum16(m, start, off, sum);
1058
1059 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
1060 ip6->ip6_src.s6_addr16[1] = s;
1061 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
1062 ip6->ip6_dst.s6_addr16[1] = d;
1063 }
1064
1065 uh->uh_sum = in6_pseudo(&ip6->ip6_src, &ip6->ip6_dst,
1066 sum + htonl(ulen + IPPROTO_UDP));
1067 }
1068 uh->uh_sum ^= 0xffff;
1069 } else {
1070 udp_in6_cksum_stats(ulen);
1071 uh->uh_sum = in6_cksum(m, IPPROTO_UDP, off, ulen);
1072 }
1073
1074 if (uh->uh_sum != 0) {
1075badsum:
1076 udpstat.udps_badsum++;
1077 IF_UDP_STATINC(ifp, badchksum);
1078 return (-1);
1079 }
1080
1081 return (0);
1082}