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