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