xref: /original-bsd/sys/kern/uipc_syscalls.c (revision a76afa45)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)uipc_syscalls.c	7.10 (Berkeley) 05/09/89
18  */
19 
20 #include "param.h"
21 #include "user.h"
22 #include "proc.h"
23 #include "file.h"
24 #include "buf.h"
25 #include "malloc.h"
26 #include "mbuf.h"
27 #include "protosw.h"
28 #include "socket.h"
29 #include "socketvar.h"
30 
31 /*
32  * System call interface to the socket abstraction.
33  */
34 
35 struct	file *getsock();
36 extern	struct fileops socketops;
37 
38 socket()
39 {
40 	register struct a {
41 		int	domain;
42 		int	type;
43 		int	protocol;
44 	} *uap = (struct a *)u.u_ap;
45 	struct socket *so;
46 	struct file *fp;
47 	int fd;
48 
49 	if (u.u_error = falloc(&fp, &fd))
50 		return;
51 	fp->f_flag = FREAD|FWRITE;
52 	fp->f_type = DTYPE_SOCKET;
53 	fp->f_ops = &socketops;
54 	u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol);
55 	if (u.u_error)
56 		goto bad;
57 	fp->f_data = (caddr_t)so;
58 	u.u_r.r_val1 = fd;
59 	return;
60 bad:
61 	u.u_ofile[fd] = 0;
62 	crfree(fp->f_cred);
63 	fp->f_count = 0;
64 }
65 
66 bind()
67 {
68 	register struct a {
69 		int	s;
70 		caddr_t	name;
71 		int	namelen;
72 	} *uap = (struct a *)u.u_ap;
73 	register struct file *fp;
74 	struct mbuf *nam;
75 
76 	fp = getsock(uap->s);
77 	if (fp == 0)
78 		return;
79 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
80 	if (u.u_error)
81 		return;
82 	u.u_error = sobind((struct socket *)fp->f_data, nam);
83 	m_freem(nam);
84 }
85 
86 listen()
87 {
88 	register struct a {
89 		int	s;
90 		int	backlog;
91 	} *uap = (struct a *)u.u_ap;
92 	register struct file *fp;
93 
94 	fp = getsock(uap->s);
95 	if (fp == 0)
96 		return;
97 	u.u_error = solisten((struct socket *)fp->f_data, uap->backlog);
98 }
99 
100 #ifdef COMPAT_43
101 accept()
102 {
103 	accept1(0);
104 }
105 
106 oaccept()
107 {
108 	accept1(1);
109 }
110 
111 accept1(compat_43)
112 #else
113 accept()
114 #endif
115 {
116 	register struct a {
117 		int	s;
118 		caddr_t	name;
119 		int	*anamelen;
120 	} *uap = (struct a *)u.u_ap;
121 	struct file *fp;
122 	struct mbuf *nam;
123 	int namelen;
124 	int s;
125 	register struct socket *so;
126 
127 	if (uap->name == 0)
128 		goto noname;
129 	u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
130 		sizeof (namelen));
131 	if (u.u_error)
132 		return;
133 	if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
134 		u.u_error = EFAULT;
135 		return;
136 	}
137 noname:
138 	fp = getsock(uap->s);
139 	if (fp == 0)
140 		return;
141 	s = splnet();
142 	so = (struct socket *)fp->f_data;
143 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
144 		u.u_error = EINVAL;
145 		splx(s);
146 		return;
147 	}
148 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
149 		u.u_error = EWOULDBLOCK;
150 		splx(s);
151 		return;
152 	}
153 	while (so->so_qlen == 0 && so->so_error == 0) {
154 		if (so->so_state & SS_CANTRCVMORE) {
155 			so->so_error = ECONNABORTED;
156 			break;
157 		}
158 		sleep((caddr_t)&so->so_timeo, PZERO+1);
159 	}
160 	if (so->so_error) {
161 		u.u_error = so->so_error;
162 		so->so_error = 0;
163 		splx(s);
164 		return;
165 	}
166 	if (u.u_error = falloc(&fp, &u.u_r.r_val1)) {
167 		splx(s);
168 		return;
169 	}
170 	{ struct socket *aso = so->so_q;
171 	  if (soqremque(aso, 1) == 0)
172 		panic("accept");
173 	  so = aso;
174 	}
175 	fp->f_type = DTYPE_SOCKET;
176 	fp->f_flag = FREAD|FWRITE;
177 	fp->f_ops = &socketops;
178 	fp->f_data = (caddr_t)so;
179 	nam = m_get(M_WAIT, MT_SONAME);
180 	(void) soaccept(so, nam);
181 	if (uap->name) {
182 #ifdef COMPAT_43
183 		if (compat_43)
184 			mtod(nam, struct osockaddr *)->sa_family =
185 			    mtod(nam, struct sockaddr *)->sa_family;
186 #endif
187 		if (namelen > nam->m_len)
188 			namelen = nam->m_len;
189 		/* SHOULD COPY OUT A CHAIN HERE */
190 		(void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
191 		    (u_int)namelen);
192 		(void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
193 		    sizeof (*uap->anamelen));
194 	}
195 	m_freem(nam);
196 	splx(s);
197 }
198 
199 connect()
200 {
201 	register struct a {
202 		int	s;
203 		caddr_t	name;
204 		int	namelen;
205 	} *uap = (struct a *)u.u_ap;
206 	register struct file *fp;
207 	register struct socket *so;
208 	struct mbuf *nam;
209 	int s;
210 
211 	fp = getsock(uap->s);
212 	if (fp == 0)
213 		return;
214 	so = (struct socket *)fp->f_data;
215 	if ((so->so_state & SS_NBIO) &&
216 	    (so->so_state & SS_ISCONNECTING)) {
217 		u.u_error = EALREADY;
218 		return;
219 	}
220 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
221 	if (u.u_error)
222 		return;
223 	u.u_error = soconnect(so, nam);
224 	if (u.u_error)
225 		goto bad;
226 	if ((so->so_state & SS_NBIO) &&
227 	    (so->so_state & SS_ISCONNECTING)) {
228 		u.u_error = EINPROGRESS;
229 		m_freem(nam);
230 		return;
231 	}
232 	s = splnet();
233 	if (setjmp(&u.u_qsave)) {
234 		if (u.u_error == 0)
235 			u.u_error = EINTR;
236 		goto bad2;
237 	}
238 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
239 		sleep((caddr_t)&so->so_timeo, PZERO+1);
240 	u.u_error = so->so_error;
241 	so->so_error = 0;
242 bad2:
243 	splx(s);
244 bad:
245 	so->so_state &= ~SS_ISCONNECTING;
246 	m_freem(nam);
247 }
248 
249 socketpair()
250 {
251 	register struct a {
252 		int	domain;
253 		int	type;
254 		int	protocol;
255 		int	*rsv;
256 	} *uap = (struct a *)u.u_ap;
257 	struct file *fp1, *fp2;
258 	struct socket *so1, *so2;
259 	int fd, sv[2];
260 
261 	if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
262 		u.u_error = EFAULT;
263 		return;
264 	}
265 	u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
266 	if (u.u_error)
267 		return;
268 	u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
269 	if (u.u_error)
270 		goto free1;
271 	if (u.u_error = falloc(&fp1, &fd))
272 		goto free2;
273 	sv[0] = fd;
274 	fp1->f_flag = FREAD|FWRITE;
275 	fp1->f_type = DTYPE_SOCKET;
276 	fp1->f_ops = &socketops;
277 	fp1->f_data = (caddr_t)so1;
278 	if (u.u_error = falloc(&fp2, &fd))
279 		goto free3;
280 	fp2->f_flag = FREAD|FWRITE;
281 	fp2->f_type = DTYPE_SOCKET;
282 	fp2->f_ops = &socketops;
283 	fp2->f_data = (caddr_t)so2;
284 	sv[1] = fd;
285 	u.u_error = soconnect2(so1, so2);
286 	if (u.u_error)
287 		goto free4;
288 	if (uap->type == SOCK_DGRAM) {
289 		/*
290 		 * Datagram socket connection is asymmetric.
291 		 */
292 		 u.u_error = soconnect2(so2, so1);
293 		 if (u.u_error)
294 			goto free4;
295 	}
296 	(void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
297 	u.u_r.r_val1 = sv[0];
298 	u.u_r.r_val2 = sv[1];
299 	return;
300 free4:
301 	crfree(fp2->f_cred);
302 	fp2->f_count = 0;
303 	u.u_ofile[sv[1]] = 0;
304 free3:
305 	crfree(fp1->f_cred);
306 	fp1->f_count = 0;
307 	u.u_ofile[sv[0]] = 0;
308 free2:
309 	(void)soclose(so2);
310 free1:
311 	(void)soclose(so1);
312 }
313 
314 sendto()
315 {
316 	register struct a {
317 		int	s;
318 		caddr_t	buf;
319 		int	len;
320 		int	flags;
321 		caddr_t	to;
322 		int	tolen;
323 	} *uap = (struct a *)u.u_ap;
324 	struct msghdr msg;
325 	struct iovec aiov;
326 
327 	msg.msg_name = uap->to;
328 	msg.msg_namelen = uap->tolen;
329 	msg.msg_iov = &aiov;
330 	msg.msg_iovlen = 1;
331 	aiov.iov_base = uap->buf;
332 	aiov.iov_len = uap->len;
333 	msg.msg_accrights = 0;
334 	msg.msg_control = 0;
335 	sendit(uap->s, &msg, uap->flags);
336 }
337 
338 #ifdef COMPAT_43
339 
340 osend()
341 {
342 	register struct a {
343 		int	s;
344 		caddr_t	buf;
345 		int	len;
346 		int	flags;
347 	} *uap = (struct a *)u.u_ap;
348 	struct msghdr msg;
349 	struct iovec aiov;
350 
351 	msg.msg_name = 0;
352 	msg.msg_namelen = 0;
353 	msg.msg_iov = &aiov;
354 	msg.msg_iovlen = 1;
355 	aiov.iov_base = uap->buf;
356 	aiov.iov_len = uap->len;
357 	msg.msg_accrights = 0;
358 	msg.msg_control = 0;
359 	sendit(uap->s, &msg, uap->flags);
360 }
361 
362 osendmsg()
363 {
364 	register struct a {
365 		int	s;
366 		caddr_t	msg;
367 		int	flags;
368 	} *uap = (struct a *)u.u_ap;
369 	struct msghdr msg;
370 	struct iovec aiov[MSG_MAXIOVLEN];
371 
372 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
373 	if (u.u_error)
374 		return;
375 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
376 		u.u_error = EMSGSIZE;
377 		return;
378 	}
379 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
380 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
381 	if (u.u_error)
382 		return;
383 	msg.msg_control = 0;
384 	msg.msg_controllen = 0;
385 	sendit(uap->s, &msg, uap->flags);
386 }
387 #endif
388 
389 sendmsg()
390 {
391 	register struct a {
392 		int	s;
393 		caddr_t	msg;
394 		int	flags;
395 	} *uap = (struct a *)u.u_ap;
396 	struct msghdr msg;
397 	struct iovec aiov[MSG_MAXIOVLEN];
398 
399 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
400 	if (u.u_error)
401 		return;
402 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
403 		u.u_error = EMSGSIZE;
404 		return;
405 	}
406 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
407 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
408 	if (u.u_error)
409 		return;
410 	msg.msg_iov = aiov;
411 	sendit(uap->s, &msg, uap->flags);
412 }
413 
414 sendit(s, mp, flags)
415 	int s;
416 	register struct msghdr *mp;
417 	int flags;
418 {
419 	register struct file *fp;
420 	struct uio auio;
421 	register struct iovec *iov;
422 	register int i;
423 	struct mbuf *to, *rights, *control;
424 	int len;
425 
426 	fp = getsock(s);
427 	if (fp == 0)
428 		return;
429 	auio.uio_iov = mp->msg_iov;
430 	auio.uio_iovcnt = mp->msg_iovlen;
431 	auio.uio_segflg = UIO_USERSPACE;
432 	auio.uio_rw = UIO_WRITE;
433 	auio.uio_offset = 0;			/* XXX */
434 	auio.uio_resid = 0;
435 	iov = mp->msg_iov;
436 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
437 		if (iov->iov_len < 0) {
438 			u.u_error = EINVAL;
439 			return;
440 		}
441 		if (iov->iov_len == 0)
442 			continue;
443 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
444 			u.u_error = EFAULT;
445 			return;
446 		}
447 		auio.uio_resid += iov->iov_len;
448 	}
449 	if (mp->msg_name) {
450 		u.u_error =
451 		    sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
452 		if (u.u_error)
453 			return;
454 	} else
455 		to = 0;
456 	if (mp->msg_accrights) {
457 		u.u_error =
458 		    sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
459 		    MT_RIGHTS);
460 		if (u.u_error)
461 			goto bad;
462 	} else
463 		rights = 0;
464 	if (mp->msg_control) {
465 		u.u_error =
466 		    sockargs(&control, mp->msg_control, mp->msg_controllen,
467 		    MT_CONTROL);
468 		if (u.u_error)
469 			goto bad;
470 	} else
471 		control = 0;
472 	len = auio.uio_resid;
473 	if (setjmp(&u.u_qsave)) {			/* XXX */
474 		if (auio.uio_resid == len) {
475 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
476 				u.u_error = EINTR;
477 			else
478 				u.u_eosys = RESTARTSYS;
479 		}
480 	} else
481 		u.u_error = sosend((struct socket *)fp->f_data, to, &auio,
482 		    flags, rights, control);
483 	u.u_r.r_val1 = len - auio.uio_resid;
484 bad:
485 	if (rights)
486 		m_freem(rights);
487 	if (to)
488 		m_freem(to);
489 	if (control)
490 		m_freem(control);
491 }
492 
493 #ifdef COMPAT_43
494 recvfrom()
495 {
496 	recvfrom1(0);
497 }
498 
499 orecvfrom()
500 {
501 	recvfrom1(1);
502 }
503 
504 recvfrom1(compat_43)
505 {	/* vi will want an extra } to be happy! */
506 #else
507 recvfrom()
508 {
509 	int compat_43 = 0;
510 #endif
511 	register struct a {
512 		int	s;
513 		caddr_t	buf;
514 		int	len;
515 		int	flags;
516 		caddr_t	from;
517 		int	*fromlenaddr;
518 	} *uap = (struct a *)u.u_ap;
519 	struct msghdr msg;
520 	struct iovec aiov;
521 	int len;
522 
523 	if (uap->fromlenaddr) {
524 		u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
525 		   sizeof (len));
526 		if (u.u_error)
527 			return;
528 	} else
529 		len = 0;
530 	msg.msg_name = uap->from;
531 	msg.msg_namelen = len;
532 	msg.msg_iov = &aiov;
533 	msg.msg_iovlen = 1;
534 	aiov.iov_base = uap->buf;
535 	aiov.iov_len = uap->len;
536 	msg.msg_accrights = 0;
537 	msg.msg_control = 0;
538 	msg.msg_flags = uap->flags;
539 	recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, compat_43);
540 }
541 #ifdef COMPAT_43
542 orecv()
543 {
544 	register struct a {
545 		int	s;
546 		caddr_t	buf;
547 		int	len;
548 		int	flags;
549 	} *uap = (struct a *)u.u_ap;
550 	struct msghdr msg;
551 	struct iovec aiov;
552 
553 	msg.msg_name = 0;
554 	msg.msg_namelen = 0;
555 	msg.msg_iov = &aiov;
556 	msg.msg_iovlen = 1;
557 	aiov.iov_base = uap->buf;
558 	aiov.iov_len = uap->len;
559 	msg.msg_accrights = 0;
560 	msg.msg_control = 0;
561 	msg.msg_flags = uap->flags;
562 	recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
563 }
564 
565 orecvmsg()
566 {
567 	register struct a {
568 		int	s;
569 		struct	omsghdr *msg;
570 		int	flags;
571 	} *uap = (struct a *)u.u_ap;
572 	struct msghdr msg;
573 	struct iovec aiov[MSG_MAXIOVLEN];
574 
575 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
576 	    sizeof (struct omsghdr));
577 	if (u.u_error)
578 		return;
579 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
580 		u.u_error = EMSGSIZE;
581 		return;
582 	}
583 	msg.msg_control = 0;
584 	msg.msg_flags = uap->flags;
585 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
586 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
587 	if (u.u_error)
588 		return;
589 	msg.msg_iov = aiov;
590 	if (msg.msg_accrights)
591 		if (useracc((caddr_t)msg.msg_accrights,
592 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
593 			u.u_error = EFAULT;
594 			return;
595 		}
596 
597 	recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen,
598 	    (caddr_t)&uap->msg->msg_accrightslen, /* compat_43 */1);
599 }
600 #endif
601 
602 recvmsg()
603 {
604 	register struct a {
605 		int	s;
606 		struct	msghdr *msg;
607 		int	flags;
608 	} *uap = (struct a *)u.u_ap;
609 	struct msghdr msg;
610 	struct iovec aiov[MSG_MAXIOVLEN], *uiov;
611 
612 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
613 	if (u.u_error)
614 		return;
615 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
616 		u.u_error = EMSGSIZE;
617 		return;
618 	}
619 	msg.msg_flags = uap->flags;
620 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
621 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
622 	if (u.u_error)
623 		return;
624 	uiov = msg.msg_iov;
625 	msg.msg_iov = aiov;
626 	if (msg.msg_accrights)
627 		if (useracc((caddr_t)msg.msg_accrights,
628 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
629 			u.u_error = EFAULT;
630 			return;
631 		}
632 	if (msg.msg_control)
633 		if (useracc((caddr_t)msg.msg_control,
634 		    (unsigned)msg.msg_controllen, B_WRITE) == 0) {
635 			u.u_error = EFAULT;
636 			return;
637 		}
638 	recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
639 	msg.msg_iov = uiov;
640 	u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
641 }
642 
643 /* ARGSUSED */
644 recvit(s, mp, namelenp, rightslenp, compat_43)
645 	int s, compat_43;
646 	register struct msghdr *mp;
647 	caddr_t namelenp, rightslenp;
648 {
649 	register struct file *fp;
650 	struct uio auio;
651 	register struct iovec *iov;
652 	register int i;
653 	int len;
654 	struct mbuf *from = 0, *rights = 0, *control = 0;
655 
656 	fp = getsock(s);
657 	if (fp == 0)
658 		return;
659 	auio.uio_iov = mp->msg_iov;
660 	auio.uio_iovcnt = mp->msg_iovlen;
661 	auio.uio_segflg = UIO_USERSPACE;
662 	auio.uio_rw = UIO_READ;
663 	auio.uio_offset = 0;			/* XXX */
664 	auio.uio_resid = 0;
665 	iov = mp->msg_iov;
666 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
667 		if (iov->iov_len < 0) {
668 			u.u_error = EINVAL;
669 			return;
670 		}
671 		if (iov->iov_len == 0)
672 			continue;
673 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
674 			u.u_error = EFAULT;
675 			return;
676 		}
677 		auio.uio_resid += iov->iov_len;
678 	}
679 	len = auio.uio_resid;
680 	if (setjmp(&u.u_qsave)) {			/* XXX */
681 		if (auio.uio_resid == len) {
682 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
683 				u.u_error = EINTR;
684 			else
685 				u.u_eosys = RESTARTSYS;
686 		}
687 	} else
688 		u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio,
689 		    &mp->msg_flags, &rights, &control);
690 	u.u_r.r_val1 = len - auio.uio_resid;
691 	if (mp->msg_name) {
692 		len = mp->msg_namelen;
693 		if (len <= 0 || from == 0)
694 			len = 0;
695 		else {
696 #ifdef COMPAT_43
697 			if (compat_43)
698 				mtod(from, struct osockaddr *)->sa_family =
699 				    mtod(from, struct sockaddr *)->sa_family;
700 #endif
701 			if (len > from->m_len)		/* ??? */
702 				len = from->m_len;
703 			(void) copyout(mtod(from, caddr_t),
704 			    (caddr_t)mp->msg_name, (unsigned)len);
705 		}
706 		mp->msg_namelen = len;
707 		if (namelenp)
708 			(void) copyout((caddr_t)&len, namelenp, sizeof (int));
709 	}
710 	if (mp->msg_accrights) {
711 		len = mp->msg_accrightslen;
712 		if (len <= 0 || rights == 0)
713 			len = 0;
714 		else {
715 			if (len > rights->m_len)
716 				len = rights->m_len;
717 			(void) copyout((caddr_t)mtod(rights, caddr_t),
718 			    (caddr_t)mp->msg_accrights, (unsigned)len);
719 		}
720 		mp->msg_accrightslen = len;
721 		if (rightslenp)
722 			(void) copyout((caddr_t)&len, rightslenp, sizeof (int));
723 	}
724 	if (mp->msg_control) {
725 		len = mp->msg_controllen;
726 		if (len <= 0 || control == 0)
727 			len = 0;
728 		else {
729 			if (len >= control->m_len)
730 				len = control->m_len;
731 			else
732 				mp->msg_flags |= MSG_CTRUNC;
733 			(void) copyout((caddr_t)mtod(control, caddr_t),
734 			    (caddr_t)mp->msg_control, (unsigned)len);
735 		}
736 		mp->msg_controllen = len;
737 	}
738 	if (rights)
739 		m_freem(rights);
740 	if (from)
741 		m_freem(from);
742 	if (control)
743 		m_freem(control);
744 }
745 
746 shutdown()
747 {
748 	struct a {
749 		int	s;
750 		int	how;
751 	} *uap = (struct a *)u.u_ap;
752 	struct file *fp;
753 
754 	fp = getsock(uap->s);
755 	if (fp == 0)
756 		return;
757 	u.u_error = soshutdown((struct socket *)fp->f_data, uap->how);
758 }
759 
760 setsockopt()
761 {
762 	struct a {
763 		int	s;
764 		int	level;
765 		int	name;
766 		caddr_t	val;
767 		int	valsize;
768 	} *uap = (struct a *)u.u_ap;
769 	struct file *fp;
770 	struct mbuf *m = NULL;
771 
772 	fp = getsock(uap->s);
773 	if (fp == 0)
774 		return;
775 	if (uap->valsize > MLEN) {
776 		u.u_error = EINVAL;
777 		return;
778 	}
779 	if (uap->val) {
780 		m = m_get(M_WAIT, MT_SOOPTS);
781 		if (m == NULL) {
782 			u.u_error = ENOBUFS;
783 			return;
784 		}
785 		u.u_error =
786 		    copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
787 		if (u.u_error) {
788 			(void) m_free(m);
789 			return;
790 		}
791 		m->m_len = uap->valsize;
792 	}
793 	u.u_error =
794 	    sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m);
795 }
796 
797 getsockopt()
798 {
799 	struct a {
800 		int	s;
801 		int	level;
802 		int	name;
803 		caddr_t	val;
804 		int	*avalsize;
805 	} *uap = (struct a *)u.u_ap;
806 	struct file *fp;
807 	struct mbuf *m = NULL;
808 	int valsize;
809 
810 	fp = getsock(uap->s);
811 	if (fp == 0)
812 		return;
813 	if (uap->val) {
814 		u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
815 			sizeof (valsize));
816 		if (u.u_error)
817 			return;
818 	} else
819 		valsize = 0;
820 	u.u_error =
821 	    sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m);
822 	if (u.u_error)
823 		goto bad;
824 	if (uap->val && valsize && m != NULL) {
825 		if (valsize > m->m_len)
826 			valsize = m->m_len;
827 		u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
828 		if (u.u_error)
829 			goto bad;
830 		u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
831 		    sizeof (valsize));
832 	}
833 bad:
834 	if (m != NULL)
835 		(void) m_free(m);
836 }
837 
838 pipe()
839 {
840 	struct file *rf, *wf;
841 	struct socket *rso, *wso;
842 	int fd, r;
843 
844 	u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
845 	if (u.u_error)
846 		return;
847 	u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
848 	if (u.u_error)
849 		goto free1;
850 	if (u.u_error = falloc(&rf, &fd))
851 		goto free2;
852 	u.u_r.r_val1 = fd;
853 	rf->f_flag = FREAD;
854 	rf->f_type = DTYPE_SOCKET;
855 	rf->f_ops = &socketops;
856 	rf->f_data = (caddr_t)rso;
857 	if (u.u_error = falloc(&wf, &fd))
858 		goto free3;
859 	wf->f_flag = FWRITE;
860 	wf->f_type = DTYPE_SOCKET;
861 	wf->f_ops = &socketops;
862 	wf->f_data = (caddr_t)wso;
863 	u.u_r.r_val2 = fd;
864 	if (u.u_error = unp_connect2(wso, rso))
865 		goto free4;
866 	wso->so_state |= SS_CANTRCVMORE;
867 	rso->so_state |= SS_CANTSENDMORE;
868 	return;
869 free4:
870 	wf->f_count = 0;
871 	u.u_ofile[u.u_r.r_val2] = 0;
872 free3:
873 	rf->f_count = 0;
874 	u.u_ofile[u.u_r.r_val1] = 0;
875 free2:
876 	(void)soclose(wso);
877 free1:
878 	(void)soclose(rso);
879 }
880 
881 /*
882  * Get socket name.
883  */
884 #ifdef COMPAT_43
885 getsockname()
886 {
887 	getsockname1(0);
888 }
889 
890 ogetsockname()
891 {
892 	getsockname1(1);
893 }
894 
895 getsockname1(compat_43)
896 #else
897 getsockname()
898 #endif
899 {
900 	register struct a {
901 		int	fdes;
902 		caddr_t	asa;
903 		int	*alen;
904 	} *uap = (struct a *)u.u_ap;
905 	register struct file *fp;
906 	register struct socket *so;
907 	struct mbuf *m;
908 	int len;
909 
910 	fp = getsock(uap->fdes);
911 	if (fp == 0)
912 		return;
913 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
914 	if (u.u_error)
915 		return;
916 	so = (struct socket *)fp->f_data;
917 	m = m_getclr(M_WAIT, MT_SONAME);
918 	if (m == NULL) {
919 		u.u_error = ENOBUFS;
920 		return;
921 	}
922 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
923 	if (u.u_error)
924 		goto bad;
925 	if (len > m->m_len)
926 		len = m->m_len;
927 #ifdef COMPAT_43
928 	if (compat_43)
929 		mtod(m, struct osockaddr *)->sa_family =
930 		    mtod(m, struct sockaddr *)->sa_family;
931 #endif
932 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
933 	if (u.u_error == 0)
934 		u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen,
935 		    sizeof (len));
936 bad:
937 	m_freem(m);
938 }
939 
940 /*
941  * Get name of peer for connected socket.
942  */
943 #ifdef COMPAT_43
944 getpeername()
945 {
946 	getpeername1(0);
947 }
948 
949 ogetpeername()
950 {
951 	getpeername1(1);
952 }
953 
954 getpeername1(compat_43)
955 #else
956 getpeername()
957 #endif
958 {
959 	register struct a {
960 		int	fdes;
961 		caddr_t	asa;
962 		int	*alen;
963 	} *uap = (struct a *)u.u_ap;
964 	register struct file *fp;
965 	register struct socket *so;
966 	struct mbuf *m;
967 	int len;
968 
969 	fp = getsock(uap->fdes);
970 	if (fp == 0)
971 		return;
972 	so = (struct socket *)fp->f_data;
973 	if ((so->so_state & SS_ISCONNECTED) == 0) {
974 		u.u_error = ENOTCONN;
975 		return;
976 	}
977 	m = m_getclr(M_WAIT, MT_SONAME);
978 	if (m == NULL) {
979 		u.u_error = ENOBUFS;
980 		return;
981 	}
982 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
983 	if (u.u_error)
984 		return;
985 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
986 	if (u.u_error)
987 		goto bad;
988 	if (len > m->m_len)
989 		len = m->m_len;
990 #ifdef COMPAT_43
991 	if (compat_43)
992 		mtod(m, struct osockaddr *)->sa_family =
993 		    mtod(m, struct sockaddr *)->sa_family;
994 #endif
995 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
996 	if (u.u_error)
997 		goto bad;
998 	u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
999 bad:
1000 	m_freem(m);
1001 }
1002 
1003 sockargs(aname, name, namelen, type)
1004 	struct mbuf **aname;
1005 	caddr_t name;
1006 	int namelen, type;
1007 {
1008 	register struct mbuf *m;
1009 	int error;
1010 
1011 	if ((u_int)namelen > MLEN)
1012 		return (EINVAL);
1013 	m = m_get(M_WAIT, type);
1014 	if (m == NULL)
1015 		return (ENOBUFS);
1016 	m->m_len = namelen;
1017 	error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
1018 	if (error)
1019 		(void) m_free(m);
1020 	else
1021 		*aname = m;
1022 	if (type == MT_SONAME) {
1023 		register struct sockaddr *sa = mtod(m, struct sockaddr *);
1024 #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
1025 		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1026 			sa->sa_family = sa->sa_len;
1027 #endif
1028 		sa->sa_len = namelen;
1029 	}
1030 	return (error);
1031 }
1032 
1033 struct file *
1034 getsock(fdes)
1035 	int fdes;
1036 {
1037 	register struct file *fp;
1038 
1039 	if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) {
1040 		u.u_error = EBADF;
1041 		return (0);
1042 	}
1043 	if (fp->f_type != DTYPE_SOCKET) {
1044 		u.u_error = ENOTSOCK;
1045 		return (0);
1046 	}
1047 	return (fp);
1048 }
1049