xref: /openbsd/sys/kern/uipc_syscalls.c (revision 2de7505c)
1 /*	$OpenBSD: uipc_syscalls.c,v 1.220 2024/11/05 09:14:19 claudio 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
sys_socket(struct proc * p,void * v,register_t * retval)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
isdnssocket(struct socket * so)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
dns_portcheck(struct proc * p,struct socket * so,void * nam,size_t namelen)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
sys_bind(struct proc * p,void * v,register_t * retval)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_shared(so);
189 	error = sobind(so, nam, p);
190 	sounlock_shared(so);
191 	m_freem(nam);
192 out:
193 	FRELE(fp, p);
194 	return (error);
195 }
196 
197 int
sys_listen(struct proc * p,void * v,register_t * retval)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
sys_accept(struct proc * p,void * v,register_t * retval)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
sys_accept4(struct proc * p,void * v,register_t * retval)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
doaccept(struct proc * p,int sock,struct sockaddr * name,socklen_t * anamelen,int flags,register_t * retval)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 		    "netacc", 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_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
sys_connect(struct proc * p,void * v,register_t * retval)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_shared(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 		    "netcon", 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_shared(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
sys_socketpair(struct proc * p,void * v,register_t * retval)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
sys_sendto(struct proc * p,void * v,register_t * retval)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
sys_sendmsg(struct proc * p,void * v,register_t * retval)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
sys_sendmmsg(struct proc * p,void * v,register_t * retval)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
sendit(struct proc * p,int s,struct msghdr * mp,int flags,register_t * retsize)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 			ptsignal(p, SIGPIPE, STHREAD);
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
sys_recvfrom(struct proc * p,void * v,register_t * retval)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
sys_recvmsg(struct proc * p,void * v,register_t * retval)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
sys_recvmmsg(struct proc * p,void * v,register_t * retval)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
recvit(struct proc * p,int s,struct msghdr * mp,caddr_t namelenp,register_t * retsize)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
sys_shutdown(struct proc * p,void * v,register_t * retval)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
sys_setsockopt(struct proc * p,void * v,register_t * retval)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_WAIT);
1215 			if ((m->m_flags & M_EXT) == 0) {
1216 				error = ENOBUFS;
1217 				goto bad;
1218 			}
1219 		}
1220 		error = copyin(SCARG(uap, val), mtod(m, caddr_t),
1221 		    SCARG(uap, valsize));
1222 		if (error) {
1223 			goto bad;
1224 		}
1225 		m->m_len = SCARG(uap, valsize);
1226 	}
1227 	so = fp->f_data;
1228 	error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1229 bad:
1230 	m_freem(m);
1231 	FRELE(fp, p);
1232 	return (error);
1233 }
1234 
1235 int
sys_getsockopt(struct proc * p,void * v,register_t * retval)1236 sys_getsockopt(struct proc *p, void *v, register_t *retval)
1237 {
1238 	struct sys_getsockopt_args /* {
1239 		syscallarg(int) s;
1240 		syscallarg(int) level;
1241 		syscallarg(int) name;
1242 		syscallarg(void *) val;
1243 		syscallarg(socklen_t *) avalsize;
1244 	} */ *uap = v;
1245 	struct file *fp;
1246 	struct mbuf *m = NULL;
1247 	socklen_t valsize;
1248 	struct socket *so;
1249 	int error;
1250 
1251 	if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1252 		return (error);
1253 	error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
1254 	if (error)
1255 		goto out;
1256 	if (SCARG(uap, val)) {
1257 		error = copyin(SCARG(uap, avalsize),
1258 		    &valsize, sizeof (valsize));
1259 		if (error)
1260 			goto out;
1261 	} else
1262 		valsize = 0;
1263 	m = m_get(M_WAIT, MT_SOOPTS);
1264 	so = fp->f_data;
1265 	error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1266 	if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
1267 		if (valsize > m->m_len)
1268 			valsize = m->m_len;
1269 		error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1270 		if (error == 0)
1271 			error = copyout(&valsize,
1272 			    SCARG(uap, avalsize), sizeof (valsize));
1273 	}
1274 	m_free(m);
1275 out:
1276 	FRELE(fp, p);
1277 	return (error);
1278 }
1279 
1280 /*
1281  * Get socket name.
1282  */
1283 int
sys_getsockname(struct proc * p,void * v,register_t * retval)1284 sys_getsockname(struct proc *p, void *v, register_t *retval)
1285 {
1286 	struct sys_getsockname_args /* {
1287 		syscallarg(int) fdes;
1288 		syscallarg(struct sockaddr *) asa;
1289 		syscallarg(socklen_t *) alen;
1290 	} */ *uap = v;
1291 	struct file *fp;
1292 	struct socket *so;
1293 	struct mbuf *m = NULL;
1294 	socklen_t len;
1295 	int error;
1296 
1297 	if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1298 		return (error);
1299 	error = copyin(SCARG(uap, alen), &len, sizeof (len));
1300 	if (error)
1301 		goto bad;
1302 	so = fp->f_data;
1303 	if (so->so_state & SS_YP) {
1304 		error = ENOTSOCK;
1305 		goto bad;
1306 	}
1307 	error = pledge_socket(p, -1, so->so_state);
1308 	if (error)
1309 		goto bad;
1310 	if (so->so_state & SS_YP) {
1311 		error = ENOTSOCK;
1312 		goto bad;
1313 	}
1314 	m = m_getclr(M_WAIT, MT_SONAME);
1315 	solock_shared(so);
1316 	error = pru_sockaddr(so, m);
1317 	sounlock_shared(so);
1318 	if (error)
1319 		goto bad;
1320 	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1321 bad:
1322 	FRELE(fp, p);
1323 	m_freem(m);
1324 	return (error);
1325 }
1326 
1327 /*
1328  * Get name of peer for connected socket.
1329  */
1330 int
sys_getpeername(struct proc * p,void * v,register_t * retval)1331 sys_getpeername(struct proc *p, void *v, register_t *retval)
1332 {
1333 	struct sys_getpeername_args /* {
1334 		syscallarg(int) fdes;
1335 		syscallarg(struct sockaddr *) asa;
1336 		syscallarg(socklen_t *) alen;
1337 	} */ *uap = v;
1338 	struct file *fp;
1339 	struct socket *so;
1340 	struct mbuf *m = NULL;
1341 	socklen_t len;
1342 	int error;
1343 
1344 	if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1345 		return (error);
1346 	so = fp->f_data;
1347 	error = pledge_socket(p, -1, so->so_state);
1348 	if (error)
1349 		goto bad;
1350 	if (so->so_state & SS_YP) {
1351 		error = ENOTSOCK;
1352 		goto bad;
1353 	}
1354 	if ((so->so_state & SS_ISCONNECTED) == 0) {
1355 		error = ENOTCONN;
1356 		goto bad;
1357 	}
1358 	error = copyin(SCARG(uap, alen), &len, sizeof (len));
1359 	if (error)
1360 		goto bad;
1361 	m = m_getclr(M_WAIT, MT_SONAME);
1362 	solock_shared(so);
1363 	error = pru_peeraddr(so, m);
1364 	sounlock_shared(so);
1365 	if (error)
1366 		goto bad;
1367 	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1368 bad:
1369 	FRELE(fp, p);
1370 	m_freem(m);
1371 	return (error);
1372 }
1373 
1374 int
sockargs(struct mbuf ** mp,const void * buf,size_t buflen,int type)1375 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1376 {
1377 	struct sockaddr *sa;
1378 	struct mbuf *m;
1379 	int error;
1380 
1381 	/*
1382 	 * We can't allow socket names > UCHAR_MAX in length, since that
1383 	 * will overflow sa_len. Also, control data more than MCLBYTES in
1384 	 * length is just too much.
1385 	 * Memory for sa_len and sa_family must exist.
1386 	 */
1387 	if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1388 	    (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1389 		return (EINVAL);
1390 
1391 	/* Allocate an mbuf to hold the arguments. */
1392 	m = m_get(M_WAIT, type);
1393 	if (buflen > MLEN) {
1394 		MCLGET(m, M_WAITOK);
1395 		if ((m->m_flags & M_EXT) == 0) {
1396 			m_free(m);
1397 			return ENOBUFS;
1398 		}
1399 	}
1400 	m->m_len = buflen;
1401 	error = copyin(buf, mtod(m, caddr_t), buflen);
1402 	if (error) {
1403 		(void) m_free(m);
1404 		return (error);
1405 	}
1406 	*mp = m;
1407 	if (type == MT_SONAME) {
1408 		sa = mtod(m, struct sockaddr *);
1409 		sa->sa_len = buflen;
1410 	}
1411 	return (0);
1412 }
1413 
1414 int
getsock(struct proc * p,int fdes,struct file ** fpp)1415 getsock(struct proc *p, int fdes, struct file **fpp)
1416 {
1417 	struct file *fp;
1418 
1419 	fp = fd_getfile(p->p_fd, fdes);
1420 	if (fp == NULL)
1421 		return (EBADF);
1422 	if (fp->f_type != DTYPE_SOCKET) {
1423 		FRELE(fp, p);
1424 		return (ENOTSOCK);
1425 	}
1426 	*fpp = fp;
1427 
1428 	return (0);
1429 }
1430 
1431 int
sys_setrtable(struct proc * p,void * v,register_t * retval)1432 sys_setrtable(struct proc *p, void *v, register_t *retval)
1433 {
1434 	struct sys_setrtable_args /* {
1435 		syscallarg(int) rtableid;
1436 	} */ *uap = v;
1437 	u_int ps_rtableid = p->p_p->ps_rtableid;
1438 	int rtableid, error;
1439 
1440 	rtableid = SCARG(uap, rtableid);
1441 
1442 	if (ps_rtableid == rtableid)
1443 		return (0);
1444 	if (ps_rtableid != 0 && (error = suser(p)) != 0)
1445 		return (error);
1446 	if (rtableid < 0 || !rtable_exists((u_int)rtableid))
1447 		return (EINVAL);
1448 
1449 	p->p_p->ps_rtableid = (u_int)rtableid;
1450 	return (0);
1451 }
1452 
1453 int
sys_getrtable(struct proc * p,void * v,register_t * retval)1454 sys_getrtable(struct proc *p, void *v, register_t *retval)
1455 {
1456 	*retval = (int)p->p_p->ps_rtableid;
1457 	return (0);
1458 }
1459 
1460 int
copyaddrout(struct proc * p,struct mbuf * name,struct sockaddr * sa,socklen_t buflen,socklen_t * outlen)1461 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
1462     socklen_t buflen, socklen_t *outlen)
1463 {
1464 	int error;
1465 	socklen_t namelen = name->m_len;
1466 
1467 	/* SHOULD COPY OUT A CHAIN HERE */
1468 	error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
1469 	if (error == 0) {
1470 #ifdef KTRACE
1471 		if (KTRPOINT(p, KTR_STRUCT))
1472 			ktrsockaddr(p, mtod(name, caddr_t), namelen);
1473 #endif
1474 		error = copyout(&namelen, outlen, sizeof(*outlen));
1475 	}
1476 
1477 	return (error);
1478 }
1479 
1480 #ifndef SMALL_KERNEL
1481 int
ypsockargs(struct mbuf ** mp,const void * buf,size_t buflen,int type)1482 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1483 {
1484 	struct sockaddr *sa;
1485 	struct mbuf *m;
1486 
1487 	/*
1488 	 * We can't allow socket names > UCHAR_MAX in length, since that
1489 	 * will overflow sa_len. Also, control data more than MCLBYTES in
1490 	 * length is just too much.
1491 	 * Memory for sa_len and sa_family must exist.
1492 	 */
1493 	if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1494 	    (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1495 		return (EINVAL);
1496 
1497 	/* Allocate an mbuf to hold the arguments. */
1498 	m = m_get(M_WAIT, type);
1499 	if (buflen > MLEN) {
1500 		MCLGET(m, M_WAITOK);
1501 		if ((m->m_flags & M_EXT) == 0) {
1502 			m_free(m);
1503 			return ENOBUFS;
1504 		}
1505 	}
1506 	m->m_len = buflen;
1507 	bcopy(buf, mtod(m, caddr_t), buflen);
1508 	*mp = m;
1509 	if (type == MT_SONAME) {
1510 		sa = mtod(m, struct sockaddr *);
1511 		sa->sa_len = buflen;
1512 	}
1513 	return (0);
1514 }
1515 #endif /* SMALL_KERNEL */
1516 
1517 int
sys_ypconnect(struct proc * p,void * v,register_t * retval)1518 sys_ypconnect(struct proc *p, void *v, register_t *retval)
1519 {
1520 #ifdef SMALL_KERNEL
1521 	return EAFNOSUPPORT;
1522 #else
1523 	struct sys_ypconnect_args /* {
1524 		syscallarg(int) type;
1525 	} */ *uap = v;
1526 	struct nameidata nid;
1527 	struct vattr va;
1528 	struct uio uio;
1529 	struct iovec iov;
1530 	struct filedesc *fdp = p->p_fd;
1531 	struct socket *so;
1532 	struct file *fp;
1533 	struct flock fl;
1534 	char *name;
1535 	struct mbuf *nam = NULL;
1536 	int error, fd = -1;
1537 	struct ypbinding {
1538 		u_short ypbind_port;
1539 		int status;
1540 		in_addr_t in;
1541 		u_short ypserv_udp_port;
1542 		u_short garbage;
1543 		u_short ypserv_tcp_port;
1544 	} __packed data;
1545 	struct sockaddr_in ypsin;
1546 
1547 	if (!domainname[0] || strchr(domainname, '/'))
1548 		return EAFNOSUPPORT;
1549 
1550 	switch (SCARG(uap, type)) {
1551 	case SOCK_STREAM:
1552 	case SOCK_DGRAM:
1553 		break;
1554 	default:
1555 		return EAFNOSUPPORT;
1556 	}
1557 
1558 	if (p->p_p->ps_flags & PS_CHROOT)
1559 		return EACCES;
1560 	KERNEL_LOCK();
1561 	name = pool_get(&namei_pool, PR_WAITOK);
1562 	snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname);
1563 	NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p);
1564 	nid.ni_pledge = PLEDGE_RPATH;
1565 
1566 	error = namei(&nid);
1567 	pool_put(&namei_pool, name);
1568 	if (error)
1569 		goto out;
1570 	error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
1571 	if (error)
1572 		goto verror;
1573 	if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) {
1574 		error = EFTYPE;
1575 		goto verror;
1576 	}
1577 
1578 	/*
1579 	 * Check that a lock is held on the file (hopefully by ypbind),
1580 	 * otherwise the file might be old
1581 	 */
1582 	fl.l_start = 0;
1583 	fl.l_len = 0;
1584 	fl.l_pid = 0;
1585 	fl.l_type = F_WRLCK;
1586 	fl.l_whence = SEEK_SET;
1587 	error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX);
1588 	if (error)
1589 		goto verror;
1590 	if (fl.l_type == F_UNLCK) {
1591 		error = EOWNERDEAD;
1592 		goto verror;
1593 	}
1594 
1595 	iov.iov_base = &data;
1596 	iov.iov_len = sizeof data;
1597 	uio.uio_iov = &iov;
1598 	uio.uio_iovcnt = 1;
1599 	uio.uio_offset = 0;
1600 	uio.uio_resid = iov.iov_len;
1601 	uio.uio_segflg = UIO_SYSSPACE;
1602 	uio.uio_rw = UIO_READ;
1603 	uio.uio_procp = p;
1604 
1605 	error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred);
1606 	if (error) {
1607 verror:
1608 		if (nid.ni_vp)
1609 			vput(nid.ni_vp);
1610 out:
1611 		KERNEL_UNLOCK();
1612 		return (error);
1613 	}
1614 	vput(nid.ni_vp);
1615 	KERNEL_UNLOCK();
1616 
1617 	bzero(&ypsin, sizeof ypsin);
1618 	ypsin.sin_len = sizeof ypsin;
1619 	ypsin.sin_family = AF_INET;
1620 	if (SCARG(uap, type) == SOCK_STREAM)
1621 		ypsin.sin_port = data.ypserv_tcp_port;
1622 	else
1623 		ypsin.sin_port = data.ypserv_udp_port;
1624 	if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20)
1625 		return EPERM;
1626 	memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr);
1627 
1628 	error = socreate(AF_INET, &so, SCARG(uap, type), 0);
1629 	if (error)
1630 		return (error);
1631 
1632 	error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME);
1633 	if (error) {
1634 		soclose(so, MSG_DONTWAIT);
1635 		return (error);
1636 	}
1637 
1638 #ifdef KTRACE
1639 	if (KTRPOINT(p, KTR_STRUCT))
1640 		ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in));
1641 #endif
1642 	solock(so);
1643 
1644 	/* Secure YP maps require reserved ports */
1645 	if (suser(p) == 0)
1646 		sotoinpcb(so)->inp_flags |= INP_LOWPORT;
1647 
1648 	error = soconnect(so, nam);
1649 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1650 		error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
1651 		    "ypcon", INFSLP);
1652 		if (error)
1653 			break;
1654 	}
1655 	m_freem(nam);
1656 	so->so_state |= SS_YP;		/* impose some restrictions */
1657 	sounlock(so);
1658 	if (error) {
1659 		soclose(so, MSG_DONTWAIT);
1660 		return (error);
1661 	}
1662 
1663 	fdplock(fdp);
1664 	error = falloc(p, &fp, &fd);
1665 	if (error) {
1666 		fdpunlock(fdp);
1667 		soclose(so, MSG_DONTWAIT);
1668 		return (error);
1669 	}
1670 
1671 	fp->f_flag = FREAD | FWRITE | FNONBLOCK;
1672 	fp->f_type = DTYPE_SOCKET;
1673 	fp->f_ops = &socketops;
1674 	fp->f_data = so;
1675 	fdinsert(fdp, fd, UF_EXCLOSE, fp);
1676 	fdpunlock(fdp);
1677 	FRELE(fp, p);
1678 	*retval = fd;
1679 	return (error);
1680 #endif /* SMALL_KERNEL */
1681 }
1682