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