xref: /netbsd-src/sys/kern/uipc_syscalls.c (revision 93f9db1b75d415b78f73ed629beeb86235153473)
1 /*	$NetBSD: uipc_syscalls.c,v 1.38 1998/08/04 19:48:35 kleink Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1989, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)uipc_syscalls.c	8.6 (Berkeley) 2/14/95
36  */
37 
38 #include "opt_ktrace.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/filedesc.h>
43 #include <sys/proc.h>
44 #include <sys/file.h>
45 #include <sys/buf.h>
46 #include <sys/malloc.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/un.h>
53 #ifdef KTRACE
54 #include <sys/ktrace.h>
55 #endif
56 
57 #include <sys/mount.h>
58 #include <sys/syscallargs.h>
59 
60 /*
61  * System call interface to the socket abstraction.
62  */
63 extern	struct fileops socketops;
64 
65 int
66 sys_socket(p, v, retval)
67 	struct proc *p;
68 	void *v;
69 	register_t *retval;
70 {
71 	register struct sys_socket_args /* {
72 		syscallarg(int) domain;
73 		syscallarg(int) type;
74 		syscallarg(int) protocol;
75 	} */ *uap = v;
76 	struct filedesc *fdp = p->p_fd;
77 	struct socket *so;
78 	struct file *fp;
79 	int fd, error;
80 
81 	if ((error = falloc(p, &fp, &fd)) != 0)
82 		return (error);
83 	fp->f_flag = FREAD|FWRITE;
84 	fp->f_type = DTYPE_SOCKET;
85 	fp->f_ops = &socketops;
86 	error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
87 			 SCARG(uap, protocol));
88 	if (error) {
89 		fdp->fd_ofiles[fd] = 0;
90 		ffree(fp);
91 	} else {
92 		fp->f_data = (caddr_t)so;
93 		*retval = fd;
94 	}
95 	return (error);
96 }
97 
98 /* ARGSUSED */
99 int
100 sys_bind(p, v, retval)
101 	struct proc *p;
102 	void *v;
103 	register_t *retval;
104 {
105 	register struct sys_bind_args /* {
106 		syscallarg(int) s;
107 		syscallarg(const struct sockaddr *) name;
108 		syscallarg(int) namelen;
109 	} */ *uap = v;
110 	struct file *fp;
111 	struct mbuf *nam;
112 	int error;
113 
114 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
115 		return (error);
116 	error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
117 	    MT_SONAME);
118 	if (error)
119 		return (error);
120 	error = sobind((struct socket *)fp->f_data, nam);
121 	m_freem(nam);
122 	return (error);
123 }
124 
125 /* ARGSUSED */
126 int
127 sys_listen(p, v, retval)
128 	struct proc *p;
129 	void *v;
130 	register_t *retval;
131 {
132 	register struct sys_listen_args /* {
133 		syscallarg(int) s;
134 		syscallarg(int) backlog;
135 	} */ *uap = v;
136 	struct file *fp;
137 	int error;
138 
139 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
140 		return (error);
141 	return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog)));
142 }
143 
144 int
145 sys_accept(p, v, retval)
146 	struct proc *p;
147 	void *v;
148 	register_t *retval;
149 {
150 	register struct sys_accept_args /* {
151 		syscallarg(int) s;
152 		syscallarg(struct sockaddr *) name;
153 		syscallarg(int *) anamelen;
154 	} */ *uap = v;
155 	struct file *fp;
156 	struct mbuf *nam;
157 	int namelen, error, s, tmpfd;
158 	register struct socket *so;
159 
160 	if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
161 	    (caddr_t)&namelen, sizeof(namelen))))
162 		return (error);
163 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
164 		return (error);
165 	s = splsoftnet();
166 	so = (struct socket *)fp->f_data;
167 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
168 		splx(s);
169 		return (EINVAL);
170 	}
171 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
172 		splx(s);
173 		return (EWOULDBLOCK);
174 	}
175 	while (so->so_qlen == 0 && so->so_error == 0) {
176 		if (so->so_state & SS_CANTRCVMORE) {
177 			so->so_error = ECONNABORTED;
178 			break;
179 		}
180 		error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
181 			       netcon, 0);
182 		if (error) {
183 			splx(s);
184 			return (error);
185 		}
186 	}
187 	if (so->so_error) {
188 		error = so->so_error;
189 		so->so_error = 0;
190 		splx(s);
191 		return (error);
192 	}
193 	if ((error = falloc(p, &fp, &tmpfd)) != 0) {
194 		splx(s);
195 		return (error);
196 	}
197 	*retval = tmpfd;
198 	{ struct socket *aso = so->so_q.tqh_first;
199 	  if (soqremque(aso, 1) == 0)
200 		panic("accept");
201 	  so = aso;
202 	}
203 	fp->f_type = DTYPE_SOCKET;
204 	fp->f_flag = FREAD|FWRITE;
205 	fp->f_ops = &socketops;
206 	fp->f_data = (caddr_t)so;
207 	nam = m_get(M_WAIT, MT_SONAME);
208 	(void) soaccept(so, nam);
209 	if (SCARG(uap, name)) {
210 		if (namelen > nam->m_len)
211 			namelen = nam->m_len;
212 		/* SHOULD COPY OUT A CHAIN HERE */
213 		if ((error = copyout(mtod(nam, caddr_t),
214 		    (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0)
215 			error = copyout((caddr_t)&namelen,
216 			    (caddr_t)SCARG(uap, anamelen),
217 			    sizeof(*SCARG(uap, anamelen)));
218 	}
219 	m_freem(nam);
220 	splx(s);
221 	return (error);
222 }
223 
224 /* ARGSUSED */
225 int
226 sys_connect(p, v, retval)
227 	struct proc *p;
228 	void *v;
229 	register_t *retval;
230 {
231 	register struct sys_connect_args /* {
232 		syscallarg(int) s;
233 		syscallarg(const struct sockaddr *) name;
234 		syscallarg(int) namelen;
235 	} */ *uap = v;
236 	struct file *fp;
237 	register struct socket *so;
238 	struct mbuf *nam;
239 	int error, s;
240 
241 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
242 		return (error);
243 	so = (struct socket *)fp->f_data;
244 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
245 		return (EALREADY);
246 	error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
247 	    MT_SONAME);
248 	if (error)
249 		return (error);
250 	error = soconnect(so, nam);
251 	if (error)
252 		goto bad;
253 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
254 		m_freem(nam);
255 		return (EINPROGRESS);
256 	}
257 	s = splsoftnet();
258 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
259 		error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
260 			       netcon, 0);
261 		if (error)
262 			break;
263 	}
264 	if (error == 0) {
265 		error = so->so_error;
266 		so->so_error = 0;
267 	}
268 	splx(s);
269 bad:
270 	so->so_state &= ~SS_ISCONNECTING;
271 	m_freem(nam);
272 	if (error == ERESTART)
273 		error = EINTR;
274 	return (error);
275 }
276 
277 int
278 sys_socketpair(p, v, retval)
279 	struct proc *p;
280 	void *v;
281 	register_t *retval;
282 {
283 	register struct sys_socketpair_args /* {
284 		syscallarg(int) domain;
285 		syscallarg(int) type;
286 		syscallarg(int) protocol;
287 		syscallarg(int *) rsv;
288 	} */ *uap = v;
289 	register struct filedesc *fdp = p->p_fd;
290 	struct file *fp1, *fp2;
291 	struct socket *so1, *so2;
292 	int fd, error, sv[2];
293 
294 	error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
295 			 SCARG(uap, protocol));
296 	if (error)
297 		return (error);
298 	error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
299 			 SCARG(uap, protocol));
300 	if (error)
301 		goto free1;
302 	if ((error = falloc(p, &fp1, &fd)) != 0)
303 		goto free2;
304 	sv[0] = fd;
305 	fp1->f_flag = FREAD|FWRITE;
306 	fp1->f_type = DTYPE_SOCKET;
307 	fp1->f_ops = &socketops;
308 	fp1->f_data = (caddr_t)so1;
309 	if ((error = falloc(p, &fp2, &fd)) != 0)
310 		goto free3;
311 	fp2->f_flag = FREAD|FWRITE;
312 	fp2->f_type = DTYPE_SOCKET;
313 	fp2->f_ops = &socketops;
314 	fp2->f_data = (caddr_t)so2;
315 	sv[1] = fd;
316 	if ((error = soconnect2(so1, so2)) != 0)
317 		goto free4;
318 	if (SCARG(uap, type) == SOCK_DGRAM) {
319 		/*
320 		 * Datagram socket connection is asymmetric.
321 		 */
322 		 if ((error = soconnect2(so2, so1)) != 0)
323 			goto free4;
324 	}
325 	error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
326 	    2 * sizeof(int));
327 	return (error);
328 free4:
329 	ffree(fp2);
330 	fdp->fd_ofiles[sv[1]] = 0;
331 free3:
332 	ffree(fp1);
333 	fdp->fd_ofiles[sv[0]] = 0;
334 free2:
335 	(void)soclose(so2);
336 free1:
337 	(void)soclose(so1);
338 	return (error);
339 }
340 
341 int
342 sys_sendto(p, v, retval)
343 	struct proc *p;
344 	void *v;
345 	register_t *retval;
346 {
347 	register struct sys_sendto_args /* {
348 		syscallarg(int) s;
349 		syscallarg(const void *) buf;
350 		syscallarg(size_t) len;
351 		syscallarg(int) flags;
352 		syscallarg(const struct sockaddr *) to;
353 		syscallarg(int) tolen;
354 	} */ *uap = v;
355 	struct msghdr msg;
356 	struct iovec aiov;
357 
358 	msg.msg_name = (caddr_t)SCARG(uap, to);		/* XXX kills const */
359 	msg.msg_namelen = SCARG(uap, tolen);
360 	msg.msg_iov = &aiov;
361 	msg.msg_iovlen = 1;
362 	msg.msg_control = 0;
363 #ifdef COMPAT_OLDSOCK
364 	msg.msg_flags = 0;
365 #endif
366 	aiov.iov_base = (char *)SCARG(uap, buf);	/* XXX kills const */
367 	aiov.iov_len = SCARG(uap, len);
368 	return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
369 }
370 
371 int
372 sys_sendmsg(p, v, retval)
373 	struct proc *p;
374 	void *v;
375 	register_t *retval;
376 {
377 	register struct sys_sendmsg_args /* {
378 		syscallarg(int) s;
379 		syscallarg(const struct msghdr *) msg;
380 		syscallarg(int) flags;
381 	} */ *uap = v;
382 	struct msghdr msg;
383 	struct iovec aiov[UIO_SMALLIOV], *iov;
384 	int error;
385 
386 	error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
387 	if (error)
388 		return (error);
389 	if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
390 		if ((u_int)msg.msg_iovlen > IOV_MAX)
391 			return (EMSGSIZE);
392 		MALLOC(iov, struct iovec *,
393 		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
394 		       M_WAITOK);
395 	} else if ((u_int)msg.msg_iovlen > 0)
396 		iov = aiov;
397 	else
398 		return (EMSGSIZE);
399 	error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
400 	    (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
401 	if (error)
402 		goto done;
403 	msg.msg_iov = iov;
404 #ifdef COMPAT_OLDSOCK
405 	msg.msg_flags = 0;
406 #endif
407 	error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
408 done:
409 	if (iov != aiov)
410 		FREE(iov, M_IOV);
411 	return (error);
412 }
413 
414 int
415 sendit(p, s, mp, flags, retsize)
416 	register struct proc *p;
417 	int s;
418 	register struct msghdr *mp;
419 	int flags;
420 	register_t *retsize;
421 {
422 	struct file *fp;
423 	struct uio auio;
424 	register struct iovec *iov;
425 	register int i;
426 	struct mbuf *to, *control;
427 	int len, error;
428 	struct socket *so;
429 #ifdef KTRACE
430 	struct iovec *ktriov = NULL;
431 #endif
432 
433 	if ((error = getsock(p->p_fd, s, &fp)) != 0)
434 		return (error);
435 	auio.uio_iov = mp->msg_iov;
436 	auio.uio_iovcnt = mp->msg_iovlen;
437 	auio.uio_segflg = UIO_USERSPACE;
438 	auio.uio_rw = UIO_WRITE;
439 	auio.uio_procp = p;
440 	auio.uio_offset = 0;			/* XXX */
441 	auio.uio_resid = 0;
442 	iov = mp->msg_iov;
443 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
444 #if 0
445 		/* cannot happen; iov_len is unsigned */
446 		if (iov->iov_len < 0)
447 			return (EINVAL);
448 #endif
449 		/*
450 		 * Writes return ssize_t because -1 is returned on error.
451 		 * Therefore, we must restrict the length to SSIZE_MAX to
452 		 * avoid garbage return values.
453 		 */
454 		auio.uio_resid += iov->iov_len;
455 		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX)
456 			return (EINVAL);
457 	}
458 	if (mp->msg_name) {
459 		error = sockargs(&to, mp->msg_name, mp->msg_namelen,
460 				 MT_SONAME);
461 		if (error)
462 			return (error);
463 	} else
464 		to = 0;
465 	if (mp->msg_control) {
466 		if (mp->msg_controllen < sizeof(struct cmsghdr)
467 #ifdef COMPAT_OLDSOCK
468 		    && mp->msg_flags != MSG_COMPAT
469 #endif
470 		) {
471 			error = EINVAL;
472 			goto bad;
473 		}
474 		error = sockargs(&control, mp->msg_control,
475 				 mp->msg_controllen, MT_CONTROL);
476 		if (error)
477 			goto bad;
478 #ifdef COMPAT_OLDSOCK
479 		if (mp->msg_flags == MSG_COMPAT) {
480 			register struct cmsghdr *cm;
481 
482 			M_PREPEND(control, sizeof(*cm), M_WAIT);
483 			if (control == 0) {
484 				error = ENOBUFS;
485 				goto bad;
486 			} else {
487 				cm = mtod(control, struct cmsghdr *);
488 				cm->cmsg_len = control->m_len;
489 				cm->cmsg_level = SOL_SOCKET;
490 				cm->cmsg_type = SCM_RIGHTS;
491 			}
492 		}
493 #endif
494 	} else
495 		control = 0;
496 #ifdef KTRACE
497 	if (KTRPOINT(p, KTR_GENIO)) {
498 		int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
499 
500 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
501 		memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
502 	}
503 #endif
504 	len = auio.uio_resid;
505 	so = (struct socket *)fp->f_data;
506 	error = (*so->so_send)(so, to, &auio, NULL, control, flags);
507 	if (error) {
508 		if (auio.uio_resid != len && (error == ERESTART ||
509 		    error == EINTR || error == EWOULDBLOCK))
510 			error = 0;
511 		if (error == EPIPE)
512 			psignal(p, SIGPIPE);
513 	}
514 	if (error == 0)
515 		*retsize = len - auio.uio_resid;
516 #ifdef KTRACE
517 	if (ktriov != NULL) {
518 		if (error == 0)
519 			ktrgenio(p->p_tracep, s, UIO_WRITE,
520 				ktriov, *retsize, error);
521 		FREE(ktriov, M_TEMP);
522 	}
523 #endif
524 bad:
525 	if (to)
526 		m_freem(to);
527 	return (error);
528 }
529 
530 int
531 sys_recvfrom(p, v, retval)
532 	struct proc *p;
533 	void *v;
534 	register_t *retval;
535 {
536 	register struct sys_recvfrom_args /* {
537 		syscallarg(int) s;
538 		syscallarg(void *) buf;
539 		syscallarg(size_t) len;
540 		syscallarg(int) flags;
541 		syscallarg(struct sockaddr *) from;
542 		syscallarg(int *) fromlenaddr;
543 	} */ *uap = v;
544 	struct msghdr msg;
545 	struct iovec aiov;
546 	int error;
547 
548 	if (SCARG(uap, fromlenaddr)) {
549 		error = copyin((caddr_t)SCARG(uap, fromlenaddr),
550 			       (caddr_t)&msg.msg_namelen,
551 			       sizeof(msg.msg_namelen));
552 		if (error)
553 			return (error);
554 	} else
555 		msg.msg_namelen = 0;
556 	msg.msg_name = (caddr_t)SCARG(uap, from);
557 	msg.msg_iov = &aiov;
558 	msg.msg_iovlen = 1;
559 	aiov.iov_base = SCARG(uap, buf);
560 	aiov.iov_len = SCARG(uap, len);
561 	msg.msg_control = 0;
562 	msg.msg_flags = SCARG(uap, flags);
563 	return (recvit(p, SCARG(uap, s), &msg,
564 		       (caddr_t)SCARG(uap, fromlenaddr), retval));
565 }
566 
567 int
568 sys_recvmsg(p, v, retval)
569 	struct proc *p;
570 	void *v;
571 	register_t *retval;
572 {
573 	register struct sys_recvmsg_args /* {
574 		syscallarg(int) s;
575 		syscallarg(struct msghdr *) msg;
576 		syscallarg(int) flags;
577 	} */ *uap = v;
578 	struct msghdr msg;
579 	struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
580 	register int error;
581 
582 	error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
583 		       sizeof(msg));
584 	if (error)
585 		return (error);
586 	if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
587 		if ((u_int)msg.msg_iovlen > IOV_MAX)
588 			return (EMSGSIZE);
589 		MALLOC(iov, struct iovec *,
590 		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
591 		       M_WAITOK);
592 	} else if ((u_int)msg.msg_iovlen > 0)
593 		iov = aiov;
594 	else
595 		return (EMSGSIZE);
596 #ifdef COMPAT_OLDSOCK
597 	msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
598 #else
599 	msg.msg_flags = SCARG(uap, flags);
600 #endif
601 	uiov = msg.msg_iov;
602 	msg.msg_iov = iov;
603 	error = copyin((caddr_t)uiov, (caddr_t)iov,
604 	    (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
605 	if (error)
606 		goto done;
607 	if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
608 		msg.msg_iov = uiov;
609 		error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
610 		    sizeof(msg));
611 	}
612 done:
613 	if (iov != aiov)
614 		FREE(iov, M_IOV);
615 	return (error);
616 }
617 
618 int
619 recvit(p, s, mp, namelenp, retsize)
620 	register struct proc *p;
621 	int s;
622 	register struct msghdr *mp;
623 	caddr_t namelenp;
624 	register_t *retsize;
625 {
626 	struct file *fp;
627 	struct uio auio;
628 	register struct iovec *iov;
629 	register int i;
630 	int len, error;
631 	struct mbuf *from = 0, *control = 0;
632 	struct socket *so;
633 #ifdef KTRACE
634 	struct iovec *ktriov = NULL;
635 #endif
636 
637 	if ((error = getsock(p->p_fd, s, &fp)) != 0)
638 		return (error);
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_READ;
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 #if 0
649 		/* cannot happen iov_len is unsigned */
650 		if (iov->iov_len < 0)
651 			return (EINVAL);
652 #endif
653 		/*
654 		 * Reads return ssize_t because -1 is returned on error.
655 		 * Therefore we must restrict the length to SSIZE_MAX to
656 		 * avoid garbage return values.
657 		 */
658 		auio.uio_resid += iov->iov_len;
659 		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX)
660 			return (EINVAL);
661 	}
662 #ifdef KTRACE
663 	if (KTRPOINT(p, KTR_GENIO)) {
664 		int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
665 
666 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
667 		memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
668 	}
669 #endif
670 	len = auio.uio_resid;
671 	so = (struct socket *)fp->f_data;
672 	error = (*so->so_receive)(so, &from, &auio, NULL,
673 			  mp->msg_control ? &control : NULL, &mp->msg_flags);
674 	if (error) {
675 		if (auio.uio_resid != len && (error == ERESTART ||
676 		    error == EINTR || error == EWOULDBLOCK))
677 			error = 0;
678 	}
679 #ifdef KTRACE
680 	if (ktriov != NULL) {
681 		if (error == 0)
682 			ktrgenio(p->p_tracep, s, UIO_READ,
683 				ktriov, len - auio.uio_resid, error);
684 		FREE(ktriov, M_TEMP);
685 	}
686 #endif
687 	if (error)
688 		goto out;
689 	*retsize = len - auio.uio_resid;
690 	if (mp->msg_name) {
691 		len = mp->msg_namelen;
692 		if (len <= 0 || from == 0)
693 			len = 0;
694 		else {
695 #ifdef COMPAT_OLDSOCK
696 			if (mp->msg_flags & MSG_COMPAT)
697 				mtod(from, struct osockaddr *)->sa_family =
698 				    mtod(from, struct sockaddr *)->sa_family;
699 #endif
700 			if (len > from->m_len)
701 				len = from->m_len;
702 			/* else if len < from->m_len ??? */
703 			error = copyout(mtod(from, caddr_t),
704 					(caddr_t)mp->msg_name, (unsigned)len);
705 			if (error)
706 				goto out;
707 		}
708 		mp->msg_namelen = len;
709 		if (namelenp &&
710 		    (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) {
711 #ifdef COMPAT_OLDSOCK
712 			if (mp->msg_flags & MSG_COMPAT)
713 				error = 0;	/* old recvfrom didn't check */
714 			else
715 #endif
716 			goto out;
717 		}
718 	}
719 	if (mp->msg_control) {
720 #ifdef COMPAT_OLDSOCK
721 		/*
722 		 * We assume that old recvmsg calls won't receive access
723 		 * rights and other control info, esp. as control info
724 		 * is always optional and those options didn't exist in 4.3.
725 		 * If we receive rights, trim the cmsghdr; anything else
726 		 * is tossed.
727 		 */
728 		if (control && mp->msg_flags & MSG_COMPAT) {
729 			if (mtod(control, struct cmsghdr *)->cmsg_level !=
730 			    SOL_SOCKET ||
731 			    mtod(control, struct cmsghdr *)->cmsg_type !=
732 			    SCM_RIGHTS) {
733 				mp->msg_controllen = 0;
734 				goto out;
735 			}
736 			control->m_len -= sizeof(struct cmsghdr);
737 			control->m_data += sizeof(struct cmsghdr);
738 		}
739 #endif
740 		len = mp->msg_controllen;
741 		if (len <= 0 || control == 0)
742 			len = 0;
743 		else {
744 			struct mbuf *m = control;
745 			caddr_t p = (caddr_t)mp->msg_control;
746 
747 			do {
748 				i = m->m_len;
749 				if (len < i) {
750 					mp->msg_flags |= MSG_CTRUNC;
751 					i = len;
752 				}
753 				error = copyout(mtod(m, caddr_t), p,
754 				    (unsigned)i);
755 				if (m->m_next)
756 					i = ALIGN(i);
757 				p += i;
758 				len -= i;
759 				if (error != 0 || len <= 0)
760 					break;
761 			} while ((m = m->m_next) != NULL);
762 			len = p - (caddr_t)mp->msg_control;
763 		}
764 		mp->msg_controllen = len;
765 	}
766 out:
767 	if (from)
768 		m_freem(from);
769 	if (control)
770 		m_freem(control);
771 	return (error);
772 }
773 
774 /* ARGSUSED */
775 int
776 sys_shutdown(p, v, retval)
777 	struct proc *p;
778 	void *v;
779 	register_t *retval;
780 {
781 	register struct sys_shutdown_args /* {
782 		syscallarg(int) s;
783 		syscallarg(int) how;
784 	} */ *uap = v;
785 	struct file *fp;
786 	int error;
787 
788 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
789 		return (error);
790 	return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how)));
791 }
792 
793 /* ARGSUSED */
794 int
795 sys_setsockopt(p, v, retval)
796 	struct proc *p;
797 	void *v;
798 	register_t *retval;
799 {
800 	register struct sys_setsockopt_args /* {
801 		syscallarg(int) s;
802 		syscallarg(int) level;
803 		syscallarg(int) name;
804 		syscallarg(const void *) val;
805 		syscallarg(int) valsize;
806 	} */ *uap = v;
807 	struct file *fp;
808 	struct mbuf *m = NULL;
809 	int error;
810 
811 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
812 		return (error);
813 	if (SCARG(uap, valsize) > MLEN)
814 		return (EINVAL);
815 	if (SCARG(uap, val)) {
816 		m = m_get(M_WAIT, MT_SOOPTS);
817 		error = copyin(SCARG(uap, val), mtod(m, caddr_t),
818 			       (u_int)SCARG(uap, valsize));
819 		if (error) {
820 			(void) m_free(m);
821 			return (error);
822 		}
823 		m->m_len = SCARG(uap, valsize);
824 	}
825 	return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
826 			 SCARG(uap, name), m));
827 }
828 
829 /* ARGSUSED */
830 int
831 sys_getsockopt(p, v, retval)
832 	struct proc *p;
833 	void *v;
834 	register_t *retval;
835 {
836 	register struct sys_getsockopt_args /* {
837 		syscallarg(int) s;
838 		syscallarg(int) level;
839 		syscallarg(int) name;
840 		syscallarg(void *) val;
841 		syscallarg(int *) avalsize;
842 	} */ *uap = v;
843 	struct file *fp;
844 	struct mbuf *m = NULL;
845 	int valsize, error;
846 
847 	if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
848 		return (error);
849 	if (SCARG(uap, val)) {
850 		error = copyin((caddr_t)SCARG(uap, avalsize),
851 			       (caddr_t)&valsize, sizeof(valsize));
852 		if (error)
853 			return (error);
854 	} else
855 		valsize = 0;
856 	if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
857 	    SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
858 	    m != NULL) {
859 		if (valsize > m->m_len)
860 			valsize = m->m_len;
861 		error = copyout(mtod(m, caddr_t), SCARG(uap, val),
862 		    (u_int)valsize);
863 		if (error == 0)
864 			error = copyout((caddr_t)&valsize,
865 			    (caddr_t)SCARG(uap, avalsize), sizeof(valsize));
866 	}
867 	if (m != NULL)
868 		(void) m_free(m);
869 	return (error);
870 }
871 
872 /* ARGSUSED */
873 int
874 sys_pipe(p, v, retval)
875 	struct proc *p;
876 	void *v;
877 	register_t *retval;
878 {
879 	register struct filedesc *fdp = p->p_fd;
880 	struct file *rf, *wf;
881 	struct socket *rso, *wso;
882 	int fd, error;
883 
884 	if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
885 		return (error);
886 	if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
887 		goto free1;
888 	if ((error = falloc(p, &rf, &fd)) != 0)
889 		goto free2;
890 	retval[0] = fd;
891 	rf->f_flag = FREAD;
892 	rf->f_type = DTYPE_SOCKET;
893 	rf->f_ops = &socketops;
894 	rf->f_data = (caddr_t)rso;
895 	if ((error = falloc(p, &wf, &fd)) != 0)
896 		goto free3;
897 	wf->f_flag = FWRITE;
898 	wf->f_type = DTYPE_SOCKET;
899 	wf->f_ops = &socketops;
900 	wf->f_data = (caddr_t)wso;
901 	retval[1] = fd;
902 	if ((error = unp_connect2(wso, rso)) != 0)
903 		goto free4;
904 	return (0);
905 free4:
906 	ffree(wf);
907 	fdp->fd_ofiles[retval[1]] = 0;
908 free3:
909 	ffree(rf);
910 	fdp->fd_ofiles[retval[0]] = 0;
911 free2:
912 	(void)soclose(wso);
913 free1:
914 	(void)soclose(rso);
915 	return (error);
916 }
917 
918 /*
919  * Get socket name.
920  */
921 /* ARGSUSED */
922 int
923 sys_getsockname(p, v, retval)
924 	struct proc *p;
925 	void *v;
926 	register_t *retval;
927 {
928 	register struct sys_getsockname_args /* {
929 		syscallarg(int) fdes;
930 		syscallarg(struct sockaddr *) asa;
931 		syscallarg(int *) alen;
932 	} */ *uap = v;
933 	struct file *fp;
934 	register struct socket *so;
935 	struct mbuf *m;
936 	int len, error;
937 
938 	if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
939 		return (error);
940 	error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
941 	if (error)
942 		return (error);
943 	so = (struct socket *)fp->f_data;
944 	m = m_getclr(M_WAIT, MT_SONAME);
945 	error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
946 	    m, (struct mbuf *)0, (struct proc *)0);
947 	if (error)
948 		goto bad;
949 	if (len > m->m_len)
950 		len = m->m_len;
951 	error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len);
952 	if (error == 0)
953 		error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
954 		    sizeof(len));
955 bad:
956 	m_freem(m);
957 	return (error);
958 }
959 
960 /*
961  * Get name of peer for connected socket.
962  */
963 /* ARGSUSED */
964 int
965 sys_getpeername(p, v, retval)
966 	struct proc *p;
967 	void *v;
968 	register_t *retval;
969 {
970 	register struct sys_getpeername_args /* {
971 		syscallarg(int) fdes;
972 		syscallarg(struct sockaddr *) asa;
973 		syscallarg(int *) alen;
974 	} */ *uap = v;
975 	struct file *fp;
976 	register struct socket *so;
977 	struct mbuf *m;
978 	int len, error;
979 
980 	if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
981 		return (error);
982 	so = (struct socket *)fp->f_data;
983 	if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
984 		return (ENOTCONN);
985 	error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
986 	if (error)
987 		return (error);
988 	m = m_getclr(M_WAIT, MT_SONAME);
989 	error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
990 	    m, (struct mbuf *)0, (struct proc *)0);
991 	if (error)
992 		goto bad;
993 	if (len > m->m_len)
994 		len = m->m_len;
995 	error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len);
996 	if (error)
997 		goto bad;
998 	error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
999 bad:
1000 	m_freem(m);
1001 	return (error);
1002 }
1003 
1004 /*
1005  * XXX In a perfect world, we wouldn't pass around socket control
1006  * XXX arguments in mbufs, and this could go away.
1007  */
1008 int
1009 sockargs(mp, buf, buflen, type)
1010 	struct mbuf **mp;
1011 	const void *buf;
1012 	int buflen, type;
1013 {
1014 	register struct sockaddr *sa;
1015 	register struct mbuf *m;
1016 	int error;
1017 
1018 	/*
1019 	 * We can't allow socket names > UCHAR_MAX in length, since that
1020 	 * will overflow sa_len.
1021 	 */
1022 	if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
1023 		return (EINVAL);
1024 
1025 	/* Allocate an mbuf to hold the arguments. */
1026 	m = m_get(M_WAIT, type);
1027 	if ((u_int)buflen > MLEN) {
1028 		/*
1029 		 * Won't fit into a regular mbuf, so we allocate just
1030 		 * enough external storage to hold the argument.
1031 		 */
1032 		MEXTMALLOC(m, buflen, M_WAITOK);
1033 	}
1034 	m->m_len = buflen;
1035 	error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1036 	if (error) {
1037 		(void) m_free(m);
1038 		return (error);
1039 	}
1040 	*mp = m;
1041 	if (type == MT_SONAME) {
1042 		sa = mtod(m, struct sockaddr *);
1043 
1044 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1045 		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1046 			sa->sa_family = sa->sa_len;
1047 #endif
1048 		sa->sa_len = buflen;
1049 	}
1050 	return (0);
1051 }
1052 
1053 int
1054 getsock(fdp, fdes, fpp)
1055 	struct filedesc *fdp;
1056 	int fdes;
1057 	struct file **fpp;
1058 {
1059 	register struct file *fp;
1060 
1061 	if ((unsigned)fdes >= fdp->fd_nfiles ||
1062 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
1063 		return (EBADF);
1064 	if (fp->f_type != DTYPE_SOCKET)
1065 		return (ENOTSOCK);
1066 	*fpp = fp;
1067 	return (0);
1068 }
1069