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