xref: /openbsd/sys/kern/uipc_syscalls.c (revision 2b46a8cb)
1 /*	$OpenBSD: uipc_syscalls.c,v 1.206 2022/12/05 23:18:37 deraadt Exp $	*/
2 /*	$NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1982, 1986, 1989, 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  *	@(#)uipc_syscalls.c	8.4 (Berkeley) 2/21/94
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/filedesc.h>
38 #include <sys/namei.h>
39 #include <sys/pool.h>
40 #include <sys/proc.h>
41 #include <sys/fcntl.h>
42 #include <sys/kernel.h>
43 #include <sys/file.h>
44 #include <sys/vnode.h>
45 #include <sys/malloc.h>
46 #include <sys/event.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/signalvar.h>
52 #include <sys/pledge.h>
53 #ifdef KTRACE
54 #include <sys/ktrace.h>
55 #endif
56 #include <sys/unistd.h>
57 
58 #include <sys/mount.h>
59 #include <sys/syscallargs.h>
60 
61 #include <sys/domain.h>
62 #include <netinet/in.h>
63 #include <net/rtable.h>
64 
65 int	copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t,
66 	    socklen_t *);
67 
68 int
69 sys_socket(struct proc *p, void *v, register_t *retval)
70 {
71 	struct sys_socket_args /* {
72 		syscallarg(int) domain;
73 		syscallarg(int) type;
74 		syscallarg(int) protocol;
75 	} */ *uap = v;
76 	struct filedesc *fdp = p->p_fd;
77 	struct socket *so;
78 	struct file *fp;
79 	int type = SCARG(uap, type);
80 	int domain = SCARG(uap, domain);
81 	int fd, cloexec, nonblock, fflag, error;
82 	unsigned int ss = 0;
83 
84 	if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
85 		return (EINVAL);
86 
87 	if (ISSET(type, SOCK_DNS))
88 		ss |= SS_DNS;
89 	error = pledge_socket(p, domain, ss);
90 	if (error)
91 		return (error);
92 
93 	type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS);
94 	cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
95 	nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
96 	fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
97 
98 	error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol));
99 	if (error)
100 		return (error);
101 
102 	fdplock(fdp);
103 	error = falloc(p, &fp, &fd);
104 	if (error) {
105 		fdpunlock(fdp);
106 		soclose(so, MSG_DONTWAIT);
107 	} else {
108 		fp->f_flag = fflag;
109 		fp->f_type = DTYPE_SOCKET;
110 		fp->f_ops = &socketops;
111 		so->so_state |= ss;
112 		fp->f_data = so;
113 		fdinsert(fdp, fd, cloexec, fp);
114 		fdpunlock(fdp);
115 		FRELE(fp, p);
116 		*retval = fd;
117 	}
118 	return (error);
119 }
120 
121 static inline int
122 isdnssocket(struct socket *so)
123 {
124 	return (so->so_state & SS_DNS);
125 }
126 
127 /* For SS_DNS sockets, only allow port DNS (port 53) */
128 static int
129 dns_portcheck(struct proc *p, struct socket *so, void *nam, size_t namelen)
130 {
131 	int error = EINVAL;
132 
133 	switch (so->so_proto->pr_domain->dom_family) {
134 	case AF_INET:
135 		if (namelen < sizeof(struct sockaddr_in))
136 			break;
137 		if (((struct sockaddr_in *)nam)->sin_port == htons(53))
138 			error = 0;
139 		break;
140 #ifdef INET6
141 	case AF_INET6:
142 		if (namelen < sizeof(struct sockaddr_in6))
143 			break;
144 		if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53))
145 			error = 0;
146 #endif
147 	}
148 	if (error && p->p_p->ps_flags & PS_PLEDGE)
149 		return (pledge_fail(p, EPERM, PLEDGE_DNS));
150 	return error;
151 }
152 
153 int
154 sys_bind(struct proc *p, void *v, register_t *retval)
155 {
156 	struct sys_bind_args /* {
157 		syscallarg(int) s;
158 		syscallarg(const struct sockaddr *) name;
159 		syscallarg(socklen_t) namelen;
160 	} */ *uap = v;
161 	struct file *fp;
162 	struct mbuf *nam;
163 	struct socket *so;
164 	int error;
165 
166 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
167 		return (error);
168 	so = fp->f_data;
169 	error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
170 	    so->so_state);
171 	if (error)
172 		goto out;
173 	if (so->so_state & SS_YP) {
174 		error = ENOTSOCK;
175 		goto out;
176 	}
177 	error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
178 	    MT_SONAME);
179 	if (error)
180 		goto out;
181 #ifdef KTRACE
182 	if (KTRPOINT(p, KTR_STRUCT))
183 		ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
184 #endif
185 	solock(so);
186 	error = sobind(so, nam, p);
187 	sounlock(so);
188 	m_freem(nam);
189 out:
190 	FRELE(fp, p);
191 	return (error);
192 }
193 
194 int
195 sys_listen(struct proc *p, void *v, register_t *retval)
196 {
197 	struct sys_listen_args /* {
198 		syscallarg(int) s;
199 		syscallarg(int) backlog;
200 	} */ *uap = v;
201 	struct file *fp;
202 	struct socket *so;
203 	int error;
204 
205 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
206 		return (error);
207 	so = fp->f_data;
208 	if (so->so_state & SS_YP)
209 		return ENOTSOCK;
210 	solock(so);
211 	error = solisten(so, SCARG(uap, backlog));
212 	sounlock(so);
213 	FRELE(fp, p);
214 	return (error);
215 }
216 
217 int
218 sys_accept(struct proc *p, void *v, register_t *retval)
219 {
220 	struct sys_accept_args /* {
221 		syscallarg(int) s;
222 		syscallarg(struct sockaddr *) name;
223 		syscallarg(socklen_t *) anamelen;
224 	} */ *uap = v;
225 
226 	return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
227 	    SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval));
228 }
229 
230 int
231 sys_accept4(struct proc *p, void *v, register_t *retval)
232 {
233 	struct sys_accept4_args /* {
234 		syscallarg(int) s;
235 		syscallarg(struct sockaddr *) name;
236 		syscallarg(socklen_t *) anamelen;
237 		syscallarg(socklen_t *) int flags;
238 	} */ *uap = v;
239 
240 	if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
241 		return (EINVAL);
242 
243 	return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
244 	    SCARG(uap, anamelen), SCARG(uap, flags), retval));
245 }
246 
247 int
248 doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
249     int flags, register_t *retval)
250 {
251 	struct filedesc *fdp = p->p_fd;
252 	struct file *fp, *headfp;
253 	struct mbuf *nam;
254 	socklen_t namelen;
255 	int error, tmpfd;
256 	struct socket *head, *so;
257 	int cloexec, nflag, persocket;
258 
259 	cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
260 
261 	if (name && (error = copyin(anamelen, &namelen, sizeof (namelen))))
262 		return (error);
263 	if ((error = getsock(p, sock, &fp)) != 0)
264 		return (error);
265 
266 	headfp = fp;
267 
268 	fdplock(fdp);
269 	error = falloc(p, &fp, &tmpfd);
270 	fdpunlock(fdp);
271 	if (error) {
272 		FRELE(headfp, p);
273 		return (error);
274 	}
275 
276 	nam = m_get(M_WAIT, MT_SONAME);
277 
278 	head = headfp->f_data;
279 	solock(head);
280 
281 	persocket = solock_persocket(head);
282 
283 	if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
284 		error = EINVAL;
285 		goto out_unlock;
286 	}
287 	if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) {
288 		if (head->so_state & SS_CANTRCVMORE)
289 			error = ECONNABORTED;
290 		else
291 			error = EWOULDBLOCK;
292 		goto out_unlock;
293 	}
294 	while (head->so_qlen == 0 && head->so_error == 0) {
295 		if (head->so_state & SS_CANTRCVMORE) {
296 			head->so_error = ECONNABORTED;
297 			break;
298 		}
299 		error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH,
300 		    "netcon", INFSLP);
301 		if (error)
302 			goto out_unlock;
303 	}
304 	if (head->so_error) {
305 		error = head->so_error;
306 		head->so_error = 0;
307 		goto out_unlock;
308 	}
309 
310 	/*
311 	 * Do not sleep after we have taken the socket out of the queue.
312 	 */
313 	so = TAILQ_FIRST(&head->so_q);
314 
315 	if (persocket)
316 		solock(so);
317 
318 	if (soqremque(so, 1) == 0)
319 		panic("accept");
320 
321 	/* Figure out whether the new socket should be non-blocking. */
322 	nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
323 	    : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
324 
325 	/* connection has been removed from the listen queue */
326 	KNOTE(&head->so_rcv.sb_sel.si_note, 0);
327 
328 	if (persocket)
329 		sounlock(head);
330 
331 	fp->f_type = DTYPE_SOCKET;
332 	fp->f_flag = FREAD | FWRITE | nflag;
333 	fp->f_ops = &socketops;
334 	fp->f_data = so;
335 
336 	error = soaccept(so, nam);
337 
338 	if (persocket)
339 		sounlock(so);
340 	else
341 		sounlock(head);
342 
343 	if (error)
344 		goto out;
345 
346 	if (name != NULL) {
347 		error = copyaddrout(p, nam, name, namelen, anamelen);
348 		if (error)
349 			goto out;
350 	}
351 
352 	fdplock(fdp);
353 	fdinsert(fdp, tmpfd, cloexec, fp);
354 	fdpunlock(fdp);
355 	FRELE(fp, p);
356 	*retval = tmpfd;
357 
358 	m_freem(nam);
359 	FRELE(headfp, p);
360 
361 	return 0;
362 
363 out_unlock:
364 	sounlock(head);
365 out:
366 	fdplock(fdp);
367 	fdremove(fdp, tmpfd);
368 	fdpunlock(fdp);
369 	closef(fp, p);
370 
371 	m_freem(nam);
372 	FRELE(headfp, p);
373 
374 	return (error);
375 }
376 
377 int
378 sys_connect(struct proc *p, void *v, register_t *retval)
379 {
380 	struct sys_connect_args /* {
381 		syscallarg(int) s;
382 		syscallarg(const struct sockaddr *) name;
383 		syscallarg(socklen_t) namelen;
384 	} */ *uap = v;
385 	struct file *fp;
386 	struct socket *so;
387 	struct mbuf *nam;
388 	int error, interrupted = 0;
389 
390 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
391 		return (error);
392 	so = fp->f_data;
393 	error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
394 	    so->so_state);
395 	if (error)
396 		goto out;
397 	if (so->so_state & SS_YP) {
398 		error = ENOTSOCK;
399 		goto out;
400 	}
401 	error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
402 	    MT_SONAME);
403 	if (error)
404 		goto out;
405 #ifdef KTRACE
406 	if (KTRPOINT(p, KTR_STRUCT))
407 		ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
408 #endif
409 	solock(so);
410 	if (isdnssocket(so)) {
411 		error = dns_portcheck(p, so, mtod(nam, void *), nam->m_len);
412 		if (error)
413 			goto unlock;
414 	}
415 	if (so->so_state & SS_ISCONNECTING) {
416 		error = EALREADY;
417 		goto unlock;
418 	}
419 	error = soconnect(so, nam);
420 	if (error)
421 		goto bad;
422 	if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) {
423 		error = EINPROGRESS;
424 		goto unlock;
425 	}
426 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
427 		error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
428 		    "netcon2", INFSLP);
429 		if (error) {
430 			if (error == EINTR || error == ERESTART)
431 				interrupted = 1;
432 			break;
433 		}
434 	}
435 	if (error == 0) {
436 		error = so->so_error;
437 		so->so_error = 0;
438 	}
439 bad:
440 	if (!interrupted)
441 		so->so_state &= ~SS_ISCONNECTING;
442 unlock:
443 	sounlock(so);
444 	m_freem(nam);
445 out:
446 	FRELE(fp, p);
447 	if (error == ERESTART)
448 		error = EINTR;
449 	return (error);
450 }
451 
452 int
453 sys_socketpair(struct proc *p, void *v, register_t *retval)
454 {
455 	struct sys_socketpair_args /* {
456 		syscallarg(int) domain;
457 		syscallarg(int) type;
458 		syscallarg(int) protocol;
459 		syscallarg(int *) rsv;
460 	} */ *uap = v;
461 	struct filedesc *fdp = p->p_fd;
462 	struct file *fp1 = NULL, *fp2 = NULL;
463 	struct socket *so1, *so2;
464 	int type, cloexec, nonblock, fflag, error, sv[2];
465 
466 	type  = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
467 	cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
468 	nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
469 	fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
470 
471 	error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol));
472 	if (error)
473 		return (error);
474 	error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol));
475 	if (error)
476 		goto free1;
477 
478 	error = soconnect2(so1, so2);
479 	if (error != 0)
480 		goto free2;
481 
482 	if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) {
483 		/*
484 		 * Datagram socket connection is asymmetric.
485 		 */
486 		error = soconnect2(so2, so1);
487 		if (error != 0)
488 			goto free2;
489 	}
490 	fdplock(fdp);
491 	if ((error = falloc(p, &fp1, &sv[0])) != 0)
492 		goto free3;
493 	fp1->f_flag = fflag;
494 	fp1->f_type = DTYPE_SOCKET;
495 	fp1->f_ops = &socketops;
496 	fp1->f_data = so1;
497 	if ((error = falloc(p, &fp2, &sv[1])) != 0)
498 		goto free4;
499 	fp2->f_flag = fflag;
500 	fp2->f_type = DTYPE_SOCKET;
501 	fp2->f_ops = &socketops;
502 	fp2->f_data = so2;
503 	error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
504 	if (error == 0) {
505 		fdinsert(fdp, sv[0], cloexec, fp1);
506 		fdinsert(fdp, sv[1], cloexec, fp2);
507 		fdpunlock(fdp);
508 #ifdef KTRACE
509 		if (KTRPOINT(p, KTR_STRUCT))
510 			ktrfds(p, sv, 2);
511 #endif
512 		FRELE(fp1, p);
513 		FRELE(fp2, p);
514 		return (0);
515 	}
516 	fdremove(fdp, sv[1]);
517 free4:
518 	fdremove(fdp, sv[0]);
519 free3:
520 	fdpunlock(fdp);
521 
522 	if (fp2 != NULL) {
523 		closef(fp2, p);
524 		so2 = NULL;
525 	}
526 	if (fp1 != NULL) {
527 		closef(fp1, p);
528 		so1 = NULL;
529 	}
530 free2:
531 	if (so2 != NULL)
532 		(void)soclose(so2, 0);
533 free1:
534 	if (so1 != NULL)
535 		(void)soclose(so1, 0);
536 	return (error);
537 }
538 
539 int
540 sys_sendto(struct proc *p, void *v, register_t *retval)
541 {
542 	struct sys_sendto_args /* {
543 		syscallarg(int) s;
544 		syscallarg(const void *) buf;
545 		syscallarg(size_t) len;
546 		syscallarg(int) flags;
547 		syscallarg(const struct sockaddr *) to;
548 		syscallarg(socklen_t) tolen;
549 	} */ *uap = v;
550 	struct msghdr msg;
551 	struct iovec aiov;
552 
553 	msg.msg_name = (caddr_t)SCARG(uap, to);
554 	msg.msg_namelen = SCARG(uap, tolen);
555 	msg.msg_iov = &aiov;
556 	msg.msg_iovlen = 1;
557 	msg.msg_control = NULL;
558 	msg.msg_flags = 0;
559 	aiov.iov_base = (char *)SCARG(uap, buf);
560 	aiov.iov_len = SCARG(uap, len);
561 	return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
562 }
563 
564 int
565 sys_sendmsg(struct proc *p, void *v, register_t *retval)
566 {
567 	struct sys_sendmsg_args /* {
568 		syscallarg(int) s;
569 		syscallarg(const struct msghdr *) msg;
570 		syscallarg(int) flags;
571 	} */ *uap = v;
572 	struct msghdr msg;
573 	struct iovec aiov[UIO_SMALLIOV], *iov;
574 	int error;
575 
576 	error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
577 	if (error)
578 		return (error);
579 #ifdef KTRACE
580 	if (KTRPOINT(p, KTR_STRUCT))
581 		ktrmsghdr(p, &msg);
582 #endif
583 
584 	if (msg.msg_iovlen > IOV_MAX)
585 		return (EMSGSIZE);
586 	if (msg.msg_iovlen > UIO_SMALLIOV)
587 		iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
588 		    M_IOV, M_WAITOK);
589 	else
590 		iov = aiov;
591 	if (msg.msg_iovlen &&
592 	    (error = copyin(msg.msg_iov, iov,
593 		    msg.msg_iovlen * sizeof (struct iovec))))
594 		goto done;
595 #ifdef KTRACE
596 	if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
597 		ktriovec(p, iov, msg.msg_iovlen);
598 #endif
599 	msg.msg_iov = iov;
600 	msg.msg_flags = 0;
601 	error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
602 done:
603 	if (iov != aiov)
604 		free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
605 	return (error);
606 }
607 
608 int
609 sys_sendmmsg(struct proc *p, void *v, register_t *retval)
610 {
611 	struct sys_sendmmsg_args /* {
612 		syscallarg(int)			s;
613 		syscallarg(struct mmsghdr *)	mmsg;
614 		syscallarg(unsigned int)	vlen;
615 		syscallarg(int)			flags;
616 	} */ *uap = v;
617 	struct mmsghdr mmsg, *mmsgp;
618 	struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *uiov;
619 	size_t iovlen = UIO_SMALLIOV;
620 	register_t retsnd;
621 	unsigned int vlen, dgrams;
622 	int error = 0, flags, s;
623 
624 	s = SCARG(uap, s);
625 	flags = SCARG(uap, flags);
626 
627 	/* Arbitrarily capped at 1024 datagrams. */
628 	vlen = SCARG(uap, vlen);
629 	if (vlen > 1024)
630 		vlen = 1024;
631 
632 	mmsgp = SCARG(uap, mmsg);
633 	for (dgrams = 0; dgrams < vlen; dgrams++) {
634 		error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
635 		if (error)
636 			break;
637 
638 #ifdef KTRACE
639 		if (KTRPOINT(p, KTR_STRUCT))
640 			ktrmmsghdr(p, &mmsg);
641 #endif
642 
643 		if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
644 			error = EMSGSIZE;
645 			break;
646 		}
647 
648 		if (mmsg.msg_hdr.msg_iovlen > iovlen) {
649 			if (iov != aiov)
650 				free(iov, M_IOV, iovlen *
651 				    sizeof(struct iovec));
652 
653 			iovlen = mmsg.msg_hdr.msg_iovlen;
654 			iov = mallocarray(iovlen, sizeof(struct iovec),
655 			    M_IOV, M_WAITOK);
656 		}
657 
658 		if (mmsg.msg_hdr.msg_iovlen > 0) {
659 			error = copyin(mmsg.msg_hdr.msg_iov, iov,
660 			    mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
661 			if (error)
662 				break;
663 		}
664 
665 #ifdef KTRACE
666 		if (mmsg.msg_hdr.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
667 			ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
668 #endif
669 
670 		uiov = mmsg.msg_hdr.msg_iov;
671 		mmsg.msg_hdr.msg_iov = iov;
672 		mmsg.msg_hdr.msg_flags = 0;
673 
674 		error = sendit(p, s, &mmsg.msg_hdr, flags, &retsnd);
675 		if (error)
676 			break;
677 
678 		mmsg.msg_hdr.msg_iov = uiov;
679 		mmsg.msg_len = retsnd;
680 
681 		error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
682 		if (error)
683 			break;
684 	}
685 
686 	if (iov != aiov)
687 		free(iov, M_IOV, sizeof(struct iovec) * iovlen);
688 
689 	*retval = dgrams;
690 
691 	if (error && dgrams > 0)
692 		error = 0;
693 
694 	return (error);
695 }
696 
697 int
698 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
699 {
700 	struct file *fp;
701 	struct uio auio;
702 	struct iovec *iov;
703 	int i;
704 	struct mbuf *to, *control;
705 	struct socket *so;
706 	size_t len;
707 	int error;
708 #ifdef KTRACE
709 	struct iovec *ktriov = NULL;
710 	int iovlen = 0;
711 #endif
712 
713 	to = NULL;
714 
715 	if ((error = getsock(p, s, &fp)) != 0)
716 		return (error);
717 	so = fp->f_data;
718 	if (fp->f_flag & FNONBLOCK)
719 		flags |= MSG_DONTWAIT;
720 
721 	error = pledge_sendit(p, mp->msg_name);
722 	if (error)
723 		goto bad;
724 
725 	auio.uio_iov = mp->msg_iov;
726 	auio.uio_iovcnt = mp->msg_iovlen;
727 	auio.uio_segflg = UIO_USERSPACE;
728 	auio.uio_rw = UIO_WRITE;
729 	auio.uio_procp = p;
730 	auio.uio_offset = 0;			/* XXX */
731 	auio.uio_resid = 0;
732 	iov = mp->msg_iov;
733 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
734 		/* Don't allow sum > SSIZE_MAX */
735 		if (iov->iov_len > SSIZE_MAX ||
736 		    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
737 			error = EINVAL;
738 			goto bad;
739 		}
740 	}
741 	if (mp->msg_name) {
742 		error = sockargs(&to, mp->msg_name, mp->msg_namelen,
743 		    MT_SONAME);
744 		if (error)
745 			goto bad;
746 		if (isdnssocket(so)) {
747 			error = dns_portcheck(p, so, mtod(to, caddr_t),
748 			    mp->msg_namelen);
749 			if (error)
750 				goto bad;
751 		}
752 #ifdef KTRACE
753 		if (KTRPOINT(p, KTR_STRUCT))
754 			ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen);
755 #endif
756 	}
757 	if (mp->msg_control) {
758 		if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
759 			error = EINVAL;
760 			goto bad;
761 		}
762 		error = sockargs(&control, mp->msg_control,
763 		    mp->msg_controllen, MT_CONTROL);
764 		if (error)
765 			goto bad;
766 #ifdef KTRACE
767 		if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen)
768 			ktrcmsghdr(p, mtod(control, char *),
769 			    mp->msg_controllen);
770 #endif
771 	} else
772 		control = NULL;
773 #ifdef KTRACE
774 	if (KTRPOINT(p, KTR_GENIO)) {
775 		ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
776 		    M_TEMP, M_WAITOK);
777 		iovlen = auio.uio_iovcnt * sizeof (struct iovec);
778 
779 		memcpy(ktriov, auio.uio_iov, iovlen);
780 	}
781 #endif
782 	len = auio.uio_resid;
783 	error = sosend(so, to, &auio, NULL, control, flags);
784 	if (error) {
785 		if (auio.uio_resid != len && (error == ERESTART ||
786 		    error == EINTR || error == EWOULDBLOCK))
787 			error = 0;
788 		if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
789 			KERNEL_LOCK();
790 			ptsignal(p, SIGPIPE, STHREAD);
791 			KERNEL_UNLOCK();
792 		}
793 	}
794 	if (error == 0) {
795 		*retsize = len - auio.uio_resid;
796 		mtx_enter(&fp->f_mtx);
797 		fp->f_wxfer++;
798 		fp->f_wbytes += *retsize;
799 		mtx_leave(&fp->f_mtx);
800 	}
801 #ifdef KTRACE
802 	if (ktriov != NULL) {
803 		if (error == 0)
804 			ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
805 		free(ktriov, M_TEMP, iovlen);
806 	}
807 #endif
808 bad:
809 	FRELE(fp, p);
810 	m_freem(to);
811 	return (error);
812 }
813 
814 int
815 sys_recvfrom(struct proc *p, void *v, register_t *retval)
816 {
817 	struct sys_recvfrom_args /* {
818 		syscallarg(int) s;
819 		syscallarg(void *) buf;
820 		syscallarg(size_t) len;
821 		syscallarg(int) flags;
822 		syscallarg(struct sockaddr *) from;
823 		syscallarg(socklen_t *) fromlenaddr;
824 	} */ *uap = v;
825 	struct msghdr msg;
826 	struct iovec aiov;
827 	int error;
828 
829 	if (SCARG(uap, fromlenaddr)) {
830 		error = copyin(SCARG(uap, fromlenaddr),
831 		    &msg.msg_namelen, sizeof (msg.msg_namelen));
832 		if (error)
833 			return (error);
834 	} else
835 		msg.msg_namelen = 0;
836 	msg.msg_name = (caddr_t)SCARG(uap, from);
837 	msg.msg_iov = &aiov;
838 	msg.msg_iovlen = 1;
839 	aiov.iov_base = SCARG(uap, buf);
840 	aiov.iov_len = SCARG(uap, len);
841 	msg.msg_control = NULL;
842 	msg.msg_flags = SCARG(uap, flags);
843 	return (recvit(p, SCARG(uap, s), &msg,
844 	    (caddr_t)SCARG(uap, fromlenaddr), retval));
845 }
846 
847 int
848 sys_recvmsg(struct proc *p, void *v, register_t *retval)
849 {
850 	struct sys_recvmsg_args /* {
851 		syscallarg(int) s;
852 		syscallarg(struct msghdr *) msg;
853 		syscallarg(int) flags;
854 	} */ *uap = v;
855 	struct msghdr msg;
856 	struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
857 	int error;
858 
859 	error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
860 	if (error)
861 		return (error);
862 
863 	if (msg.msg_iovlen > IOV_MAX)
864 		return (EMSGSIZE);
865 	if (msg.msg_iovlen > UIO_SMALLIOV)
866 		iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
867 		    M_IOV, M_WAITOK);
868 	else
869 		iov = aiov;
870 	msg.msg_flags = SCARG(uap, flags);
871 	if (msg.msg_iovlen > 0) {
872 		error = copyin(msg.msg_iov, iov,
873 		    msg.msg_iovlen * sizeof(struct iovec));
874 		if (error)
875 			goto done;
876 	}
877 	uiov = msg.msg_iov;
878 	msg.msg_iov = iov;
879 	if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
880 		msg.msg_iov = uiov;
881 #ifdef KTRACE
882 		if (KTRPOINT(p, KTR_STRUCT)) {
883 			ktrmsghdr(p, &msg);
884 			if (msg.msg_iovlen)
885 				ktriovec(p, iov, msg.msg_iovlen);
886 		}
887 #endif
888 		error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
889 	}
890 done:
891 	if (iov != aiov)
892 		free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
893 	return (error);
894 }
895 
896 int
897 sys_recvmmsg(struct proc *p, void *v, register_t *retval)
898 {
899 	struct sys_recvmmsg_args /* {
900 		syscallarg(int)			s;
901 		syscallarg(struct mmsghdr *)	mmsg;
902 		syscallarg(unsigned int)	vlen;
903 		syscallarg(int)			flags;
904 		syscallarg(struct timespec *)	timeout;
905 	} */ *uap = v;
906 	struct mmsghdr mmsg, *mmsgp;
907 	struct timespec ts, now, *timeout;
908 	struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov;
909 	size_t iovlen = UIO_SMALLIOV;
910 	register_t retrec;
911 	unsigned int vlen, dgrams;
912 	int error = 0, flags, s;
913 
914 	timeout = SCARG(uap, timeout);
915 	if (timeout != NULL) {
916 		error = copyin(timeout, &ts, sizeof(ts));
917 		if (error)
918 			return (error);
919 #ifdef KTRACE
920 		if (KTRPOINT(p, KTR_STRUCT))
921 			ktrreltimespec(p, &ts);
922 #endif
923 		if (!timespecisvalid(&ts))
924 			return (EINVAL);
925 
926 		getnanotime(&now);
927 		timespecadd(&now, &ts, &ts);
928 	}
929 
930 	s = SCARG(uap, s);
931 	flags = SCARG(uap, flags);
932 
933 	/* Arbitrarily capped at 1024 datagrams. */
934 	vlen = SCARG(uap, vlen);
935 	if (vlen > 1024)
936 		vlen = 1024;
937 
938 	mmsgp = SCARG(uap, mmsg);
939 	for (dgrams = 0; dgrams < vlen;) {
940 		error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
941 		if (error)
942 			break;
943 
944 		if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
945 			error = EMSGSIZE;
946 			break;
947 		}
948 
949 		if (mmsg.msg_hdr.msg_iovlen > iovlen) {
950 			if (iov != aiov)
951 				free(iov, M_IOV, iovlen *
952 				    sizeof(struct iovec));
953 
954 			iovlen = mmsg.msg_hdr.msg_iovlen;
955 			iov = mallocarray(iovlen, sizeof(struct iovec),
956 			    M_IOV, M_WAITOK);
957 		}
958 
959 		if (mmsg.msg_hdr.msg_iovlen > 0) {
960 			error = copyin(mmsg.msg_hdr.msg_iov, iov,
961 			    mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
962 			if (error)
963 				break;
964 		}
965 
966 		uiov = mmsg.msg_hdr.msg_iov;
967 		mmsg.msg_hdr.msg_iov = iov;
968 		mmsg.msg_hdr.msg_flags = flags & ~MSG_WAITFORONE;
969 
970 		error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec);
971 		if (error) {
972 			if (error == EAGAIN && dgrams > 0)
973 				error = 0;
974 			break;
975 		}
976 
977 		if (flags & MSG_WAITFORONE)
978 			flags |= MSG_DONTWAIT;
979 
980 		mmsg.msg_hdr.msg_iov = uiov;
981 		mmsg.msg_len = retrec;
982 #ifdef KTRACE
983 		if (KTRPOINT(p, KTR_STRUCT)) {
984 			ktrmmsghdr(p, &mmsg);
985 			if (mmsg.msg_hdr.msg_iovlen)
986 				ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
987 		}
988 #endif
989 
990 		error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
991 		if (error)
992 			break;
993 
994 		dgrams++;
995 		if (mmsg.msg_hdr.msg_flags & MSG_OOB)
996 			break;
997 
998 		if (timeout != NULL) {
999 			getnanotime(&now);
1000 			timespecsub(&now, &ts, &now);
1001 			if (now.tv_sec > 0)
1002 				break;
1003 		}
1004 	}
1005 
1006 	if (iov != aiov)
1007 		free(iov, M_IOV, iovlen * sizeof(struct iovec));
1008 
1009 	*retval = dgrams;
1010 
1011 	/*
1012 	 * If we succeeded at least once, return 0, hopefully so->so_error
1013 	 * will catch it next time.
1014 	 */
1015 	if (error && dgrams > 0) {
1016 		struct file *fp;
1017 		struct socket *so;
1018 
1019 		if (getsock(p, s, &fp) == 0) {
1020 			so = (struct socket *)fp->f_data;
1021 			so->so_error = error;
1022 
1023 			FRELE(fp, p);
1024 		}
1025 		error = 0;
1026 	}
1027 
1028 	return (error);
1029 }
1030 
1031 int
1032 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
1033     register_t *retsize)
1034 {
1035 	struct file *fp;
1036 	struct uio auio;
1037 	struct iovec *iov;
1038 	int i;
1039 	size_t len;
1040 	int error;
1041 	struct mbuf *from = NULL, *control = NULL;
1042 #ifdef KTRACE
1043 	struct iovec *ktriov = NULL;
1044 	int iovlen = 0, kmsgflags;
1045 #endif
1046 
1047 	if ((error = getsock(p, s, &fp)) != 0)
1048 		return (error);
1049 
1050 	auio.uio_iov = mp->msg_iov;
1051 	auio.uio_iovcnt = mp->msg_iovlen;
1052 	auio.uio_segflg = UIO_USERSPACE;
1053 	auio.uio_rw = UIO_READ;
1054 	auio.uio_procp = p;
1055 	auio.uio_offset = 0;			/* XXX */
1056 	auio.uio_resid = 0;
1057 	iov = mp->msg_iov;
1058 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1059 		/* Don't allow sum > SSIZE_MAX */
1060 		if (iov->iov_len > SSIZE_MAX ||
1061 		    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
1062 			error = EINVAL;
1063 			goto out;
1064 		}
1065 	}
1066 #ifdef KTRACE
1067 	if (KTRPOINT(p, KTR_GENIO)) {
1068 		ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
1069 		    M_TEMP, M_WAITOK);
1070 		iovlen = auio.uio_iovcnt * sizeof (struct iovec);
1071 
1072 		memcpy(ktriov, auio.uio_iov, iovlen);
1073 	}
1074 	kmsgflags = mp->msg_flags;
1075 #endif
1076 	len = auio.uio_resid;
1077 	if (fp->f_flag & FNONBLOCK)
1078 		mp->msg_flags |= MSG_DONTWAIT;
1079 	error = soreceive(fp->f_data, &from, &auio, NULL,
1080 			  mp->msg_control ? &control : NULL,
1081 			  &mp->msg_flags,
1082 			  mp->msg_control ? mp->msg_controllen : 0);
1083 	if (error) {
1084 		if (auio.uio_resid != len && (error == ERESTART ||
1085 		    error == EINTR || error == EWOULDBLOCK))
1086 			error = 0;
1087 	}
1088 #ifdef KTRACE
1089 	if (ktriov != NULL) {
1090 		if (error == 0)
1091 			ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
1092 		free(ktriov, M_TEMP, iovlen);
1093 	}
1094 #endif
1095 	if (error)
1096 		goto out;
1097 	*retsize = len - auio.uio_resid;
1098 	if (mp->msg_name) {
1099 		socklen_t alen;
1100 
1101 		if (from == NULL)
1102 			alen = 0;
1103 		else {
1104 			alen = from->m_len;
1105 			error = copyout(mtod(from, caddr_t), mp->msg_name,
1106 			    MIN(alen, mp->msg_namelen));
1107 			if (error)
1108 				goto out;
1109 #ifdef KTRACE
1110 			if (KTRPOINT(p, KTR_STRUCT))
1111 				ktrsockaddr(p, mtod(from, caddr_t), alen);
1112 #endif
1113 		}
1114 		mp->msg_namelen = alen;
1115 		if (namelenp &&
1116 		    (error = copyout(&alen, namelenp, sizeof(alen)))) {
1117 			goto out;
1118 		}
1119 	}
1120 	if (mp->msg_control) {
1121 		len = mp->msg_controllen;
1122 		if (len <= 0 || control == NULL)
1123 			len = 0;
1124 		else {
1125 			struct mbuf *m = control;
1126 			caddr_t cp = mp->msg_control;
1127 
1128 			do {
1129 				i = m->m_len;
1130 				if (len < i) {
1131 					mp->msg_flags |= MSG_CTRUNC;
1132 					i = len;
1133 				}
1134 				error = copyout(mtod(m, caddr_t), cp, i);
1135 #ifdef KTRACE
1136 				if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) {
1137 					/* msg_flags potentially incorrect */
1138 					int rmsgflags = mp->msg_flags;
1139 
1140 					mp->msg_flags = kmsgflags;
1141 					ktrcmsghdr(p, mtod(m, char *), i);
1142 					mp->msg_flags = rmsgflags;
1143 				}
1144 #endif
1145 				if (m->m_next)
1146 					i = ALIGN(i);
1147 				cp += i;
1148 				len -= i;
1149 				if (error != 0 || len <= 0)
1150 					break;
1151 			} while ((m = m->m_next) != NULL);
1152 			len = cp - (caddr_t)mp->msg_control;
1153 		}
1154 		mp->msg_controllen = len;
1155 	}
1156 	if (!error) {
1157 		mtx_enter(&fp->f_mtx);
1158 		fp->f_rxfer++;
1159 		fp->f_rbytes += *retsize;
1160 		mtx_leave(&fp->f_mtx);
1161 	}
1162 out:
1163 	FRELE(fp, p);
1164 	m_freem(from);
1165 	m_freem(control);
1166 	return (error);
1167 }
1168 
1169 int
1170 sys_shutdown(struct proc *p, void *v, register_t *retval)
1171 {
1172 	struct sys_shutdown_args /* {
1173 		syscallarg(int) s;
1174 		syscallarg(int) how;
1175 	} */ *uap = v;
1176 	struct file *fp;
1177 	int error;
1178 
1179 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1180 		return (error);
1181 	error = soshutdown(fp->f_data, SCARG(uap, how));
1182 	FRELE(fp, p);
1183 	return (error);
1184 }
1185 
1186 int
1187 sys_setsockopt(struct proc *p, void *v, register_t *retval)
1188 {
1189 	struct sys_setsockopt_args /* {
1190 		syscallarg(int) s;
1191 		syscallarg(int) level;
1192 		syscallarg(int) name;
1193 		syscallarg(const void *) val;
1194 		syscallarg(socklen_t) valsize;
1195 	} */ *uap = v;
1196 	struct file *fp;
1197 	struct mbuf *m = NULL;
1198 	struct socket *so;
1199 	int error;
1200 
1201 
1202 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1203 		return (error);
1204 	error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
1205 	if (error)
1206 		goto bad;
1207 	if (SCARG(uap, valsize) > MCLBYTES) {
1208 		error = EINVAL;
1209 		goto bad;
1210 	}
1211 	if (SCARG(uap, val)) {
1212 		m = m_get(M_WAIT, MT_SOOPTS);
1213 		if (SCARG(uap, valsize) > MLEN) {
1214 			MCLGET(m, M_DONTWAIT);
1215 			if ((m->m_flags & M_EXT) == 0) {
1216 				error = ENOBUFS;
1217 				goto bad;
1218 			}
1219 		}
1220 		if (m == NULL) {
1221 			error = ENOBUFS;
1222 			goto bad;
1223 		}
1224 		error = copyin(SCARG(uap, val), mtod(m, caddr_t),
1225 		    SCARG(uap, valsize));
1226 		if (error) {
1227 			goto bad;
1228 		}
1229 		m->m_len = SCARG(uap, valsize);
1230 	}
1231 	so = fp->f_data;
1232 	solock(so);
1233 	error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1234 	sounlock(so);
1235 bad:
1236 	m_freem(m);
1237 	FRELE(fp, p);
1238 	return (error);
1239 }
1240 
1241 int
1242 sys_getsockopt(struct proc *p, void *v, register_t *retval)
1243 {
1244 	struct sys_getsockopt_args /* {
1245 		syscallarg(int) s;
1246 		syscallarg(int) level;
1247 		syscallarg(int) name;
1248 		syscallarg(void *) val;
1249 		syscallarg(socklen_t *) avalsize;
1250 	} */ *uap = v;
1251 	struct file *fp;
1252 	struct mbuf *m = NULL;
1253 	socklen_t valsize;
1254 	struct socket *so;
1255 	int error;
1256 
1257 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1258 		return (error);
1259 	error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
1260 	if (error)
1261 		goto out;
1262 	if (SCARG(uap, val)) {
1263 		error = copyin(SCARG(uap, avalsize),
1264 		    &valsize, sizeof (valsize));
1265 		if (error)
1266 			goto out;
1267 	} else
1268 		valsize = 0;
1269 	m = m_get(M_WAIT, MT_SOOPTS);
1270 	so = fp->f_data;
1271 	solock_shared(so);
1272 	error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1273 	sounlock_shared(so);
1274 	if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
1275 		if (valsize > m->m_len)
1276 			valsize = m->m_len;
1277 		error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1278 		if (error == 0)
1279 			error = copyout(&valsize,
1280 			    SCARG(uap, avalsize), sizeof (valsize));
1281 	}
1282 	m_free(m);
1283 out:
1284 	FRELE(fp, p);
1285 	return (error);
1286 }
1287 
1288 /*
1289  * Get socket name.
1290  */
1291 int
1292 sys_getsockname(struct proc *p, void *v, register_t *retval)
1293 {
1294 	struct sys_getsockname_args /* {
1295 		syscallarg(int) fdes;
1296 		syscallarg(struct sockaddr *) asa;
1297 		syscallarg(socklen_t *) alen;
1298 	} */ *uap = v;
1299 	struct file *fp;
1300 	struct socket *so;
1301 	struct mbuf *m = NULL;
1302 	socklen_t len;
1303 	int error;
1304 
1305 	if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1306 		return (error);
1307 	error = copyin(SCARG(uap, alen), &len, sizeof (len));
1308 	if (error)
1309 		goto bad;
1310 	so = fp->f_data;
1311 	if (so->so_state & SS_YP) {
1312 		error = ENOTSOCK;
1313 		goto bad;
1314 	}
1315 	error = pledge_socket(p, -1, so->so_state);
1316 	if (error)
1317 		goto bad;
1318 	if (so->so_state & SS_YP) {
1319 		error = ENOTSOCK;
1320 		goto bad;
1321 	}
1322 	m = m_getclr(M_WAIT, MT_SONAME);
1323 	solock_shared(so);
1324 	error = pru_sockaddr(so, m);
1325 	sounlock_shared(so);
1326 	if (error)
1327 		goto bad;
1328 	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1329 bad:
1330 	FRELE(fp, p);
1331 	m_freem(m);
1332 	return (error);
1333 }
1334 
1335 /*
1336  * Get name of peer for connected socket.
1337  */
1338 int
1339 sys_getpeername(struct proc *p, void *v, register_t *retval)
1340 {
1341 	struct sys_getpeername_args /* {
1342 		syscallarg(int) fdes;
1343 		syscallarg(struct sockaddr *) asa;
1344 		syscallarg(socklen_t *) alen;
1345 	} */ *uap = v;
1346 	struct file *fp;
1347 	struct socket *so;
1348 	struct mbuf *m = NULL;
1349 	socklen_t len;
1350 	int error;
1351 
1352 	if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1353 		return (error);
1354 	so = fp->f_data;
1355 	error = pledge_socket(p, -1, so->so_state);
1356 	if (error)
1357 		goto bad;
1358 	if (so->so_state & SS_YP) {
1359 		error = ENOTSOCK;
1360 		goto bad;
1361 	}
1362 	if ((so->so_state & SS_ISCONNECTED) == 0) {
1363 		error = ENOTCONN;
1364 		goto bad;
1365 	}
1366 	error = copyin(SCARG(uap, alen), &len, sizeof (len));
1367 	if (error)
1368 		goto bad;
1369 	m = m_getclr(M_WAIT, MT_SONAME);
1370 	solock_shared(so);
1371 	error = pru_peeraddr(so, m);
1372 	sounlock_shared(so);
1373 	if (error)
1374 		goto bad;
1375 	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1376 bad:
1377 	FRELE(fp, p);
1378 	m_freem(m);
1379 	return (error);
1380 }
1381 
1382 int
1383 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1384 {
1385 	struct sockaddr *sa;
1386 	struct mbuf *m;
1387 	int error;
1388 
1389 	/*
1390 	 * We can't allow socket names > UCHAR_MAX in length, since that
1391 	 * will overflow sa_len. Also, control data more than MCLBYTES in
1392 	 * length is just too much.
1393 	 * Memory for sa_len and sa_family must exist.
1394 	 */
1395 	if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1396 	    (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1397 		return (EINVAL);
1398 
1399 	/* Allocate an mbuf to hold the arguments. */
1400 	m = m_get(M_WAIT, type);
1401 	if (buflen > MLEN) {
1402 		MCLGET(m, M_WAITOK);
1403 		if ((m->m_flags & M_EXT) == 0) {
1404 			m_free(m);
1405 			return ENOBUFS;
1406 		}
1407 	}
1408 	m->m_len = buflen;
1409 	error = copyin(buf, mtod(m, caddr_t), buflen);
1410 	if (error) {
1411 		(void) m_free(m);
1412 		return (error);
1413 	}
1414 	*mp = m;
1415 	if (type == MT_SONAME) {
1416 		sa = mtod(m, struct sockaddr *);
1417 		sa->sa_len = buflen;
1418 	}
1419 	return (0);
1420 }
1421 
1422 int
1423 getsock(struct proc *p, int fdes, struct file **fpp)
1424 {
1425 	struct file *fp;
1426 
1427 	fp = fd_getfile(p->p_fd, fdes);
1428 	if (fp == NULL)
1429 		return (EBADF);
1430 	if (fp->f_type != DTYPE_SOCKET) {
1431 		FRELE(fp, p);
1432 		return (ENOTSOCK);
1433 	}
1434 	*fpp = fp;
1435 
1436 	return (0);
1437 }
1438 
1439 int
1440 sys_setrtable(struct proc *p, void *v, register_t *retval)
1441 {
1442 	struct sys_setrtable_args /* {
1443 		syscallarg(int) rtableid;
1444 	} */ *uap = v;
1445 	u_int ps_rtableid = p->p_p->ps_rtableid;
1446 	int rtableid, error;
1447 
1448 	rtableid = SCARG(uap, rtableid);
1449 
1450 	if (ps_rtableid == rtableid)
1451 		return (0);
1452 	if (ps_rtableid != 0 && (error = suser(p)) != 0)
1453 		return (error);
1454 	if (rtableid < 0 || !rtable_exists((u_int)rtableid))
1455 		return (EINVAL);
1456 
1457 	p->p_p->ps_rtableid = (u_int)rtableid;
1458 	return (0);
1459 }
1460 
1461 int
1462 sys_getrtable(struct proc *p, void *v, register_t *retval)
1463 {
1464 	*retval = (int)p->p_p->ps_rtableid;
1465 	return (0);
1466 }
1467 
1468 int
1469 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
1470     socklen_t buflen, socklen_t *outlen)
1471 {
1472 	int error;
1473 	socklen_t namelen = name->m_len;
1474 
1475 	/* SHOULD COPY OUT A CHAIN HERE */
1476 	error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
1477 	if (error == 0) {
1478 #ifdef KTRACE
1479 		if (KTRPOINT(p, KTR_STRUCT))
1480 			ktrsockaddr(p, mtod(name, caddr_t), namelen);
1481 #endif
1482 		error = copyout(&namelen, outlen, sizeof(*outlen));
1483 	}
1484 
1485 	return (error);
1486 }
1487 
1488 #ifndef SMALL_KERNEL
1489 int
1490 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1491 {
1492 	struct sockaddr *sa;
1493 	struct mbuf *m;
1494 
1495 	/*
1496 	 * We can't allow socket names > UCHAR_MAX in length, since that
1497 	 * will overflow sa_len. Also, control data more than MCLBYTES in
1498 	 * length is just too much.
1499 	 * Memory for sa_len and sa_family must exist.
1500 	 */
1501 	if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1502 	    (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1503 		return (EINVAL);
1504 
1505 	/* Allocate an mbuf to hold the arguments. */
1506 	m = m_get(M_WAIT, type);
1507 	if (buflen > MLEN) {
1508 		MCLGET(m, M_WAITOK);
1509 		if ((m->m_flags & M_EXT) == 0) {
1510 			m_free(m);
1511 			return ENOBUFS;
1512 		}
1513 	}
1514 	m->m_len = buflen;
1515 	bcopy(buf, mtod(m, caddr_t), buflen);
1516 	*mp = m;
1517 	if (type == MT_SONAME) {
1518 		sa = mtod(m, struct sockaddr *);
1519 		sa->sa_len = buflen;
1520 	}
1521 	return (0);
1522 }
1523 #endif /* SMALL_KERNEL */
1524 
1525 int
1526 sys_ypconnect(struct proc *p, void *v, register_t *retval)
1527 {
1528 #ifdef SMALL_KERNEL
1529 	return EAFNOSUPPORT;
1530 #else
1531 	struct sys_ypconnect_args /* {
1532 		syscallarg(int) type;
1533 	} */ *uap = v;
1534 	struct nameidata nid;
1535 	struct vattr va;
1536 	struct uio uio;
1537 	struct iovec iov;
1538 	struct filedesc *fdp = p->p_fd;
1539 	struct socket *so;
1540 	struct file *fp;
1541 	struct flock fl;
1542 	char *name;
1543 	struct mbuf *nam = NULL;
1544 	int error, fd = -1;
1545 	struct ypbinding {
1546 		u_short ypbind_port;
1547 		int status;
1548 		in_addr_t in;
1549 		u_short ypserv_udp_port;
1550 		u_short garbage;
1551 		u_short ypserv_tcp_port;
1552 	} __packed data;
1553 	struct sockaddr_in ypsin;
1554 
1555 	if (!domainname[0] || strchr(domainname, '/'))
1556 		return EAFNOSUPPORT;
1557 
1558 	switch (SCARG(uap, type)) {
1559 	case SOCK_STREAM:
1560 	case SOCK_DGRAM:
1561 		break;
1562 	default:
1563 		return EAFNOSUPPORT;
1564 	}
1565 
1566 	if (p->p_p->ps_flags & PS_CHROOT)
1567 		return EACCES;
1568 	name = pool_get(&namei_pool, PR_WAITOK);
1569 	snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname);
1570 	NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p);
1571 	nid.ni_pledge = PLEDGE_RPATH;
1572 
1573 	KERNEL_LOCK();
1574 	error = namei(&nid);
1575 	pool_put(&namei_pool, name);
1576 	if (error)
1577 		goto out;
1578 	error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
1579 	if (error)
1580 		goto verror;
1581 	if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) {
1582 		error = EFTYPE;
1583 		goto verror;
1584 	}
1585 
1586 	/*
1587 	 * Check that a lock is held on the file (hopefully by ypbind),
1588 	 * otherwise the file might be old
1589 	 */
1590 	fl.l_start = 0;
1591 	fl.l_len = 0;
1592 	fl.l_pid = 0;
1593 	fl.l_type = F_WRLCK;
1594 	fl.l_whence = SEEK_SET;
1595 	error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX);
1596 	if (error)
1597 		goto verror;
1598 	if (fl.l_type == F_UNLCK) {
1599 		error = EOWNERDEAD;
1600 		goto verror;
1601 	}
1602 
1603 	iov.iov_base = &data;
1604 	iov.iov_len = sizeof data;
1605 	uio.uio_iov = &iov;
1606 	uio.uio_iovcnt = 1;
1607 	uio.uio_offset = 0;
1608 	uio.uio_resid = iov.iov_len;
1609 	uio.uio_segflg = UIO_SYSSPACE;
1610 	uio.uio_rw = UIO_READ;
1611 	uio.uio_procp = p;
1612 
1613 	error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred);
1614 	if (error) {
1615 verror:
1616 		if (nid.ni_vp)
1617 			vput(nid.ni_vp);
1618 out:
1619 		KERNEL_UNLOCK();
1620 		return (error);
1621 	}
1622 	vput(nid.ni_vp);
1623 	KERNEL_UNLOCK();
1624 
1625 	bzero(&ypsin, sizeof ypsin);
1626 	ypsin.sin_len = sizeof ypsin;
1627 	ypsin.sin_family = AF_INET;
1628 	if (SCARG(uap, type) == SOCK_STREAM)
1629 		ypsin.sin_port = data.ypserv_tcp_port;
1630 	else
1631 		ypsin.sin_port = data.ypserv_udp_port;
1632 	if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20)
1633 		return EPERM;
1634 	memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr);
1635 
1636 	error = socreate(AF_INET, &so, SCARG(uap, type), 0);
1637 	if (error)
1638 		return (error);
1639 
1640 	error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME);
1641 	if (error) {
1642 		soclose(so, MSG_DONTWAIT);
1643 		return (error);
1644 	}
1645 
1646 #ifdef KTRACE
1647 	if (KTRPOINT(p, KTR_STRUCT))
1648 		ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in));
1649 #endif
1650 	solock(so);
1651 	error = soconnect(so, nam);
1652 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1653 		error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
1654 		    "netcon2", INFSLP);
1655 		if (error)
1656 			break;
1657 	}
1658 	m_freem(nam);
1659 	so->so_state |= SS_YP;		/* impose some restrictions */
1660 	sounlock(so);
1661 	if (error) {
1662 		soclose(so, MSG_DONTWAIT);
1663 		return (error);
1664 	}
1665 
1666 	fdplock(fdp);
1667 	error = falloc(p, &fp, &fd);
1668 	if (error) {
1669 		fdpunlock(fdp);
1670 		soclose(so, MSG_DONTWAIT);
1671 		return (error);
1672 	}
1673 
1674 	fp->f_flag = FREAD | FWRITE | FNONBLOCK;
1675 	fp->f_type = DTYPE_SOCKET;
1676 	fp->f_ops = &socketops;
1677 	fp->f_data = so;
1678 	fdinsert(fdp, fd, UF_EXCLOSE, fp);
1679 	fdpunlock(fdp);
1680 	FRELE(fp, p);
1681 	*retval = fd;
1682 	return (error);
1683 #endif /* SMALL_KERNEL */
1684 }
1685