xref: /openbsd/sys/kern/uipc_syscalls.c (revision 69690c9b)
1 /*	$OpenBSD: uipc_syscalls.c,v 1.200 2022/08/13 21:01:46 mvs 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/ioctl.h>
46 #include <sys/malloc.h>
47 #include <sys/event.h>
48 #include <sys/mbuf.h>
49 #include <sys/protosw.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/signalvar.h>
53 #include <sys/pledge.h>
54 #include <sys/unpcb.h>
55 #include <sys/un.h>
56 #ifdef KTRACE
57 #include <sys/ktrace.h>
58 #endif
59 #include <sys/unistd.h>
60 
61 #include <sys/mount.h>
62 #include <sys/syscallargs.h>
63 
64 #include <sys/domain.h>
65 #include <netinet/in.h>
66 #include <net/route.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_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_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(&head->so_rcv.sb_sel.si_note, 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 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
613 {
614 	struct file *fp;
615 	struct uio auio;
616 	struct iovec *iov;
617 	int i;
618 	struct mbuf *to, *control;
619 	struct socket *so;
620 	size_t len;
621 	int error;
622 #ifdef KTRACE
623 	struct iovec *ktriov = NULL;
624 	int iovlen = 0;
625 #endif
626 
627 	to = NULL;
628 
629 	if ((error = getsock(p, s, &fp)) != 0)
630 		return (error);
631 	so = fp->f_data;
632 	if (fp->f_flag & FNONBLOCK)
633 		flags |= MSG_DONTWAIT;
634 
635 	error = pledge_sendit(p, mp->msg_name);
636 	if (error)
637 		goto bad;
638 
639 	auio.uio_iov = mp->msg_iov;
640 	auio.uio_iovcnt = mp->msg_iovlen;
641 	auio.uio_segflg = UIO_USERSPACE;
642 	auio.uio_rw = UIO_WRITE;
643 	auio.uio_procp = p;
644 	auio.uio_offset = 0;			/* XXX */
645 	auio.uio_resid = 0;
646 	iov = mp->msg_iov;
647 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
648 		/* Don't allow sum > SSIZE_MAX */
649 		if (iov->iov_len > SSIZE_MAX ||
650 		    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
651 			error = EINVAL;
652 			goto bad;
653 		}
654 	}
655 	if (mp->msg_name) {
656 		error = sockargs(&to, mp->msg_name, mp->msg_namelen,
657 		    MT_SONAME);
658 		if (error)
659 			goto bad;
660 		if (isdnssocket(so)) {
661 			error = dns_portcheck(p, so, mtod(to, caddr_t),
662 			    mp->msg_namelen);
663 			if (error)
664 				goto bad;
665 		}
666 #ifdef KTRACE
667 		if (KTRPOINT(p, KTR_STRUCT))
668 			ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen);
669 #endif
670 	}
671 	if (mp->msg_control) {
672 		if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
673 			error = EINVAL;
674 			goto bad;
675 		}
676 		error = sockargs(&control, mp->msg_control,
677 		    mp->msg_controllen, MT_CONTROL);
678 		if (error)
679 			goto bad;
680 #ifdef KTRACE
681 		if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen)
682 			ktrcmsghdr(p, mtod(control, char *),
683 			    mp->msg_controllen);
684 #endif
685 	} else
686 		control = NULL;
687 #ifdef KTRACE
688 	if (KTRPOINT(p, KTR_GENIO)) {
689 		ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
690 		    M_TEMP, M_WAITOK);
691 		iovlen = auio.uio_iovcnt * sizeof (struct iovec);
692 
693 		memcpy(ktriov, auio.uio_iov, iovlen);
694 	}
695 #endif
696 	len = auio.uio_resid;
697 	error = sosend(so, to, &auio, NULL, control, flags);
698 	if (error) {
699 		if (auio.uio_resid != len && (error == ERESTART ||
700 		    error == EINTR || error == EWOULDBLOCK))
701 			error = 0;
702 		if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
703 			KERNEL_LOCK();
704 			ptsignal(p, SIGPIPE, STHREAD);
705 			KERNEL_UNLOCK();
706 		}
707 	}
708 	if (error == 0) {
709 		*retsize = len - auio.uio_resid;
710 		mtx_enter(&fp->f_mtx);
711 		fp->f_wxfer++;
712 		fp->f_wbytes += *retsize;
713 		mtx_leave(&fp->f_mtx);
714 	}
715 #ifdef KTRACE
716 	if (ktriov != NULL) {
717 		if (error == 0)
718 			ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
719 		free(ktriov, M_TEMP, iovlen);
720 	}
721 #endif
722 bad:
723 	FRELE(fp, p);
724 	m_freem(to);
725 	return (error);
726 }
727 
728 int
729 sys_recvfrom(struct proc *p, void *v, register_t *retval)
730 {
731 	struct sys_recvfrom_args /* {
732 		syscallarg(int) s;
733 		syscallarg(void *) buf;
734 		syscallarg(size_t) len;
735 		syscallarg(int) flags;
736 		syscallarg(struct sockaddr *) from;
737 		syscallarg(socklen_t *) fromlenaddr;
738 	} */ *uap = v;
739 	struct msghdr msg;
740 	struct iovec aiov;
741 	int error;
742 
743 	if (SCARG(uap, fromlenaddr)) {
744 		error = copyin(SCARG(uap, fromlenaddr),
745 		    &msg.msg_namelen, sizeof (msg.msg_namelen));
746 		if (error)
747 			return (error);
748 	} else
749 		msg.msg_namelen = 0;
750 	msg.msg_name = (caddr_t)SCARG(uap, from);
751 	msg.msg_iov = &aiov;
752 	msg.msg_iovlen = 1;
753 	aiov.iov_base = SCARG(uap, buf);
754 	aiov.iov_len = SCARG(uap, len);
755 	msg.msg_control = NULL;
756 	msg.msg_flags = SCARG(uap, flags);
757 	return (recvit(p, SCARG(uap, s), &msg,
758 	    (caddr_t)SCARG(uap, fromlenaddr), retval));
759 }
760 
761 int
762 sys_recvmsg(struct proc *p, void *v, register_t *retval)
763 {
764 	struct sys_recvmsg_args /* {
765 		syscallarg(int) s;
766 		syscallarg(struct msghdr *) msg;
767 		syscallarg(int) flags;
768 	} */ *uap = v;
769 	struct msghdr msg;
770 	struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
771 	int error;
772 
773 	error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
774 	if (error)
775 		return (error);
776 
777 	if (msg.msg_iovlen > IOV_MAX)
778 		return (EMSGSIZE);
779 	if (msg.msg_iovlen > UIO_SMALLIOV)
780 		iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
781 		    M_IOV, M_WAITOK);
782 	else
783 		iov = aiov;
784 	msg.msg_flags = SCARG(uap, flags);
785 	if (msg.msg_iovlen > 0) {
786 		error = copyin(msg.msg_iov, iov,
787 		    msg.msg_iovlen * sizeof(struct iovec));
788 		if (error)
789 			goto done;
790 	}
791 	uiov = msg.msg_iov;
792 	msg.msg_iov = iov;
793 	if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
794 		msg.msg_iov = uiov;
795 #ifdef KTRACE
796 		if (KTRPOINT(p, KTR_STRUCT)) {
797 			ktrmsghdr(p, &msg);
798 			if (msg.msg_iovlen)
799 				ktriovec(p, iov, msg.msg_iovlen);
800 		}
801 #endif
802 		error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
803 	}
804 done:
805 	if (iov != aiov)
806 		free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
807 	return (error);
808 }
809 
810 int
811 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
812     register_t *retsize)
813 {
814 	struct file *fp;
815 	struct uio auio;
816 	struct iovec *iov;
817 	int i;
818 	size_t len;
819 	int error;
820 	struct mbuf *from = NULL, *control = NULL;
821 #ifdef KTRACE
822 	struct iovec *ktriov = NULL;
823 	int iovlen = 0, kmsgflags;
824 #endif
825 
826 	if ((error = getsock(p, s, &fp)) != 0)
827 		return (error);
828 
829 	auio.uio_iov = mp->msg_iov;
830 	auio.uio_iovcnt = mp->msg_iovlen;
831 	auio.uio_segflg = UIO_USERSPACE;
832 	auio.uio_rw = UIO_READ;
833 	auio.uio_procp = p;
834 	auio.uio_offset = 0;			/* XXX */
835 	auio.uio_resid = 0;
836 	iov = mp->msg_iov;
837 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
838 		/* Don't allow sum > SSIZE_MAX */
839 		if (iov->iov_len > SSIZE_MAX ||
840 		    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
841 			error = EINVAL;
842 			goto out;
843 		}
844 	}
845 #ifdef KTRACE
846 	if (KTRPOINT(p, KTR_GENIO)) {
847 		ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
848 		    M_TEMP, M_WAITOK);
849 		iovlen = auio.uio_iovcnt * sizeof (struct iovec);
850 
851 		memcpy(ktriov, auio.uio_iov, iovlen);
852 	}
853 	kmsgflags = mp->msg_flags;
854 #endif
855 	len = auio.uio_resid;
856 	if (fp->f_flag & FNONBLOCK)
857 		mp->msg_flags |= MSG_DONTWAIT;
858 	error = soreceive(fp->f_data, &from, &auio, NULL,
859 			  mp->msg_control ? &control : NULL,
860 			  &mp->msg_flags,
861 			  mp->msg_control ? mp->msg_controllen : 0);
862 	if (error) {
863 		if (auio.uio_resid != len && (error == ERESTART ||
864 		    error == EINTR || error == EWOULDBLOCK))
865 			error = 0;
866 	}
867 #ifdef KTRACE
868 	if (ktriov != NULL) {
869 		if (error == 0)
870 			ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
871 		free(ktriov, M_TEMP, iovlen);
872 	}
873 #endif
874 	if (error)
875 		goto out;
876 	*retsize = len - auio.uio_resid;
877 	if (mp->msg_name) {
878 		socklen_t alen;
879 
880 		if (from == NULL)
881 			alen = 0;
882 		else {
883 			alen = from->m_len;
884 			error = copyout(mtod(from, caddr_t), mp->msg_name,
885 			    MIN(alen, mp->msg_namelen));
886 			if (error)
887 				goto out;
888 #ifdef KTRACE
889 			if (KTRPOINT(p, KTR_STRUCT))
890 				ktrsockaddr(p, mtod(from, caddr_t), alen);
891 #endif
892 		}
893 		mp->msg_namelen = alen;
894 		if (namelenp &&
895 		    (error = copyout(&alen, namelenp, sizeof(alen)))) {
896 			goto out;
897 		}
898 	}
899 	if (mp->msg_control) {
900 		len = mp->msg_controllen;
901 		if (len <= 0 || control == NULL)
902 			len = 0;
903 		else {
904 			struct mbuf *m = control;
905 			caddr_t cp = mp->msg_control;
906 
907 			do {
908 				i = m->m_len;
909 				if (len < i) {
910 					mp->msg_flags |= MSG_CTRUNC;
911 					i = len;
912 				}
913 				error = copyout(mtod(m, caddr_t), cp, i);
914 #ifdef KTRACE
915 				if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) {
916 					/* msg_flags potentially incorrect */
917 					int rmsgflags = mp->msg_flags;
918 
919 					mp->msg_flags = kmsgflags;
920 					ktrcmsghdr(p, mtod(m, char *), i);
921 					mp->msg_flags = rmsgflags;
922 				}
923 #endif
924 				if (m->m_next)
925 					i = ALIGN(i);
926 				cp += i;
927 				len -= i;
928 				if (error != 0 || len <= 0)
929 					break;
930 			} while ((m = m->m_next) != NULL);
931 			len = cp - (caddr_t)mp->msg_control;
932 		}
933 		mp->msg_controllen = len;
934 	}
935 	if (!error) {
936 		mtx_enter(&fp->f_mtx);
937 		fp->f_rxfer++;
938 		fp->f_rbytes += *retsize;
939 		mtx_leave(&fp->f_mtx);
940 	}
941 out:
942 	FRELE(fp, p);
943 	m_freem(from);
944 	m_freem(control);
945 	return (error);
946 }
947 
948 int
949 sys_shutdown(struct proc *p, void *v, register_t *retval)
950 {
951 	struct sys_shutdown_args /* {
952 		syscallarg(int) s;
953 		syscallarg(int) how;
954 	} */ *uap = v;
955 	struct file *fp;
956 	int error;
957 
958 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
959 		return (error);
960 	error = soshutdown(fp->f_data, SCARG(uap, how));
961 	FRELE(fp, p);
962 	return (error);
963 }
964 
965 int
966 sys_setsockopt(struct proc *p, void *v, register_t *retval)
967 {
968 	struct sys_setsockopt_args /* {
969 		syscallarg(int) s;
970 		syscallarg(int) level;
971 		syscallarg(int) name;
972 		syscallarg(const void *) val;
973 		syscallarg(socklen_t) valsize;
974 	} */ *uap = v;
975 	struct file *fp;
976 	struct mbuf *m = NULL;
977 	struct socket *so;
978 	int error;
979 
980 
981 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
982 		return (error);
983 	error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
984 	if (error)
985 		goto bad;
986 	if (SCARG(uap, valsize) > MCLBYTES) {
987 		error = EINVAL;
988 		goto bad;
989 	}
990 	if (SCARG(uap, val)) {
991 		m = m_get(M_WAIT, MT_SOOPTS);
992 		if (SCARG(uap, valsize) > MLEN) {
993 			MCLGET(m, M_DONTWAIT);
994 			if ((m->m_flags & M_EXT) == 0) {
995 				error = ENOBUFS;
996 				goto bad;
997 			}
998 		}
999 		if (m == NULL) {
1000 			error = ENOBUFS;
1001 			goto bad;
1002 		}
1003 		error = copyin(SCARG(uap, val), mtod(m, caddr_t),
1004 		    SCARG(uap, valsize));
1005 		if (error) {
1006 			goto bad;
1007 		}
1008 		m->m_len = SCARG(uap, valsize);
1009 	}
1010 	so = fp->f_data;
1011 	solock(so);
1012 	error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1013 	sounlock(so);
1014 bad:
1015 	m_freem(m);
1016 	FRELE(fp, p);
1017 	return (error);
1018 }
1019 
1020 int
1021 sys_getsockopt(struct proc *p, void *v, register_t *retval)
1022 {
1023 	struct sys_getsockopt_args /* {
1024 		syscallarg(int) s;
1025 		syscallarg(int) level;
1026 		syscallarg(int) name;
1027 		syscallarg(void *) val;
1028 		syscallarg(socklen_t *) avalsize;
1029 	} */ *uap = v;
1030 	struct file *fp;
1031 	struct mbuf *m = NULL;
1032 	socklen_t valsize;
1033 	struct socket *so;
1034 	int error;
1035 
1036 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1037 		return (error);
1038 	error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
1039 	if (error)
1040 		goto out;
1041 	if (SCARG(uap, val)) {
1042 		error = copyin(SCARG(uap, avalsize),
1043 		    &valsize, sizeof (valsize));
1044 		if (error)
1045 			goto out;
1046 	} else
1047 		valsize = 0;
1048 	m = m_get(M_WAIT, MT_SOOPTS);
1049 	so = fp->f_data;
1050 	solock(so);
1051 	error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1052 	sounlock(so);
1053 	if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
1054 		if (valsize > m->m_len)
1055 			valsize = m->m_len;
1056 		error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1057 		if (error == 0)
1058 			error = copyout(&valsize,
1059 			    SCARG(uap, avalsize), sizeof (valsize));
1060 	}
1061 	m_free(m);
1062 out:
1063 	FRELE(fp, p);
1064 	return (error);
1065 }
1066 
1067 /*
1068  * Get socket name.
1069  */
1070 int
1071 sys_getsockname(struct proc *p, void *v, register_t *retval)
1072 {
1073 	struct sys_getsockname_args /* {
1074 		syscallarg(int) fdes;
1075 		syscallarg(struct sockaddr *) asa;
1076 		syscallarg(socklen_t *) alen;
1077 	} */ *uap = v;
1078 	struct file *fp;
1079 	struct socket *so;
1080 	struct mbuf *m = NULL;
1081 	socklen_t len;
1082 	int error;
1083 
1084 	if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1085 		return (error);
1086 	error = copyin(SCARG(uap, alen), &len, sizeof (len));
1087 	if (error)
1088 		goto bad;
1089 	so = fp->f_data;
1090 	if (so->so_state & SS_YP) {
1091 		error = ENOTSOCK;
1092 		goto bad;
1093 	}
1094 	error = pledge_socket(p, -1, so->so_state);
1095 	if (error)
1096 		goto bad;
1097 	if (so->so_state & SS_YP) {
1098 		error = ENOTSOCK;
1099 		goto bad;
1100 	}
1101 	m = m_getclr(M_WAIT, MT_SONAME);
1102 	solock(so);
1103 	error = pru_sockaddr(so, m);
1104 	sounlock(so);
1105 	if (error)
1106 		goto bad;
1107 	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1108 bad:
1109 	FRELE(fp, p);
1110 	m_freem(m);
1111 	return (error);
1112 }
1113 
1114 /*
1115  * Get name of peer for connected socket.
1116  */
1117 int
1118 sys_getpeername(struct proc *p, void *v, register_t *retval)
1119 {
1120 	struct sys_getpeername_args /* {
1121 		syscallarg(int) fdes;
1122 		syscallarg(struct sockaddr *) asa;
1123 		syscallarg(socklen_t *) alen;
1124 	} */ *uap = v;
1125 	struct file *fp;
1126 	struct socket *so;
1127 	struct mbuf *m = NULL;
1128 	socklen_t len;
1129 	int error;
1130 
1131 	if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1132 		return (error);
1133 	so = fp->f_data;
1134 	error = pledge_socket(p, -1, so->so_state);
1135 	if (error)
1136 		goto bad;
1137 	if (so->so_state & SS_YP) {
1138 		error = ENOTSOCK;
1139 		goto bad;
1140 	}
1141 	if ((so->so_state & SS_ISCONNECTED) == 0) {
1142 		error = ENOTCONN;
1143 		goto bad;
1144 	}
1145 	error = copyin(SCARG(uap, alen), &len, sizeof (len));
1146 	if (error)
1147 		goto bad;
1148 	m = m_getclr(M_WAIT, MT_SONAME);
1149 	solock(so);
1150 	error = pru_peeraddr(so, m);
1151 	sounlock(so);
1152 	if (error)
1153 		goto bad;
1154 	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1155 bad:
1156 	FRELE(fp, p);
1157 	m_freem(m);
1158 	return (error);
1159 }
1160 
1161 int
1162 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1163 {
1164 	struct sockaddr *sa;
1165 	struct mbuf *m;
1166 	int error;
1167 
1168 	/*
1169 	 * We can't allow socket names > UCHAR_MAX in length, since that
1170 	 * will overflow sa_len. Also, control data more than MCLBYTES in
1171 	 * length is just too much.
1172 	 * Memory for sa_len and sa_family must exist.
1173 	 */
1174 	if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1175 	    (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1176 		return (EINVAL);
1177 
1178 	/* Allocate an mbuf to hold the arguments. */
1179 	m = m_get(M_WAIT, type);
1180 	if (buflen > MLEN) {
1181 		MCLGET(m, M_WAITOK);
1182 		if ((m->m_flags & M_EXT) == 0) {
1183 			m_free(m);
1184 			return ENOBUFS;
1185 		}
1186 	}
1187 	m->m_len = buflen;
1188 	error = copyin(buf, mtod(m, caddr_t), buflen);
1189 	if (error) {
1190 		(void) m_free(m);
1191 		return (error);
1192 	}
1193 	*mp = m;
1194 	if (type == MT_SONAME) {
1195 		sa = mtod(m, struct sockaddr *);
1196 		sa->sa_len = buflen;
1197 	}
1198 	return (0);
1199 }
1200 
1201 int
1202 getsock(struct proc *p, int fdes, struct file **fpp)
1203 {
1204 	struct file *fp;
1205 
1206 	fp = fd_getfile(p->p_fd, fdes);
1207 	if (fp == NULL)
1208 		return (EBADF);
1209 	if (fp->f_type != DTYPE_SOCKET) {
1210 		FRELE(fp, p);
1211 		return (ENOTSOCK);
1212 	}
1213 	*fpp = fp;
1214 
1215 	return (0);
1216 }
1217 
1218 int
1219 sys_setrtable(struct proc *p, void *v, register_t *retval)
1220 {
1221 	struct sys_setrtable_args /* {
1222 		syscallarg(int) rtableid;
1223 	} */ *uap = v;
1224 	u_int ps_rtableid = p->p_p->ps_rtableid;
1225 	int rtableid, error;
1226 
1227 	rtableid = SCARG(uap, rtableid);
1228 
1229 	if (ps_rtableid == rtableid)
1230 		return (0);
1231 	if (ps_rtableid != 0 && (error = suser(p)) != 0)
1232 		return (error);
1233 	if (rtableid < 0 || !rtable_exists((u_int)rtableid))
1234 		return (EINVAL);
1235 
1236 	p->p_p->ps_rtableid = (u_int)rtableid;
1237 	return (0);
1238 }
1239 
1240 int
1241 sys_getrtable(struct proc *p, void *v, register_t *retval)
1242 {
1243 	*retval = (int)p->p_p->ps_rtableid;
1244 	return (0);
1245 }
1246 
1247 int
1248 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
1249     socklen_t buflen, socklen_t *outlen)
1250 {
1251 	int error;
1252 	socklen_t namelen = name->m_len;
1253 
1254 	/* SHOULD COPY OUT A CHAIN HERE */
1255 	error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
1256 	if (error == 0) {
1257 #ifdef KTRACE
1258 		if (KTRPOINT(p, KTR_STRUCT))
1259 			ktrsockaddr(p, mtod(name, caddr_t), namelen);
1260 #endif
1261 		error = copyout(&namelen, outlen, sizeof(*outlen));
1262 	}
1263 
1264 	return (error);
1265 }
1266 
1267 #ifndef SMALL_KERNEL
1268 int
1269 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1270 {
1271 	struct sockaddr *sa;
1272 	struct mbuf *m;
1273 
1274 	/*
1275 	 * We can't allow socket names > UCHAR_MAX in length, since that
1276 	 * will overflow sa_len. Also, control data more than MCLBYTES in
1277 	 * length is just too much.
1278 	 * Memory for sa_len and sa_family must exist.
1279 	 */
1280 	if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1281 	    (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1282 		return (EINVAL);
1283 
1284 	/* Allocate an mbuf to hold the arguments. */
1285 	m = m_get(M_WAIT, type);
1286 	if (buflen > MLEN) {
1287 		MCLGET(m, M_WAITOK);
1288 		if ((m->m_flags & M_EXT) == 0) {
1289 			m_free(m);
1290 			return ENOBUFS;
1291 		}
1292 	}
1293 	m->m_len = buflen;
1294 	bcopy(buf, mtod(m, caddr_t), buflen);
1295 	*mp = m;
1296 	if (type == MT_SONAME) {
1297 		sa = mtod(m, struct sockaddr *);
1298 		sa->sa_len = buflen;
1299 	}
1300 	return (0);
1301 }
1302 #endif /* SMALL_KERNEL */
1303 
1304 int
1305 sys_ypconnect(struct proc *p, void *v, register_t *retval)
1306 {
1307 #ifdef SMALL_KERNEL
1308 	return EAFNOSUPPORT;
1309 #else
1310 	struct sys_ypconnect_args /* {
1311 		syscallarg(int) type;
1312 	} */ *uap = v;
1313 	struct nameidata nid;
1314 	struct vattr va;
1315 	struct uio uio;
1316 	struct iovec iov;
1317 	struct filedesc *fdp = p->p_fd;
1318 	struct socket *so;
1319 	struct file *fp;
1320 	struct flock fl;
1321 	char *name;
1322 	struct mbuf *nam = NULL;
1323 	int error, fd = -1;
1324 	struct ypbinding {
1325 		u_short ypbind_port;
1326 		int status;
1327 		in_addr_t in;
1328 		u_short ypserv_udp_port;
1329 		u_short garbage;
1330 		u_short ypserv_tcp_port;
1331 	} __packed data;
1332 	struct sockaddr_in ypsin;
1333 
1334 	if (!domainname[0] || strchr(domainname, '/'))
1335 		return EAFNOSUPPORT;
1336 
1337 	switch (SCARG(uap, type)) {
1338 	case SOCK_STREAM:
1339 	case SOCK_DGRAM:
1340 		break;
1341 	default:
1342 		return EAFNOSUPPORT;
1343 	}
1344 
1345 	if (p->p_p->ps_flags & PS_CHROOT)
1346 		return EACCES;
1347 	name = pool_get(&namei_pool, PR_WAITOK);
1348 	snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname);
1349 	NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p);
1350 	nid.ni_pledge = PLEDGE_RPATH;
1351 
1352 	KERNEL_LOCK();
1353 	error = namei(&nid);
1354 	pool_put(&namei_pool, name);
1355 	if (error)
1356 		goto out;
1357 	error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
1358 	if (error)
1359 		goto verror;
1360 	if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) {
1361 		error = EFTYPE;
1362 		goto verror;
1363 	}
1364 
1365 	/*
1366 	 * Check that a lock is held on the file (hopefully by ypbind),
1367 	 * otherwise the file might be old
1368 	 */
1369 	fl.l_start = 0;
1370 	fl.l_len = 0;
1371 	fl.l_pid = 0;
1372 	fl.l_type = F_WRLCK;
1373 	fl.l_whence = SEEK_SET;
1374 	error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX);
1375 	if (error)
1376 		goto verror;
1377 	if (fl.l_type == F_UNLCK) {
1378 		error = EOWNERDEAD;
1379 		goto verror;
1380 	}
1381 
1382 	iov.iov_base = &data;
1383 	iov.iov_len = sizeof data;
1384 	uio.uio_iov = &iov;
1385 	uio.uio_iovcnt = 1;
1386 	uio.uio_offset = 0;
1387 	uio.uio_resid = iov.iov_len;
1388 	uio.uio_segflg = UIO_SYSSPACE;
1389 	uio.uio_rw = UIO_READ;
1390 	uio.uio_procp = p;
1391 
1392 	error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred);
1393 	if (error) {
1394 verror:
1395 		if (nid.ni_vp)
1396 			vput(nid.ni_vp);
1397 out:
1398 		KERNEL_UNLOCK();
1399 		return (error);
1400 	}
1401 	vput(nid.ni_vp);
1402 	KERNEL_UNLOCK();
1403 
1404 	bzero(&ypsin, sizeof ypsin);
1405 	ypsin.sin_len = sizeof ypsin;
1406 	ypsin.sin_family = AF_INET;
1407 	if (SCARG(uap, type) == SOCK_STREAM)
1408 		ypsin.sin_port = data.ypserv_tcp_port;
1409 	else
1410 		ypsin.sin_port = data.ypserv_udp_port;
1411 	if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20)
1412 		return EPERM;
1413 	memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr);
1414 
1415 	error = socreate(AF_INET, &so, SCARG(uap, type), 0);
1416 	if (error)
1417 		return (error);
1418 
1419 	error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME);
1420 	if (error) {
1421 		soclose(so, MSG_DONTWAIT);
1422 		return (error);
1423 	}
1424 
1425 #ifdef KTRACE
1426 	if (KTRPOINT(p, KTR_STRUCT))
1427 		ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in));
1428 #endif
1429 	solock(so);
1430 	error = soconnect(so, nam);
1431 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1432 		error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
1433 		    "netcon2", INFSLP);
1434 		if (error)
1435 			break;
1436 	}
1437 	m_freem(nam);
1438 	so->so_state |= SS_YP;		/* impose some restrictions */
1439 	sounlock(so);
1440 	if (error) {
1441 		soclose(so, MSG_DONTWAIT);
1442 		return (error);
1443 	}
1444 
1445 	fdplock(fdp);
1446 	error = falloc(p, &fp, &fd);
1447 	if (error) {
1448 		fdpunlock(fdp);
1449 		soclose(so, MSG_DONTWAIT);
1450 		return (error);
1451 	}
1452 
1453 	fp->f_flag = FREAD | FWRITE | FNONBLOCK;
1454 	fp->f_type = DTYPE_SOCKET;
1455 	fp->f_ops = &socketops;
1456 	fp->f_data = so;
1457 	fdinsert(fdp, fd, UF_EXCLOSE, fp);
1458 	fdpunlock(fdp);
1459 	FRELE(fp, p);
1460 	*retval = fd;
1461 	return (error);
1462 #endif /* SMALL_KERNEL */
1463 }
1464