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