xref: /csrg-svn/sys/kern/uipc_syscalls.c (revision 37478)
1 /*
2  * Copyright (c) 1982, 1986, 1988 The 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.8 (Berkeley) 04/22/89
18  */
19 
20 #include "param.h"
21 #include "dir.h"
22 #include "user.h"
23 #include "proc.h"
24 #include "file.h"
25 #include "buf.h"
26 #include "malloc.h"
27 #include "mbuf.h"
28 #include "protosw.h"
29 #include "socket.h"
30 #include "socketvar.h"
31 
32 /*
33  * System call interface to the socket abstraction.
34  */
35 
36 struct	file *getsock();
37 extern	struct fileops socketops;
38 
39 socket()
40 {
41 	register struct a {
42 		int	domain;
43 		int	type;
44 		int	protocol;
45 	} *uap = (struct a *)u.u_ap;
46 	struct socket *so;
47 	register struct file *fp;
48 
49 	if ((fp = falloc()) == NULL)
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 	return;
59 bad:
60 	u.u_ofile[u.u_r.r_val1] = 0;
61 	fp->f_count = 0;
62 }
63 
64 bind()
65 {
66 	register struct a {
67 		int	s;
68 		caddr_t	name;
69 		int	namelen;
70 	} *uap = (struct a *)u.u_ap;
71 	register struct file *fp;
72 	struct mbuf *nam;
73 
74 	fp = getsock(uap->s);
75 	if (fp == 0)
76 		return;
77 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
78 	if (u.u_error)
79 		return;
80 	u.u_error = sobind((struct socket *)fp->f_data, nam);
81 	m_freem(nam);
82 }
83 
84 listen()
85 {
86 	register struct a {
87 		int	s;
88 		int	backlog;
89 	} *uap = (struct a *)u.u_ap;
90 	register struct file *fp;
91 
92 	fp = getsock(uap->s);
93 	if (fp == 0)
94 		return;
95 	u.u_error = solisten((struct socket *)fp->f_data, uap->backlog);
96 }
97 
98 #ifdef COMPAT_43
99 accept()
100 {
101 	accept1(0);
102 }
103 
104 oaccept()
105 {
106 	accept1(1);
107 }
108 
109 accept1(compat_43)
110 #else
111 accept()
112 #endif
113 {
114 	register struct a {
115 		int	s;
116 		caddr_t	name;
117 		int	*anamelen;
118 	} *uap = (struct a *)u.u_ap;
119 	register struct file *fp;
120 	struct mbuf *nam;
121 	int namelen;
122 	int s;
123 	register struct socket *so;
124 
125 	if (uap->name == 0)
126 		goto noname;
127 	u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
128 		sizeof (namelen));
129 	if (u.u_error)
130 		return;
131 	if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
132 		u.u_error = EFAULT;
133 		return;
134 	}
135 noname:
136 	fp = getsock(uap->s);
137 	if (fp == 0)
138 		return;
139 	s = splnet();
140 	so = (struct socket *)fp->f_data;
141 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
142 		u.u_error = EINVAL;
143 		splx(s);
144 		return;
145 	}
146 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
147 		u.u_error = EWOULDBLOCK;
148 		splx(s);
149 		return;
150 	}
151 	while (so->so_qlen == 0 && so->so_error == 0) {
152 		if (so->so_state & SS_CANTRCVMORE) {
153 			so->so_error = ECONNABORTED;
154 			break;
155 		}
156 		sleep((caddr_t)&so->so_timeo, PZERO+1);
157 	}
158 	if (so->so_error) {
159 		u.u_error = so->so_error;
160 		so->so_error = 0;
161 		splx(s);
162 		return;
163 	}
164 	if (ufalloc(0) < 0) {
165 		splx(s);
166 		return;
167 	}
168 	fp = falloc();
169 	if (fp == 0) {
170 		u.u_ofile[u.u_r.r_val1] = 0;
171 		splx(s);
172 		return;
173 	}
174 	{ struct socket *aso = so->so_q;
175 	  if (soqremque(aso, 1) == 0)
176 		panic("accept");
177 	  so = aso;
178 	}
179 	fp->f_type = DTYPE_SOCKET;
180 	fp->f_flag = FREAD|FWRITE;
181 	fp->f_ops = &socketops;
182 	fp->f_data = (caddr_t)so;
183 	nam = m_get(M_WAIT, MT_SONAME);
184 	(void) soaccept(so, nam);
185 	if (uap->name) {
186 #ifdef COMPAT_43
187 		if (compat_43)
188 			mtod(nam, struct osockaddr *)->sa_family =
189 			    mtod(nam, struct sockaddr *)->sa_family;
190 #endif
191 		if (namelen > nam->m_len)
192 			namelen = nam->m_len;
193 		/* SHOULD COPY OUT A CHAIN HERE */
194 		(void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
195 		    (u_int)namelen);
196 		(void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
197 		    sizeof (*uap->anamelen));
198 	}
199 	m_freem(nam);
200 	splx(s);
201 }
202 
203 connect()
204 {
205 	register struct a {
206 		int	s;
207 		caddr_t	name;
208 		int	namelen;
209 	} *uap = (struct a *)u.u_ap;
210 	register struct file *fp;
211 	register struct socket *so;
212 	struct mbuf *nam;
213 	int s;
214 
215 	fp = getsock(uap->s);
216 	if (fp == 0)
217 		return;
218 	so = (struct socket *)fp->f_data;
219 	if ((so->so_state & SS_NBIO) &&
220 	    (so->so_state & SS_ISCONNECTING)) {
221 		u.u_error = EALREADY;
222 		return;
223 	}
224 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
225 	if (u.u_error)
226 		return;
227 	u.u_error = soconnect(so, nam);
228 	if (u.u_error)
229 		goto bad;
230 	if ((so->so_state & SS_NBIO) &&
231 	    (so->so_state & SS_ISCONNECTING)) {
232 		u.u_error = EINPROGRESS;
233 		m_freem(nam);
234 		return;
235 	}
236 	s = splnet();
237 	if (setjmp(&u.u_qsave)) {
238 		if (u.u_error == 0)
239 			u.u_error = EINTR;
240 		goto bad2;
241 	}
242 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
243 		sleep((caddr_t)&so->so_timeo, PZERO+1);
244 	u.u_error = so->so_error;
245 	so->so_error = 0;
246 bad2:
247 	splx(s);
248 bad:
249 	so->so_state &= ~SS_ISCONNECTING;
250 	m_freem(nam);
251 }
252 
253 socketpair()
254 {
255 	register struct a {
256 		int	domain;
257 		int	type;
258 		int	protocol;
259 		int	*rsv;
260 	} *uap = (struct a *)u.u_ap;
261 	register struct file *fp1, *fp2;
262 	struct socket *so1, *so2;
263 	int sv[2];
264 
265 	if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
266 		u.u_error = EFAULT;
267 		return;
268 	}
269 	u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
270 	if (u.u_error)
271 		return;
272 	u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
273 	if (u.u_error)
274 		goto freeit;
275 	fp1 = falloc();
276 	if (fp1 == NULL)
277 		goto free2;
278 	sv[0] = u.u_r.r_val1;
279 	fp1->f_flag = FREAD|FWRITE;
280 	fp1->f_type = DTYPE_SOCKET;
281 	fp1->f_ops = &socketops;
282 	fp1->f_data = (caddr_t)so1;
283 	fp2 = falloc();
284 	if (fp2 == NULL)
285 		goto free3;
286 	fp2->f_flag = FREAD|FWRITE;
287 	fp2->f_type = DTYPE_SOCKET;
288 	fp2->f_ops = &socketops;
289 	fp2->f_data = (caddr_t)so2;
290 	sv[1] = u.u_r.r_val1;
291 	u.u_error = soconnect2(so1, so2);
292 	if (u.u_error)
293 		goto free4;
294 	if (uap->type == SOCK_DGRAM) {
295 		/*
296 		 * Datagram socket connection is asymmetric.
297 		 */
298 		 u.u_error = soconnect2(so2, so1);
299 		 if (u.u_error)
300 			goto free4;
301 	}
302 	u.u_r.r_val1 = 0;
303 	(void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
304 	return;
305 free4:
306 	fp2->f_count = 0;
307 	u.u_ofile[sv[1]] = 0;
308 free3:
309 	fp1->f_count = 0;
310 	u.u_ofile[sv[0]] = 0;
311 free2:
312 	(void)soclose(so2);
313 freeit:
314 	(void)soclose(so1);
315 }
316 
317 sendto()
318 {
319 	register struct a {
320 		int	s;
321 		caddr_t	buf;
322 		int	len;
323 		int	flags;
324 		caddr_t	to;
325 		int	tolen;
326 	} *uap = (struct a *)u.u_ap;
327 	struct msghdr msg;
328 	struct iovec aiov;
329 
330 	msg.msg_name = uap->to;
331 	msg.msg_namelen = uap->tolen;
332 	msg.msg_iov = &aiov;
333 	msg.msg_iovlen = 1;
334 	aiov.iov_base = uap->buf;
335 	aiov.iov_len = uap->len;
336 	msg.msg_accrights = 0;
337 	msg.msg_control = 0;
338 	sendit(uap->s, &msg, uap->flags);
339 }
340 
341 #ifdef COMPAT_43
342 
343 osend()
344 {
345 	register struct a {
346 		int	s;
347 		caddr_t	buf;
348 		int	len;
349 		int	flags;
350 	} *uap = (struct a *)u.u_ap;
351 	struct msghdr msg;
352 	struct iovec aiov;
353 
354 	msg.msg_name = 0;
355 	msg.msg_namelen = 0;
356 	msg.msg_iov = &aiov;
357 	msg.msg_iovlen = 1;
358 	aiov.iov_base = uap->buf;
359 	aiov.iov_len = uap->len;
360 	msg.msg_accrights = 0;
361 	msg.msg_control = 0;
362 	sendit(uap->s, &msg, uap->flags);
363 }
364 
365 osendmsg()
366 {
367 	register struct a {
368 		int	s;
369 		caddr_t	msg;
370 		int	flags;
371 	} *uap = (struct a *)u.u_ap;
372 	struct msghdr msg;
373 	struct iovec aiov[MSG_MAXIOVLEN];
374 
375 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
376 	if (u.u_error)
377 		return;
378 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
379 		u.u_error = EMSGSIZE;
380 		return;
381 	}
382 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
383 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
384 	if (u.u_error)
385 		return;
386 	msg.msg_control = 0;
387 	msg.msg_controllen = 0;
388 	sendit(uap->s, &msg, uap->flags);
389 }
390 #endif
391 
392 sendmsg()
393 {
394 	register struct a {
395 		int	s;
396 		caddr_t	msg;
397 		int	flags;
398 	} *uap = (struct a *)u.u_ap;
399 	struct msghdr msg;
400 	struct iovec aiov[MSG_MAXIOVLEN];
401 
402 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
403 	if (u.u_error)
404 		return;
405 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
406 		u.u_error = EMSGSIZE;
407 		return;
408 	}
409 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
410 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
411 	if (u.u_error)
412 		return;
413 	msg.msg_iov = aiov;
414 	sendit(uap->s, &msg, uap->flags);
415 }
416 
417 sendit(s, mp, flags)
418 	int s;
419 	register struct msghdr *mp;
420 	int flags;
421 {
422 	register struct file *fp;
423 	struct uio auio;
424 	register struct iovec *iov;
425 	register int i;
426 	struct mbuf *to, *rights, *control;
427 	int len;
428 
429 	fp = getsock(s);
430 	if (fp == 0)
431 		return;
432 	auio.uio_iov = mp->msg_iov;
433 	auio.uio_iovcnt = mp->msg_iovlen;
434 	auio.uio_segflg = UIO_USERSPACE;
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 (iov->iov_len < 0) {
440 			u.u_error = EINVAL;
441 			return;
442 		}
443 		if (iov->iov_len == 0)
444 			continue;
445 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
446 			u.u_error = EFAULT;
447 			return;
448 		}
449 		auio.uio_resid += iov->iov_len;
450 	}
451 	if (mp->msg_name) {
452 		u.u_error =
453 		    sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
454 		if (u.u_error)
455 			return;
456 	} else
457 		to = 0;
458 	if (mp->msg_accrights) {
459 		u.u_error =
460 		    sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
461 		    MT_RIGHTS);
462 		if (u.u_error)
463 			goto bad;
464 	} else
465 		rights = 0;
466 	if (mp->msg_control) {
467 		u.u_error =
468 		    sockargs(&control, mp->msg_control, mp->msg_controllen,
469 		    MT_CONTROL);
470 		if (u.u_error)
471 			goto bad;
472 	} else
473 		control = 0;
474 	len = auio.uio_resid;
475 	if (setjmp(&u.u_qsave)) {			/* XXX */
476 		if (auio.uio_resid == len) {
477 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
478 				u.u_error = EINTR;
479 			else
480 				u.u_eosys = RESTARTSYS;
481 		}
482 	} else
483 		u.u_error = sosend((struct socket *)fp->f_data, to, &auio,
484 		    flags, rights, control);
485 	u.u_r.r_val1 = len - auio.uio_resid;
486 bad:
487 	if (rights)
488 		m_freem(rights);
489 	if (to)
490 		m_freem(to);
491 	if (control)
492 		m_freem(control);
493 }
494 
495 #ifdef COMPAT_43
496 recvfrom()
497 {
498 	recvfrom1(0);
499 }
500 
501 orecvfrom()
502 {
503 	recvfrom1(1);
504 }
505 
506 recvfrom1(compat_43)
507 {	/* vi will want an extra } to be happy! */
508 #else
509 recvfrom()
510 {
511 	int compat_43 = 0;
512 #endif
513 	register struct a {
514 		int	s;
515 		caddr_t	buf;
516 		int	len;
517 		int	flags;
518 		caddr_t	from;
519 		int	*fromlenaddr;
520 	} *uap = (struct a *)u.u_ap;
521 	struct msghdr msg;
522 	struct iovec aiov;
523 	int len;
524 
525 	if (uap->fromlenaddr) {
526 		u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
527 		   sizeof (len));
528 		if (u.u_error)
529 			return;
530 	} else
531 		len = 0;
532 	msg.msg_name = uap->from;
533 	msg.msg_namelen = len;
534 	msg.msg_iov = &aiov;
535 	msg.msg_iovlen = 1;
536 	aiov.iov_base = uap->buf;
537 	aiov.iov_len = uap->len;
538 	msg.msg_accrights = 0;
539 	msg.msg_control = 0;
540 	msg.msg_flags = uap->flags;
541 	recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, compat_43);
542 }
543 #ifdef COMPAT_43
544 orecv()
545 {
546 	register struct a {
547 		int	s;
548 		caddr_t	buf;
549 		int	len;
550 		int	flags;
551 	} *uap = (struct a *)u.u_ap;
552 	struct msghdr msg;
553 	struct iovec aiov;
554 
555 	msg.msg_name = 0;
556 	msg.msg_namelen = 0;
557 	msg.msg_iov = &aiov;
558 	msg.msg_iovlen = 1;
559 	aiov.iov_base = uap->buf;
560 	aiov.iov_len = uap->len;
561 	msg.msg_accrights = 0;
562 	msg.msg_control = 0;
563 	msg.msg_flags = uap->flags;
564 	recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
565 }
566 
567 orecvmsg()
568 {
569 	register struct a {
570 		int	s;
571 		struct	omsghdr *msg;
572 		int	flags;
573 	} *uap = (struct a *)u.u_ap;
574 	struct msghdr msg;
575 	struct iovec aiov[MSG_MAXIOVLEN];
576 
577 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
578 	    sizeof (struct omsghdr));
579 	if (u.u_error)
580 		return;
581 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
582 		u.u_error = EMSGSIZE;
583 		return;
584 	}
585 	msg.msg_control = 0;
586 	msg.msg_flags = uap->flags;
587 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
588 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
589 	if (u.u_error)
590 		return;
591 	msg.msg_iov = aiov;
592 	if (msg.msg_accrights)
593 		if (useracc((caddr_t)msg.msg_accrights,
594 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
595 			u.u_error = EFAULT;
596 			return;
597 		}
598 
599 	recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen,
600 	    (caddr_t)&uap->msg->msg_accrightslen, /* compat_43 */1);
601 }
602 #endif
603 
604 recvmsg()
605 {
606 	register struct a {
607 		int	s;
608 		struct	msghdr *msg;
609 		int	flags;
610 	} *uap = (struct a *)u.u_ap;
611 	struct msghdr msg;
612 	struct iovec aiov[MSG_MAXIOVLEN], *uiov;
613 
614 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
615 	if (u.u_error)
616 		return;
617 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
618 		u.u_error = EMSGSIZE;
619 		return;
620 	}
621 	msg.msg_flags = uap->flags;
622 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
623 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
624 	if (u.u_error)
625 		return;
626 	uiov = msg.msg_iov;
627 	msg.msg_iov = aiov;
628 	if (msg.msg_accrights)
629 		if (useracc((caddr_t)msg.msg_accrights,
630 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
631 			u.u_error = EFAULT;
632 			return;
633 		}
634 	if (msg.msg_control)
635 		if (useracc((caddr_t)msg.msg_control,
636 		    (unsigned)msg.msg_controllen, B_WRITE) == 0) {
637 			u.u_error = EFAULT;
638 			return;
639 		}
640 	recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
641 	msg.msg_iov = uiov;
642 	u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
643 }
644 
645 recvit(s, mp, namelenp, rightslenp, compat_43)
646 	int s, compat_43;
647 	register struct msghdr *mp;
648 	caddr_t namelenp, rightslenp;
649 {
650 	register struct file *fp;
651 	struct uio auio;
652 	register struct iovec *iov;
653 	register int i;
654 	int len;
655 	struct mbuf *from = 0, *rights = 0, *control = 0;
656 
657 	fp = getsock(s);
658 	if (fp == 0)
659 		return;
660 	auio.uio_iov = mp->msg_iov;
661 	auio.uio_iovcnt = mp->msg_iovlen;
662 	auio.uio_segflg = UIO_USERSPACE;
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 	register struct file *rf, *wf;
841 	struct socket *rso, *wso;
842 	int 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 freeit;
850 	rf = falloc();
851 	if (rf == NULL)
852 		goto free2;
853 	r = u.u_r.r_val1;
854 	rf->f_flag = FREAD;
855 	rf->f_type = DTYPE_SOCKET;
856 	rf->f_ops = &socketops;
857 	rf->f_data = (caddr_t)rso;
858 	wf = falloc();
859 	if (wf == NULL)
860 		goto free3;
861 	wf->f_flag = FWRITE;
862 	wf->f_type = DTYPE_SOCKET;
863 	wf->f_ops = &socketops;
864 	wf->f_data = (caddr_t)wso;
865 	u.u_r.r_val2 = u.u_r.r_val1;
866 	u.u_r.r_val1 = r;
867 	if (u.u_error = unp_connect2(wso, rso))
868 		goto free4;
869 	wso->so_state |= SS_CANTRCVMORE;
870 	rso->so_state |= SS_CANTSENDMORE;
871 	return;
872 free4:
873 	wf->f_count = 0;
874 	u.u_ofile[u.u_r.r_val2] = 0;
875 free3:
876 	rf->f_count = 0;
877 	u.u_ofile[r] = 0;
878 free2:
879 	(void)soclose(wso);
880 freeit:
881 	(void)soclose(rso);
882 }
883 
884 /*
885  * Get socket name.
886  */
887 #ifdef COMPAT_43
888 getsockname()
889 {
890 	getsockname1(0);
891 }
892 
893 ogetsockname()
894 {
895 	getsockname1(1);
896 }
897 
898 getsockname1(compat_43)
899 #else
900 getsockname()
901 #endif
902 {
903 	register struct a {
904 		int	fdes;
905 		caddr_t	asa;
906 		int	*alen;
907 	} *uap = (struct a *)u.u_ap;
908 	register struct file *fp;
909 	register struct socket *so;
910 	struct mbuf *m;
911 	int len;
912 
913 	fp = getsock(uap->fdes);
914 	if (fp == 0)
915 		return;
916 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
917 	if (u.u_error)
918 		return;
919 	so = (struct socket *)fp->f_data;
920 	m = m_getclr(M_WAIT, MT_SONAME);
921 	if (m == NULL) {
922 		u.u_error = ENOBUFS;
923 		return;
924 	}
925 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
926 	if (u.u_error)
927 		goto bad;
928 	if (len > m->m_len)
929 		len = m->m_len;
930 #ifdef COMPAT_43
931 	if (compat_43)
932 		mtod(m, struct osockaddr *)->sa_family =
933 		    mtod(m, struct sockaddr *)->sa_family;
934 #endif
935 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
936 	if (u.u_error == 0)
937 		u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen,
938 		    sizeof (len));
939 bad:
940 	m_freem(m);
941 }
942 
943 /*
944  * Get name of peer for connected socket.
945  */
946 #ifdef COMPAT_43
947 getpeername()
948 {
949 	getpeername1(0);
950 }
951 
952 ogetpeername()
953 {
954 	getpeername1(1);
955 }
956 
957 getpeername1(compat_43)
958 #else
959 getpeername()
960 #endif
961 {
962 	register struct a {
963 		int	fdes;
964 		caddr_t	asa;
965 		int	*alen;
966 	} *uap = (struct a *)u.u_ap;
967 	register struct file *fp;
968 	register struct socket *so;
969 	struct mbuf *m;
970 	int len;
971 
972 	fp = getsock(uap->fdes);
973 	if (fp == 0)
974 		return;
975 	so = (struct socket *)fp->f_data;
976 	if ((so->so_state & SS_ISCONNECTED) == 0) {
977 		u.u_error = ENOTCONN;
978 		return;
979 	}
980 	m = m_getclr(M_WAIT, MT_SONAME);
981 	if (m == NULL) {
982 		u.u_error = ENOBUFS;
983 		return;
984 	}
985 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
986 	if (u.u_error)
987 		return;
988 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
989 	if (u.u_error)
990 		goto bad;
991 	if (len > m->m_len)
992 		len = m->m_len;
993 #ifdef COMPAT_43
994 	if (compat_43)
995 		mtod(m, struct osockaddr *)->sa_family =
996 		    mtod(m, struct sockaddr *)->sa_family;
997 #endif
998 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
999 	if (u.u_error)
1000 		goto bad;
1001 	u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
1002 bad:
1003 	m_freem(m);
1004 }
1005 
1006 sockargs(aname, name, namelen, type)
1007 	struct mbuf **aname;
1008 	caddr_t name;
1009 	int namelen, type;
1010 {
1011 	register struct mbuf *m;
1012 	int error;
1013 
1014 	if ((u_int)namelen > MLEN)
1015 		return (EINVAL);
1016 	m = m_get(M_WAIT, type);
1017 	if (m == NULL)
1018 		return (ENOBUFS);
1019 	m->m_len = namelen;
1020 	error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
1021 	if (error)
1022 		(void) m_free(m);
1023 	else
1024 		*aname = m;
1025 	if (type == MT_SONAME) {
1026 		register struct sockaddr *sa = mtod(m, struct sockaddr *);
1027 #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
1028 		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1029 			sa->sa_family = sa->sa_len;
1030 #endif
1031 		sa->sa_len = namelen;
1032 	}
1033 	return (error);
1034 }
1035 
1036 struct file *
1037 getsock(fdes)
1038 	int fdes;
1039 {
1040 	register struct file *fp;
1041 
1042 	fp = getf(fdes);
1043 	if (fp == NULL)
1044 		return (0);
1045 	if (fp->f_type != DTYPE_SOCKET) {
1046 		u.u_error = ENOTSOCK;
1047 		return (0);
1048 	}
1049 	return (fp);
1050 }
1051