Home | History | Annotate | Line # | Download | only in kern
uipc_syscalls.c revision 1.16
      1 /*	$NetBSD: uipc_syscalls.c,v 1.16 1995/10/07 06:28:46 mycroft 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.4 (Berkeley) 2/21/94
     36  */
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/filedesc.h>
     41 #include <sys/proc.h>
     42 #include <sys/file.h>
     43 #include <sys/buf.h>
     44 #include <sys/malloc.h>
     45 #include <sys/mbuf.h>
     46 #include <sys/protosw.h>
     47 #include <sys/socket.h>
     48 #include <sys/socketvar.h>
     49 #ifdef KTRACE
     50 #include <sys/ktrace.h>
     51 #endif
     52 
     53 #include <sys/mount.h>
     54 #include <sys/syscallargs.h>
     55 
     56 /*
     57  * System call interface to the socket abstraction.
     58  */
     59 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \
     60     defined(COMPAT_HPUX)
     61 #define COMPAT_OLDSOCK
     62 #define MSG_COMPAT	0x8000
     63 #endif
     64 
     65 extern	struct fileops socketops;
     66 
     67 int
     68 sys_socket(p, v, retval)
     69 	struct proc *p;
     70 	void *v;
     71 	register_t *retval;
     72 {
     73 	register struct sys_socket_args /* {
     74 		syscallarg(int) domain;
     75 		syscallarg(int) type;
     76 		syscallarg(int) protocol;
     77 	} */ *uap = v;
     78 	struct filedesc *fdp = p->p_fd;
     79 	struct socket *so;
     80 	struct file *fp;
     81 	int fd, error;
     82 
     83 	if (error = falloc(p, &fp, &fd))
     84 		return (error);
     85 	fp->f_flag = FREAD|FWRITE;
     86 	fp->f_type = DTYPE_SOCKET;
     87 	fp->f_ops = &socketops;
     88 	if (error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
     89 	    SCARG(uap, protocol))) {
     90 		fdp->fd_ofiles[fd] = 0;
     91 		ffree(fp);
     92 	} else {
     93 		fp->f_data = (caddr_t)so;
     94 		*retval = fd;
     95 	}
     96 	return (error);
     97 }
     98 
     99 /* ARGSUSED */
    100 int
    101 sys_bind(p, v, retval)
    102 	struct proc *p;
    103 	void *v;
    104 	register_t *retval;
    105 {
    106 	register struct sys_bind_args /* {
    107 		syscallarg(int) s;
    108 		syscallarg(caddr_t) name;
    109 		syscallarg(int) namelen;
    110 	} */ *uap = v;
    111 	struct file *fp;
    112 	struct mbuf *nam;
    113 	int error;
    114 
    115 	if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
    116 		return (error);
    117 	if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
    118 	    MT_SONAME))
    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))
    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(caddr_t) 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))
    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 		if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
    181 		    netcon, 0)) {
    182 			splx(s);
    183 			return (error);
    184 		}
    185 	}
    186 	if (so->so_error) {
    187 		error = so->so_error;
    188 		so->so_error = 0;
    189 		splx(s);
    190 		return (error);
    191 	}
    192 	if (error = falloc(p, &fp, &tmpfd)) {
    193 		splx(s);
    194 		return (error);
    195 	}
    196 	*retval = tmpfd;
    197 	{ struct socket *aso = so->so_q;
    198 	  if (soqremque(aso, 1) == 0)
    199 		panic("accept");
    200 	  so = aso;
    201 	}
    202 	fp->f_type = DTYPE_SOCKET;
    203 	fp->f_flag = FREAD|FWRITE;
    204 	fp->f_ops = &socketops;
    205 	fp->f_data = (caddr_t)so;
    206 	nam = m_get(M_WAIT, MT_SONAME);
    207 	(void) soaccept(so, nam);
    208 	if (SCARG(uap, name)) {
    209 		if (namelen > nam->m_len)
    210 			namelen = nam->m_len;
    211 		/* SHOULD COPY OUT A CHAIN HERE */
    212 		if ((error = copyout(mtod(nam, caddr_t),
    213 		    (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0)
    214 			error = copyout((caddr_t)&namelen,
    215 			    (caddr_t)SCARG(uap, anamelen),
    216 			    sizeof (*SCARG(uap, anamelen)));
    217 	}
    218 	m_freem(nam);
    219 	splx(s);
    220 	return (error);
    221 }
    222 
    223 /* ARGSUSED */
    224 int
    225 sys_connect(p, v, retval)
    226 	struct proc *p;
    227 	void *v;
    228 	register_t *retval;
    229 {
    230 	register struct sys_connect_args /* {
    231 		syscallarg(int) s;
    232 		syscallarg(caddr_t) name;
    233 		syscallarg(int) namelen;
    234 	} */ *uap = v;
    235 	struct file *fp;
    236 	register struct socket *so;
    237 	struct mbuf *nam;
    238 	int error, s;
    239 
    240 	if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
    241 		return (error);
    242 	so = (struct socket *)fp->f_data;
    243 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
    244 		return (EALREADY);
    245 	if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
    246 	    MT_SONAME))
    247 		return (error);
    248 	error = soconnect(so, nam);
    249 	if (error)
    250 		goto bad;
    251 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
    252 		m_freem(nam);
    253 		return (EINPROGRESS);
    254 	}
    255 	s = splsoftnet();
    256 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
    257 		if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
    258 		    netcon, 0))
    259 			break;
    260 	if (error == 0) {
    261 		error = so->so_error;
    262 		so->so_error = 0;
    263 	}
    264 	splx(s);
    265 bad:
    266 	so->so_state &= ~SS_ISCONNECTING;
    267 	m_freem(nam);
    268 	if (error == ERESTART)
    269 		error = EINTR;
    270 	return (error);
    271 }
    272 
    273 int
    274 sys_socketpair(p, v, retval)
    275 	struct proc *p;
    276 	void *v;
    277 	register_t *retval;
    278 {
    279 	register struct sys_socketpair_args /* {
    280 		syscallarg(int) domain;
    281 		syscallarg(int) type;
    282 		syscallarg(int) protocol;
    283 		syscallarg(int *) rsv;
    284 	} */ *uap = v;
    285 	register struct filedesc *fdp = p->p_fd;
    286 	struct file *fp1, *fp2;
    287 	struct socket *so1, *so2;
    288 	int fd, error, sv[2];
    289 
    290 	if (error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
    291 	    SCARG(uap, protocol)))
    292 		return (error);
    293 	if (error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
    294 	    SCARG(uap, protocol)))
    295 		goto free1;
    296 	if (error = falloc(p, &fp1, &fd))
    297 		goto free2;
    298 	sv[0] = fd;
    299 	fp1->f_flag = FREAD|FWRITE;
    300 	fp1->f_type = DTYPE_SOCKET;
    301 	fp1->f_ops = &socketops;
    302 	fp1->f_data = (caddr_t)so1;
    303 	if (error = falloc(p, &fp2, &fd))
    304 		goto free3;
    305 	fp2->f_flag = FREAD|FWRITE;
    306 	fp2->f_type = DTYPE_SOCKET;
    307 	fp2->f_ops = &socketops;
    308 	fp2->f_data = (caddr_t)so2;
    309 	sv[1] = fd;
    310 	if (error = soconnect2(so1, so2))
    311 		goto free4;
    312 	if (SCARG(uap, type) == SOCK_DGRAM) {
    313 		/*
    314 		 * Datagram socket connection is asymmetric.
    315 		 */
    316 		 if (error = soconnect2(so2, so1))
    317 			goto free4;
    318 	}
    319 	error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
    320 	    2 * sizeof (int));
    321 	retval[0] = sv[0];		/* XXX ??? */
    322 	retval[1] = sv[1];		/* XXX ??? */
    323 	return (error);
    324 free4:
    325 	ffree(fp2);
    326 	fdp->fd_ofiles[sv[1]] = 0;
    327 free3:
    328 	ffree(fp1);
    329 	fdp->fd_ofiles[sv[0]] = 0;
    330 free2:
    331 	(void)soclose(so2);
    332 free1:
    333 	(void)soclose(so1);
    334 	return (error);
    335 }
    336 
    337 int
    338 sys_sendto(p, v, retval)
    339 	struct proc *p;
    340 	void *v;
    341 	register_t *retval;
    342 {
    343 	register struct sys_sendto_args /* {
    344 		syscallarg(int) s;
    345 		syscallarg(caddr_t) buf;
    346 		syscallarg(size_t) len;
    347 		syscallarg(int) flags;
    348 		syscallarg(caddr_t) to;
    349 		syscallarg(int) tolen;
    350 	} */ *uap = v;
    351 	struct msghdr msg;
    352 	struct iovec aiov;
    353 
    354 	msg.msg_name = SCARG(uap, to);
    355 	msg.msg_namelen = SCARG(uap, tolen);
    356 	msg.msg_iov = &aiov;
    357 	msg.msg_iovlen = 1;
    358 	msg.msg_control = 0;
    359 #ifdef COMPAT_OLDSOCK
    360 	msg.msg_flags = 0;
    361 #endif
    362 	aiov.iov_base = SCARG(uap, buf);
    363 	aiov.iov_len = SCARG(uap, len);
    364 	return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
    365 }
    366 
    367 int
    368 sys_sendmsg(p, v, retval)
    369 	struct proc *p;
    370 	void *v;
    371 	register_t *retval;
    372 {
    373 	register struct sys_sendmsg_args /* {
    374 		syscallarg(int) s;
    375 		syscallarg(caddr_t) msg;
    376 		syscallarg(int) flags;
    377 	} */ *uap = v;
    378 	struct msghdr msg;
    379 	struct iovec aiov[UIO_SMALLIOV], *iov;
    380 	int error;
    381 
    382 	if (error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg)))
    383 		return (error);
    384 	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
    385 		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
    386 			return (EMSGSIZE);
    387 		MALLOC(iov, struct iovec *,
    388 		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
    389 		       M_WAITOK);
    390 	} else
    391 		iov = aiov;
    392 	if (msg.msg_iovlen &&
    393 	    (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
    394 	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
    395 		goto done;
    396 	msg.msg_iov = iov;
    397 #ifdef COMPAT_OLDSOCK
    398 	msg.msg_flags = 0;
    399 #endif
    400 	error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
    401 done:
    402 	if (iov != aiov)
    403 		FREE(iov, M_IOV);
    404 	return (error);
    405 }
    406 
    407 int
    408 sendit(p, s, mp, flags, retsize)
    409 	register struct proc *p;
    410 	int s;
    411 	register struct msghdr *mp;
    412 	int flags;
    413 	register_t *retsize;
    414 {
    415 	struct file *fp;
    416 	struct uio auio;
    417 	register struct iovec *iov;
    418 	register int i;
    419 	struct mbuf *to, *control;
    420 	int len, error;
    421 #ifdef KTRACE
    422 	struct iovec *ktriov = NULL;
    423 #endif
    424 
    425 	if (error = getsock(p->p_fd, s, &fp))
    426 		return (error);
    427 	auio.uio_iov = mp->msg_iov;
    428 	auio.uio_iovcnt = mp->msg_iovlen;
    429 	auio.uio_segflg = UIO_USERSPACE;
    430 	auio.uio_rw = UIO_WRITE;
    431 	auio.uio_procp = p;
    432 	auio.uio_offset = 0;			/* XXX */
    433 	auio.uio_resid = 0;
    434 	iov = mp->msg_iov;
    435 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
    436 		if (iov->iov_len < 0)
    437 			return (EINVAL);
    438 		if ((auio.uio_resid += iov->iov_len) < 0)
    439 			return (EINVAL);
    440 	}
    441 	if (mp->msg_name) {
    442 		if (error = sockargs(&to, mp->msg_name, mp->msg_namelen,
    443 		    MT_SONAME))
    444 			return (error);
    445 	} else
    446 		to = 0;
    447 	if (mp->msg_control) {
    448 		if (mp->msg_controllen < sizeof(struct cmsghdr)
    449 #ifdef COMPAT_OLDSOCK
    450 		    && mp->msg_flags != MSG_COMPAT
    451 #endif
    452 		) {
    453 			error = EINVAL;
    454 			goto bad;
    455 		}
    456 		if (error = sockargs(&control, mp->msg_control,
    457 		    mp->msg_controllen, MT_CONTROL))
    458 			goto bad;
    459 #ifdef COMPAT_OLDSOCK
    460 		if (mp->msg_flags == MSG_COMPAT) {
    461 			register struct cmsghdr *cm;
    462 
    463 			M_PREPEND(control, sizeof(*cm), M_WAIT);
    464 			if (control == 0) {
    465 				error = ENOBUFS;
    466 				goto bad;
    467 			} else {
    468 				cm = mtod(control, struct cmsghdr *);
    469 				cm->cmsg_len = control->m_len;
    470 				cm->cmsg_level = SOL_SOCKET;
    471 				cm->cmsg_type = SCM_RIGHTS;
    472 			}
    473 		}
    474 #endif
    475 	} else
    476 		control = 0;
    477 #ifdef KTRACE
    478 	if (KTRPOINT(p, KTR_GENIO)) {
    479 		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
    480 
    481 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
    482 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
    483 	}
    484 #endif
    485 	len = auio.uio_resid;
    486 	if (error = sosend((struct socket *)fp->f_data, to, &auio,
    487 	    (struct mbuf *)0, control, flags)) {
    488 		if (auio.uio_resid != len && (error == ERESTART ||
    489 		    error == EINTR || error == EWOULDBLOCK))
    490 			error = 0;
    491 		if (error == EPIPE)
    492 			psignal(p, SIGPIPE);
    493 	}
    494 	if (error == 0)
    495 		*retsize = len - auio.uio_resid;
    496 #ifdef KTRACE
    497 	if (ktriov != NULL) {
    498 		if (error == 0)
    499 			ktrgenio(p->p_tracep, s, UIO_WRITE,
    500 				ktriov, *retsize, error);
    501 		FREE(ktriov, M_TEMP);
    502 	}
    503 #endif
    504 bad:
    505 	if (to)
    506 		m_freem(to);
    507 	return (error);
    508 }
    509 
    510 int
    511 sys_recvfrom(p, v, retval)
    512 	struct proc *p;
    513 	void *v;
    514 	register_t *retval;
    515 {
    516 	register struct sys_recvfrom_args /* {
    517 		syscallarg(int) s;
    518 		syscallarg(caddr_t) buf;
    519 		syscallarg(size_t) len;
    520 		syscallarg(int) flags;
    521 		syscallarg(caddr_t) from;
    522 		syscallarg(int *) fromlenaddr;
    523 	} */ *uap = v;
    524 	struct msghdr msg;
    525 	struct iovec aiov;
    526 	int error;
    527 
    528 	if (SCARG(uap, fromlenaddr)) {
    529 		if (error = copyin((caddr_t)SCARG(uap, fromlenaddr),
    530 		    (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)))
    531 			return (error);
    532 	} else
    533 		msg.msg_namelen = 0;
    534 	msg.msg_name = SCARG(uap, from);
    535 	msg.msg_iov = &aiov;
    536 	msg.msg_iovlen = 1;
    537 	aiov.iov_base = SCARG(uap, buf);
    538 	aiov.iov_len = SCARG(uap, len);
    539 	msg.msg_control = 0;
    540 	msg.msg_flags = SCARG(uap, flags);
    541 	return (recvit(p, SCARG(uap, s), &msg,
    542 	    (caddr_t)SCARG(uap, fromlenaddr), retval));
    543 }
    544 
    545 int
    546 sys_recvmsg(p, v, retval)
    547 	struct proc *p;
    548 	void *v;
    549 	register_t *retval;
    550 {
    551 	register struct sys_recvmsg_args /* {
    552 		syscallarg(int) s;
    553 		syscallarg(struct msghdr *) msg;
    554 		syscallarg(int) flags;
    555 	} */ *uap = v;
    556 	struct msghdr msg;
    557 	struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
    558 	register int error;
    559 
    560 	if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
    561 	    sizeof (msg)))
    562 		return (error);
    563 	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
    564 		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
    565 			return (EMSGSIZE);
    566 		MALLOC(iov, struct iovec *,
    567 		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
    568 		       M_WAITOK);
    569 	} else
    570 		iov = aiov;
    571 #ifdef COMPAT_OLDSOCK
    572 	msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
    573 #else
    574 	msg.msg_flags = SCARG(uap, flags);
    575 #endif
    576 	uiov = msg.msg_iov;
    577 	msg.msg_iov = iov;
    578 	if (error = copyin((caddr_t)uiov, (caddr_t)iov,
    579 	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
    580 		goto done;
    581 	if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
    582 		msg.msg_iov = uiov;
    583 		error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
    584 		    sizeof(msg));
    585 	}
    586 done:
    587 	if (iov != aiov)
    588 		FREE(iov, M_IOV);
    589 	return (error);
    590 }
    591 
    592 int
    593 recvit(p, s, mp, namelenp, retsize)
    594 	register struct proc *p;
    595 	int s;
    596 	register struct msghdr *mp;
    597 	caddr_t namelenp;
    598 	register_t *retsize;
    599 {
    600 	struct file *fp;
    601 	struct uio auio;
    602 	register struct iovec *iov;
    603 	register int i;
    604 	int len, error;
    605 	struct mbuf *from = 0, *control = 0;
    606 #ifdef KTRACE
    607 	struct iovec *ktriov = NULL;
    608 #endif
    609 
    610 	if (error = getsock(p->p_fd, s, &fp))
    611 		return (error);
    612 	auio.uio_iov = mp->msg_iov;
    613 	auio.uio_iovcnt = mp->msg_iovlen;
    614 	auio.uio_segflg = UIO_USERSPACE;
    615 	auio.uio_rw = UIO_READ;
    616 	auio.uio_procp = p;
    617 	auio.uio_offset = 0;			/* XXX */
    618 	auio.uio_resid = 0;
    619 	iov = mp->msg_iov;
    620 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
    621 		if (iov->iov_len < 0)
    622 			return (EINVAL);
    623 		if ((auio.uio_resid += iov->iov_len) < 0)
    624 			return (EINVAL);
    625 	}
    626 #ifdef KTRACE
    627 	if (KTRPOINT(p, KTR_GENIO)) {
    628 		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
    629 
    630 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
    631 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
    632 	}
    633 #endif
    634 	len = auio.uio_resid;
    635 	if (error = soreceive((struct socket *)fp->f_data, &from, &auio,
    636 	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
    637 	    &mp->msg_flags)) {
    638 		if (auio.uio_resid != len && (error == ERESTART ||
    639 		    error == EINTR || error == EWOULDBLOCK))
    640 			error = 0;
    641 	}
    642 #ifdef KTRACE
    643 	if (ktriov != NULL) {
    644 		if (error == 0)
    645 			ktrgenio(p->p_tracep, s, UIO_READ,
    646 				ktriov, len - auio.uio_resid, error);
    647 		FREE(ktriov, M_TEMP);
    648 	}
    649 #endif
    650 	if (error)
    651 		goto out;
    652 	*retsize = len - auio.uio_resid;
    653 	if (mp->msg_name) {
    654 		len = mp->msg_namelen;
    655 		if (len <= 0 || from == 0)
    656 			len = 0;
    657 		else {
    658 #ifdef COMPAT_OLDSOCK
    659 			if (mp->msg_flags & MSG_COMPAT)
    660 				mtod(from, struct osockaddr *)->sa_family =
    661 				    mtod(from, struct sockaddr *)->sa_family;
    662 #endif
    663 			if (len > from->m_len)
    664 				len = from->m_len;
    665 			/* else if len < from->m_len ??? */
    666 			if (error = copyout(mtod(from, caddr_t),
    667 			    (caddr_t)mp->msg_name, (unsigned)len))
    668 				goto out;
    669 		}
    670 		mp->msg_namelen = len;
    671 		if (namelenp &&
    672 		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
    673 #ifdef COMPAT_OLDSOCK
    674 			if (mp->msg_flags & MSG_COMPAT)
    675 				error = 0;	/* old recvfrom didn't check */
    676 			else
    677 #endif
    678 			goto out;
    679 		}
    680 	}
    681 	if (mp->msg_control) {
    682 #ifdef COMPAT_OLDSOCK
    683 		/*
    684 		 * We assume that old recvmsg calls won't receive access
    685 		 * rights and other control info, esp. as control info
    686 		 * is always optional and those options didn't exist in 4.3.
    687 		 * If we receive rights, trim the cmsghdr; anything else
    688 		 * is tossed.
    689 		 */
    690 		if (control && mp->msg_flags & MSG_COMPAT) {
    691 			if (mtod(control, struct cmsghdr *)->cmsg_level !=
    692 			    SOL_SOCKET ||
    693 			    mtod(control, struct cmsghdr *)->cmsg_type !=
    694 			    SCM_RIGHTS) {
    695 				mp->msg_controllen = 0;
    696 				goto out;
    697 			}
    698 			control->m_len -= sizeof (struct cmsghdr);
    699 			control->m_data += sizeof (struct cmsghdr);
    700 		}
    701 #endif
    702 		len = mp->msg_controllen;
    703 		if (len <= 0 || control == 0)
    704 			len = 0;
    705 		else {
    706 			if (len >= control->m_len)
    707 				len = control->m_len;
    708 			else
    709 				mp->msg_flags |= MSG_CTRUNC;
    710 			error = copyout((caddr_t)mtod(control, caddr_t),
    711 			    (caddr_t)mp->msg_control, (unsigned)len);
    712 		}
    713 		mp->msg_controllen = len;
    714 	}
    715 out:
    716 	if (from)
    717 		m_freem(from);
    718 	if (control)
    719 		m_freem(control);
    720 	return (error);
    721 }
    722 
    723 /* ARGSUSED */
    724 int
    725 sys_shutdown(p, v, retval)
    726 	struct proc *p;
    727 	void *v;
    728 	register_t *retval;
    729 {
    730 	register struct sys_shutdown_args /* {
    731 		syscallarg(int) s;
    732 		syscallarg(int) how;
    733 	} */ *uap = v;
    734 	struct file *fp;
    735 	int error;
    736 
    737 	if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
    738 		return (error);
    739 	return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how)));
    740 }
    741 
    742 /* ARGSUSED */
    743 int
    744 sys_setsockopt(p, v, retval)
    745 	struct proc *p;
    746 	void *v;
    747 	register_t *retval;
    748 {
    749 	register struct sys_setsockopt_args /* {
    750 		syscallarg(int) s;
    751 		syscallarg(int) level;
    752 		syscallarg(int) name;
    753 		syscallarg(caddr_t) val;
    754 		syscallarg(int) valsize;
    755 	} */ *uap = v;
    756 	struct file *fp;
    757 	struct mbuf *m = NULL;
    758 	int error;
    759 
    760 	if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
    761 		return (error);
    762 	if (SCARG(uap, valsize) > MLEN)
    763 		return (EINVAL);
    764 	if (SCARG(uap, val)) {
    765 		m = m_get(M_WAIT, MT_SOOPTS);
    766 		if (m == NULL)
    767 			return (ENOBUFS);
    768 		if (error = copyin(SCARG(uap, val), mtod(m, caddr_t),
    769 		    (u_int)SCARG(uap, valsize))) {
    770 			(void) m_free(m);
    771 			return (error);
    772 		}
    773 		m->m_len = SCARG(uap, valsize);
    774 	}
    775 	return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
    776 	    SCARG(uap, name), m));
    777 }
    778 
    779 /* ARGSUSED */
    780 int
    781 sys_getsockopt(p, v, retval)
    782 	struct proc *p;
    783 	void *v;
    784 	register_t *retval;
    785 {
    786 	register struct sys_getsockopt_args /* {
    787 		syscallarg(int) s;
    788 		syscallarg(int) level;
    789 		syscallarg(int) name;
    790 		syscallarg(caddr_t) val;
    791 		syscallarg(int *) avalsize;
    792 	} */ *uap = v;
    793 	struct file *fp;
    794 	struct mbuf *m = NULL;
    795 	int valsize, error;
    796 
    797 	if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
    798 		return (error);
    799 	if (SCARG(uap, val)) {
    800 		if (error = copyin((caddr_t)SCARG(uap, avalsize),
    801 		    (caddr_t)&valsize, sizeof (valsize)))
    802 			return (error);
    803 	} else
    804 		valsize = 0;
    805 	if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
    806 	    SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
    807 	    m != NULL) {
    808 		if (valsize > m->m_len)
    809 			valsize = m->m_len;
    810 		error = copyout(mtod(m, caddr_t), SCARG(uap, val),
    811 		    (u_int)valsize);
    812 		if (error == 0)
    813 			error = copyout((caddr_t)&valsize,
    814 			    (caddr_t)SCARG(uap, avalsize), sizeof (valsize));
    815 	}
    816 	if (m != NULL)
    817 		(void) m_free(m);
    818 	return (error);
    819 }
    820 
    821 /* ARGSUSED */
    822 int
    823 sys_pipe(p, v, retval)
    824 	struct proc *p;
    825 	void *v;
    826 	register_t *retval;
    827 {
    828 	register struct filedesc *fdp = p->p_fd;
    829 	struct file *rf, *wf;
    830 	struct socket *rso, *wso;
    831 	int fd, error;
    832 
    833 	if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0))
    834 		return (error);
    835 	if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0))
    836 		goto free1;
    837 	if (error = falloc(p, &rf, &fd))
    838 		goto free2;
    839 	retval[0] = fd;
    840 	rf->f_flag = FREAD;
    841 	rf->f_type = DTYPE_SOCKET;
    842 	rf->f_ops = &socketops;
    843 	rf->f_data = (caddr_t)rso;
    844 	if (error = falloc(p, &wf, &fd))
    845 		goto free3;
    846 	wf->f_flag = FWRITE;
    847 	wf->f_type = DTYPE_SOCKET;
    848 	wf->f_ops = &socketops;
    849 	wf->f_data = (caddr_t)wso;
    850 	retval[1] = fd;
    851 	if (error = unp_connect2(wso, rso))
    852 		goto free4;
    853 	return (0);
    854 free4:
    855 	ffree(wf);
    856 	fdp->fd_ofiles[retval[1]] = 0;
    857 free3:
    858 	ffree(rf);
    859 	fdp->fd_ofiles[retval[0]] = 0;
    860 free2:
    861 	(void)soclose(wso);
    862 free1:
    863 	(void)soclose(rso);
    864 	return (error);
    865 }
    866 
    867 /*
    868  * Get socket name.
    869  */
    870 /* ARGSUSED */
    871 int
    872 sys_getsockname(p, v, retval)
    873 	struct proc *p;
    874 	void *v;
    875 	register_t *retval;
    876 {
    877 	register struct sys_getsockname_args /* {
    878 		syscallarg(int) fdes;
    879 		syscallarg(caddr_t) asa;
    880 		syscallarg(int *) alen;
    881 	} */ *uap = v;
    882 	struct file *fp;
    883 	register struct socket *so;
    884 	struct mbuf *m;
    885 	int len, error;
    886 
    887 	if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp))
    888 		return (error);
    889 	if (error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len,
    890 	    sizeof (len)))
    891 		return (error);
    892 	so = (struct socket *)fp->f_data;
    893 	m = m_getclr(M_WAIT, MT_SONAME);
    894 	if (m == NULL)
    895 		return (ENOBUFS);
    896 	if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
    897 		goto bad;
    898 	if (len > m->m_len)
    899 		len = m->m_len;
    900 	error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len);
    901 	if (error == 0)
    902 		error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
    903 		    sizeof (len));
    904 bad:
    905 	m_freem(m);
    906 	return (error);
    907 }
    908 
    909 /*
    910  * Get name of peer for connected socket.
    911  */
    912 /* ARGSUSED */
    913 int
    914 sys_getpeername(p, v, retval)
    915 	struct proc *p;
    916 	void *v;
    917 	register_t *retval;
    918 {
    919 	register struct sys_getpeername_args /* {
    920 		syscallarg(int) fdes;
    921 		syscallarg(caddr_t) asa;
    922 		syscallarg(int *) alen;
    923 	} */ *uap = v;
    924 	struct file *fp;
    925 	register struct socket *so;
    926 	struct mbuf *m;
    927 	int len, error;
    928 
    929 	if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp))
    930 		return (error);
    931 	so = (struct socket *)fp->f_data;
    932 	if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
    933 		return (ENOTCONN);
    934 	if (error =
    935 	    copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)))
    936 		return (error);
    937 	m = m_getclr(M_WAIT, MT_SONAME);
    938 	if (m == NULL)
    939 		return (ENOBUFS);
    940 	if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
    941 		goto bad;
    942 	if (len > m->m_len)
    943 		len = m->m_len;
    944 	if (error =
    945 	    copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len))
    946 		goto bad;
    947 	error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof (len));
    948 bad:
    949 	m_freem(m);
    950 	return (error);
    951 }
    952 
    953 int
    954 sockargs(mp, buf, buflen, type)
    955 	struct mbuf **mp;
    956 	caddr_t buf;
    957 	int buflen, type;
    958 {
    959 	register struct sockaddr *sa;
    960 	register struct mbuf *m;
    961 	int error;
    962 
    963 	if ((u_int)buflen > MLEN) {
    964 #ifdef COMPAT_OLDSOCK
    965 		if (type == MT_SONAME && (u_int)buflen <= 112)
    966 			buflen = MLEN;		/* unix domain compat. hack */
    967 		else
    968 #endif
    969 		return (EINVAL);
    970 	}
    971 	m = m_get(M_WAIT, type);
    972 	if (m == NULL)
    973 		return (ENOBUFS);
    974 	m->m_len = buflen;
    975 	error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
    976 	if (error) {
    977 		(void) m_free(m);
    978 		return (error);
    979 	}
    980 	*mp = m;
    981 	if (type == MT_SONAME) {
    982 		sa = mtod(m, struct sockaddr *);
    983 
    984 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
    985 		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
    986 			sa->sa_family = sa->sa_len;
    987 #endif
    988 		sa->sa_len = buflen;
    989 	}
    990 	return (0);
    991 }
    992 
    993 int
    994 getsock(fdp, fdes, fpp)
    995 	struct filedesc *fdp;
    996 	int fdes;
    997 	struct file **fpp;
    998 {
    999 	register struct file *fp;
   1000 
   1001 	if ((unsigned)fdes >= fdp->fd_nfiles ||
   1002 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
   1003 		return (EBADF);
   1004 	if (fp->f_type != DTYPE_SOCKET)
   1005 		return (ENOTSOCK);
   1006 	*fpp = fp;
   1007 	return (0);
   1008 }
   1009