xref: /freebsd/sys/netinet/udp_usrreq.c (revision 5129159789cc9d7bc514e4546b88e3427695002d)
1 /*
2  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)udp_usrreq.c	8.6 (Berkeley) 5/23/95
34  * $FreeBSD$
35  */
36 
37 #include "opt_inet6.h"
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/domain.h>
45 #include <sys/proc.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/sysctl.h>
50 #include <sys/syslog.h>
51 
52 #include <vm/vm_zone.h>
53 
54 #include <net/if.h>
55 #include <net/route.h>
56 
57 #include <netinet/in.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/ip.h>
60 #ifdef INET6
61 #include <netinet/ip6.h>
62 #endif
63 #include <netinet/in_pcb.h>
64 #include <netinet/in_var.h>
65 #include <netinet/ip_var.h>
66 #ifdef INET6
67 #include <netinet6/ip6_var.h>
68 #endif
69 #include <netinet/ip_icmp.h>
70 #include <netinet/icmp_var.h>
71 #include <netinet/udp.h>
72 #include <netinet/udp_var.h>
73 
74 #ifdef IPSEC
75 #include <netinet6/ipsec.h>
76 #endif /*IPSEC*/
77 
78 /*
79  * UDP protocol implementation.
80  * Per RFC 768, August, 1980.
81  */
82 #ifndef	COMPAT_42
83 static int	udpcksum = 1;
84 #else
85 static int	udpcksum = 0;		/* XXX */
86 #endif
87 SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
88 		&udpcksum, 0, "");
89 
90 int	log_in_vain = 0;
91 SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
92     &log_in_vain, 0, "Log all incoming UDP packets");
93 
94 static int	blackhole = 0;
95 SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
96 	&blackhole, 0, "Do not send port unreachables for refused connects");
97 
98 struct	inpcbhead udb;		/* from udp_var.h */
99 #define	udb6	udb  /* for KAME src sync over BSD*'s */
100 struct	inpcbinfo udbinfo;
101 
102 #ifndef UDBHASHSIZE
103 #define UDBHASHSIZE 16
104 #endif
105 
106 struct	udpstat udpstat;	/* from udp_var.h */
107 SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
108     &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
109 
110 static struct	sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
111 #ifdef INET6
112 struct udp_in6 {
113 	struct sockaddr_in6	uin6_sin;
114 	u_char			uin6_init_done : 1;
115 } udp_in6 = {
116 	{ sizeof(udp_in6.uin6_sin), AF_INET6 },
117 	0
118 };
119 struct udp_ip6 {
120 	struct ip6_hdr		uip6_ip6;
121 	u_char			uip6_init_done : 1;
122 } udp_ip6;
123 #endif /* INET6 */
124 
125 static void udp_append __P((struct inpcb *last, struct ip *ip,
126 			    struct mbuf *n, int off));
127 #ifdef INET6
128 static void ip_2_ip6_hdr __P((struct ip6_hdr *ip6, struct ip *ip));
129 #endif
130 
131 static int udp_detach __P((struct socket *so));
132 static	int udp_output __P((struct inpcb *, struct mbuf *, struct sockaddr *,
133 			    struct mbuf *, struct proc *));
134 
135 void
136 udp_init()
137 {
138 	LIST_INIT(&udb);
139 	udbinfo.listhead = &udb;
140 	udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
141 	udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
142 					&udbinfo.porthashmask);
143 	udbinfo.ipi_zone = zinit("udpcb", sizeof(struct inpcb), maxsockets,
144 				 ZONE_INTERRUPT, 0);
145 }
146 
147 void
148 udp_input(m, off, proto)
149 	register struct mbuf *m;
150 	int off, proto;
151 {
152 	int iphlen = off;
153 	register struct ip *ip;
154 	register struct udphdr *uh;
155 	register struct inpcb *inp;
156 	struct mbuf *opts = 0;
157 	int len;
158 	struct ip save_ip;
159 	struct sockaddr *append_sa;
160 
161 	udpstat.udps_ipackets++;
162 
163 	/*
164 	 * Strip IP options, if any; should skip this,
165 	 * make available to user, and use on returned packets,
166 	 * but we don't yet have a way to check the checksum
167 	 * with options still present.
168 	 */
169 	if (iphlen > sizeof (struct ip)) {
170 		ip_stripoptions(m, (struct mbuf *)0);
171 		iphlen = sizeof(struct ip);
172 	}
173 
174 	/*
175 	 * Get IP and UDP header together in first mbuf.
176 	 */
177 	ip = mtod(m, struct ip *);
178 	if (m->m_len < iphlen + sizeof(struct udphdr)) {
179 		if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
180 			udpstat.udps_hdrops++;
181 			return;
182 		}
183 		ip = mtod(m, struct ip *);
184 	}
185 	uh = (struct udphdr *)((caddr_t)ip + iphlen);
186 
187 	/*
188 	 * Make mbuf data length reflect UDP length.
189 	 * If not enough data to reflect UDP length, drop.
190 	 */
191 	len = ntohs((u_short)uh->uh_ulen);
192 	if (ip->ip_len != len) {
193 		if (len > ip->ip_len || len < sizeof(struct udphdr)) {
194 			udpstat.udps_badlen++;
195 			goto bad;
196 		}
197 		m_adj(m, len - ip->ip_len);
198 		/* ip->ip_len = len; */
199 	}
200 	/*
201 	 * Save a copy of the IP header in case we want restore it
202 	 * for sending an ICMP error message in response.
203 	 */
204 	save_ip = *ip;
205 
206 	/*
207 	 * Checksum extended UDP header and data.
208 	 */
209 	if (uh->uh_sum) {
210 		bzero(((struct ipovly *)ip)->ih_x1, 9);
211 		((struct ipovly *)ip)->ih_len = uh->uh_ulen;
212 		uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
213 		if (uh->uh_sum) {
214 			udpstat.udps_badsum++;
215 			m_freem(m);
216 			return;
217 		}
218 	}
219 
220 	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
221 	    in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
222 		struct inpcb *last;
223 		/*
224 		 * Deliver a multicast or broadcast datagram to *all* sockets
225 		 * for which the local and remote addresses and ports match
226 		 * those of the incoming datagram.  This allows more than
227 		 * one process to receive multi/broadcasts on the same port.
228 		 * (This really ought to be done for unicast datagrams as
229 		 * well, but that would cause problems with existing
230 		 * applications that open both address-specific sockets and
231 		 * a wildcard socket listening to the same port -- they would
232 		 * end up receiving duplicates of every unicast datagram.
233 		 * Those applications open the multiple sockets to overcome an
234 		 * inadequacy of the UDP socket interface, but for backwards
235 		 * compatibility we avoid the problem here rather than
236 		 * fixing the interface.  Maybe 4.5BSD will remedy this?)
237 		 */
238 
239 		/*
240 		 * Construct sockaddr format source address.
241 		 */
242 		udp_in.sin_port = uh->uh_sport;
243 		udp_in.sin_addr = ip->ip_src;
244 		/*
245 		 * Locate pcb(s) for datagram.
246 		 * (Algorithm copied from raw_intr().)
247 		 */
248 		last = NULL;
249 #ifdef INET6
250 		udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
251 #endif
252 		LIST_FOREACH(inp, &udb, inp_list) {
253 #ifdef INET6
254 			if ((inp->inp_vflag & INP_IPV4) == NULL)
255 				continue;
256 #endif
257 			if (inp->inp_lport != uh->uh_dport)
258 				continue;
259 			if (inp->inp_laddr.s_addr != INADDR_ANY) {
260 				if (inp->inp_laddr.s_addr !=
261 				    ip->ip_dst.s_addr)
262 					continue;
263 			}
264 			if (inp->inp_faddr.s_addr != INADDR_ANY) {
265 				if (inp->inp_faddr.s_addr !=
266 				    ip->ip_src.s_addr ||
267 				    inp->inp_fport != uh->uh_sport)
268 					continue;
269 			}
270 
271 			if (last != NULL) {
272 				struct mbuf *n;
273 
274 #ifdef IPSEC
275 				/* check AH/ESP integrity. */
276 				if (ipsec4_in_reject_so(m, last->inp_socket))
277 					ipsecstat.in_polvio++;
278 					/* do not inject data to pcb */
279 				else
280 #endif /*IPSEC*/
281 				if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
282 					udp_append(last, ip, n,
283 						   iphlen +
284 						   sizeof(struct udphdr));
285 			}
286 			last = inp;
287 			/*
288 			 * Don't look for additional matches if this one does
289 			 * not have either the SO_REUSEPORT or SO_REUSEADDR
290 			 * socket options set.  This heuristic avoids searching
291 			 * through all pcbs in the common case of a non-shared
292 			 * port.  It * assumes that an application will never
293 			 * clear these options after setting them.
294 			 */
295 			if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
296 				break;
297 		}
298 
299 		if (last == NULL) {
300 			/*
301 			 * No matching pcb found; discard datagram.
302 			 * (No need to send an ICMP Port Unreachable
303 			 * for a broadcast or multicast datgram.)
304 			 */
305 			udpstat.udps_noportbcast++;
306 			goto bad;
307 		}
308 #ifdef IPSEC
309 		/* check AH/ESP integrity. */
310 		if (ipsec4_in_reject_so(m, last->inp_socket)) {
311 			ipsecstat.in_polvio++;
312 			goto bad;
313 		}
314 #endif /*IPSEC*/
315 		udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
316 		return;
317 	}
318 	/*
319 	 * Locate pcb for datagram.
320 	 */
321 	inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
322 	    ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
323 	if (inp == NULL) {
324 		if (log_in_vain) {
325 			char buf[4*sizeof "123"];
326 
327 			strcpy(buf, inet_ntoa(ip->ip_dst));
328 			log(LOG_INFO,
329 			    "Connection attempt to UDP %s:%d from %s:%d\n",
330 			    buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
331 			    ntohs(uh->uh_sport));
332 		}
333 		udpstat.udps_noport++;
334 		if (m->m_flags & (M_BCAST | M_MCAST)) {
335 			udpstat.udps_noportbcast++;
336 			goto bad;
337 		}
338 		*ip = save_ip;
339 #ifdef ICMP_BANDLIM
340 		if (badport_bandlim(0) < 0)
341 			goto bad;
342 #endif
343 		if (!blackhole)
344 			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
345 		else
346 			goto bad;
347 		return;
348 	}
349 #ifdef IPSEC
350 	if (ipsec4_in_reject_so(m, inp->inp_socket)) {
351 		ipsecstat.in_polvio++;
352 		goto bad;
353 	}
354 #endif /*IPSEC*/
355 
356 	/*
357 	 * Construct sockaddr format source address.
358 	 * Stuff source address and datagram in user buffer.
359 	 */
360 	udp_in.sin_port = uh->uh_sport;
361 	udp_in.sin_addr = ip->ip_src;
362 	if (inp->inp_flags & INP_CONTROLOPTS
363 	    || inp->inp_socket->so_options & SO_TIMESTAMP) {
364 #ifdef INET6
365 		if (inp->inp_vflag & INP_IPV6) {
366 			int savedflags;
367 
368 			ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
369 			savedflags = inp->inp_flags;
370 			inp->inp_flags &= ~INP_UNMAPPABLEOPTS;
371 			ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m);
372 			inp->inp_flags = savedflags;
373 		} else
374 #endif
375 		ip_savecontrol(inp, &opts, ip, m);
376 	}
377 	iphlen += sizeof(struct udphdr);
378 	m_adj(m, iphlen);
379 #ifdef INET6
380 	if (inp->inp_vflag & INP_IPV6) {
381 		in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
382 		append_sa = (struct sockaddr *)&udp_in6;
383 	} else
384 #endif
385 	append_sa = (struct sockaddr *)&udp_in;
386 	if (sbappendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts) == 0) {
387 		udpstat.udps_fullsock++;
388 		goto bad;
389 	}
390 	sorwakeup(inp->inp_socket);
391 	return;
392 bad:
393 	m_freem(m);
394 	if (opts)
395 		m_freem(opts);
396 	return;
397 }
398 
399 #if defined(INET6)
400 static void
401 ip_2_ip6_hdr(ip6, ip)
402 	struct ip6_hdr *ip6;
403 	struct ip *ip;
404 {
405 	bzero(ip6, sizeof(*ip6));
406 
407 	ip6->ip6_vfc = IPV6_VERSION;
408 	ip6->ip6_plen = ip->ip_len;
409 	ip6->ip6_nxt = ip->ip_p;
410 	ip6->ip6_hlim = ip->ip_ttl;
411 	ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
412 		IPV6_ADDR_INT32_SMP;
413 	ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
414 	ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
415 }
416 #endif
417 
418 /*
419  * subroutine of udp_input(), mainly for source code readability.
420  * caller must properly init udp_ip6 and udp_in6 beforehand.
421  */
422 static void
423 udp_append(last, ip, n, off)
424 	struct inpcb *last;
425 	struct ip *ip;
426 	struct mbuf *n;
427 	int off;
428 {
429 	struct sockaddr *append_sa;
430 	struct mbuf *opts = 0;
431 
432 	if (last->inp_flags & INP_CONTROLOPTS ||
433 	    last->inp_socket->so_options & SO_TIMESTAMP) {
434 #ifdef INET6
435 		if (last->inp_vflag & INP_IPV6) {
436 			int savedflags;
437 
438 			if (udp_ip6.uip6_init_done == 0) {
439 				ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
440 				udp_ip6.uip6_init_done = 1;
441 			}
442 			savedflags = last->inp_flags;
443 			last->inp_flags &= ~INP_UNMAPPABLEOPTS;
444 			ip6_savecontrol(last, &opts, &udp_ip6.uip6_ip6, n);
445 			last->inp_flags = savedflags;
446 		} else
447 #endif
448 		ip_savecontrol(last, &opts, ip, n);
449 	}
450 #ifdef INET6
451 	if (last->inp_vflag & INP_IPV6) {
452 		if (udp_in6.uin6_init_done == 0) {
453 			in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
454 			udp_in6.uin6_init_done = 1;
455 		}
456 		append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
457 	} else
458 #endif
459 	append_sa = (struct sockaddr *)&udp_in;
460 	m_adj(n, off);
461 	if (sbappendaddr(&last->inp_socket->so_rcv, append_sa, n, opts) == 0) {
462 		m_freem(n);
463 		if (opts)
464 			m_freem(opts);
465 		udpstat.udps_fullsock++;
466 	} else
467 		sorwakeup(last->inp_socket);
468 }
469 
470 /*
471  * Notify a udp user of an asynchronous error;
472  * just wake up so that he can collect error status.
473  */
474 void
475 udp_notify(inp, errno)
476 	register struct inpcb *inp;
477 	int errno;
478 {
479 	inp->inp_socket->so_error = errno;
480 	sorwakeup(inp->inp_socket);
481 	sowwakeup(inp->inp_socket);
482 }
483 
484 void
485 udp_ctlinput(cmd, sa, vip)
486 	int cmd;
487 	struct sockaddr *sa;
488 	void *vip;
489 {
490 	register struct ip *ip = vip;
491 	register struct udphdr *uh;
492 
493 	if (!PRC_IS_REDIRECT(cmd) &&
494 	    ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0))
495 		return;
496 	if (ip) {
497 		uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
498 		in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
499 			cmd, udp_notify);
500 	} else
501 		in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
502 }
503 
504 static int
505 udp_pcblist SYSCTL_HANDLER_ARGS
506 {
507 	int error, i, n, s;
508 	struct inpcb *inp, **inp_list;
509 	inp_gen_t gencnt;
510 	struct xinpgen xig;
511 
512 	/*
513 	 * The process of preparing the TCB list is too time-consuming and
514 	 * resource-intensive to repeat twice on every request.
515 	 */
516 	if (req->oldptr == 0) {
517 		n = udbinfo.ipi_count;
518 		req->oldidx = 2 * (sizeof xig)
519 			+ (n + n/8) * sizeof(struct xinpcb);
520 		return 0;
521 	}
522 
523 	if (req->newptr != 0)
524 		return EPERM;
525 
526 	/*
527 	 * OK, now we're committed to doing something.
528 	 */
529 	s = splnet();
530 	gencnt = udbinfo.ipi_gencnt;
531 	n = udbinfo.ipi_count;
532 	splx(s);
533 
534 	xig.xig_len = sizeof xig;
535 	xig.xig_count = n;
536 	xig.xig_gen = gencnt;
537 	xig.xig_sogen = so_gencnt;
538 	error = SYSCTL_OUT(req, &xig, sizeof xig);
539 	if (error)
540 		return error;
541 
542 	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
543 	if (inp_list == 0)
544 		return ENOMEM;
545 
546 	s = splnet();
547 	for (inp = udbinfo.listhead->lh_first, i = 0; inp && i < n;
548 	     inp = inp->inp_list.le_next) {
549 		if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp))
550 			inp_list[i++] = inp;
551 	}
552 	splx(s);
553 	n = i;
554 
555 	error = 0;
556 	for (i = 0; i < n; i++) {
557 		inp = inp_list[i];
558 		if (inp->inp_gencnt <= gencnt) {
559 			struct xinpcb xi;
560 			xi.xi_len = sizeof xi;
561 			/* XXX should avoid extra copy */
562 			bcopy(inp, &xi.xi_inp, sizeof *inp);
563 			if (inp->inp_socket)
564 				sotoxsocket(inp->inp_socket, &xi.xi_socket);
565 			error = SYSCTL_OUT(req, &xi, sizeof xi);
566 		}
567 	}
568 	if (!error) {
569 		/*
570 		 * Give the user an updated idea of our state.
571 		 * If the generation differs from what we told
572 		 * her before, she knows that something happened
573 		 * while we were processing this request, and it
574 		 * might be necessary to retry.
575 		 */
576 		s = splnet();
577 		xig.xig_gen = udbinfo.ipi_gencnt;
578 		xig.xig_sogen = so_gencnt;
579 		xig.xig_count = udbinfo.ipi_count;
580 		splx(s);
581 		error = SYSCTL_OUT(req, &xig, sizeof xig);
582 	}
583 	free(inp_list, M_TEMP);
584 	return error;
585 }
586 
587 SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
588 	    udp_pcblist, "S,xinpcb", "List of active UDP sockets");
589 
590 static int
591 udp_getcred SYSCTL_HANDLER_ARGS
592 {
593 	struct sockaddr_in addrs[2];
594 	struct inpcb *inp;
595 	int error, s;
596 
597 	error = suser(req->p);
598 	if (error)
599 		return (error);
600 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
601 	if (error)
602 		return (error);
603 	s = splnet();
604 	inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
605 				addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
606 	if (inp == NULL || inp->inp_socket == NULL) {
607 		error = ENOENT;
608 		goto out;
609 	}
610 	error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
611 out:
612 	splx(s);
613 	return (error);
614 }
615 
616 SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
617     0, 0, udp_getcred, "S,ucred", "Get the ucred of a UDP connection");
618 
619 static int
620 udp_output(inp, m, addr, control, p)
621 	register struct inpcb *inp;
622 	struct mbuf *m;
623 	struct sockaddr *addr;
624 	struct mbuf *control;
625 	struct proc *p;
626 {
627 	register struct udpiphdr *ui;
628 	register int len = m->m_pkthdr.len;
629 	struct in_addr laddr;
630 	struct sockaddr_in *sin;
631 	int s = 0, error = 0;
632 
633 	if (control)
634 		m_freem(control);		/* XXX */
635 
636 	if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
637 		error = EMSGSIZE;
638 		goto release;
639 	}
640 
641 	if (addr) {
642 		sin = (struct sockaddr_in *)addr;
643 		prison_remote_ip(p, 0, &sin->sin_addr.s_addr);
644 		laddr = inp->inp_laddr;
645 		if (inp->inp_faddr.s_addr != INADDR_ANY) {
646 			error = EISCONN;
647 			goto release;
648 		}
649 		/*
650 		 * Must block input while temporarily connected.
651 		 */
652 		s = splnet();
653 		error = in_pcbconnect(inp, addr, p);
654 		if (error) {
655 			splx(s);
656 			goto release;
657 		}
658 	} else {
659 		if (inp->inp_faddr.s_addr == INADDR_ANY) {
660 			error = ENOTCONN;
661 			goto release;
662 		}
663 	}
664 	/*
665 	 * Calculate data length and get a mbuf
666 	 * for UDP and IP headers.
667 	 */
668 	M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
669 	if (m == 0) {
670 		error = ENOBUFS;
671 		if (addr)
672 			splx(s);
673 		goto release;
674 	}
675 
676 	/*
677 	 * Fill in mbuf with extended UDP header
678 	 * and addresses and length put into network format.
679 	 */
680 	ui = mtod(m, struct udpiphdr *);
681 	bzero(ui->ui_x1, sizeof(ui->ui_x1));
682 	ui->ui_pr = IPPROTO_UDP;
683 	ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
684 	ui->ui_src = inp->inp_laddr;
685 	ui->ui_dst = inp->inp_faddr;
686 	ui->ui_sport = inp->inp_lport;
687 	ui->ui_dport = inp->inp_fport;
688 	ui->ui_ulen = ui->ui_len;
689 
690 	/*
691 	 * Stuff checksum and output datagram.
692 	 */
693 	ui->ui_sum = 0;
694 	if (udpcksum) {
695 	    if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
696 		ui->ui_sum = 0xffff;
697 	}
698 	((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
699 	((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl;	/* XXX */
700 	((struct ip *)ui)->ip_tos = inp->inp_ip_tos;	/* XXX */
701 	udpstat.udps_opackets++;
702 
703 #ifdef IPSEC
704 	m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket;
705 #endif /*IPSEC*/
706 
707 	error = ip_output(m, inp->inp_options, &inp->inp_route,
708 	    inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
709 	    inp->inp_moptions);
710 
711 	if (addr) {
712 		in_pcbdisconnect(inp);
713 		inp->inp_laddr = laddr;	/* XXX rehash? */
714 		splx(s);
715 	}
716 	return (error);
717 
718 release:
719 	m_freem(m);
720 	return (error);
721 }
722 
723 u_long	udp_sendspace = 9216;		/* really max datagram size */
724 					/* 40 1K datagrams */
725 SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
726     &udp_sendspace, 0, "Maximum outgoing UDP datagram size");
727 
728 u_long	udp_recvspace = 40 * (1024 +
729 #ifdef INET6
730 				      sizeof(struct sockaddr_in6)
731 #else
732 				      sizeof(struct sockaddr_in)
733 #endif
734 				      );
735 SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
736     &udp_recvspace, 0, "Maximum incoming UDP datagram size");
737 
738 static int
739 udp_abort(struct socket *so)
740 {
741 	struct inpcb *inp;
742 	int s;
743 
744 	inp = sotoinpcb(so);
745 	if (inp == 0)
746 		return EINVAL;	/* ??? possible? panic instead? */
747 	soisdisconnected(so);
748 	s = splnet();
749 	in_pcbdetach(inp);
750 	splx(s);
751 	return 0;
752 }
753 
754 static int
755 udp_attach(struct socket *so, int proto, struct proc *p)
756 {
757 	struct inpcb *inp;
758 	int s, error;
759 
760 	inp = sotoinpcb(so);
761 	if (inp != 0)
762 		return EINVAL;
763 
764 	error = soreserve(so, udp_sendspace, udp_recvspace);
765 	if (error)
766 		return error;
767 	s = splnet();
768 	error = in_pcballoc(so, &udbinfo, p);
769 	splx(s);
770 	if (error)
771 		return error;
772 
773 	inp = (struct inpcb *)so->so_pcb;
774 	inp->inp_vflag |= INP_IPV4;
775 	inp->inp_ip_ttl = ip_defttl;
776 #ifdef IPSEC
777 	error = ipsec_init_policy(so, &inp->inp_sp);
778 	if (error != 0) {
779 		in_pcbdetach(inp);
780 		return error;
781 	}
782 #endif /*IPSEC*/
783 	return 0;
784 }
785 
786 static int
787 udp_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
788 {
789 	struct inpcb *inp;
790 	int s, error;
791 
792 	inp = sotoinpcb(so);
793 	if (inp == 0)
794 		return EINVAL;
795 	s = splnet();
796 	error = in_pcbbind(inp, nam, p);
797 	splx(s);
798 	return error;
799 }
800 
801 static int
802 udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
803 {
804 	struct inpcb *inp;
805 	int s, error;
806 	struct sockaddr_in *sin;
807 
808 	inp = sotoinpcb(so);
809 	if (inp == 0)
810 		return EINVAL;
811 	if (inp->inp_faddr.s_addr != INADDR_ANY)
812 		return EISCONN;
813 	s = splnet();
814 	sin = (struct sockaddr_in *)nam;
815 	prison_remote_ip(p, 0, &sin->sin_addr.s_addr);
816 	error = in_pcbconnect(inp, nam, p);
817 	splx(s);
818 	if (error == 0)
819 		soisconnected(so);
820 	return error;
821 }
822 
823 static int
824 udp_detach(struct socket *so)
825 {
826 	struct inpcb *inp;
827 	int s;
828 
829 	inp = sotoinpcb(so);
830 	if (inp == 0)
831 		return EINVAL;
832 	s = splnet();
833 	in_pcbdetach(inp);
834 	splx(s);
835 	return 0;
836 }
837 
838 static int
839 udp_disconnect(struct socket *so)
840 {
841 	struct inpcb *inp;
842 	int s;
843 
844 	inp = sotoinpcb(so);
845 	if (inp == 0)
846 		return EINVAL;
847 	if (inp->inp_faddr.s_addr == INADDR_ANY)
848 		return ENOTCONN;
849 
850 	s = splnet();
851 	in_pcbdisconnect(inp);
852 	inp->inp_laddr.s_addr = INADDR_ANY;
853 	splx(s);
854 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
855 	return 0;
856 }
857 
858 static int
859 udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
860 	    struct mbuf *control, struct proc *p)
861 {
862 	struct inpcb *inp;
863 
864 	inp = sotoinpcb(so);
865 	if (inp == 0) {
866 		m_freem(m);
867 		return EINVAL;
868 	}
869 	return udp_output(inp, m, addr, control, p);
870 }
871 
872 int
873 udp_shutdown(struct socket *so)
874 {
875 	struct inpcb *inp;
876 
877 	inp = sotoinpcb(so);
878 	if (inp == 0)
879 		return EINVAL;
880 	socantsendmore(so);
881 	return 0;
882 }
883 
884 struct pr_usrreqs udp_usrreqs = {
885 	udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect,
886 	pru_connect2_notsupp, in_control, udp_detach, udp_disconnect,
887 	pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
888 	pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
889 	in_setsockaddr, sosend, soreceive, sopoll
890 };
891 
892