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