1/*	$OpenBSD: udp_usrreq.c,v 1.320 2024/04/17 20:48:51 bluhm Exp $	*/
2/*	$NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $	*/
3
4/*
5 * Copyright (c) 1982, 1986, 1988, 1990, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 *	@(#)COPYRIGHT	1.1 (NRL) 17 January 1995
33 *
34 * NRL grants permission for redistribution and use in source and binary
35 * forms, with or without modification, of the software and documentation
36 * created at NRL provided that the following conditions are met:
37 *
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 *    must display the following acknowledgements:
45 *	This product includes software developed by the University of
46 *	California, Berkeley and its contributors.
47 *	This product includes software developed at the Information
48 *	Technology Division, US Naval Research Laboratory.
49 * 4. Neither the name of the NRL nor the names of its contributors
50 *    may be used to endorse or promote products derived from this software
51 *    without specific prior written permission.
52 *
53 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
54 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
56 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
57 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 *
65 * The views and conclusions contained in the software and documentation
66 * are those of the authors and should not be interpreted as representing
67 * official policies, either expressed or implied, of the US Naval
68 * Research Laboratory (NRL).
69 */
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/mbuf.h>
74#include <sys/protosw.h>
75#include <sys/socket.h>
76#include <sys/socketvar.h>
77#include <sys/sysctl.h>
78#include <sys/domain.h>
79
80#include <net/if.h>
81#include <net/if_var.h>
82#include <net/if_media.h>
83#include <net/route.h>
84
85#include <netinet/in.h>
86#include <netinet/in_var.h>
87#include <netinet/ip.h>
88#include <netinet/in_pcb.h>
89#include <netinet/ip_var.h>
90#include <netinet/ip_icmp.h>
91#include <netinet/udp.h>
92#include <netinet/udp_var.h>
93
94#ifdef IPSEC
95#include <netinet/ip_ipsp.h>
96#include <netinet/ip_esp.h>
97#endif
98
99#ifdef INET6
100#include <netinet6/in6_var.h>
101#include <netinet6/ip6_var.h>
102#include <netinet6/ip6protosw.h>
103#endif /* INET6 */
104
105#include "pf.h"
106#if NPF > 0
107#include <net/pfvar.h>
108#endif
109
110#ifdef PIPEX
111#include <netinet/if_ether.h>
112#include <net/pipex.h>
113#endif
114
115/*
116 * UDP protocol implementation.
117 * Per RFC 768, August, 1980.
118 */
119int	udpcksum = 1;
120
121u_int	udp_sendspace = 9216;		/* really max datagram size */
122u_int	udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
123					/* 40 1K datagrams */
124
125const struct pr_usrreqs udp_usrreqs = {
126	.pru_attach	= udp_attach,
127	.pru_detach	= udp_detach,
128	.pru_lock	= udp_lock,
129	.pru_unlock	= udp_unlock,
130	.pru_locked	= udp_locked,
131	.pru_bind	= udp_bind,
132	.pru_connect	= udp_connect,
133	.pru_disconnect	= udp_disconnect,
134	.pru_shutdown	= udp_shutdown,
135	.pru_send	= udp_send,
136	.pru_control	= in_control,
137	.pru_sockaddr	= in_sockaddr,
138	.pru_peeraddr	= in_peeraddr,
139};
140
141#ifdef INET6
142const struct pr_usrreqs udp6_usrreqs = {
143	.pru_attach	= udp_attach,
144	.pru_detach	= udp_detach,
145	.pru_lock	= udp_lock,
146	.pru_unlock	= udp_unlock,
147	.pru_locked	= udp_locked,
148	.pru_bind	= udp_bind,
149	.pru_connect	= udp_connect,
150	.pru_disconnect	= udp_disconnect,
151	.pru_shutdown	= udp_shutdown,
152	.pru_send	= udp_send,
153	.pru_control	= in6_control,
154	.pru_sockaddr	= in6_sockaddr,
155	.pru_peeraddr	= in6_peeraddr,
156};
157#endif
158
159const struct sysctl_bounded_args udpctl_vars[] = {
160	{ UDPCTL_CHECKSUM, &udpcksum, 0, 1 },
161	{ UDPCTL_RECVSPACE, &udp_recvspace, 0, INT_MAX },
162	{ UDPCTL_SENDSPACE, &udp_sendspace, 0, INT_MAX },
163};
164
165struct	inpcbtable udbtable;
166#ifdef INET6
167struct	inpcbtable udb6table;
168#endif
169struct	cpumem *udpcounters;
170
171void	udp_sbappend(struct inpcb *, struct mbuf *, struct ip *,
172	    struct ip6_hdr *, int, struct udphdr *, struct sockaddr *,
173	    u_int32_t);
174int	udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *);
175void	udp_notify(struct inpcb *, int);
176int	udp_sysctl_udpstat(void *, size_t *, void *);
177
178#ifndef	UDB_INITIAL_HASH_SIZE
179#define	UDB_INITIAL_HASH_SIZE	128
180#endif
181
182void
183udp_init(void)
184{
185	udpcounters = counters_alloc(udps_ncounters);
186	in_pcbinit(&udbtable, UDB_INITIAL_HASH_SIZE);
187#ifdef INET6
188	in_pcbinit(&udb6table, UDB_INITIAL_HASH_SIZE);
189#endif
190}
191
192int
193udp_input(struct mbuf **mp, int *offp, int proto, int af)
194{
195	struct mbuf *m = *mp;
196	int iphlen = *offp;
197	struct ip *ip = NULL;
198	struct udphdr *uh;
199	struct inpcb *inp = NULL;
200	struct ip save_ip;
201	int len;
202	u_int16_t savesum;
203	union {
204		struct sockaddr sa;
205		struct sockaddr_in sin;
206#ifdef INET6
207		struct sockaddr_in6 sin6;
208#endif /* INET6 */
209	} srcsa, dstsa;
210	struct ip6_hdr *ip6 = NULL;
211	u_int32_t ipsecflowinfo = 0;
212
213	udpstat_inc(udps_ipackets);
214
215	IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
216	if (!uh) {
217		udpstat_inc(udps_hdrops);
218		return IPPROTO_DONE;
219	}
220
221	/* Check for illegal destination port 0 */
222	if (uh->uh_dport == 0) {
223		udpstat_inc(udps_noport);
224		goto bad;
225	}
226
227	/*
228	 * Make mbuf data length reflect UDP length.
229	 * If not enough data to reflect UDP length, drop.
230	 */
231	len = ntohs((u_int16_t)uh->uh_ulen);
232	switch (af) {
233	case AF_INET:
234		if (m->m_pkthdr.len - iphlen != len) {
235			if (len > (m->m_pkthdr.len - iphlen) ||
236			    len < sizeof(struct udphdr)) {
237				udpstat_inc(udps_badlen);
238				goto bad;
239			}
240			m_adj(m, len - (m->m_pkthdr.len - iphlen));
241		}
242		ip = mtod(m, struct ip *);
243		/*
244		 * Save a copy of the IP header in case we want restore it
245		 * for sending an ICMP error message in response.
246		 */
247		save_ip = *ip;
248		break;
249#ifdef INET6
250	case AF_INET6:
251		/* jumbograms */
252		if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff)
253			len = m->m_pkthdr.len - iphlen;
254		if (len != m->m_pkthdr.len - iphlen) {
255			udpstat_inc(udps_badlen);
256			goto bad;
257		}
258		ip6 = mtod(m, struct ip6_hdr *);
259		break;
260#endif /* INET6 */
261	default:
262		unhandled_af(af);
263	}
264
265	/*
266	 * Checksum extended UDP header and data.
267	 * from W.R.Stevens: check incoming udp cksums even if
268	 *	udpcksum is not set.
269	 */
270	savesum = uh->uh_sum;
271	if (uh->uh_sum == 0) {
272		udpstat_inc(udps_nosum);
273#ifdef INET6
274		/*
275		 * In IPv6, the UDP checksum is ALWAYS used.
276		 */
277		if (ip6)
278			goto bad;
279#endif /* INET6 */
280	} else {
281		if ((m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_OK) == 0) {
282			if (m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_BAD) {
283				udpstat_inc(udps_badsum);
284				goto bad;
285			}
286			udpstat_inc(udps_inswcsum);
287
288			if (ip)
289				uh->uh_sum = in4_cksum(m, IPPROTO_UDP,
290				    iphlen, len);
291#ifdef INET6
292			else if (ip6)
293				uh->uh_sum = in6_cksum(m, IPPROTO_UDP,
294				    iphlen, len);
295#endif /* INET6 */
296			if (uh->uh_sum != 0) {
297				udpstat_inc(udps_badsum);
298				goto bad;
299			}
300		}
301	}
302
303#ifdef IPSEC
304	if (udpencap_enable && udpencap_port && esp_enable &&
305#if NPF > 0
306	    !(m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) &&
307#endif
308	    uh->uh_dport == htons(udpencap_port)) {
309		u_int32_t spi;
310		int skip = iphlen + sizeof(struct udphdr);
311
312		if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) {
313			/* packet too short */
314			m_freem(m);
315			return IPPROTO_DONE;
316		}
317		m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
318		/*
319		 * decapsulate if the SPI is not zero, otherwise pass
320		 * to userland
321		 */
322		if (spi != 0) {
323			int protoff;
324
325			if ((m = *mp = m_pullup(m, skip)) == NULL) {
326				udpstat_inc(udps_hdrops);
327				return IPPROTO_DONE;
328			}
329
330			/* remove the UDP header */
331			bcopy(mtod(m, u_char *),
332			    mtod(m, u_char *) + sizeof(struct udphdr), iphlen);
333			m_adj(m, sizeof(struct udphdr));
334			skip -= sizeof(struct udphdr);
335
336			espstat_inc(esps_udpencin);
337			protoff = af == AF_INET ? offsetof(struct ip, ip_p) :
338			    offsetof(struct ip6_hdr, ip6_nxt);
339			return ipsec_common_input(mp, skip, protoff,
340			    af, IPPROTO_ESP, 1);
341		}
342	}
343#endif /* IPSEC */
344
345	switch (af) {
346	case AF_INET:
347		bzero(&srcsa, sizeof(struct sockaddr_in));
348		srcsa.sin.sin_len = sizeof(struct sockaddr_in);
349		srcsa.sin.sin_family = AF_INET;
350		srcsa.sin.sin_port = uh->uh_sport;
351		srcsa.sin.sin_addr = ip->ip_src;
352
353		bzero(&dstsa, sizeof(struct sockaddr_in));
354		dstsa.sin.sin_len = sizeof(struct sockaddr_in);
355		dstsa.sin.sin_family = AF_INET;
356		dstsa.sin.sin_port = uh->uh_dport;
357		dstsa.sin.sin_addr = ip->ip_dst;
358		break;
359#ifdef INET6
360	case AF_INET6:
361		bzero(&srcsa, sizeof(struct sockaddr_in6));
362		srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
363		srcsa.sin6.sin6_family = AF_INET6;
364		srcsa.sin6.sin6_port = uh->uh_sport;
365#if 0 /*XXX inbound flowinfo */
366		srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow;
367#endif
368		/* KAME hack: recover scopeid */
369		in6_recoverscope(&srcsa.sin6, &ip6->ip6_src);
370
371		bzero(&dstsa, sizeof(struct sockaddr_in6));
372		dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
373		dstsa.sin6.sin6_family = AF_INET6;
374		dstsa.sin6.sin6_port = uh->uh_dport;
375#if 0 /*XXX inbound flowinfo */
376		dstsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow;
377#endif
378		/* KAME hack: recover scopeid */
379		in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst);
380		break;
381#endif /* INET6 */
382	}
383
384	if (m->m_flags & (M_BCAST|M_MCAST)) {
385		SIMPLEQ_HEAD(, inpcb) inpcblist;
386		struct inpcbtable *table;
387
388		/*
389		 * Deliver a multicast or broadcast datagram to *all* sockets
390		 * for which the local and remote addresses and ports match
391		 * those of the incoming datagram.  This allows more than
392		 * one process to receive multi/broadcasts on the same port.
393		 * (This really ought to be done for unicast datagrams as
394		 * well, but that would cause problems with existing
395		 * applications that open both address-specific sockets and
396		 * a wildcard socket listening to the same port -- they would
397		 * end up receiving duplicates of every unicast datagram.
398		 * Those applications open the multiple sockets to overcome an
399		 * inadequacy of the UDP socket interface, but for backwards
400		 * compatibility we avoid the problem here rather than
401		 * fixing the interface.  Maybe 4.5BSD will remedy this?)
402		 */
403
404		/*
405		 * Locate pcb(s) for datagram.
406		 * (Algorithm copied from raw_intr().)
407		 */
408		SIMPLEQ_INIT(&inpcblist);
409#ifdef INET6
410		if (ip6)
411			table = &udb6table;
412		else
413#endif
414			table = &udbtable;
415
416		rw_enter_write(&table->inpt_notify);
417		mtx_enter(&table->inpt_mtx);
418		TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
419			if (ip6)
420				KASSERT(ISSET(inp->inp_flags, INP_IPV6));
421			else
422				KASSERT(!ISSET(inp->inp_flags, INP_IPV6));
423
424			if (inp->inp_socket->so_rcv.sb_state & SS_CANTRCVMORE)
425				continue;
426			if (rtable_l2(inp->inp_rtableid) !=
427			    rtable_l2(m->m_pkthdr.ph_rtableid))
428				continue;
429			if (inp->inp_lport != uh->uh_dport)
430				continue;
431#ifdef INET6
432			if (ip6) {
433				if (inp->inp_ip6_minhlim &&
434				    inp->inp_ip6_minhlim > ip6->ip6_hlim)
435					continue;
436				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
437					if (!IN6_ARE_ADDR_EQUAL(
438					    &inp->inp_laddr6, &ip6->ip6_dst))
439						continue;
440			} else
441#endif /* INET6 */
442			{
443				if (inp->inp_ip_minttl &&
444				    inp->inp_ip_minttl > ip->ip_ttl)
445					continue;
446
447				if (inp->inp_laddr.s_addr != INADDR_ANY) {
448					if (inp->inp_laddr.s_addr !=
449					    ip->ip_dst.s_addr)
450						continue;
451				}
452			}
453#ifdef INET6
454			if (ip6) {
455				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
456					if (!IN6_ARE_ADDR_EQUAL(
457					    &inp->inp_faddr6, &ip6->ip6_src) ||
458					    inp->inp_fport != uh->uh_sport)
459						continue;
460			} else
461#endif /* INET6 */
462			if (inp->inp_faddr.s_addr != INADDR_ANY) {
463				if (inp->inp_faddr.s_addr !=
464				    ip->ip_src.s_addr ||
465				    inp->inp_fport != uh->uh_sport)
466					continue;
467			}
468
469			in_pcbref(inp);
470			SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify);
471
472			/*
473			 * Don't look for additional matches if this one does
474			 * not have either the SO_REUSEPORT or SO_REUSEADDR
475			 * socket options set.  This heuristic avoids searching
476			 * through all pcbs in the common case of a non-shared
477			 * port.  It assumes that an application will never
478			 * clear these options after setting them.
479			 */
480			if ((inp->inp_socket->so_options & (SO_REUSEPORT |
481			    SO_REUSEADDR)) == 0)
482				break;
483		}
484		mtx_leave(&table->inpt_mtx);
485
486		if (SIMPLEQ_EMPTY(&inpcblist)) {
487			rw_exit_write(&table->inpt_notify);
488
489			/*
490			 * No matching pcb found; discard datagram.
491			 * (No need to send an ICMP Port Unreachable
492			 * for a broadcast or multicast datgram.)
493			 */
494			udpstat_inc(udps_noportbcast);
495			goto bad;
496		}
497
498		while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) {
499			struct mbuf *n;
500
501			SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify);
502			if (SIMPLEQ_EMPTY(&inpcblist))
503				n = m;
504			else
505				n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
506			if (n != NULL) {
507				udp_sbappend(inp, n, ip, ip6, iphlen, uh,
508				    &srcsa.sa, 0);
509			}
510			in_pcbunref(inp);
511		}
512		rw_exit_write(&table->inpt_notify);
513
514		return IPPROTO_DONE;
515	}
516	/*
517	 * Locate pcb for datagram.
518	 */
519#if NPF > 0
520	inp = pf_inp_lookup(m);
521#endif
522	if (inp == NULL) {
523#ifdef INET6
524		if (ip6) {
525			inp = in6_pcblookup(&udb6table, &ip6->ip6_src,
526			    uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
527			    m->m_pkthdr.ph_rtableid);
528		} else
529#endif /* INET6 */
530		{
531			inp = in_pcblookup(&udbtable, ip->ip_src,
532			    uh->uh_sport, ip->ip_dst, uh->uh_dport,
533			    m->m_pkthdr.ph_rtableid);
534		}
535	}
536	if (inp == NULL) {
537		udpstat_inc(udps_pcbhashmiss);
538#ifdef INET6
539		if (ip6) {
540			inp = in6_pcblookup_listen(&udb6table, &ip6->ip6_dst,
541			    uh->uh_dport, m, m->m_pkthdr.ph_rtableid);
542		} else
543#endif /* INET6 */
544		{
545			inp = in_pcblookup_listen(&udbtable, ip->ip_dst,
546			    uh->uh_dport, m, m->m_pkthdr.ph_rtableid);
547		}
548	}
549
550#ifdef IPSEC
551	if (ipsec_in_use) {
552		struct m_tag *mtag;
553		struct tdb_ident *tdbi;
554		struct tdb *tdb;
555		int error;
556
557		mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
558		if (mtag != NULL) {
559			tdbi = (struct tdb_ident *)(mtag + 1);
560			tdb = gettdb(tdbi->rdomain, tdbi->spi,
561			    &tdbi->dst, tdbi->proto);
562		} else
563			tdb = NULL;
564		error = ipsp_spd_lookup(m, af, iphlen, IPSP_DIRECTION_IN,
565		    tdb, inp ? &inp->inp_seclevel : NULL, NULL, NULL);
566		if (error) {
567			udpstat_inc(udps_nosec);
568			tdb_unref(tdb);
569			goto bad;
570		}
571		/* create ipsec options, id is not modified after creation */
572		if (tdb && tdb->tdb_ids)
573			ipsecflowinfo = tdb->tdb_ids->id_flow;
574		tdb_unref(tdb);
575	}
576#endif /*IPSEC */
577
578	if (inp == NULL) {
579		udpstat_inc(udps_noport);
580		if (m->m_flags & (M_BCAST | M_MCAST)) {
581			udpstat_inc(udps_noportbcast);
582			goto bad;
583		}
584#ifdef INET6
585		if (ip6) {
586			uh->uh_sum = savesum;
587			icmp6_error(m, ICMP6_DST_UNREACH,
588			    ICMP6_DST_UNREACH_NOPORT,0);
589		} else
590#endif /* INET6 */
591		{
592			*ip = save_ip;
593			uh->uh_sum = savesum;
594			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,
595			    0, 0);
596		}
597		return IPPROTO_DONE;
598	}
599
600	KASSERT(sotoinpcb(inp->inp_socket) == inp);
601	soassertlocked(inp->inp_socket);
602
603#ifdef INET6
604	if (ip6 && inp->inp_ip6_minhlim &&
605	    inp->inp_ip6_minhlim > ip6->ip6_hlim) {
606		goto bad;
607	} else
608#endif
609	if (ip && inp->inp_ip_minttl &&
610	    inp->inp_ip_minttl > ip->ip_ttl) {
611		goto bad;
612	}
613
614#if NPF > 0
615	if (inp->inp_socket->so_state & SS_ISCONNECTED)
616		pf_inp_link(m, inp);
617#endif
618
619#ifdef PIPEX
620	if (pipex_enable && inp->inp_pipex) {
621		struct pipex_session *session;
622		int off = iphlen + sizeof(struct udphdr);
623
624		if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) {
625			m = *mp = pipex_l2tp_input(m, off, session,
626			    ipsecflowinfo);
627			pipex_rele_session(session);
628			if (m == NULL) {
629				in_pcbunref(inp);
630				return IPPROTO_DONE;
631			}
632		}
633	}
634#endif
635
636	udp_sbappend(inp, m, ip, ip6, iphlen, uh, &srcsa.sa, ipsecflowinfo);
637	in_pcbunref(inp);
638	return IPPROTO_DONE;
639bad:
640	m_freem(m);
641	in_pcbunref(inp);
642	return IPPROTO_DONE;
643}
644
645void
646udp_sbappend(struct inpcb *inp, struct mbuf *m, struct ip *ip,
647    struct ip6_hdr *ip6, int hlen, struct udphdr *uh,
648    struct sockaddr *srcaddr, u_int32_t ipsecflowinfo)
649{
650	struct socket *so = inp->inp_socket;
651	struct mbuf *opts = NULL;
652
653	hlen += sizeof(*uh);
654
655	if (inp->inp_upcall != NULL) {
656		m = (*inp->inp_upcall)(inp->inp_upcall_arg, m,
657		    ip, ip6, uh, hlen);
658		if (m == NULL)
659			return;
660	}
661
662#ifdef INET6
663	if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS ||
664	    so->so_options & SO_TIMESTAMP))
665		ip6_savecontrol(inp, m, &opts);
666#endif /* INET6 */
667	if (ip && (inp->inp_flags & INP_CONTROLOPTS ||
668	    so->so_options & SO_TIMESTAMP))
669		ip_savecontrol(inp, &opts, ip, m);
670#ifdef INET6
671	if (ip6 && (inp->inp_flags & IN6P_RECVDSTPORT)) {
672		struct mbuf **mp = &opts;
673
674		while (*mp)
675			mp = &(*mp)->m_next;
676		*mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t),
677		    IPV6_RECVDSTPORT, IPPROTO_IPV6);
678	}
679#endif /* INET6 */
680	if (ip && (inp->inp_flags & INP_RECVDSTPORT)) {
681		struct mbuf **mp = &opts;
682
683		while (*mp)
684			mp = &(*mp)->m_next;
685		*mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t),
686		    IP_RECVDSTPORT, IPPROTO_IP);
687	}
688#ifdef IPSEC
689	if (ipsecflowinfo && (inp->inp_flags & INP_IPSECFLOWINFO)) {
690		struct mbuf **mp = &opts;
691
692		while (*mp)
693			mp = &(*mp)->m_next;
694		*mp = sbcreatecontrol((caddr_t)&ipsecflowinfo,
695		    sizeof(u_int32_t), IP_IPSECFLOWINFO, IPPROTO_IP);
696	}
697#endif
698	m_adj(m, hlen);
699
700	mtx_enter(&so->so_rcv.sb_mtx);
701	if (sbappendaddr(so, &so->so_rcv, srcaddr, m, opts) == 0) {
702		mtx_leave(&so->so_rcv.sb_mtx);
703		udpstat_inc(udps_fullsock);
704		m_freem(m);
705		m_freem(opts);
706		return;
707	}
708	mtx_leave(&so->so_rcv.sb_mtx);
709
710	sorwakeup(so);
711}
712
713/*
714 * Notify a udp user of an asynchronous error;
715 * just wake up so that he can collect error status.
716 */
717void
718udp_notify(struct inpcb *inp, int errno)
719{
720	inp->inp_socket->so_error = errno;
721	sorwakeup(inp->inp_socket);
722	sowwakeup(inp->inp_socket);
723}
724
725#ifdef INET6
726void
727udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d)
728{
729	struct udphdr uh;
730	struct sockaddr_in6 sa6;
731	struct ip6_hdr *ip6;
732	struct mbuf *m;
733	int off;
734	void *cmdarg;
735	struct ip6ctlparam *ip6cp = NULL;
736	struct udp_portonly {
737		u_int16_t uh_sport;
738		u_int16_t uh_dport;
739	} *uhp;
740	struct inpcb *inp;
741	void (*notify)(struct inpcb *, int) = udp_notify;
742
743	if (sa == NULL)
744		return;
745	if (sa->sa_family != AF_INET6 ||
746	    sa->sa_len != sizeof(struct sockaddr_in6))
747		return;
748
749	if ((unsigned)cmd >= PRC_NCMDS)
750		return;
751	if (PRC_IS_REDIRECT(cmd))
752		notify = in_rtchange, d = NULL;
753	else if (cmd == PRC_HOSTDEAD)
754		d = NULL;
755	else if (cmd == PRC_MSGSIZE)
756		; /* special code is present, see below */
757	else if (inet6ctlerrmap[cmd] == 0)
758		return;
759
760	/* if the parameter is from icmp6, decode it. */
761	if (d != NULL) {
762		ip6cp = (struct ip6ctlparam *)d;
763		m = ip6cp->ip6c_m;
764		ip6 = ip6cp->ip6c_ip6;
765		off = ip6cp->ip6c_off;
766		cmdarg = ip6cp->ip6c_cmdarg;
767	} else {
768		m = NULL;
769		ip6 = NULL;
770		cmdarg = NULL;
771		/* XXX: translate addresses into internal form */
772		sa6 = *satosin6(sa);
773		if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
774			/* should be impossible */
775			return;
776		}
777	}
778
779	if (ip6cp && ip6cp->ip6c_finaldst) {
780		bzero(&sa6, sizeof(sa6));
781		sa6.sin6_family = AF_INET6;
782		sa6.sin6_len = sizeof(sa6);
783		sa6.sin6_addr = *ip6cp->ip6c_finaldst;
784		/* XXX: assuming M is valid in this case */
785		sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx,
786		    ip6cp->ip6c_finaldst);
787		if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL, NULL)) {
788			/* should be impossible */
789			return;
790		}
791	} else {
792		/* XXX: translate addresses into internal form */
793		sa6 = *satosin6(sa);
794		if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
795			/* should be impossible */
796			return;
797		}
798	}
799
800	if (ip6) {
801		/*
802		 * XXX: We assume that when IPV6 is non NULL,
803		 * M and OFF are valid.
804		 */
805		struct sockaddr_in6 sa6_src;
806
807		/* check if we can safely examine src and dst ports */
808		if (m->m_pkthdr.len < off + sizeof(*uhp))
809			return;
810
811		bzero(&uh, sizeof(uh));
812		m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
813
814		bzero(&sa6_src, sizeof(sa6_src));
815		sa6_src.sin6_family = AF_INET6;
816		sa6_src.sin6_len = sizeof(sa6_src);
817		sa6_src.sin6_addr = ip6->ip6_src;
818		sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx,
819		    &ip6->ip6_src);
820		if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL)) {
821			/* should be impossible */
822			return;
823		}
824
825		if (cmd == PRC_MSGSIZE) {
826			/*
827			 * Check to see if we have a valid UDP socket
828			 * corresponding to the address in the ICMPv6 message
829			 * payload.
830			 */
831			inp = in6_pcblookup(&udb6table, &sa6.sin6_addr,
832			    uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport,
833			    rdomain);
834#if 0
835			/*
836			 * As the use of sendto(2) is fairly popular,
837			 * we may want to allow non-connected pcb too.
838			 * But it could be too weak against attacks...
839			 * We should at least check if the local address (= s)
840			 * is really ours.
841			 */
842			if (inp == NULL) {
843				inp = in6_pcblookup_listen(&udb6table,
844				    &sa6_src.sin6_addr, uh.uh_sport, NULL,
845				    rdomain))
846			}
847#endif
848
849			/*
850			 * Depending on the value of "valid" and routing table
851			 * size (mtudisc_{hi,lo}wat), we will:
852			 * - recalculate the new MTU and create the
853			 *   corresponding routing entry, or
854			 * - ignore the MTU change notification.
855			 */
856			icmp6_mtudisc_update((struct ip6ctlparam *)d,
857			    inp != NULL);
858			in_pcbunref(inp);
859
860			/*
861			 * regardless of if we called icmp6_mtudisc_update(),
862			 * we need to call in6_pcbnotify(), to notify path
863			 * MTU change to the userland (2292bis-02), because
864			 * some unconnected sockets may share the same
865			 * destination and want to know the path MTU.
866			 */
867		}
868
869		in6_pcbnotify(&udb6table, &sa6, uh.uh_dport,
870		    &sa6_src, uh.uh_sport, rdomain, cmd, cmdarg, notify);
871	} else {
872		in6_pcbnotify(&udb6table, &sa6, 0,
873		    &sa6_any, 0, rdomain, cmd, cmdarg, notify);
874	}
875}
876#endif
877
878void
879udp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v)
880{
881	struct ip *ip = v;
882	struct udphdr *uhp;
883	struct in_addr faddr;
884	struct inpcb *inp;
885	void (*notify)(struct inpcb *, int) = udp_notify;
886	int errno;
887
888	if (sa == NULL)
889		return;
890	if (sa->sa_family != AF_INET ||
891	    sa->sa_len != sizeof(struct sockaddr_in))
892		return;
893	faddr = satosin(sa)->sin_addr;
894	if (faddr.s_addr == INADDR_ANY)
895		return;
896
897	if ((unsigned)cmd >= PRC_NCMDS)
898		return;
899	errno = inetctlerrmap[cmd];
900	if (PRC_IS_REDIRECT(cmd))
901		notify = in_rtchange, ip = 0;
902	else if (cmd == PRC_HOSTDEAD)
903		ip = 0;
904	else if (errno == 0)
905		return;
906	if (ip) {
907		uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
908
909#ifdef IPSEC
910		/* PMTU discovery for udpencap */
911		if (cmd == PRC_MSGSIZE && ip_mtudisc && udpencap_enable &&
912		    udpencap_port && uhp->uh_sport == htons(udpencap_port)) {
913			udpencap_ctlinput(cmd, sa, rdomain, v);
914			return;
915		}
916#endif
917		inp = in_pcblookup(&udbtable,
918		    ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport,
919		    rdomain);
920		if (inp != NULL)
921			notify(inp, errno);
922		in_pcbunref(inp);
923	} else
924		in_pcbnotifyall(&udbtable, satosin(sa), rdomain, errno, notify);
925}
926
927int
928udp_output(struct inpcb *inp, struct mbuf *m, struct mbuf *addr,
929    struct mbuf *control)
930{
931	struct sockaddr_in *sin = NULL;
932	struct udpiphdr *ui;
933	u_int32_t ipsecflowinfo = 0;
934	struct sockaddr_in src_sin;
935	int len = m->m_pkthdr.len;
936	struct in_addr laddr;
937	int error = 0;
938
939#ifdef INET6
940	if (ISSET(inp->inp_flags, INP_IPV6))
941		return (udp6_output(inp, m, addr, control));
942#endif
943
944	/*
945	 * Compute the packet length of the IP header, and
946	 * punt if the length looks bogus.
947	 */
948	if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
949		error = EMSGSIZE;
950		goto release;
951	}
952
953	memset(&src_sin, 0, sizeof(src_sin));
954
955	if (control) {
956		u_int clen;
957		struct cmsghdr *cm;
958		caddr_t cmsgs;
959
960		/*
961		 * XXX: Currently, we assume all the optional information is
962		 * stored in a single mbuf.
963		 */
964		if (control->m_next) {
965			error = EINVAL;
966			goto release;
967		}
968
969		clen = control->m_len;
970		cmsgs = mtod(control, caddr_t);
971		do {
972			if (clen < CMSG_LEN(0)) {
973				error = EINVAL;
974				goto release;
975			}
976			cm = (struct cmsghdr *)cmsgs;
977			if (cm->cmsg_len < CMSG_LEN(0) ||
978			    CMSG_ALIGN(cm->cmsg_len) > clen) {
979				error = EINVAL;
980				goto release;
981			}
982#ifdef IPSEC
983			if ((inp->inp_flags & INP_IPSECFLOWINFO) != 0 &&
984			    cm->cmsg_len == CMSG_LEN(sizeof(ipsecflowinfo)) &&
985			    cm->cmsg_level == IPPROTO_IP &&
986			    cm->cmsg_type == IP_IPSECFLOWINFO) {
987				ipsecflowinfo = *(u_int32_t *)CMSG_DATA(cm);
988			} else
989#endif
990			if (cm->cmsg_len == CMSG_LEN(sizeof(struct in_addr)) &&
991			    cm->cmsg_level == IPPROTO_IP &&
992			    cm->cmsg_type == IP_SENDSRCADDR) {
993				memcpy(&src_sin.sin_addr, CMSG_DATA(cm),
994				    sizeof(struct in_addr));
995				src_sin.sin_family = AF_INET;
996				src_sin.sin_len = sizeof(src_sin);
997				/* no check on reuse when sin->sin_port == 0 */
998				if ((error = in_pcbaddrisavail(inp, &src_sin,
999				    0, curproc)))
1000					goto release;
1001			}
1002			clen -= CMSG_ALIGN(cm->cmsg_len);
1003			cmsgs += CMSG_ALIGN(cm->cmsg_len);
1004		} while (clen);
1005	}
1006
1007	if (addr) {
1008		if ((error = in_nam2sin(addr, &sin)))
1009			goto release;
1010		if (sin->sin_port == 0) {
1011			error = EADDRNOTAVAIL;
1012			goto release;
1013		}
1014		if (inp->inp_faddr.s_addr != INADDR_ANY) {
1015			error = EISCONN;
1016			goto release;
1017		}
1018		error = in_pcbselsrc(&laddr, sin, inp);
1019		if (error)
1020			goto release;
1021
1022		if (inp->inp_lport == 0) {
1023			error = in_pcbbind(inp, NULL, curproc);
1024			if (error)
1025				goto release;
1026		}
1027
1028		if (src_sin.sin_len > 0 &&
1029		    src_sin.sin_addr.s_addr != INADDR_ANY &&
1030		    src_sin.sin_addr.s_addr != inp->inp_laddr.s_addr) {
1031			src_sin.sin_port = inp->inp_lport;
1032			if (inp->inp_laddr.s_addr != INADDR_ANY &&
1033			    (error =
1034			    in_pcbaddrisavail(inp, &src_sin, 0, curproc)))
1035				goto release;
1036			laddr = src_sin.sin_addr;
1037		}
1038	} else {
1039		if (inp->inp_faddr.s_addr == INADDR_ANY) {
1040			error = ENOTCONN;
1041			goto release;
1042		}
1043		laddr = inp->inp_laddr;
1044	}
1045
1046	/*
1047	 * Calculate data length and get a mbuf
1048	 * for UDP and IP headers.
1049	 */
1050	M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
1051	if (m == NULL) {
1052		error = ENOBUFS;
1053		goto bail;
1054	}
1055
1056	/*
1057	 * Fill in mbuf with extended UDP header
1058	 * and addresses and length put into network format.
1059	 */
1060	ui = mtod(m, struct udpiphdr *);
1061	bzero(ui->ui_x1, sizeof ui->ui_x1);
1062	ui->ui_pr = IPPROTO_UDP;
1063	ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
1064	ui->ui_src = laddr;
1065	ui->ui_dst = sin ? sin->sin_addr : inp->inp_faddr;
1066	ui->ui_sport = inp->inp_lport;
1067	ui->ui_dport = sin ? sin->sin_port : inp->inp_fport;
1068	ui->ui_ulen = ui->ui_len;
1069	((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
1070	((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl;
1071	((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos;
1072	if (udpcksum)
1073		m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
1074
1075	udpstat_inc(udps_opackets);
1076
1077	/* force routing table */
1078	m->m_pkthdr.ph_rtableid = inp->inp_rtableid;
1079
1080#if NPF > 0
1081	if (inp->inp_socket->so_state & SS_ISCONNECTED)
1082		pf_mbuf_link_inpcb(m, inp);
1083#endif
1084
1085	error = ip_output(m, inp->inp_options, &inp->inp_route,
1086	    (inp->inp_socket->so_options & SO_BROADCAST), inp->inp_moptions,
1087	    &inp->inp_seclevel, ipsecflowinfo);
1088
1089bail:
1090	m_freem(control);
1091	return (error);
1092
1093release:
1094	m_freem(m);
1095	goto bail;
1096}
1097
1098int
1099udp_attach(struct socket *so, int proto, int wait)
1100{
1101	struct inpcbtable *table;
1102	int error;
1103
1104	if (so->so_pcb != NULL)
1105		return EINVAL;
1106
1107	if ((error = soreserve(so, udp_sendspace, udp_recvspace)))
1108		return error;
1109
1110	NET_ASSERT_LOCKED();
1111#ifdef INET6
1112	if (so->so_proto->pr_domain->dom_family == PF_INET6)
1113		table = &udb6table;
1114	else
1115#endif
1116		table = &udbtable;
1117	if ((error = in_pcballoc(so, table, wait)))
1118		return error;
1119#ifdef INET6
1120	if (ISSET(sotoinpcb(so)->inp_flags, INP_IPV6))
1121		sotoinpcb(so)->inp_ipv6.ip6_hlim = ip6_defhlim;
1122	else
1123#endif
1124		sotoinpcb(so)->inp_ip.ip_ttl = ip_defttl;
1125	return 0;
1126}
1127
1128int
1129udp_detach(struct socket *so)
1130{
1131	struct inpcb *inp;
1132
1133	soassertlocked(so);
1134
1135	inp = sotoinpcb(so);
1136	if (inp == NULL)
1137		return (EINVAL);
1138
1139	in_pcbdetach(inp);
1140	return (0);
1141}
1142
1143void
1144udp_lock(struct socket *so)
1145{
1146	struct inpcb *inp = sotoinpcb(so);
1147
1148	NET_ASSERT_LOCKED();
1149	mtx_enter(&inp->inp_mtx);
1150}
1151
1152void
1153udp_unlock(struct socket *so)
1154{
1155	struct inpcb *inp = sotoinpcb(so);
1156
1157	NET_ASSERT_LOCKED();
1158	mtx_leave(&inp->inp_mtx);
1159}
1160
1161int
1162udp_locked(struct socket *so)
1163{
1164	struct inpcb *inp = sotoinpcb(so);
1165
1166	return mtx_owned(&inp->inp_mtx);
1167}
1168
1169int
1170udp_bind(struct socket *so, struct mbuf *addr, struct proc *p)
1171{
1172	struct inpcb *inp = sotoinpcb(so);
1173
1174	soassertlocked(so);
1175	return in_pcbbind(inp, addr, p);
1176}
1177
1178int
1179udp_connect(struct socket *so, struct mbuf *addr)
1180{
1181	struct inpcb *inp = sotoinpcb(so);
1182	int error;
1183
1184	soassertlocked(so);
1185
1186#ifdef INET6
1187	if (ISSET(inp->inp_flags, INP_IPV6)) {
1188		if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
1189			return (EISCONN);
1190	} else
1191#endif
1192	{
1193		if (inp->inp_faddr.s_addr != INADDR_ANY)
1194			return (EISCONN);
1195	}
1196	error = in_pcbconnect(inp, addr);
1197	if (error)
1198		return (error);
1199
1200	soisconnected(so);
1201	return (0);
1202}
1203
1204int
1205udp_disconnect(struct socket *so)
1206{
1207	struct inpcb *inp = sotoinpcb(so);
1208
1209	soassertlocked(so);
1210
1211#ifdef INET6
1212	if (ISSET(inp->inp_flags, INP_IPV6)) {
1213		if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
1214			return (ENOTCONN);
1215	} else
1216#endif
1217	{
1218		if (inp->inp_faddr.s_addr == INADDR_ANY)
1219			return (ENOTCONN);
1220	}
1221	in_pcbunset_laddr(inp);
1222	in_pcbdisconnect(inp);
1223	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
1224
1225	return (0);
1226}
1227
1228int
1229udp_shutdown(struct socket *so)
1230{
1231	soassertlocked(so);
1232	socantsendmore(so);
1233	return (0);
1234}
1235
1236int
1237udp_send(struct socket *so, struct mbuf *m, struct mbuf *addr,
1238    struct mbuf *control)
1239{
1240	struct inpcb *inp = sotoinpcb(so);
1241
1242	soassertlocked(so);
1243
1244#ifdef PIPEX
1245	if (inp->inp_pipex) {
1246		struct pipex_session *session;
1247
1248		if (addr != NULL)
1249			session =
1250			    pipex_l2tp_userland_lookup_session(m,
1251				mtod(addr, struct sockaddr *));
1252		else
1253#ifdef INET6
1254		if (ISSET(inp->inp_flags, INP_IPV6))
1255			session =
1256			    pipex_l2tp_userland_lookup_session_ipv6(
1257				m, inp->inp_faddr6);
1258		else
1259#endif
1260			session =
1261			    pipex_l2tp_userland_lookup_session_ipv4(
1262				m, inp->inp_faddr);
1263		if (session != NULL) {
1264			m = pipex_l2tp_userland_output(m, session);
1265			pipex_rele_session(session);
1266
1267			if (m == NULL) {
1268				m_freem(control);
1269				return (ENOMEM);
1270			}
1271		}
1272	}
1273#endif
1274
1275	return (udp_output(inp, m, addr, control));
1276}
1277
1278/*
1279 * Sysctl for udp variables.
1280 */
1281int
1282udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
1283    size_t newlen)
1284{
1285	int error;
1286
1287	/* All sysctl names at this level are terminal. */
1288	if (namelen != 1)
1289		return (ENOTDIR);
1290
1291	switch (name[0]) {
1292	case UDPCTL_BADDYNAMIC:
1293		NET_LOCK();
1294		error = sysctl_struct(oldp, oldlenp, newp, newlen,
1295		    baddynamicports.udp, sizeof(baddynamicports.udp));
1296		NET_UNLOCK();
1297		return (error);
1298
1299	case UDPCTL_ROOTONLY:
1300		if (newp && securelevel > 0)
1301			return (EPERM);
1302		NET_LOCK();
1303		error = sysctl_struct(oldp, oldlenp, newp, newlen,
1304		    rootonlyports.udp, sizeof(rootonlyports.udp));
1305		NET_UNLOCK();
1306		return (error);
1307
1308	case UDPCTL_STATS:
1309		if (newp != NULL)
1310			return (EPERM);
1311
1312		return (udp_sysctl_udpstat(oldp, oldlenp, newp));
1313
1314	default:
1315		NET_LOCK();
1316		error = sysctl_bounded_arr(udpctl_vars, nitems(udpctl_vars),
1317		    name, namelen, oldp, oldlenp, newp, newlen);
1318		NET_UNLOCK();
1319		return (error);
1320	}
1321	/* NOTREACHED */
1322}
1323
1324int
1325udp_sysctl_udpstat(void *oldp, size_t *oldlenp, void *newp)
1326{
1327	uint64_t counters[udps_ncounters];
1328	struct udpstat udpstat;
1329	u_long *words = (u_long *)&udpstat;
1330	int i;
1331
1332	CTASSERT(sizeof(udpstat) == (nitems(counters) * sizeof(u_long)));
1333	memset(&udpstat, 0, sizeof udpstat);
1334	counters_read(udpcounters, counters, nitems(counters), NULL);
1335
1336	for (i = 0; i < nitems(counters); i++)
1337		words[i] = (u_long)counters[i];
1338
1339	return (sysctl_rdstruct(oldp, oldlenp, newp,
1340	    &udpstat, sizeof(udpstat)));
1341}
1342