xref: /freebsd/sys/kern/uipc_syscalls.c (revision 0de89efe5c443f213c7ea28773ef2dc6cf3af2ed)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)uipc_syscalls.c	8.4 (Berkeley) 2/21/94
34  * $Id: uipc_syscalls.c,v 1.29 1997/08/17 19:47:28 wollman Exp $
35  */
36 
37 #include "opt_ktrace.h"
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sysproto.h>
42 #include <sys/filedesc.h>
43 #include <sys/proc.h>
44 #include <sys/fcntl.h>
45 #include <sys/file.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 #ifdef KTRACE
53 #include <sys/ktrace.h>
54 #endif
55 
56 extern int sendit __P((struct proc *p, int s, struct msghdr *mp, int flags,
57 		       int *retsize));
58 extern int recvit __P((struct proc *p, int s, struct msghdr *mp,
59 		       caddr_t namelenp, int *retsize));
60 
61 static int accept1 __P((struct proc *p, struct accept_args *uap, int *retval,
62 			int compat));
63 static int getsockname1 __P((struct proc *p, struct getsockname_args *uap,
64 			     int *retval, int compat));
65 static int getpeername1 __P((struct proc *p, struct getpeername_args *uap,
66 			     int *retval, int compat));
67 
68 /*
69  * System call interface to the socket abstraction.
70  */
71 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
72 #define COMPAT_OLDSOCK
73 #endif
74 
75 extern	struct fileops socketops;
76 
77 int
78 socket(p, uap, retval)
79 	struct proc *p;
80 	register struct socket_args /* {
81 		int	domain;
82 		int	type;
83 		int	protocol;
84 	} */ *uap;
85 	int *retval;
86 {
87 	struct filedesc *fdp = p->p_fd;
88 	struct socket *so;
89 	struct file *fp;
90 	int fd, error;
91 
92 	error = falloc(p, &fp, &fd);
93 	if (error)
94 		return (error);
95 	fp->f_flag = FREAD|FWRITE;
96 	fp->f_type = DTYPE_SOCKET;
97 	fp->f_ops = &socketops;
98 	error = socreate(uap->domain, &so, uap->type, uap->protocol, p);
99 	if (error) {
100 		fdp->fd_ofiles[fd] = 0;
101 		ffree(fp);
102 	} else {
103 		fp->f_data = (caddr_t)so;
104 		*retval = fd;
105 	}
106 	return (error);
107 }
108 
109 /* ARGSUSED */
110 int
111 bind(p, uap, retval)
112 	struct proc *p;
113 	register struct bind_args /* {
114 		int	s;
115 		caddr_t	name;
116 		int	namelen;
117 	} */ *uap;
118 	int *retval;
119 {
120 	struct file *fp;
121 	struct sockaddr *sa;
122 	int error;
123 
124 	error = getsock(p->p_fd, uap->s, &fp);
125 	if (error)
126 		return (error);
127 	error = getsockaddr(&sa, uap->name, uap->namelen);
128 	if (error)
129 		return (error);
130 	error = sobind((struct socket *)fp->f_data, sa, p);
131 	FREE(sa, M_SONAME);
132 	return (error);
133 }
134 
135 /* ARGSUSED */
136 int
137 listen(p, uap, retval)
138 	struct proc *p;
139 	register struct listen_args /* {
140 		int	s;
141 		int	backlog;
142 	} */ *uap;
143 	int *retval;
144 {
145 	struct file *fp;
146 	int error;
147 
148 	error = getsock(p->p_fd, uap->s, &fp);
149 	if (error)
150 		return (error);
151 	return (solisten((struct socket *)fp->f_data, uap->backlog, p));
152 }
153 
154 static int
155 accept1(p, uap, retval, compat)
156 	struct proc *p;
157 	register struct accept_args /* {
158 		int	s;
159 		caddr_t	name;
160 		int	*anamelen;
161 	} */ *uap;
162 	int *retval;
163 	int compat;
164 {
165 	struct file *fp;
166 	struct sockaddr *sa;
167 	int namelen, error, s;
168 	struct socket *head, *so;
169 	short fflag;		/* type must match fp->f_flag */
170 
171 	if (uap->name) {
172 		error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
173 			sizeof (namelen));
174 		if(error)
175 			return (error);
176 	}
177 	error = getsock(p->p_fd, uap->s, &fp);
178 	if (error)
179 		return (error);
180 	s = splnet();
181 	head = (struct socket *)fp->f_data;
182 	if ((head->so_options & SO_ACCEPTCONN) == 0) {
183 		splx(s);
184 		return (EINVAL);
185 	}
186 	if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
187 		splx(s);
188 		return (EWOULDBLOCK);
189 	}
190 	while (head->so_comp.tqh_first == NULL && head->so_error == 0) {
191 		if (head->so_state & SS_CANTRCVMORE) {
192 			head->so_error = ECONNABORTED;
193 			break;
194 		}
195 		error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
196 		    "accept", 0);
197 		if (error) {
198 			splx(s);
199 			return (error);
200 		}
201 	}
202 	if (head->so_error) {
203 		error = head->so_error;
204 		head->so_error = 0;
205 		splx(s);
206 		return (error);
207 	}
208 
209 	/*
210 	 * At this point we know that there is at least one connection
211 	 * ready to be accepted. Remove it from the queue prior to
212 	 * allocating the file descriptor for it since falloc() may
213 	 * block allowing another process to accept the connection
214 	 * instead.
215 	 */
216 	so = head->so_comp.tqh_first;
217 	TAILQ_REMOVE(&head->so_comp, so, so_list);
218 	head->so_qlen--;
219 
220 	fflag = fp->f_flag;
221 	error = falloc(p, &fp, retval);
222 	if (error) {
223 		/*
224 		 * Probably ran out of file descriptors. Put the
225 		 * unaccepted connection back onto the queue and
226 		 * do another wakeup so some other process might
227 		 * have a chance at it.
228 		 */
229 		TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
230 		head->so_qlen++;
231 		wakeup_one(&head->so_timeo);
232 		splx(s);
233 		return (error);
234 	}
235 
236 	so->so_state &= ~SS_COMP;
237 	so->so_head = NULL;
238 
239 	fp->f_type = DTYPE_SOCKET;
240 	fp->f_flag = fflag;
241 	fp->f_ops = &socketops;
242 	fp->f_data = (caddr_t)so;
243 	sa = 0;
244 	(void) soaccept(so, &sa);
245 	if (sa == 0) {
246 		namelen = 0;
247 		if (uap->name)
248 			goto gotnoname;
249 		return 0;
250 	}
251 	if (uap->name) {
252 #ifdef COMPAT_OLDSOCK
253 		if (compat)
254 			((struct osockaddr *)sa)->sa_family =
255 			    sa->sa_family;
256 #endif
257 		if (namelen > sa->sa_len)
258 			namelen = sa->sa_len;
259 		error = copyout(sa, (caddr_t)uap->name, (u_int)namelen);
260 		if (!error)
261 gotnoname:
262 			error = copyout((caddr_t)&namelen,
263 			    (caddr_t)uap->anamelen, sizeof (*uap->anamelen));
264 	}
265 	FREE(sa, M_SONAME);
266 	splx(s);
267 	return (error);
268 }
269 
270 int
271 accept(p, uap, retval)
272 	struct proc *p;
273 	struct accept_args *uap;
274 	int *retval;
275 {
276 
277 	return (accept1(p, uap, retval, 0));
278 }
279 
280 #ifdef COMPAT_OLDSOCK
281 int
282 oaccept(p, uap, retval)
283 	struct proc *p;
284 	struct accept_args *uap;
285 	int *retval;
286 {
287 
288 	return (accept1(p, uap, retval, 1));
289 }
290 #endif /* COMPAT_OLDSOCK */
291 
292 /* ARGSUSED */
293 int
294 connect(p, uap, retval)
295 	struct proc *p;
296 	register struct connect_args /* {
297 		int	s;
298 		caddr_t	name;
299 		int	namelen;
300 	} */ *uap;
301 	int *retval;
302 {
303 	struct file *fp;
304 	register struct socket *so;
305 	struct sockaddr *sa;
306 	int error, s;
307 
308 	error = getsock(p->p_fd, uap->s, &fp);
309 	if (error)
310 		return (error);
311 	so = (struct socket *)fp->f_data;
312 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
313 		return (EALREADY);
314 	error = getsockaddr(&sa, uap->name, uap->namelen);
315 	if (error)
316 		return (error);
317 	error = soconnect(so, sa, p);
318 	if (error)
319 		goto bad;
320 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
321 		FREE(sa, M_SONAME);
322 		return (EINPROGRESS);
323 	}
324 	s = splnet();
325 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
326 		error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
327 		    "connec", 0);
328 		if (error)
329 			break;
330 	}
331 	if (error == 0) {
332 		error = so->so_error;
333 		so->so_error = 0;
334 	}
335 	splx(s);
336 bad:
337 	so->so_state &= ~SS_ISCONNECTING;
338 	FREE(sa, M_SONAME);
339 	if (error == ERESTART)
340 		error = EINTR;
341 	return (error);
342 }
343 
344 int
345 socketpair(p, uap, retval)
346 	struct proc *p;
347 	register struct socketpair_args /* {
348 		int	domain;
349 		int	type;
350 		int	protocol;
351 		int	*rsv;
352 	} */ *uap;
353 	int retval[];
354 {
355 	register struct filedesc *fdp = p->p_fd;
356 	struct file *fp1, *fp2;
357 	struct socket *so1, *so2;
358 	int fd, error, sv[2];
359 
360 	error = socreate(uap->domain, &so1, uap->type, uap->protocol, p);
361 	if (error)
362 		return (error);
363 	error = socreate(uap->domain, &so2, uap->type, uap->protocol, p);
364 	if (error)
365 		goto free1;
366 	error = falloc(p, &fp1, &fd);
367 	if (error)
368 		goto free2;
369 	sv[0] = fd;
370 	fp1->f_flag = FREAD|FWRITE;
371 	fp1->f_type = DTYPE_SOCKET;
372 	fp1->f_ops = &socketops;
373 	fp1->f_data = (caddr_t)so1;
374 	error = falloc(p, &fp2, &fd);
375 	if (error)
376 		goto free3;
377 	fp2->f_flag = FREAD|FWRITE;
378 	fp2->f_type = DTYPE_SOCKET;
379 	fp2->f_ops = &socketops;
380 	fp2->f_data = (caddr_t)so2;
381 	sv[1] = fd;
382 	error = soconnect2(so1, so2);
383 	if (error)
384 		goto free4;
385 	if (uap->type == SOCK_DGRAM) {
386 		/*
387 		 * Datagram socket connection is asymmetric.
388 		 */
389 		 error = soconnect2(so2, so1);
390 		 if (error)
391 			goto free4;
392 	}
393 	error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
394 #if 0	/* old pipe(2) syscall compatability, unused these days */
395 	retval[0] = sv[0];		/* XXX ??? */
396 	retval[1] = sv[1];		/* XXX ??? */
397 #endif
398 	return (error);
399 free4:
400 	ffree(fp2);
401 	fdp->fd_ofiles[sv[1]] = 0;
402 free3:
403 	ffree(fp1);
404 	fdp->fd_ofiles[sv[0]] = 0;
405 free2:
406 	(void)soclose(so2);
407 free1:
408 	(void)soclose(so1);
409 	return (error);
410 }
411 
412 int
413 sendit(p, s, mp, flags, retsize)
414 	register struct proc *p;
415 	int s;
416 	register struct msghdr *mp;
417 	int flags, *retsize;
418 {
419 	struct file *fp;
420 	struct uio auio;
421 	register struct iovec *iov;
422 	register int i;
423 	struct mbuf *control;
424 	struct sockaddr *to;
425 	int len, error;
426 	struct socket *so;
427 #ifdef KTRACE
428 	struct iovec *ktriov = NULL;
429 #endif
430 
431 	error = getsock(p->p_fd, s, &fp);
432 	if (error)
433 		return (error);
434 	auio.uio_iov = mp->msg_iov;
435 	auio.uio_iovcnt = mp->msg_iovlen;
436 	auio.uio_segflg = UIO_USERSPACE;
437 	auio.uio_rw = UIO_WRITE;
438 	auio.uio_procp = p;
439 	auio.uio_offset = 0;			/* XXX */
440 	auio.uio_resid = 0;
441 	iov = mp->msg_iov;
442 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
443 		if ((auio.uio_resid += iov->iov_len) < 0)
444 			return (EINVAL);
445 	}
446 	if (mp->msg_name) {
447 		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
448 		if (error)
449 			return (error);
450 	} else
451 		to = 0;
452 	if (mp->msg_control) {
453 		if (mp->msg_controllen < sizeof(struct cmsghdr)
454 #ifdef COMPAT_OLDSOCK
455 		    && mp->msg_flags != MSG_COMPAT
456 #endif
457 		) {
458 			error = EINVAL;
459 			goto bad;
460 		}
461 		error = sockargs(&control, mp->msg_control,
462 		    mp->msg_controllen, MT_CONTROL);
463 		if (error)
464 			goto bad;
465 #ifdef COMPAT_OLDSOCK
466 		if (mp->msg_flags == MSG_COMPAT) {
467 			register struct cmsghdr *cm;
468 
469 			M_PREPEND(control, sizeof(*cm), M_WAIT);
470 			if (control == 0) {
471 				error = ENOBUFS;
472 				goto bad;
473 			} else {
474 				cm = mtod(control, struct cmsghdr *);
475 				cm->cmsg_len = control->m_len;
476 				cm->cmsg_level = SOL_SOCKET;
477 				cm->cmsg_type = SCM_RIGHTS;
478 			}
479 		}
480 #endif
481 	} else
482 		control = 0;
483 #ifdef KTRACE
484 	if (KTRPOINT(p, KTR_GENIO)) {
485 		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
486 
487 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
488 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
489 	}
490 #endif
491 	len = auio.uio_resid;
492 	so = (struct socket *)fp->f_data;
493 	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
494 						     flags, p);
495 	if (error) {
496 		if (auio.uio_resid != len && (error == ERESTART ||
497 		    error == EINTR || error == EWOULDBLOCK))
498 			error = 0;
499 		if (error == EPIPE)
500 			psignal(p, SIGPIPE);
501 	}
502 	if (error == 0)
503 		*retsize = len - auio.uio_resid;
504 #ifdef KTRACE
505 	if (ktriov != NULL) {
506 		if (error == 0)
507 			ktrgenio(p->p_tracep, s, UIO_WRITE,
508 				ktriov, *retsize, error);
509 		FREE(ktriov, M_TEMP);
510 	}
511 #endif
512 bad:
513 	if (to)
514 		FREE(to, M_SONAME);
515 	return (error);
516 }
517 
518 int
519 sendto(p, uap, retval)
520 	struct proc *p;
521 	register struct sendto_args /* {
522 		int	s;
523 		caddr_t	buf;
524 		size_t	len;
525 		int	flags;
526 		caddr_t	to;
527 		int	tolen;
528 	} */ *uap;
529 	int *retval;
530 {
531 	struct msghdr msg;
532 	struct iovec aiov;
533 
534 	msg.msg_name = uap->to;
535 	msg.msg_namelen = uap->tolen;
536 	msg.msg_iov = &aiov;
537 	msg.msg_iovlen = 1;
538 	msg.msg_control = 0;
539 #ifdef COMPAT_OLDSOCK
540 	msg.msg_flags = 0;
541 #endif
542 	aiov.iov_base = uap->buf;
543 	aiov.iov_len = uap->len;
544 	return (sendit(p, uap->s, &msg, uap->flags, retval));
545 }
546 
547 #ifdef COMPAT_OLDSOCK
548 int
549 osend(p, uap, retval)
550 	struct proc *p;
551 	register struct osend_args /* {
552 		int	s;
553 		caddr_t	buf;
554 		int	len;
555 		int	flags;
556 	} */ *uap;
557 	int *retval;
558 {
559 	struct msghdr msg;
560 	struct iovec aiov;
561 
562 	msg.msg_name = 0;
563 	msg.msg_namelen = 0;
564 	msg.msg_iov = &aiov;
565 	msg.msg_iovlen = 1;
566 	aiov.iov_base = uap->buf;
567 	aiov.iov_len = uap->len;
568 	msg.msg_control = 0;
569 	msg.msg_flags = 0;
570 	return (sendit(p, uap->s, &msg, uap->flags, retval));
571 }
572 
573 int
574 osendmsg(p, uap, retval)
575 	struct proc *p;
576 	register struct osendmsg_args /* {
577 		int	s;
578 		caddr_t	msg;
579 		int	flags;
580 	} */ *uap;
581 	int *retval;
582 {
583 	struct msghdr msg;
584 	struct iovec aiov[UIO_SMALLIOV], *iov;
585 	int error;
586 
587 	error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
588 	if (error)
589 		return (error);
590 	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
591 		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
592 			return (EMSGSIZE);
593 		MALLOC(iov, struct iovec *,
594 		      sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
595 		      M_WAITOK);
596 	} else
597 		iov = aiov;
598 	error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
599 	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
600 	if (error)
601 		goto done;
602 	msg.msg_flags = MSG_COMPAT;
603 	msg.msg_iov = iov;
604 	error = sendit(p, uap->s, &msg, uap->flags, retval);
605 done:
606 	if (iov != aiov)
607 		FREE(iov, M_IOV);
608 	return (error);
609 }
610 #endif
611 
612 int
613 sendmsg(p, uap, retval)
614 	struct proc *p;
615 	register struct sendmsg_args /* {
616 		int	s;
617 		caddr_t	msg;
618 		int	flags;
619 	} */ *uap;
620 	int *retval;
621 {
622 	struct msghdr msg;
623 	struct iovec aiov[UIO_SMALLIOV], *iov;
624 	int error;
625 
626 	error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
627 	if (error)
628 		return (error);
629 	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
630 		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
631 			return (EMSGSIZE);
632 		MALLOC(iov, struct iovec *,
633 		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
634 		       M_WAITOK);
635 	} else
636 		iov = aiov;
637 	if (msg.msg_iovlen &&
638 	    (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
639 	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
640 		goto done;
641 	msg.msg_iov = iov;
642 #ifdef COMPAT_OLDSOCK
643 	msg.msg_flags = 0;
644 #endif
645 	error = sendit(p, uap->s, &msg, uap->flags, retval);
646 done:
647 	if (iov != aiov)
648 		FREE(iov, M_IOV);
649 	return (error);
650 }
651 
652 int
653 recvit(p, s, mp, namelenp, retsize)
654 	register struct proc *p;
655 	int s;
656 	register struct msghdr *mp;
657 	caddr_t namelenp;
658 	int *retsize;
659 {
660 	struct file *fp;
661 	struct uio auio;
662 	register struct iovec *iov;
663 	register int i;
664 	int len, error;
665 	struct mbuf *m, *control = 0;
666 	caddr_t ctlbuf;
667 	struct socket *so;
668 	struct sockaddr *fromsa = 0;
669 #ifdef KTRACE
670 	struct iovec *ktriov = NULL;
671 #endif
672 
673 	error = getsock(p->p_fd, s, &fp);
674 	if (error)
675 		return (error);
676 	auio.uio_iov = mp->msg_iov;
677 	auio.uio_iovcnt = mp->msg_iovlen;
678 	auio.uio_segflg = UIO_USERSPACE;
679 	auio.uio_rw = UIO_READ;
680 	auio.uio_procp = p;
681 	auio.uio_offset = 0;			/* XXX */
682 	auio.uio_resid = 0;
683 	iov = mp->msg_iov;
684 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
685 		if ((auio.uio_resid += iov->iov_len) < 0)
686 			return (EINVAL);
687 	}
688 #ifdef KTRACE
689 	if (KTRPOINT(p, KTR_GENIO)) {
690 		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
691 
692 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
693 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
694 	}
695 #endif
696 	len = auio.uio_resid;
697 	so = (struct socket *)fp->f_data;
698 	error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
699 	    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
700 	    &mp->msg_flags);
701 	if (error) {
702 		if (auio.uio_resid != len && (error == ERESTART ||
703 		    error == EINTR || error == EWOULDBLOCK))
704 			error = 0;
705 	}
706 #ifdef KTRACE
707 	if (ktriov != NULL) {
708 		if (error == 0)
709 			ktrgenio(p->p_tracep, s, UIO_READ,
710 				ktriov, len - auio.uio_resid, error);
711 		FREE(ktriov, M_TEMP);
712 	}
713 #endif
714 	if (error)
715 		goto out;
716 	*retsize = len - auio.uio_resid;
717 	if (mp->msg_name) {
718 		len = mp->msg_namelen;
719 		if (len <= 0 || fromsa == 0)
720 			len = 0;
721 		else {
722 #ifdef COMPAT_OLDSOCK
723 			if (mp->msg_flags & MSG_COMPAT)
724 				((struct osockaddr *)fromsa)->sa_family =
725 				    fromsa->sa_family;
726 #endif
727 #ifndef MIN
728 #define MIN(a,b) ((a)>(b)?(b):(a))
729 #endif
730 			len = MIN(len, fromsa->sa_len);
731 			error = copyout(fromsa,
732 			    (caddr_t)mp->msg_name, (unsigned)len);
733 			if (error)
734 				goto out;
735 		}
736 		mp->msg_namelen = len;
737 		if (namelenp &&
738 		    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
739 #ifdef COMPAT_OLDSOCK
740 			if (mp->msg_flags & MSG_COMPAT)
741 				error = 0;	/* old recvfrom didn't check */
742 			else
743 #endif
744 			goto out;
745 		}
746 	}
747 	if (mp->msg_control) {
748 #ifdef COMPAT_OLDSOCK
749 		/*
750 		 * We assume that old recvmsg calls won't receive access
751 		 * rights and other control info, esp. as control info
752 		 * is always optional and those options didn't exist in 4.3.
753 		 * If we receive rights, trim the cmsghdr; anything else
754 		 * is tossed.
755 		 */
756 		if (control && mp->msg_flags & MSG_COMPAT) {
757 			if (mtod(control, struct cmsghdr *)->cmsg_level !=
758 			    SOL_SOCKET ||
759 			    mtod(control, struct cmsghdr *)->cmsg_type !=
760 			    SCM_RIGHTS) {
761 				mp->msg_controllen = 0;
762 				goto out;
763 			}
764 			control->m_len -= sizeof (struct cmsghdr);
765 			control->m_data += sizeof (struct cmsghdr);
766 		}
767 #endif
768 		len = mp->msg_controllen;
769 		m = control;
770 		mp->msg_controllen = 0;
771 		ctlbuf = (caddr_t) mp->msg_control;
772 
773 		while (m && len > 0) {
774 			unsigned int tocopy;
775 
776 			if (len >= m->m_len)
777 				tocopy = m->m_len;
778 			else {
779 				mp->msg_flags |= MSG_CTRUNC;
780 				tocopy = len;
781 			}
782 
783 			if (error = copyout((caddr_t)mtod(m, caddr_t),
784 					ctlbuf, tocopy))
785 				goto out;
786 
787 			ctlbuf += tocopy;
788 			len -= tocopy;
789 			m = m->m_next;
790 		}
791 		mp->msg_controllen = ctlbuf - mp->msg_control;
792 	}
793 out:
794 	if (fromsa)
795 		FREE(fromsa, M_SONAME);
796 	if (control)
797 		m_freem(control);
798 	return (error);
799 }
800 
801 int
802 recvfrom(p, uap, retval)
803 	struct proc *p;
804 	register struct recvfrom_args /* {
805 		int	s;
806 		caddr_t	buf;
807 		size_t	len;
808 		int	flags;
809 		caddr_t	from;
810 		int	*fromlenaddr;
811 	} */ *uap;
812 	int *retval;
813 {
814 	struct msghdr msg;
815 	struct iovec aiov;
816 	int error;
817 
818 	if (uap->fromlenaddr) {
819 		error = copyin((caddr_t)uap->fromlenaddr,
820 		    (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen));
821 		if (error)
822 			return (error);
823 	} else
824 		msg.msg_namelen = 0;
825 	msg.msg_name = uap->from;
826 	msg.msg_iov = &aiov;
827 	msg.msg_iovlen = 1;
828 	aiov.iov_base = uap->buf;
829 	aiov.iov_len = uap->len;
830 	msg.msg_control = 0;
831 	msg.msg_flags = uap->flags;
832 	return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval));
833 }
834 
835 #ifdef COMPAT_OLDSOCK
836 int
837 orecvfrom(p, uap, retval)
838 	struct proc *p;
839 	struct recvfrom_args *uap;
840 	int *retval;
841 {
842 
843 	uap->flags |= MSG_COMPAT;
844 	return (recvfrom(p, uap, retval));
845 }
846 #endif
847 
848 
849 #ifdef COMPAT_OLDSOCK
850 int
851 orecv(p, uap, retval)
852 	struct proc *p;
853 	register struct orecv_args /* {
854 		int	s;
855 		caddr_t	buf;
856 		int	len;
857 		int	flags;
858 	} */ *uap;
859 	int *retval;
860 {
861 	struct msghdr msg;
862 	struct iovec aiov;
863 
864 	msg.msg_name = 0;
865 	msg.msg_namelen = 0;
866 	msg.msg_iov = &aiov;
867 	msg.msg_iovlen = 1;
868 	aiov.iov_base = uap->buf;
869 	aiov.iov_len = uap->len;
870 	msg.msg_control = 0;
871 	msg.msg_flags = uap->flags;
872 	return (recvit(p, uap->s, &msg, (caddr_t)0, retval));
873 }
874 
875 /*
876  * Old recvmsg.  This code takes advantage of the fact that the old msghdr
877  * overlays the new one, missing only the flags, and with the (old) access
878  * rights where the control fields are now.
879  */
880 int
881 orecvmsg(p, uap, retval)
882 	struct proc *p;
883 	register struct orecvmsg_args /* {
884 		int	s;
885 		struct	omsghdr *msg;
886 		int	flags;
887 	} */ *uap;
888 	int *retval;
889 {
890 	struct msghdr msg;
891 	struct iovec aiov[UIO_SMALLIOV], *iov;
892 	int error;
893 
894 	error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
895 	    sizeof (struct omsghdr));
896 	if (error)
897 		return (error);
898 	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
899 		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
900 			return (EMSGSIZE);
901 		MALLOC(iov, struct iovec *,
902 		      sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
903 		      M_WAITOK);
904 	} else
905 		iov = aiov;
906 	msg.msg_flags = uap->flags | MSG_COMPAT;
907 	error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
908 	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
909 	if (error)
910 		goto done;
911 	msg.msg_iov = iov;
912 	error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval);
913 
914 	if (msg.msg_controllen && error == 0)
915 		error = copyout((caddr_t)&msg.msg_controllen,
916 		    (caddr_t)&uap->msg->msg_accrightslen, sizeof (int));
917 done:
918 	if (iov != aiov)
919 		FREE(iov, M_IOV);
920 	return (error);
921 }
922 #endif
923 
924 int
925 recvmsg(p, uap, retval)
926 	struct proc *p;
927 	register struct recvmsg_args /* {
928 		int	s;
929 		struct	msghdr *msg;
930 		int	flags;
931 	} */ *uap;
932 	int *retval;
933 {
934 	struct msghdr msg;
935 	struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
936 	register int error;
937 
938 	error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
939 	if (error)
940 		return (error);
941 	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
942 		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
943 			return (EMSGSIZE);
944 		MALLOC(iov, struct iovec *,
945 		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
946 		       M_WAITOK);
947 	} else
948 		iov = aiov;
949 #ifdef COMPAT_OLDSOCK
950 	msg.msg_flags = uap->flags &~ MSG_COMPAT;
951 #else
952 	msg.msg_flags = uap->flags;
953 #endif
954 	uiov = msg.msg_iov;
955 	msg.msg_iov = iov;
956 	error = copyin((caddr_t)uiov, (caddr_t)iov,
957 	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
958 	if (error)
959 		goto done;
960 	error = recvit(p, uap->s, &msg, (caddr_t)0, retval);
961 	if (!error) {
962 		msg.msg_iov = uiov;
963 		error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
964 	}
965 done:
966 	if (iov != aiov)
967 		FREE(iov, M_IOV);
968 	return (error);
969 }
970 
971 /* ARGSUSED */
972 int
973 shutdown(p, uap, retval)
974 	struct proc *p;
975 	register struct shutdown_args /* {
976 		int	s;
977 		int	how;
978 	} */ *uap;
979 	int *retval;
980 {
981 	struct file *fp;
982 	int error;
983 
984 	error = getsock(p->p_fd, uap->s, &fp);
985 	if (error)
986 		return (error);
987 	return (soshutdown((struct socket *)fp->f_data, uap->how));
988 }
989 
990 /* ARGSUSED */
991 int
992 setsockopt(p, uap, retval)
993 	struct proc *p;
994 	register struct setsockopt_args /* {
995 		int	s;
996 		int	level;
997 		int	name;
998 		caddr_t	val;
999 		int	valsize;
1000 	} */ *uap;
1001 	int *retval;
1002 {
1003 	struct file *fp;
1004 	struct mbuf *m = NULL;
1005 	int error;
1006 
1007 	error = getsock(p->p_fd, uap->s, &fp);
1008 	if (error)
1009 		return (error);
1010 	if (uap->valsize > MLEN)
1011 		return (EINVAL);
1012 	if (uap->val) {
1013 		m = m_get(M_WAIT, MT_SOOPTS);
1014 		if (m == NULL)
1015 			return (ENOBUFS);
1016 		error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
1017 		if (error) {
1018 			(void) m_free(m);
1019 			return (error);
1020 		}
1021 		m->m_len = uap->valsize;
1022 	}
1023 	return (sosetopt((struct socket *)fp->f_data, uap->level,
1024 	    uap->name, m, p));
1025 }
1026 
1027 /* ARGSUSED */
1028 int
1029 getsockopt(p, uap, retval)
1030 	struct proc *p;
1031 	register struct getsockopt_args /* {
1032 		int	s;
1033 		int	level;
1034 		int	name;
1035 		caddr_t	val;
1036 		int	*avalsize;
1037 	} */ *uap;
1038 	int *retval;
1039 {
1040 	struct file *fp;
1041 	struct mbuf *m = NULL, *m0;
1042 	int op, i, valsize, error;
1043 
1044 	error = getsock(p->p_fd, uap->s, &fp);
1045 	if (error)
1046 		return (error);
1047 	if (uap->val) {
1048 		error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
1049 		    sizeof (valsize));
1050 		if (error)
1051 			return (error);
1052 	} else
1053 		valsize = 0;
1054 	if ((error = sogetopt((struct socket *)fp->f_data, uap->level,
1055 	    uap->name, &m, p)) == 0 && uap->val && valsize && m != NULL) {
1056 		op = 0;
1057 		while (m && !error && op < valsize) {
1058 			i = min(m->m_len, (valsize - op));
1059 			error = copyout(mtod(m, caddr_t), uap->val, (u_int)i);
1060 			op += i;
1061 			uap->val += i;
1062 			m0 = m;
1063 			MFREE(m0,m);
1064 		}
1065 		valsize = op;
1066 		if (error == 0)
1067 			error = copyout((caddr_t)&valsize,
1068 			    (caddr_t)uap->avalsize, sizeof (valsize));
1069 	}
1070 	if (m != NULL)
1071 		(void) m_free(m);
1072 	return (error);
1073 }
1074 
1075 /*
1076  * Get socket name.
1077  */
1078 /* ARGSUSED */
1079 static int
1080 getsockname1(p, uap, retval, compat)
1081 	struct proc *p;
1082 	register struct getsockname_args /* {
1083 		int	fdes;
1084 		caddr_t	asa;
1085 		int	*alen;
1086 	} */ *uap;
1087 	int *retval;
1088 	int compat;
1089 {
1090 	struct file *fp;
1091 	register struct socket *so;
1092 	struct sockaddr *sa;
1093 	int len, error;
1094 
1095 	error = getsock(p->p_fd, uap->fdes, &fp);
1096 	if (error)
1097 		return (error);
1098 	error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
1099 	if (error)
1100 		return (error);
1101 	so = (struct socket *)fp->f_data;
1102 	sa = 0;
1103 	error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
1104 	if (error)
1105 		goto bad;
1106 	if (sa == 0) {
1107 		len = 0;
1108 		goto gotnothing;
1109 	}
1110 
1111 	len = MIN(len, sa->sa_len);
1112 #ifdef COMPAT_OLDSOCK
1113 	if (compat)
1114 		((struct osockaddr *)sa)->sa_family = sa->sa_family;
1115 #endif
1116 	error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
1117 	if (error == 0)
1118 gotnothing:
1119 		error = copyout((caddr_t)&len, (caddr_t)uap->alen,
1120 		    sizeof (len));
1121 bad:
1122 	if (sa)
1123 		FREE(sa, M_SONAME);
1124 	return (error);
1125 }
1126 
1127 int
1128 getsockname(p, uap, retval)
1129 	struct proc *p;
1130 	struct getsockname_args *uap;
1131 	int *retval;
1132 {
1133 
1134 	return (getsockname1(p, uap, retval, 0));
1135 }
1136 
1137 #ifdef COMPAT_OLDSOCK
1138 int
1139 ogetsockname(p, uap, retval)
1140 	struct proc *p;
1141 	struct getsockname_args *uap;
1142 	int *retval;
1143 {
1144 
1145 	return (getsockname1(p, uap, retval, 1));
1146 }
1147 #endif /* COMPAT_OLDSOCK */
1148 
1149 /*
1150  * Get name of peer for connected socket.
1151  */
1152 /* ARGSUSED */
1153 static int
1154 getpeername1(p, uap, retval, compat)
1155 	struct proc *p;
1156 	register struct getpeername_args /* {
1157 		int	fdes;
1158 		caddr_t	asa;
1159 		int	*alen;
1160 	} */ *uap;
1161 	int *retval;
1162 	int compat;
1163 {
1164 	struct file *fp;
1165 	register struct socket *so;
1166 	struct sockaddr *sa;
1167 	int len, error;
1168 
1169 	error = getsock(p->p_fd, uap->fdes, &fp);
1170 	if (error)
1171 		return (error);
1172 	so = (struct socket *)fp->f_data;
1173 	if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
1174 		return (ENOTCONN);
1175 	error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
1176 	if (error)
1177 		return (error);
1178 	sa = 0;
1179 	error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
1180 	if (error)
1181 		goto bad;
1182 	if (sa == 0) {
1183 		len = 0;
1184 		goto gotnothing;
1185 	}
1186 	len = MIN(len, sa->sa_len);
1187 #ifdef COMPAT_OLDSOCK
1188 	if (compat)
1189 		((struct osockaddr *)sa)->sa_family =
1190 		    sa->sa_family;
1191 #endif
1192 	error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
1193 	if (error)
1194 		goto bad;
1195 gotnothing:
1196 	error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
1197 bad:
1198 	if (sa) FREE(sa, M_SONAME);
1199 	return (error);
1200 }
1201 
1202 int
1203 getpeername(p, uap, retval)
1204 	struct proc *p;
1205 	struct getpeername_args *uap;
1206 	int *retval;
1207 {
1208 
1209 	return (getpeername1(p, uap, retval, 0));
1210 }
1211 
1212 #ifdef COMPAT_OLDSOCK
1213 int
1214 ogetpeername(p, uap, retval)
1215 	struct proc *p;
1216 	struct ogetpeername_args *uap;
1217 	int *retval;
1218 {
1219 
1220 	/* XXX uap should have type `getpeername_args *' to begin with. */
1221 	return (getpeername1(p, (struct getpeername_args *)uap, retval, 1));
1222 }
1223 #endif /* COMPAT_OLDSOCK */
1224 
1225 int
1226 sockargs(mp, buf, buflen, type)
1227 	struct mbuf **mp;
1228 	caddr_t buf;
1229 	int buflen, type;
1230 {
1231 	register struct sockaddr *sa;
1232 	register struct mbuf *m;
1233 	int error;
1234 
1235 	if ((u_int)buflen > MLEN) {
1236 #ifdef COMPAT_OLDSOCK
1237 		if (type == MT_SONAME && (u_int)buflen <= 112)
1238 			buflen = MLEN;		/* unix domain compat. hack */
1239 		else
1240 #endif
1241 		return (EINVAL);
1242 	}
1243 	m = m_get(M_WAIT, type);
1244 	if (m == NULL)
1245 		return (ENOBUFS);
1246 	m->m_len = buflen;
1247 	error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1248 	if (error)
1249 		(void) m_free(m);
1250 	else {
1251 		*mp = m;
1252 		if (type == MT_SONAME) {
1253 			sa = mtod(m, struct sockaddr *);
1254 
1255 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1256 			if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1257 				sa->sa_family = sa->sa_len;
1258 #endif
1259 			sa->sa_len = buflen;
1260 		}
1261 	}
1262 	return (error);
1263 }
1264 
1265 int
1266 getsockaddr(namp, uaddr, len)
1267 	struct sockaddr **namp;
1268 	caddr_t uaddr;
1269 	size_t len;
1270 {
1271 	struct sockaddr *sa;
1272 	int error;
1273 
1274 	if (len > SOCK_MAXADDRLEN)
1275 		return ENAMETOOLONG;
1276 	MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
1277 	error = copyin(uaddr, sa, len);
1278 	if (error) {
1279 		FREE(sa, M_SONAME);
1280 	} else {
1281 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1282 		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1283 			sa->sa_family = sa->sa_len;
1284 #endif
1285 		sa->sa_len = len;
1286 		*namp = sa;
1287 	}
1288 	return error;
1289 }
1290 
1291 int
1292 getsock(fdp, fdes, fpp)
1293 	struct filedesc *fdp;
1294 	int fdes;
1295 	struct file **fpp;
1296 {
1297 	register struct file *fp;
1298 
1299 	if ((unsigned)fdes >= fdp->fd_nfiles ||
1300 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
1301 		return (EBADF);
1302 	if (fp->f_type != DTYPE_SOCKET)
1303 		return (ENOTSOCK);
1304 	*fpp = fp;
1305 	return (0);
1306 }
1307