xref: /csrg-svn/sys/kern/uipc_syscalls.c (revision 34858)
1 /*
2  * Copyright (c) 1982, 1986 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.5 (Berkeley) 06/29/88
18  */
19 
20 #include "param.h"
21 #include "dir.h"
22 #include "user.h"
23 #include "file.h"
24 #include "buf.h"
25 #include "mbuf.h"
26 #include "protosw.h"
27 #include "socket.h"
28 #include "socketvar.h"
29 
30 /*
31  * System call interface to the socket abstraction.
32  */
33 
34 struct	file *getsock();
35 extern	struct fileops socketops;
36 
37 socket()
38 {
39 	register struct a {
40 		int	domain;
41 		int	type;
42 		int	protocol;
43 	} *uap = (struct a *)u.u_ap;
44 	struct socket *so;
45 	register struct file *fp;
46 
47 	if ((fp = falloc()) == NULL)
48 		return;
49 	fp->f_flag = FREAD|FWRITE;
50 	fp->f_type = DTYPE_SOCKET;
51 	fp->f_ops = &socketops;
52 	u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol);
53 	if (u.u_error)
54 		goto bad;
55 	fp->f_data = (caddr_t)so;
56 	return;
57 bad:
58 	u.u_ofile[u.u_r.r_val1] = 0;
59 	fp->f_count = 0;
60 }
61 
62 bind()
63 {
64 	register struct a {
65 		int	s;
66 		caddr_t	name;
67 		int	namelen;
68 	} *uap = (struct a *)u.u_ap;
69 	register struct file *fp;
70 	struct mbuf *nam;
71 
72 	fp = getsock(uap->s);
73 	if (fp == 0)
74 		return;
75 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
76 	if (u.u_error)
77 		return;
78 	u.u_error = sobind((struct socket *)fp->f_data, nam);
79 	m_freem(nam);
80 }
81 
82 listen()
83 {
84 	register struct a {
85 		int	s;
86 		int	backlog;
87 	} *uap = (struct a *)u.u_ap;
88 	register struct file *fp;
89 
90 	fp = getsock(uap->s);
91 	if (fp == 0)
92 		return;
93 	u.u_error = solisten((struct socket *)fp->f_data, uap->backlog);
94 }
95 
96 accept()
97 {
98 	register struct a {
99 		int	s;
100 		caddr_t	name;
101 		int	*anamelen;
102 	} *uap = (struct a *)u.u_ap;
103 	register struct file *fp;
104 	struct mbuf *nam;
105 	int namelen;
106 	int s;
107 	register struct socket *so;
108 
109 	if (uap->name == 0)
110 		goto noname;
111 	u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
112 		sizeof (namelen));
113 	if (u.u_error)
114 		return;
115 	if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
116 		u.u_error = EFAULT;
117 		return;
118 	}
119 noname:
120 	fp = getsock(uap->s);
121 	if (fp == 0)
122 		return;
123 	s = splnet();
124 	so = (struct socket *)fp->f_data;
125 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
126 		u.u_error = EINVAL;
127 		splx(s);
128 		return;
129 	}
130 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
131 		u.u_error = EWOULDBLOCK;
132 		splx(s);
133 		return;
134 	}
135 	while (so->so_qlen == 0 && so->so_error == 0) {
136 		if (so->so_state & SS_CANTRCVMORE) {
137 			so->so_error = ECONNABORTED;
138 			break;
139 		}
140 		sleep((caddr_t)&so->so_timeo, PZERO+1);
141 	}
142 	if (so->so_error) {
143 		u.u_error = so->so_error;
144 		so->so_error = 0;
145 		splx(s);
146 		return;
147 	}
148 	if (ufalloc(0) < 0) {
149 		splx(s);
150 		return;
151 	}
152 	fp = falloc();
153 	if (fp == 0) {
154 		u.u_ofile[u.u_r.r_val1] = 0;
155 		splx(s);
156 		return;
157 	}
158 	{ struct socket *aso = so->so_q;
159 	  if (soqremque(aso, 1) == 0)
160 		panic("accept");
161 	  so = aso;
162 	}
163 	fp->f_type = DTYPE_SOCKET;
164 	fp->f_flag = FREAD|FWRITE;
165 	fp->f_ops = &socketops;
166 	fp->f_data = (caddr_t)so;
167 	nam = m_get(M_WAIT, MT_SONAME);
168 	(void) soaccept(so, nam);
169 	if (uap->name) {
170 		if (namelen > nam->m_len)
171 			namelen = nam->m_len;
172 		/* SHOULD COPY OUT A CHAIN HERE */
173 		(void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
174 		    (u_int)namelen);
175 		(void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
176 		    sizeof (*uap->anamelen));
177 	}
178 	m_freem(nam);
179 	splx(s);
180 }
181 
182 connect()
183 {
184 	register struct a {
185 		int	s;
186 		caddr_t	name;
187 		int	namelen;
188 	} *uap = (struct a *)u.u_ap;
189 	register struct file *fp;
190 	register struct socket *so;
191 	struct mbuf *nam;
192 	int s;
193 
194 	fp = getsock(uap->s);
195 	if (fp == 0)
196 		return;
197 	so = (struct socket *)fp->f_data;
198 	if ((so->so_state & SS_NBIO) &&
199 	    (so->so_state & SS_ISCONNECTING)) {
200 		u.u_error = EALREADY;
201 		return;
202 	}
203 	u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
204 	if (u.u_error)
205 		return;
206 	u.u_error = soconnect(so, nam);
207 	if (u.u_error)
208 		goto bad;
209 	if ((so->so_state & SS_NBIO) &&
210 	    (so->so_state & SS_ISCONNECTING)) {
211 		u.u_error = EINPROGRESS;
212 		m_freem(nam);
213 		return;
214 	}
215 	s = splnet();
216 	if (setjmp(&u.u_qsave)) {
217 		if (u.u_error == 0)
218 			u.u_error = EINTR;
219 		goto bad2;
220 	}
221 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
222 		sleep((caddr_t)&so->so_timeo, PZERO+1);
223 	u.u_error = so->so_error;
224 	so->so_error = 0;
225 bad2:
226 	splx(s);
227 bad:
228 	so->so_state &= ~SS_ISCONNECTING;
229 	m_freem(nam);
230 }
231 
232 socketpair()
233 {
234 	register struct a {
235 		int	domain;
236 		int	type;
237 		int	protocol;
238 		int	*rsv;
239 	} *uap = (struct a *)u.u_ap;
240 	register struct file *fp1, *fp2;
241 	struct socket *so1, *so2;
242 	int sv[2];
243 
244 	if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
245 		u.u_error = EFAULT;
246 		return;
247 	}
248 	u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
249 	if (u.u_error)
250 		return;
251 	u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
252 	if (u.u_error)
253 		goto free;
254 	fp1 = falloc();
255 	if (fp1 == NULL)
256 		goto free2;
257 	sv[0] = u.u_r.r_val1;
258 	fp1->f_flag = FREAD|FWRITE;
259 	fp1->f_type = DTYPE_SOCKET;
260 	fp1->f_ops = &socketops;
261 	fp1->f_data = (caddr_t)so1;
262 	fp2 = falloc();
263 	if (fp2 == NULL)
264 		goto free3;
265 	fp2->f_flag = FREAD|FWRITE;
266 	fp2->f_type = DTYPE_SOCKET;
267 	fp2->f_ops = &socketops;
268 	fp2->f_data = (caddr_t)so2;
269 	sv[1] = u.u_r.r_val1;
270 	u.u_error = soconnect2(so1, so2);
271 	if (u.u_error)
272 		goto free4;
273 	if (uap->type == SOCK_DGRAM) {
274 		/*
275 		 * Datagram socket connection is asymmetric.
276 		 */
277 		 u.u_error = soconnect2(so2, so1);
278 		 if (u.u_error)
279 			goto free4;
280 	}
281 	u.u_r.r_val1 = 0;
282 	(void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
283 	return;
284 free4:
285 	fp2->f_count = 0;
286 	u.u_ofile[sv[1]] = 0;
287 free3:
288 	fp1->f_count = 0;
289 	u.u_ofile[sv[0]] = 0;
290 free2:
291 	(void)soclose(so2);
292 free:
293 	(void)soclose(so1);
294 }
295 
296 sendto()
297 {
298 	register struct a {
299 		int	s;
300 		caddr_t	buf;
301 		int	len;
302 		int	flags;
303 		caddr_t	to;
304 		int	tolen;
305 	} *uap = (struct a *)u.u_ap;
306 	struct msghdr msg;
307 	struct iovec aiov;
308 
309 	msg.msg_name = uap->to;
310 	msg.msg_namelen = uap->tolen;
311 	msg.msg_iov = &aiov;
312 	msg.msg_iovlen = 1;
313 	aiov.iov_base = uap->buf;
314 	aiov.iov_len = uap->len;
315 	msg.msg_accrights = 0;
316 	msg.msg_accrightslen = 0;
317 	sendit(uap->s, &msg, uap->flags);
318 }
319 
320 send()
321 {
322 	register struct a {
323 		int	s;
324 		caddr_t	buf;
325 		int	len;
326 		int	flags;
327 	} *uap = (struct a *)u.u_ap;
328 	struct msghdr msg;
329 	struct iovec aiov;
330 
331 	msg.msg_name = 0;
332 	msg.msg_namelen = 0;
333 	msg.msg_iov = &aiov;
334 	msg.msg_iovlen = 1;
335 	aiov.iov_base = uap->buf;
336 	aiov.iov_len = uap->len;
337 	msg.msg_accrights = 0;
338 	msg.msg_accrightslen = 0;
339 	sendit(uap->s, &msg, uap->flags);
340 }
341 
342 sendmsg()
343 {
344 	register struct a {
345 		int	s;
346 		caddr_t	msg;
347 		int	flags;
348 	} *uap = (struct a *)u.u_ap;
349 	struct msghdr msg;
350 	struct iovec aiov[MSG_MAXIOVLEN];
351 
352 	u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
353 	if (u.u_error)
354 		return;
355 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
356 		u.u_error = EMSGSIZE;
357 		return;
358 	}
359 	u.u_error =
360 	    copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
361 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
362 	if (u.u_error)
363 		return;
364 	msg.msg_iov = aiov;
365 	sendit(uap->s, &msg, uap->flags);
366 }
367 
368 sendit(s, mp, flags)
369 	int s;
370 	register struct msghdr *mp;
371 	int flags;
372 {
373 	register struct file *fp;
374 	struct uio auio;
375 	register struct iovec *iov;
376 	register int i;
377 	struct mbuf *to, *rights;
378 	int len;
379 
380 	fp = getsock(s);
381 	if (fp == 0)
382 		return;
383 	auio.uio_iov = mp->msg_iov;
384 	auio.uio_iovcnt = mp->msg_iovlen;
385 	auio.uio_segflg = UIO_USERSPACE;
386 	auio.uio_offset = 0;			/* XXX */
387 	auio.uio_resid = 0;
388 	iov = mp->msg_iov;
389 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
390 		if (iov->iov_len < 0) {
391 			u.u_error = EINVAL;
392 			return;
393 		}
394 		if (iov->iov_len == 0)
395 			continue;
396 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
397 			u.u_error = EFAULT;
398 			return;
399 		}
400 		auio.uio_resid += iov->iov_len;
401 	}
402 	if (mp->msg_name) {
403 		u.u_error =
404 		    sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
405 		if (u.u_error)
406 			return;
407 	} else
408 		to = 0;
409 	if (mp->msg_accrights) {
410 		u.u_error =
411 		    sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
412 		    MT_RIGHTS);
413 		if (u.u_error)
414 			goto bad;
415 	} else
416 		rights = 0;
417 	len = auio.uio_resid;
418 	u.u_error =
419 	    sosend((struct socket *)fp->f_data, to, &auio, flags, rights);
420 	u.u_r.r_val1 = len - auio.uio_resid;
421 	if (rights)
422 		m_freem(rights);
423 bad:
424 	if (to)
425 		m_freem(to);
426 }
427 
428 recvfrom()
429 {
430 	register struct a {
431 		int	s;
432 		caddr_t	buf;
433 		int	len;
434 		int	flags;
435 		caddr_t	from;
436 		int	*fromlenaddr;
437 	} *uap = (struct a *)u.u_ap;
438 	struct msghdr msg;
439 	struct iovec aiov;
440 	int len;
441 
442 	u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
443 	   sizeof (len));
444 	if (u.u_error)
445 		return;
446 	msg.msg_name = uap->from;
447 	msg.msg_namelen = len;
448 	msg.msg_iov = &aiov;
449 	msg.msg_iovlen = 1;
450 	aiov.iov_base = uap->buf;
451 	aiov.iov_len = uap->len;
452 	msg.msg_accrights = 0;
453 	msg.msg_accrightslen = 0;
454 	recvit(uap->s, &msg, uap->flags, (caddr_t)uap->fromlenaddr, (caddr_t)0);
455 }
456 
457 recv()
458 {
459 	register struct a {
460 		int	s;
461 		caddr_t	buf;
462 		int	len;
463 		int	flags;
464 	} *uap = (struct a *)u.u_ap;
465 	struct msghdr msg;
466 	struct iovec aiov;
467 
468 	msg.msg_name = 0;
469 	msg.msg_namelen = 0;
470 	msg.msg_iov = &aiov;
471 	msg.msg_iovlen = 1;
472 	aiov.iov_base = uap->buf;
473 	aiov.iov_len = uap->len;
474 	msg.msg_accrights = 0;
475 	msg.msg_accrightslen = 0;
476 	recvit(uap->s, &msg, uap->flags, (caddr_t)0, (caddr_t)0);
477 }
478 
479 recvmsg()
480 {
481 	register struct a {
482 		int	s;
483 		struct	msghdr *msg;
484 		int	flags;
485 	} *uap = (struct a *)u.u_ap;
486 	struct msghdr msg;
487 	struct iovec aiov[MSG_MAXIOVLEN];
488 
489 	u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
490 	if (u.u_error)
491 		return;
492 	if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
493 		u.u_error = EMSGSIZE;
494 		return;
495 	}
496 	u.u_error =
497 	    copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
498 		(unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
499 	if (u.u_error)
500 		return;
501 	msg.msg_iov = aiov;
502 	if (msg.msg_accrights)
503 		if (useracc((caddr_t)msg.msg_accrights,
504 		    (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
505 			u.u_error = EFAULT;
506 			return;
507 		}
508 	recvit(uap->s, &msg, uap->flags,
509 	    (caddr_t)&uap->msg->msg_namelen,
510 	    (caddr_t)&uap->msg->msg_accrightslen);
511 }
512 
513 recvit(s, mp, flags, namelenp, rightslenp)
514 	int s;
515 	register struct msghdr *mp;
516 	int flags;
517 	caddr_t namelenp, rightslenp;
518 {
519 	register struct file *fp;
520 	struct uio auio;
521 	register struct iovec *iov;
522 	register int i;
523 	struct mbuf *from, *rights;
524 	int len;
525 
526 	fp = getsock(s);
527 	if (fp == 0)
528 		return;
529 	auio.uio_iov = mp->msg_iov;
530 	auio.uio_iovcnt = mp->msg_iovlen;
531 	auio.uio_segflg = UIO_USERSPACE;
532 	auio.uio_offset = 0;			/* XXX */
533 	auio.uio_resid = 0;
534 	iov = mp->msg_iov;
535 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
536 		if (iov->iov_len < 0) {
537 			u.u_error = EINVAL;
538 			return;
539 		}
540 		if (iov->iov_len == 0)
541 			continue;
542 		if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
543 			u.u_error = EFAULT;
544 			return;
545 		}
546 		auio.uio_resid += iov->iov_len;
547 	}
548 	len = auio.uio_resid;
549 	u.u_error =
550 	    soreceive((struct socket *)fp->f_data, &from, &auio,
551 		flags, &rights);
552 	u.u_r.r_val1 = len - auio.uio_resid;
553 	if (mp->msg_name) {
554 		len = mp->msg_namelen;
555 		if (len <= 0 || from == 0)
556 			len = 0;
557 		else {
558 			if (len > from->m_len)
559 				len = from->m_len;
560 			(void) copyout((caddr_t)mtod(from, caddr_t),
561 			    (caddr_t)mp->msg_name, (unsigned)len);
562 		}
563 		(void) copyout((caddr_t)&len, namelenp, sizeof (int));
564 	}
565 	if (mp->msg_accrights) {
566 		len = mp->msg_accrightslen;
567 		if (len <= 0 || rights == 0)
568 			len = 0;
569 		else {
570 			if (len > rights->m_len)
571 				len = rights->m_len;
572 			(void) copyout((caddr_t)mtod(rights, caddr_t),
573 			    (caddr_t)mp->msg_accrights, (unsigned)len);
574 		}
575 		(void) copyout((caddr_t)&len, rightslenp, sizeof (int));
576 	}
577 	if (rights)
578 		m_freem(rights);
579 	if (from)
580 		m_freem(from);
581 }
582 
583 shutdown()
584 {
585 	struct a {
586 		int	s;
587 		int	how;
588 	} *uap = (struct a *)u.u_ap;
589 	struct file *fp;
590 
591 	fp = getsock(uap->s);
592 	if (fp == 0)
593 		return;
594 	u.u_error = soshutdown((struct socket *)fp->f_data, uap->how);
595 }
596 
597 setsockopt()
598 {
599 	struct a {
600 		int	s;
601 		int	level;
602 		int	name;
603 		caddr_t	val;
604 		int	valsize;
605 	} *uap = (struct a *)u.u_ap;
606 	struct file *fp;
607 	struct mbuf *m = NULL;
608 
609 	fp = getsock(uap->s);
610 	if (fp == 0)
611 		return;
612 	if (uap->valsize > MLEN) {
613 		u.u_error = EINVAL;
614 		return;
615 	}
616 	if (uap->val) {
617 		m = m_get(M_WAIT, MT_SOOPTS);
618 		if (m == NULL) {
619 			u.u_error = ENOBUFS;
620 			return;
621 		}
622 		u.u_error =
623 		    copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
624 		if (u.u_error) {
625 			(void) m_free(m);
626 			return;
627 		}
628 		m->m_len = uap->valsize;
629 	}
630 	u.u_error =
631 	    sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m);
632 }
633 
634 getsockopt()
635 {
636 	struct a {
637 		int	s;
638 		int	level;
639 		int	name;
640 		caddr_t	val;
641 		int	*avalsize;
642 	} *uap = (struct a *)u.u_ap;
643 	struct file *fp;
644 	struct mbuf *m = NULL;
645 	int valsize;
646 
647 	fp = getsock(uap->s);
648 	if (fp == 0)
649 		return;
650 	if (uap->val) {
651 		u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
652 			sizeof (valsize));
653 		if (u.u_error)
654 			return;
655 	} else
656 		valsize = 0;
657 	u.u_error =
658 	    sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m);
659 	if (u.u_error)
660 		goto bad;
661 	if (uap->val && valsize && m != NULL) {
662 		if (valsize > m->m_len)
663 			valsize = m->m_len;
664 		u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
665 		if (u.u_error)
666 			goto bad;
667 		u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
668 		    sizeof (valsize));
669 	}
670 bad:
671 	if (m != NULL)
672 		(void) m_free(m);
673 }
674 
675 pipe()
676 {
677 	register struct file *rf, *wf;
678 	struct socket *rso, *wso;
679 	int r;
680 
681 	u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
682 	if (u.u_error)
683 		return;
684 	u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
685 	if (u.u_error)
686 		goto free;
687 	rf = falloc();
688 	if (rf == NULL)
689 		goto free2;
690 	r = u.u_r.r_val1;
691 	rf->f_flag = FREAD;
692 	rf->f_type = DTYPE_SOCKET;
693 	rf->f_ops = &socketops;
694 	rf->f_data = (caddr_t)rso;
695 	wf = falloc();
696 	if (wf == NULL)
697 		goto free3;
698 	wf->f_flag = FWRITE;
699 	wf->f_type = DTYPE_SOCKET;
700 	wf->f_ops = &socketops;
701 	wf->f_data = (caddr_t)wso;
702 	u.u_r.r_val2 = u.u_r.r_val1;
703 	u.u_r.r_val1 = r;
704 	if (u.u_error = unp_connect2(wso, rso))
705 		goto free4;
706 	wso->so_state |= SS_CANTRCVMORE;
707 	rso->so_state |= SS_CANTSENDMORE;
708 	return;
709 free4:
710 	wf->f_count = 0;
711 	u.u_ofile[u.u_r.r_val2] = 0;
712 free3:
713 	rf->f_count = 0;
714 	u.u_ofile[r] = 0;
715 free2:
716 	(void)soclose(wso);
717 free:
718 	(void)soclose(rso);
719 }
720 
721 /*
722  * Get socket name.
723  */
724 getsockname()
725 {
726 	register struct a {
727 		int	fdes;
728 		caddr_t	asa;
729 		int	*alen;
730 	} *uap = (struct a *)u.u_ap;
731 	register struct file *fp;
732 	register struct socket *so;
733 	struct mbuf *m;
734 	int len;
735 
736 	fp = getsock(uap->fdes);
737 	if (fp == 0)
738 		return;
739 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
740 	if (u.u_error)
741 		return;
742 	so = (struct socket *)fp->f_data;
743 	m = m_getclr(M_WAIT, MT_SONAME);
744 	if (m == NULL) {
745 		u.u_error = ENOBUFS;
746 		return;
747 	}
748 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
749 	if (u.u_error)
750 		goto bad;
751 	if (len > m->m_len)
752 		len = m->m_len;
753 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
754 	if (u.u_error)
755 		goto bad;
756 	u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
757 bad:
758 	m_freem(m);
759 }
760 
761 /*
762  * Get name of peer for connected socket.
763  */
764 getpeername()
765 {
766 	register struct a {
767 		int	fdes;
768 		caddr_t	asa;
769 		int	*alen;
770 	} *uap = (struct a *)u.u_ap;
771 	register struct file *fp;
772 	register struct socket *so;
773 	struct mbuf *m;
774 	int len;
775 
776 	fp = getsock(uap->fdes);
777 	if (fp == 0)
778 		return;
779 	so = (struct socket *)fp->f_data;
780 	if ((so->so_state & SS_ISCONNECTED) == 0) {
781 		u.u_error = ENOTCONN;
782 		return;
783 	}
784 	m = m_getclr(M_WAIT, MT_SONAME);
785 	if (m == NULL) {
786 		u.u_error = ENOBUFS;
787 		return;
788 	}
789 	u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
790 	if (u.u_error)
791 		return;
792 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
793 	if (u.u_error)
794 		goto bad;
795 	if (len > m->m_len)
796 		len = m->m_len;
797 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
798 	if (u.u_error)
799 		goto bad;
800 	u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
801 bad:
802 	m_freem(m);
803 }
804 
805 sockargs(aname, name, namelen, type)
806 	struct mbuf **aname;
807 	caddr_t name;
808 	int namelen, type;
809 {
810 	register struct mbuf *m;
811 	int error;
812 
813 	if ((u_int)namelen > MLEN)
814 		return (EINVAL);
815 	m = m_get(M_WAIT, type);
816 	if (m == NULL)
817 		return (ENOBUFS);
818 	m->m_len = namelen;
819 	error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
820 	if (error)
821 		(void) m_free(m);
822 	else
823 		*aname = m;
824 	return (error);
825 }
826 
827 struct file *
828 getsock(fdes)
829 	int fdes;
830 {
831 	register struct file *fp;
832 
833 	fp = getf(fdes);
834 	if (fp == NULL)
835 		return (0);
836 	if (fp->f_type != DTYPE_SOCKET) {
837 		u.u_error = ENOTSOCK;
838 		return (0);
839 	}
840 	return (fp);
841 }
842