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