xref: /original-bsd/sys/kern/uipc_syscalls.c (revision 183db9ee)
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.6 (Berkeley) 10/12/88
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 accept()
99 {
100 	register struct a {
101 		int	s;
102 		caddr_t	name;
103 		int	*anamelen;
104 	} *uap = (struct a *)u.u_ap;
105 	register struct file *fp;
106 	struct mbuf *nam;
107 	int namelen;
108 	int s;
109 	register struct socket *so;
110 
111 	if (uap->name == 0)
112 		goto noname;
113 	u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
114 		sizeof (namelen));
115 	if (u.u_error)
116 		return;
117 	if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
118 		u.u_error = EFAULT;
119 		return;
120 	}
121 noname:
122 	fp = getsock(uap->s);
123 	if (fp == 0)
124 		return;
125 	s = splnet();
126 	so = (struct socket *)fp->f_data;
127 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
128 		u.u_error = EINVAL;
129 		splx(s);
130 		return;
131 	}
132 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
133 		u.u_error = EWOULDBLOCK;
134 		splx(s);
135 		return;
136 	}
137 	while (so->so_qlen == 0 && so->so_error == 0) {
138 		if (so->so_state & SS_CANTRCVMORE) {
139 			so->so_error = ECONNABORTED;
140 			break;
141 		}
142 		sleep((caddr_t)&so->so_timeo, PZERO+1);
143 	}
144 	if (so->so_error) {
145 		u.u_error = so->so_error;
146 		so->so_error = 0;
147 		splx(s);
148 		return;
149 	}
150 	if (ufalloc(0) < 0) {
151 		splx(s);
152 		return;
153 	}
154 	fp = falloc();
155 	if (fp == 0) {
156 		u.u_ofile[u.u_r.r_val1] = 0;
157 		splx(s);
158 		return;
159 	}
160 	{ struct socket *aso = so->so_q;
161 	  if (soqremque(aso, 1) == 0)
162 		panic("accept");
163 	  so = aso;
164 	}
165 	fp->f_type = DTYPE_SOCKET;
166 	fp->f_flag = FREAD|FWRITE;
167 	fp->f_ops = &socketops;
168 	fp->f_data = (caddr_t)so;
169 	nam = m_get(M_WAIT, MT_SONAME);
170 	(void) soaccept(so, nam);
171 	if (uap->name) {
172 		if (namelen > nam->m_len)
173 			namelen = nam->m_len;
174 		/* SHOULD COPY OUT A CHAIN HERE */
175 		(void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
176 		    (u_int)namelen);
177 		(void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
178 		    sizeof (*uap->anamelen));
179 	}
180 	m_freem(nam);
181 	splx(s);
182 }
183 
184 #ifdef COMPAT_43
185 oaccept()
186 {
187 	return (accept());
188 }
189 #endif
190 
191 connect()
192 {
193 	register struct a {
194 		int	s;
195 		caddr_t	name;
196 		int	namelen;
197 	} *uap = (struct a *)u.u_ap;
198 	register struct file *fp;
199 	register struct socket *so;
200 	struct mbuf *nam;
201 	int s;
202 
203 	fp = getsock(uap->s);
204 	if (fp == 0)
205 		return;
206 	so = (struct socket *)fp->f_data;
207 	if ((so->so_state & SS_NBIO) &&
208 	    (so->so_state & SS_ISCONNECTING)) {
209 		u.u_error = EALREADY;
210 		return;
211 	}
212 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
213 	if (u.u_error)
214 		return;
215 	u.u_error = soconnect(so, nam);
216 	if (u.u_error)
217 		goto bad;
218 	if ((so->so_state & SS_NBIO) &&
219 	    (so->so_state & SS_ISCONNECTING)) {
220 		u.u_error = EINPROGRESS;
221 		m_freem(nam);
222 		return;
223 	}
224 	s = splnet();
225 	if (setjmp(&u.u_qsave)) {
226 		if (u.u_error == 0)
227 			u.u_error = EINTR;
228 		goto bad2;
229 	}
230 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
231 		sleep((caddr_t)&so->so_timeo, PZERO+1);
232 	u.u_error = so->so_error;
233 	so->so_error = 0;
234 bad2:
235 	splx(s);
236 bad:
237 	so->so_state &= ~SS_ISCONNECTING;
238 	m_freem(nam);
239 }
240 
241 socketpair()
242 {
243 	register struct a {
244 		int	domain;
245 		int	type;
246 		int	protocol;
247 		int	*rsv;
248 	} *uap = (struct a *)u.u_ap;
249 	register struct file *fp1, *fp2;
250 	struct socket *so1, *so2;
251 	int sv[2];
252 
253 	if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
254 		u.u_error = EFAULT;
255 		return;
256 	}
257 	u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
258 	if (u.u_error)
259 		return;
260 	u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
261 	if (u.u_error)
262 		goto free;
263 	fp1 = falloc();
264 	if (fp1 == NULL)
265 		goto free2;
266 	sv[0] = u.u_r.r_val1;
267 	fp1->f_flag = FREAD|FWRITE;
268 	fp1->f_type = DTYPE_SOCKET;
269 	fp1->f_ops = &socketops;
270 	fp1->f_data = (caddr_t)so1;
271 	fp2 = falloc();
272 	if (fp2 == NULL)
273 		goto free3;
274 	fp2->f_flag = FREAD|FWRITE;
275 	fp2->f_type = DTYPE_SOCKET;
276 	fp2->f_ops = &socketops;
277 	fp2->f_data = (caddr_t)so2;
278 	sv[1] = u.u_r.r_val1;
279 	u.u_error = soconnect2(so1, so2);
280 	if (u.u_error)
281 		goto free4;
282 	if (uap->type == SOCK_DGRAM) {
283 		/*
284 		 * Datagram socket connection is asymmetric.
285 		 */
286 		 u.u_error = soconnect2(so2, so1);
287 		 if (u.u_error)
288 			goto free4;
289 	}
290 	u.u_r.r_val1 = 0;
291 	(void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
292 	return;
293 free4:
294 	fp2->f_count = 0;
295 	u.u_ofile[sv[1]] = 0;
296 free3:
297 	fp1->f_count = 0;
298 	u.u_ofile[sv[0]] = 0;
299 free2:
300 	(void)soclose(so2);
301 free:
302 	(void)soclose(so1);
303 }
304 
305 sendto()
306 {
307 	register struct a {
308 		int	s;
309 		caddr_t	buf;
310 		int	len;
311 		int	flags;
312 		caddr_t	to;
313 		int	tolen;
314 	} *uap = (struct a *)u.u_ap;
315 	struct msghdr msg;
316 	struct iovec aiov;
317 
318 	msg.msg_name = uap->to;
319 	msg.msg_namelen = uap->tolen;
320 	msg.msg_iov = &aiov;
321 	msg.msg_iovlen = 1;
322 	aiov.iov_base = uap->buf;
323 	aiov.iov_len = uap->len;
324 	msg.msg_accrights = 0;
325 	msg.msg_control = 0;
326 	sendit(uap->s, &msg, uap->flags);
327 }
328 
329 #ifdef COMPAT_43
330 osend()
331 {
332 	register struct a {
333 		int	s;
334 		caddr_t	buf;
335 		int	len;
336 		int	flags;
337 	} *uap = (struct a *)u.u_ap;
338 	struct msghdr msg;
339 	struct iovec aiov;
340 
341 	msg.msg_name = 0;
342 	msg.msg_namelen = 0;
343 	msg.msg_iov = &aiov;
344 	msg.msg_iovlen = 1;
345 	aiov.iov_base = uap->buf;
346 	aiov.iov_len = uap->len;
347 	msg.msg_accrights = 0;
348 	msg.msg_control = 0;
349 	sendit(uap->s, &msg, uap->flags);
350 }
351 
352 osendmsg()
353 {
354 	register struct a {
355 		int	s;
356 		caddr_t	msg;
357 		int	flags;
358 	} *uap = (struct a *)u.u_ap;
359 	struct msghdr msg;
360 	struct iovec aiov[MSG_MAXIOVLEN];
361 
362 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
363 	if (u.u_error)
364 		return;
365 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
366 		u.u_error = EMSGSIZE;
367 		return;
368 	}
369 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
370 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
371 	if (u.u_error)
372 		return;
373 	msg.msg_control = 0;
374 	msg.msg_controllen = 0;
375 	sendit(uap->s, &msg, uap->flags);
376 }
377 #endif
378 
379 sendmsg()
380 {
381 	register struct a {
382 		int	s;
383 		caddr_t	msg;
384 		int	flags;
385 	} *uap = (struct a *)u.u_ap;
386 	struct msghdr msg;
387 	struct iovec aiov[MSG_MAXIOVLEN];
388 
389 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
390 	if (u.u_error)
391 		return;
392 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
393 		u.u_error = EMSGSIZE;
394 		return;
395 	}
396 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
397 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
398 	if (u.u_error)
399 		return;
400 	msg.msg_iov = aiov;
401 	sendit(uap->s, &msg, uap->flags);
402 }
403 
404 sendit(s, mp, flags)
405 	int s;
406 	register struct msghdr *mp;
407 	int flags;
408 {
409 	register struct file *fp;
410 	struct uio auio;
411 	register struct iovec *iov;
412 	register int i;
413 	struct mbuf *to, *rights, *control;
414 	int len;
415 
416 	fp = getsock(s);
417 	if (fp == 0)
418 		return;
419 	auio.uio_iov = mp->msg_iov;
420 	auio.uio_iovcnt = mp->msg_iovlen;
421 	auio.uio_segflg = UIO_USERSPACE;
422 	auio.uio_offset = 0;			/* XXX */
423 	auio.uio_resid = 0;
424 	iov = mp->msg_iov;
425 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
426 		if (iov->iov_len < 0) {
427 			u.u_error = EINVAL;
428 			return;
429 		}
430 		if (iov->iov_len == 0)
431 			continue;
432 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
433 			u.u_error = EFAULT;
434 			return;
435 		}
436 		auio.uio_resid += iov->iov_len;
437 	}
438 	if (mp->msg_name) {
439 		u.u_error =
440 		    sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
441 		if (u.u_error)
442 			return;
443 	} else
444 		to = 0;
445 	if (mp->msg_accrights) {
446 		u.u_error =
447 		    sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
448 		    MT_RIGHTS);
449 		if (u.u_error)
450 			goto bad;
451 	} else
452 		rights = 0;
453 	if (mp->msg_control) {
454 		u.u_error =
455 		    sockargs(&control, mp->msg_control, mp->msg_controllen,
456 		    MT_CONTROL);
457 		if (u.u_error)
458 			goto bad;
459 	} else
460 		control = 0;
461 	len = auio.uio_resid;
462 	if (setjmp(&u.u_qsave)) {			/* XXX */
463 		if (auio.uio_resid == len) {
464 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
465 				u.u_error = EINTR;
466 			else
467 				u.u_eosys = RESTARTSYS;
468 		}
469 	} else
470 		u.u_error = sosend((struct socket *)fp->f_data, to, &auio,
471 		    flags, rights, control);
472 	u.u_r.r_val1 = len - auio.uio_resid;
473 bad:
474 	if (rights)
475 		m_freem(rights);
476 	if (to)
477 		m_freem(to);
478 	if (control)
479 		m_freem(control);
480 }
481 
482 recvfrom()
483 {
484 	register struct a {
485 		int	s;
486 		caddr_t	buf;
487 		int	len;
488 		int	flags;
489 		caddr_t	from;
490 		int	*fromlenaddr;
491 	} *uap = (struct a *)u.u_ap;
492 	struct msghdr msg;
493 	struct iovec aiov;
494 	int len;
495 
496 	if (uap->fromlenaddr) {
497 		u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
498 		   sizeof (len));
499 		if (u.u_error)
500 			return;
501 	} else
502 		len = 0;
503 	msg.msg_name = uap->from;
504 	msg.msg_namelen = len;
505 	msg.msg_iov = &aiov;
506 	msg.msg_iovlen = 1;
507 	aiov.iov_base = uap->buf;
508 	aiov.iov_len = uap->len;
509 	msg.msg_accrights = 0;
510 	msg.msg_control = 0;
511 	msg.msg_flags = uap->flags;
512 	recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, (caddr_t)0);
513 }
514 
515 #ifdef COMPAT_43
516 orecvfrom()
517 {
518 	return (recvfrom());
519 }
520 
521 orecv()
522 {
523 	register struct a {
524 		int	s;
525 		caddr_t	buf;
526 		int	len;
527 		int	flags;
528 	} *uap = (struct a *)u.u_ap;
529 	struct msghdr msg;
530 	struct iovec aiov;
531 
532 	msg.msg_name = 0;
533 	msg.msg_namelen = 0;
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)0, (caddr_t)0, (caddr_t)0);
542 }
543 
544 orecvmsg()
545 {
546 	register struct a {
547 		int	s;
548 		struct	omsghdr *msg;
549 		int	flags;
550 	} *uap = (struct a *)u.u_ap;
551 	struct msghdr msg;
552 	struct iovec aiov[MSG_MAXIOVLEN];
553 
554 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
555 	    sizeof (struct omsghdr));
556 	if (u.u_error)
557 		return;
558 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
559 		u.u_error = EMSGSIZE;
560 		return;
561 	}
562 	msg.msg_control = 0;
563 	msg.msg_flags = uap->flags;
564 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
565 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
566 	if (u.u_error)
567 		return;
568 	msg.msg_iov = aiov;
569 	if (msg.msg_accrights)
570 		if (useracc((caddr_t)msg.msg_accrights,
571 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
572 			u.u_error = EFAULT;
573 			return;
574 		}
575 
576 	recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen,
577 	    (caddr_t)&uap->msg->msg_accrightslen, (caddr_t)0);
578 }
579 #endif
580 
581 recvmsg()
582 {
583 	register struct a {
584 		int	s;
585 		struct	msghdr *msg;
586 		int	flags;
587 	} *uap = (struct a *)u.u_ap;
588 	struct msghdr msg;
589 	struct iovec aiov[MSG_MAXIOVLEN];
590 
591 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
592 	if (u.u_error)
593 		return;
594 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
595 		u.u_error = EMSGSIZE;
596 		return;
597 	}
598 	msg.msg_flags = uap->flags;
599 	u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
600 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
601 	if (u.u_error)
602 		return;
603 	msg.msg_iov = aiov;
604 	if (msg.msg_accrights)
605 		if (useracc((caddr_t)msg.msg_accrights,
606 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
607 			u.u_error = EFAULT;
608 			return;
609 		}
610 	if (msg.msg_control)
611 		if (useracc((caddr_t)msg.msg_control,
612 		    (unsigned)msg.msg_controllen, B_WRITE) == 0) {
613 			u.u_error = EFAULT;
614 			return;
615 		}
616 	recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, (caddr_t)0);
617 	u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof (msg));
618 }
619 
620 recvit(s, mp, namelenp, rightslenp, controllenp)
621 	int s;
622 	register struct msghdr *mp;
623 	caddr_t namelenp, rightslenp, controllenp;
624 {
625 	register struct file *fp;
626 	struct uio auio;
627 	register struct iovec *iov;
628 	register int i;
629 	int len;
630 	struct mbuf *from = 0, *rights = 0, *control = 0;
631 
632 	fp = getsock(s);
633 	if (fp == 0)
634 		return;
635 	auio.uio_iov = mp->msg_iov;
636 	auio.uio_iovcnt = mp->msg_iovlen;
637 	auio.uio_segflg = UIO_USERSPACE;
638 	auio.uio_offset = 0;			/* XXX */
639 	auio.uio_resid = 0;
640 	iov = mp->msg_iov;
641 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
642 		if (iov->iov_len < 0) {
643 			u.u_error = EINVAL;
644 			return;
645 		}
646 		if (iov->iov_len == 0)
647 			continue;
648 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
649 			u.u_error = EFAULT;
650 			return;
651 		}
652 		auio.uio_resid += iov->iov_len;
653 	}
654 	len = auio.uio_resid;
655 	if (setjmp(&u.u_qsave)) {			/* XXX */
656 		if (auio.uio_resid == len) {
657 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
658 				u.u_error = EINTR;
659 			else
660 				u.u_eosys = RESTARTSYS;
661 		}
662 	} else
663 		u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio,
664 		    &mp->msg_flags, &rights, &control);
665 	u.u_r.r_val1 = len - auio.uio_resid;
666 	if (mp->msg_name) {
667 		len = mp->msg_namelen;
668 		if (len <= 0 || from == 0)
669 			len = 0;
670 		else {
671 			if (len > from->m_len)
672 				len = from->m_len;
673 			(void) copyout(mtod(from, caddr_t),
674 			    (caddr_t)mp->msg_name, (unsigned)len);
675 		}
676 		if (namelenp)
677 			(void) copyout((caddr_t)&len, namelenp, sizeof (int));
678 	}
679 	if (mp->msg_accrights) {
680 		len = mp->msg_accrightslen;
681 		if (len <= 0 || rights == 0)
682 			len = 0;
683 		else {
684 			if (len > rights->m_len)
685 				len = rights->m_len;
686 			(void) copyout((caddr_t)mtod(rights, caddr_t),
687 			    (caddr_t)mp->msg_accrights, (unsigned)len);
688 		}
689 		if (rightslenp)
690 			(void) copyout((caddr_t)&len, rightslenp, sizeof (int));
691 	}
692 	if (mp->msg_control) {
693 		len = mp->msg_controllen;
694 		if (len <= 0 || control == 0)
695 			len = 0;
696 		else {
697 			if (len >= control->m_len)
698 				len = control->m_len;
699 			else
700 				mp->msg_flags |= MSG_CTRUNC;
701 			(void) copyout((caddr_t)mtod(control, caddr_t),
702 			    (caddr_t)mp->msg_control, (unsigned)len);
703 		}
704 		if (controllenp)
705 			(void) copyout((caddr_t)&len, controllenp, sizeof(int));
706 	}
707 	if (rights)
708 		m_freem(rights);
709 	if (from)
710 		m_freem(from);
711 	if (control)
712 		m_freem(control);
713 }
714 
715 shutdown()
716 {
717 	struct a {
718 		int	s;
719 		int	how;
720 	} *uap = (struct a *)u.u_ap;
721 	struct file *fp;
722 
723 	fp = getsock(uap->s);
724 	if (fp == 0)
725 		return;
726 	u.u_error = soshutdown((struct socket *)fp->f_data, uap->how);
727 }
728 
729 setsockopt()
730 {
731 	struct a {
732 		int	s;
733 		int	level;
734 		int	name;
735 		caddr_t	val;
736 		int	valsize;
737 	} *uap = (struct a *)u.u_ap;
738 	struct file *fp;
739 	struct mbuf *m = NULL;
740 
741 	fp = getsock(uap->s);
742 	if (fp == 0)
743 		return;
744 	if (uap->valsize > MLEN) {
745 		u.u_error = EINVAL;
746 		return;
747 	}
748 	if (uap->val) {
749 		m = m_get(M_WAIT, MT_SOOPTS);
750 		if (m == NULL) {
751 			u.u_error = ENOBUFS;
752 			return;
753 		}
754 		u.u_error =
755 		    copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
756 		if (u.u_error) {
757 			(void) m_free(m);
758 			return;
759 		}
760 		m->m_len = uap->valsize;
761 	}
762 	u.u_error =
763 	    sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m);
764 }
765 
766 getsockopt()
767 {
768 	struct a {
769 		int	s;
770 		int	level;
771 		int	name;
772 		caddr_t	val;
773 		int	*avalsize;
774 	} *uap = (struct a *)u.u_ap;
775 	struct file *fp;
776 	struct mbuf *m = NULL;
777 	int valsize;
778 
779 	fp = getsock(uap->s);
780 	if (fp == 0)
781 		return;
782 	if (uap->val) {
783 		u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
784 			sizeof (valsize));
785 		if (u.u_error)
786 			return;
787 	} else
788 		valsize = 0;
789 	u.u_error =
790 	    sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m);
791 	if (u.u_error)
792 		goto bad;
793 	if (uap->val && valsize && m != NULL) {
794 		if (valsize > m->m_len)
795 			valsize = m->m_len;
796 		u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
797 		if (u.u_error)
798 			goto bad;
799 		u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
800 		    sizeof (valsize));
801 	}
802 bad:
803 	if (m != NULL)
804 		(void) m_free(m);
805 }
806 
807 pipe()
808 {
809 	register struct file *rf, *wf;
810 	struct socket *rso, *wso;
811 	int r;
812 
813 	u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
814 	if (u.u_error)
815 		return;
816 	u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
817 	if (u.u_error)
818 		goto free;
819 	rf = falloc();
820 	if (rf == NULL)
821 		goto free2;
822 	r = u.u_r.r_val1;
823 	rf->f_flag = FREAD;
824 	rf->f_type = DTYPE_SOCKET;
825 	rf->f_ops = &socketops;
826 	rf->f_data = (caddr_t)rso;
827 	wf = falloc();
828 	if (wf == NULL)
829 		goto free3;
830 	wf->f_flag = FWRITE;
831 	wf->f_type = DTYPE_SOCKET;
832 	wf->f_ops = &socketops;
833 	wf->f_data = (caddr_t)wso;
834 	u.u_r.r_val2 = u.u_r.r_val1;
835 	u.u_r.r_val1 = r;
836 	if (u.u_error = unp_connect2(wso, rso))
837 		goto free4;
838 	wso->so_state |= SS_CANTRCVMORE;
839 	rso->so_state |= SS_CANTSENDMORE;
840 	return;
841 free4:
842 	wf->f_count = 0;
843 	u.u_ofile[u.u_r.r_val2] = 0;
844 free3:
845 	rf->f_count = 0;
846 	u.u_ofile[r] = 0;
847 free2:
848 	(void)soclose(wso);
849 free:
850 	(void)soclose(rso);
851 }
852 
853 /*
854  * Get socket name.
855  */
856 getsockname()
857 {
858 	register struct a {
859 		int	fdes;
860 		caddr_t	asa;
861 		int	*alen;
862 	} *uap = (struct a *)u.u_ap;
863 	register struct file *fp;
864 	register struct socket *so;
865 	struct mbuf *m;
866 	int len;
867 
868 	fp = getsock(uap->fdes);
869 	if (fp == 0)
870 		return;
871 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
872 	if (u.u_error)
873 		return;
874 	so = (struct socket *)fp->f_data;
875 	m = m_getclr(M_WAIT, MT_SONAME);
876 	if (m == NULL) {
877 		u.u_error = ENOBUFS;
878 		return;
879 	}
880 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
881 	if (u.u_error)
882 		goto bad;
883 	if (len > m->m_len)
884 		len = m->m_len;
885 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
886 	if (u.u_error)
887 		goto bad;
888 	u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
889 bad:
890 	m_freem(m);
891 }
892 
893 #ifdef COMPAT_43
894 ogetsockname()
895 {
896 	return (getsockname());
897 }
898 #endif
899 
900 /*
901  * Get name of peer for connected socket.
902  */
903 getpeername()
904 {
905 	register struct a {
906 		int	fdes;
907 		caddr_t	asa;
908 		int	*alen;
909 	} *uap = (struct a *)u.u_ap;
910 	register struct file *fp;
911 	register struct socket *so;
912 	struct mbuf *m;
913 	int len;
914 
915 	fp = getsock(uap->fdes);
916 	if (fp == 0)
917 		return;
918 	so = (struct socket *)fp->f_data;
919 	if ((so->so_state & SS_ISCONNECTED) == 0) {
920 		u.u_error = ENOTCONN;
921 		return;
922 	}
923 	m = m_getclr(M_WAIT, MT_SONAME);
924 	if (m == NULL) {
925 		u.u_error = ENOBUFS;
926 		return;
927 	}
928 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
929 	if (u.u_error)
930 		return;
931 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
932 	if (u.u_error)
933 		goto bad;
934 	if (len > m->m_len)
935 		len = m->m_len;
936 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
937 	if (u.u_error)
938 		goto bad;
939 	u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
940 bad:
941 	m_freem(m);
942 }
943 
944 #ifdef COMPAT_43
945 ogetpeername()
946 {
947 	return (getpeername());
948 }
949 #endif
950 
951 sockargs(aname, name, namelen, type)
952 	struct mbuf **aname;
953 	caddr_t name;
954 	int namelen, type;
955 {
956 	register struct mbuf *m;
957 	int error;
958 
959 	if ((u_int)namelen > MLEN)
960 		return (EINVAL);
961 	m = m_get(M_WAIT, type);
962 	if (m == NULL)
963 		return (ENOBUFS);
964 	m->m_len = namelen;
965 	error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
966 	if (error)
967 		(void) m_free(m);
968 	else
969 		*aname = m;
970 	return (error);
971 }
972 
973 struct file *
974 getsock(fdes)
975 	int fdes;
976 {
977 	register struct file *fp;
978 
979 	fp = getf(fdes);
980 	if (fp == NULL)
981 		return (0);
982 	if (fp->f_type != DTYPE_SOCKET) {
983 		u.u_error = ENOTSOCK;
984 		return (0);
985 	}
986 	return (fp);
987 }
988