uipc_syscalls.c revision 1.41 1 /* $NetBSD: uipc_syscalls.c,v 1.41 1999/02/10 18:02:28 kleink Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
36 */
37
38 #include "opt_ktrace.h"
39 #include "opt_compat_freebsd.h"
40 #include "opt_compat_linux.h"
41 #include "opt_compat_sunos.h"
42 #include "opt_compat_hpux.h"
43 #include "opt_compat_ultrix.h"
44 #include "opt_compat_43.h"
45 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \
46 defined(COMPAT_HPUX) || defined(COMPAT_FREEBSD) || defined(COMPAT_ULTRIX)
47 #define COMPAT_OLDSOCK /* used by <sys/socket.h> */
48 #endif
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/filedesc.h>
53 #include <sys/proc.h>
54 #include <sys/file.h>
55 #include <sys/buf.h>
56 #include <sys/malloc.h>
57 #include <sys/mbuf.h>
58 #include <sys/protosw.h>
59 #include <sys/socket.h>
60 #include <sys/socketvar.h>
61 #include <sys/signalvar.h>
62 #include <sys/un.h>
63 #ifdef KTRACE
64 #include <sys/ktrace.h>
65 #endif
66
67 #include <sys/mount.h>
68 #include <sys/syscallargs.h>
69
70 /*
71 * System call interface to the socket abstraction.
72 */
73 extern struct fileops socketops;
74
75 int
76 sys_socket(p, v, retval)
77 struct proc *p;
78 void *v;
79 register_t *retval;
80 {
81 register struct sys_socket_args /* {
82 syscallarg(int) domain;
83 syscallarg(int) type;
84 syscallarg(int) protocol;
85 } */ *uap = v;
86 struct filedesc *fdp = p->p_fd;
87 struct socket *so;
88 struct file *fp;
89 int fd, error;
90
91 if ((error = falloc(p, &fp, &fd)) != 0)
92 return (error);
93 fp->f_flag = FREAD|FWRITE;
94 fp->f_type = DTYPE_SOCKET;
95 fp->f_ops = &socketops;
96 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
97 SCARG(uap, protocol));
98 if (error) {
99 fdp->fd_ofiles[fd] = 0;
100 ffree(fp);
101 } else {
102 fp->f_data = (caddr_t)so;
103 *retval = fd;
104 }
105 return (error);
106 }
107
108 /* ARGSUSED */
109 int
110 sys_bind(p, v, retval)
111 struct proc *p;
112 void *v;
113 register_t *retval;
114 {
115 register struct sys_bind_args /* {
116 syscallarg(int) s;
117 syscallarg(const struct sockaddr *) name;
118 syscallarg(unsigned int) namelen;
119 } */ *uap = v;
120 struct file *fp;
121 struct mbuf *nam;
122 int error;
123
124 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
125 return (error);
126 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
127 MT_SONAME);
128 if (error)
129 return (error);
130 error = sobind((struct socket *)fp->f_data, nam);
131 m_freem(nam);
132 return (error);
133 }
134
135 /* ARGSUSED */
136 int
137 sys_listen(p, v, retval)
138 struct proc *p;
139 void *v;
140 register_t *retval;
141 {
142 register struct sys_listen_args /* {
143 syscallarg(int) s;
144 syscallarg(int) backlog;
145 } */ *uap = v;
146 struct file *fp;
147 int error;
148
149 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
150 return (error);
151 return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog)));
152 }
153
154 int
155 sys_accept(p, v, retval)
156 struct proc *p;
157 void *v;
158 register_t *retval;
159 {
160 register struct sys_accept_args /* {
161 syscallarg(int) s;
162 syscallarg(struct sockaddr *) name;
163 syscallarg(unsigned int *) anamelen;
164 } */ *uap = v;
165 struct file *fp;
166 struct mbuf *nam;
167 unsigned int namelen;
168 int error, s, tmpfd;
169 register struct socket *so;
170
171 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
172 (caddr_t)&namelen, sizeof(namelen))))
173 return (error);
174 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
175 return (error);
176 s = splsoftnet();
177 so = (struct socket *)fp->f_data;
178 if ((so->so_options & SO_ACCEPTCONN) == 0) {
179 splx(s);
180 return (EINVAL);
181 }
182 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
183 splx(s);
184 return (EWOULDBLOCK);
185 }
186 while (so->so_qlen == 0 && so->so_error == 0) {
187 if (so->so_state & SS_CANTRCVMORE) {
188 so->so_error = ECONNABORTED;
189 break;
190 }
191 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
192 netcon, 0);
193 if (error) {
194 splx(s);
195 return (error);
196 }
197 }
198 if (so->so_error) {
199 error = so->so_error;
200 so->so_error = 0;
201 splx(s);
202 return (error);
203 }
204 if ((error = falloc(p, &fp, &tmpfd)) != 0) {
205 splx(s);
206 return (error);
207 }
208 *retval = tmpfd;
209 { struct socket *aso = so->so_q.tqh_first;
210 if (soqremque(aso, 1) == 0)
211 panic("accept");
212 so = aso;
213 }
214 fp->f_type = DTYPE_SOCKET;
215 fp->f_flag = FREAD|FWRITE;
216 fp->f_ops = &socketops;
217 fp->f_data = (caddr_t)so;
218 nam = m_get(M_WAIT, MT_SONAME);
219 (void) soaccept(so, nam);
220 if (SCARG(uap, name)) {
221 if (namelen > nam->m_len)
222 namelen = nam->m_len;
223 /* SHOULD COPY OUT A CHAIN HERE */
224 if ((error = copyout(mtod(nam, caddr_t),
225 (caddr_t)SCARG(uap, name), namelen)) == 0)
226 error = copyout((caddr_t)&namelen,
227 (caddr_t)SCARG(uap, anamelen),
228 sizeof(*SCARG(uap, anamelen)));
229 }
230 m_freem(nam);
231 splx(s);
232 return (error);
233 }
234
235 /* ARGSUSED */
236 int
237 sys_connect(p, v, retval)
238 struct proc *p;
239 void *v;
240 register_t *retval;
241 {
242 register struct sys_connect_args /* {
243 syscallarg(int) s;
244 syscallarg(const struct sockaddr *) name;
245 syscallarg(unsigned int) namelen;
246 } */ *uap = v;
247 struct file *fp;
248 register struct socket *so;
249 struct mbuf *nam;
250 int error, s;
251
252 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
253 return (error);
254 so = (struct socket *)fp->f_data;
255 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
256 return (EALREADY);
257 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
258 MT_SONAME);
259 if (error)
260 return (error);
261 error = soconnect(so, nam);
262 if (error)
263 goto bad;
264 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
265 m_freem(nam);
266 return (EINPROGRESS);
267 }
268 s = splsoftnet();
269 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
270 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
271 netcon, 0);
272 if (error)
273 break;
274 }
275 if (error == 0) {
276 error = so->so_error;
277 so->so_error = 0;
278 }
279 splx(s);
280 bad:
281 so->so_state &= ~SS_ISCONNECTING;
282 m_freem(nam);
283 if (error == ERESTART)
284 error = EINTR;
285 return (error);
286 }
287
288 int
289 sys_socketpair(p, v, retval)
290 struct proc *p;
291 void *v;
292 register_t *retval;
293 {
294 register struct sys_socketpair_args /* {
295 syscallarg(int) domain;
296 syscallarg(int) type;
297 syscallarg(int) protocol;
298 syscallarg(int *) rsv;
299 } */ *uap = v;
300 register struct filedesc *fdp = p->p_fd;
301 struct file *fp1, *fp2;
302 struct socket *so1, *so2;
303 int fd, error, sv[2];
304
305 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
306 SCARG(uap, protocol));
307 if (error)
308 return (error);
309 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
310 SCARG(uap, protocol));
311 if (error)
312 goto free1;
313 if ((error = falloc(p, &fp1, &fd)) != 0)
314 goto free2;
315 sv[0] = fd;
316 fp1->f_flag = FREAD|FWRITE;
317 fp1->f_type = DTYPE_SOCKET;
318 fp1->f_ops = &socketops;
319 fp1->f_data = (caddr_t)so1;
320 if ((error = falloc(p, &fp2, &fd)) != 0)
321 goto free3;
322 fp2->f_flag = FREAD|FWRITE;
323 fp2->f_type = DTYPE_SOCKET;
324 fp2->f_ops = &socketops;
325 fp2->f_data = (caddr_t)so2;
326 sv[1] = fd;
327 if ((error = soconnect2(so1, so2)) != 0)
328 goto free4;
329 if (SCARG(uap, type) == SOCK_DGRAM) {
330 /*
331 * Datagram socket connection is asymmetric.
332 */
333 if ((error = soconnect2(so2, so1)) != 0)
334 goto free4;
335 }
336 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
337 2 * sizeof(int));
338 return (error);
339 free4:
340 ffree(fp2);
341 fdp->fd_ofiles[sv[1]] = 0;
342 free3:
343 ffree(fp1);
344 fdp->fd_ofiles[sv[0]] = 0;
345 free2:
346 (void)soclose(so2);
347 free1:
348 (void)soclose(so1);
349 return (error);
350 }
351
352 int
353 sys_sendto(p, v, retval)
354 struct proc *p;
355 void *v;
356 register_t *retval;
357 {
358 register struct sys_sendto_args /* {
359 syscallarg(int) s;
360 syscallarg(const void *) buf;
361 syscallarg(size_t) len;
362 syscallarg(int) flags;
363 syscallarg(const struct sockaddr *) to;
364 syscallarg(unsigned int) tolen;
365 } */ *uap = v;
366 struct msghdr msg;
367 struct iovec aiov;
368
369 msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
370 msg.msg_namelen = SCARG(uap, tolen);
371 msg.msg_iov = &aiov;
372 msg.msg_iovlen = 1;
373 msg.msg_control = 0;
374 #ifdef COMPAT_OLDSOCK
375 msg.msg_flags = 0;
376 #endif
377 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
378 aiov.iov_len = SCARG(uap, len);
379 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
380 }
381
382 int
383 sys_sendmsg(p, v, retval)
384 struct proc *p;
385 void *v;
386 register_t *retval;
387 {
388 register struct sys_sendmsg_args /* {
389 syscallarg(int) s;
390 syscallarg(const struct msghdr *) msg;
391 syscallarg(int) flags;
392 } */ *uap = v;
393 struct msghdr msg;
394 struct iovec aiov[UIO_SMALLIOV], *iov;
395 int error;
396
397 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
398 if (error)
399 return (error);
400 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
401 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
402 return (EMSGSIZE);
403 MALLOC(iov, struct iovec *,
404 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
405 } else
406 iov = aiov;
407 if ((unsigned int)msg.msg_iovlen > 0) {
408 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
409 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
410 if (error)
411 goto done;
412 }
413 msg.msg_iov = iov;
414 #ifdef COMPAT_OLDSOCK
415 msg.msg_flags = 0;
416 #endif
417 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
418 done:
419 if (iov != aiov)
420 FREE(iov, M_IOV);
421 return (error);
422 }
423
424 int
425 sendit(p, s, mp, flags, retsize)
426 register struct proc *p;
427 int s;
428 register struct msghdr *mp;
429 int flags;
430 register_t *retsize;
431 {
432 struct file *fp;
433 struct uio auio;
434 register struct iovec *iov;
435 register int i;
436 struct mbuf *to, *control;
437 int len, error;
438 struct socket *so;
439 #ifdef KTRACE
440 struct iovec *ktriov = NULL;
441 #endif
442
443 if ((error = getsock(p->p_fd, s, &fp)) != 0)
444 return (error);
445 auio.uio_iov = mp->msg_iov;
446 auio.uio_iovcnt = mp->msg_iovlen;
447 auio.uio_segflg = UIO_USERSPACE;
448 auio.uio_rw = UIO_WRITE;
449 auio.uio_procp = p;
450 auio.uio_offset = 0; /* XXX */
451 auio.uio_resid = 0;
452 iov = mp->msg_iov;
453 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
454 #if 0
455 /* cannot happen; iov_len is unsigned */
456 if (iov->iov_len < 0)
457 return (EINVAL);
458 #endif
459 /*
460 * Writes return ssize_t because -1 is returned on error.
461 * Therefore, we must restrict the length to SSIZE_MAX to
462 * avoid garbage return values.
463 */
464 auio.uio_resid += iov->iov_len;
465 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX)
466 return (EINVAL);
467 }
468 if (mp->msg_name) {
469 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
470 MT_SONAME);
471 if (error)
472 return (error);
473 } else
474 to = 0;
475 if (mp->msg_control) {
476 if (mp->msg_controllen < sizeof(struct cmsghdr)
477 #ifdef COMPAT_OLDSOCK
478 && mp->msg_flags != MSG_COMPAT
479 #endif
480 ) {
481 error = EINVAL;
482 goto bad;
483 }
484 error = sockargs(&control, mp->msg_control,
485 mp->msg_controllen, MT_CONTROL);
486 if (error)
487 goto bad;
488 #ifdef COMPAT_OLDSOCK
489 if (mp->msg_flags == MSG_COMPAT) {
490 register struct cmsghdr *cm;
491
492 M_PREPEND(control, sizeof(*cm), M_WAIT);
493 if (control == 0) {
494 error = ENOBUFS;
495 goto bad;
496 } else {
497 cm = mtod(control, struct cmsghdr *);
498 cm->cmsg_len = control->m_len;
499 cm->cmsg_level = SOL_SOCKET;
500 cm->cmsg_type = SCM_RIGHTS;
501 }
502 }
503 #endif
504 } else
505 control = 0;
506 #ifdef KTRACE
507 if (KTRPOINT(p, KTR_GENIO)) {
508 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
509
510 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
511 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
512 }
513 #endif
514 len = auio.uio_resid;
515 so = (struct socket *)fp->f_data;
516 error = (*so->so_send)(so, to, &auio, NULL, control, flags);
517 if (error) {
518 if (auio.uio_resid != len && (error == ERESTART ||
519 error == EINTR || error == EWOULDBLOCK))
520 error = 0;
521 if (error == EPIPE)
522 psignal(p, SIGPIPE);
523 }
524 if (error == 0)
525 *retsize = len - auio.uio_resid;
526 #ifdef KTRACE
527 if (ktriov != NULL) {
528 if (error == 0)
529 ktrgenio(p->p_tracep, s, UIO_WRITE,
530 ktriov, *retsize, error);
531 FREE(ktriov, M_TEMP);
532 }
533 #endif
534 bad:
535 if (to)
536 m_freem(to);
537 return (error);
538 }
539
540 int
541 sys_recvfrom(p, v, retval)
542 struct proc *p;
543 void *v;
544 register_t *retval;
545 {
546 register struct sys_recvfrom_args /* {
547 syscallarg(int) s;
548 syscallarg(void *) buf;
549 syscallarg(size_t) len;
550 syscallarg(int) flags;
551 syscallarg(struct sockaddr *) from;
552 syscallarg(unsigned int *) fromlenaddr;
553 } */ *uap = v;
554 struct msghdr msg;
555 struct iovec aiov;
556 int error;
557
558 if (SCARG(uap, fromlenaddr)) {
559 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
560 (caddr_t)&msg.msg_namelen,
561 sizeof(msg.msg_namelen));
562 if (error)
563 return (error);
564 } else
565 msg.msg_namelen = 0;
566 msg.msg_name = (caddr_t)SCARG(uap, from);
567 msg.msg_iov = &aiov;
568 msg.msg_iovlen = 1;
569 aiov.iov_base = SCARG(uap, buf);
570 aiov.iov_len = SCARG(uap, len);
571 msg.msg_control = 0;
572 msg.msg_flags = SCARG(uap, flags);
573 return (recvit(p, SCARG(uap, s), &msg,
574 (caddr_t)SCARG(uap, fromlenaddr), retval));
575 }
576
577 int
578 sys_recvmsg(p, v, retval)
579 struct proc *p;
580 void *v;
581 register_t *retval;
582 {
583 register struct sys_recvmsg_args /* {
584 syscallarg(int) s;
585 syscallarg(struct msghdr *) msg;
586 syscallarg(int) flags;
587 } */ *uap = v;
588 struct msghdr msg;
589 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
590 register int error;
591
592 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
593 sizeof(msg));
594 if (error)
595 return (error);
596 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
597 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
598 return (EMSGSIZE);
599 MALLOC(iov, struct iovec *,
600 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
601 } else
602 iov = aiov;
603 if ((unsigned int)msg.msg_iovlen > 0) {
604 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
605 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
606 if (error)
607 goto done;
608 }
609 uiov = msg.msg_iov;
610 msg.msg_iov = iov;
611 #ifdef COMPAT_OLDSOCK
612 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
613 #else
614 msg.msg_flags = SCARG(uap, flags);
615 #endif
616 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
617 msg.msg_iov = uiov;
618 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
619 sizeof(msg));
620 }
621 done:
622 if (iov != aiov)
623 FREE(iov, M_IOV);
624 return (error);
625 }
626
627 int
628 recvit(p, s, mp, namelenp, retsize)
629 register struct proc *p;
630 int s;
631 register struct msghdr *mp;
632 caddr_t namelenp;
633 register_t *retsize;
634 {
635 struct file *fp;
636 struct uio auio;
637 register struct iovec *iov;
638 register int i;
639 int len, error;
640 struct mbuf *from = 0, *control = 0;
641 struct socket *so;
642 #ifdef KTRACE
643 struct iovec *ktriov = NULL;
644 #endif
645
646 if ((error = getsock(p->p_fd, s, &fp)) != 0)
647 return (error);
648 auio.uio_iov = mp->msg_iov;
649 auio.uio_iovcnt = mp->msg_iovlen;
650 auio.uio_segflg = UIO_USERSPACE;
651 auio.uio_rw = UIO_READ;
652 auio.uio_procp = p;
653 auio.uio_offset = 0; /* XXX */
654 auio.uio_resid = 0;
655 iov = mp->msg_iov;
656 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
657 #if 0
658 /* cannot happen iov_len is unsigned */
659 if (iov->iov_len < 0)
660 return (EINVAL);
661 #endif
662 /*
663 * Reads return ssize_t because -1 is returned on error.
664 * Therefore we must restrict the length to SSIZE_MAX to
665 * avoid garbage return values.
666 */
667 auio.uio_resid += iov->iov_len;
668 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX)
669 return (EINVAL);
670 }
671 #ifdef KTRACE
672 if (KTRPOINT(p, KTR_GENIO)) {
673 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
674
675 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
676 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
677 }
678 #endif
679 len = auio.uio_resid;
680 so = (struct socket *)fp->f_data;
681 error = (*so->so_receive)(so, &from, &auio, NULL,
682 mp->msg_control ? &control : NULL, &mp->msg_flags);
683 if (error) {
684 if (auio.uio_resid != len && (error == ERESTART ||
685 error == EINTR || error == EWOULDBLOCK))
686 error = 0;
687 }
688 #ifdef KTRACE
689 if (ktriov != NULL) {
690 if (error == 0)
691 ktrgenio(p->p_tracep, s, UIO_READ,
692 ktriov, len - auio.uio_resid, error);
693 FREE(ktriov, M_TEMP);
694 }
695 #endif
696 if (error)
697 goto out;
698 *retsize = len - auio.uio_resid;
699 if (mp->msg_name) {
700 len = mp->msg_namelen;
701 if (len <= 0 || from == 0)
702 len = 0;
703 else {
704 #ifdef COMPAT_OLDSOCK
705 if (mp->msg_flags & MSG_COMPAT)
706 mtod(from, struct osockaddr *)->sa_family =
707 mtod(from, struct sockaddr *)->sa_family;
708 #endif
709 if (len > from->m_len)
710 len = from->m_len;
711 /* else if len < from->m_len ??? */
712 error = copyout(mtod(from, caddr_t),
713 (caddr_t)mp->msg_name, (unsigned)len);
714 if (error)
715 goto out;
716 }
717 mp->msg_namelen = len;
718 if (namelenp &&
719 (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) {
720 #ifdef COMPAT_OLDSOCK
721 if (mp->msg_flags & MSG_COMPAT)
722 error = 0; /* old recvfrom didn't check */
723 else
724 #endif
725 goto out;
726 }
727 }
728 if (mp->msg_control) {
729 #ifdef COMPAT_OLDSOCK
730 /*
731 * We assume that old recvmsg calls won't receive access
732 * rights and other control info, esp. as control info
733 * is always optional and those options didn't exist in 4.3.
734 * If we receive rights, trim the cmsghdr; anything else
735 * is tossed.
736 */
737 if (control && mp->msg_flags & MSG_COMPAT) {
738 if (mtod(control, struct cmsghdr *)->cmsg_level !=
739 SOL_SOCKET ||
740 mtod(control, struct cmsghdr *)->cmsg_type !=
741 SCM_RIGHTS) {
742 mp->msg_controllen = 0;
743 goto out;
744 }
745 control->m_len -= sizeof(struct cmsghdr);
746 control->m_data += sizeof(struct cmsghdr);
747 }
748 #endif
749 len = mp->msg_controllen;
750 if (len <= 0 || control == 0)
751 len = 0;
752 else {
753 struct mbuf *m = control;
754 caddr_t p = (caddr_t)mp->msg_control;
755
756 do {
757 i = m->m_len;
758 if (len < i) {
759 mp->msg_flags |= MSG_CTRUNC;
760 i = len;
761 }
762 error = copyout(mtod(m, caddr_t), p,
763 (unsigned)i);
764 if (m->m_next)
765 i = ALIGN(i);
766 p += i;
767 len -= i;
768 if (error != 0 || len <= 0)
769 break;
770 } while ((m = m->m_next) != NULL);
771 len = p - (caddr_t)mp->msg_control;
772 }
773 mp->msg_controllen = len;
774 }
775 out:
776 if (from)
777 m_freem(from);
778 if (control)
779 m_freem(control);
780 return (error);
781 }
782
783 /* ARGSUSED */
784 int
785 sys_shutdown(p, v, retval)
786 struct proc *p;
787 void *v;
788 register_t *retval;
789 {
790 register struct sys_shutdown_args /* {
791 syscallarg(int) s;
792 syscallarg(int) how;
793 } */ *uap = v;
794 struct file *fp;
795 int error;
796
797 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
798 return (error);
799 return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how)));
800 }
801
802 /* ARGSUSED */
803 int
804 sys_setsockopt(p, v, retval)
805 struct proc *p;
806 void *v;
807 register_t *retval;
808 {
809 register struct sys_setsockopt_args /* {
810 syscallarg(int) s;
811 syscallarg(int) level;
812 syscallarg(int) name;
813 syscallarg(const void *) val;
814 syscallarg(unsigned int) valsize;
815 } */ *uap = v;
816 struct file *fp;
817 struct mbuf *m = NULL;
818 int error;
819
820 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
821 return (error);
822 if (SCARG(uap, valsize) > MLEN)
823 return (EINVAL);
824 if (SCARG(uap, val)) {
825 m = m_get(M_WAIT, MT_SOOPTS);
826 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
827 SCARG(uap, valsize));
828 if (error) {
829 (void) m_free(m);
830 return (error);
831 }
832 m->m_len = SCARG(uap, valsize);
833 }
834 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
835 SCARG(uap, name), m));
836 }
837
838 /* ARGSUSED */
839 int
840 sys_getsockopt(p, v, retval)
841 struct proc *p;
842 void *v;
843 register_t *retval;
844 {
845 register struct sys_getsockopt_args /* {
846 syscallarg(int) s;
847 syscallarg(int) level;
848 syscallarg(int) name;
849 syscallarg(void *) val;
850 syscallarg(unsigned int *) avalsize;
851 } */ *uap = v;
852 struct file *fp;
853 struct mbuf *m = NULL;
854 unsigned int valsize;
855 int error;
856
857 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
858 return (error);
859 if (SCARG(uap, val)) {
860 error = copyin((caddr_t)SCARG(uap, avalsize),
861 (caddr_t)&valsize, sizeof(valsize));
862 if (error)
863 return (error);
864 } else
865 valsize = 0;
866 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
867 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
868 m != NULL) {
869 if (valsize > m->m_len)
870 valsize = m->m_len;
871 error = copyout(mtod(m, caddr_t), SCARG(uap, val),
872 valsize);
873 if (error == 0)
874 error = copyout((caddr_t)&valsize,
875 (caddr_t)SCARG(uap, avalsize), sizeof(valsize));
876 }
877 if (m != NULL)
878 (void) m_free(m);
879 return (error);
880 }
881
882 /* ARGSUSED */
883 int
884 sys_pipe(p, v, retval)
885 struct proc *p;
886 void *v;
887 register_t *retval;
888 {
889 register struct filedesc *fdp = p->p_fd;
890 struct file *rf, *wf;
891 struct socket *rso, *wso;
892 int fd, error;
893
894 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
895 return (error);
896 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
897 goto free1;
898 if ((error = falloc(p, &rf, &fd)) != 0)
899 goto free2;
900 retval[0] = fd;
901 rf->f_flag = FREAD;
902 rf->f_type = DTYPE_SOCKET;
903 rf->f_ops = &socketops;
904 rf->f_data = (caddr_t)rso;
905 if ((error = falloc(p, &wf, &fd)) != 0)
906 goto free3;
907 wf->f_flag = FWRITE;
908 wf->f_type = DTYPE_SOCKET;
909 wf->f_ops = &socketops;
910 wf->f_data = (caddr_t)wso;
911 retval[1] = fd;
912 if ((error = unp_connect2(wso, rso)) != 0)
913 goto free4;
914 return (0);
915 free4:
916 ffree(wf);
917 fdp->fd_ofiles[retval[1]] = 0;
918 free3:
919 ffree(rf);
920 fdp->fd_ofiles[retval[0]] = 0;
921 free2:
922 (void)soclose(wso);
923 free1:
924 (void)soclose(rso);
925 return (error);
926 }
927
928 /*
929 * Get socket name.
930 */
931 /* ARGSUSED */
932 int
933 sys_getsockname(p, v, retval)
934 struct proc *p;
935 void *v;
936 register_t *retval;
937 {
938 register struct sys_getsockname_args /* {
939 syscallarg(int) fdes;
940 syscallarg(struct sockaddr *) asa;
941 syscallarg(unsigned int *) alen;
942 } */ *uap = v;
943 struct file *fp;
944 register struct socket *so;
945 struct mbuf *m;
946 unsigned int len;
947 int error;
948
949 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
950 return (error);
951 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
952 if (error)
953 return (error);
954 so = (struct socket *)fp->f_data;
955 m = m_getclr(M_WAIT, MT_SONAME);
956 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
957 m, (struct mbuf *)0, (struct proc *)0);
958 if (error)
959 goto bad;
960 if (len > m->m_len)
961 len = m->m_len;
962 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
963 if (error == 0)
964 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
965 sizeof(len));
966 bad:
967 m_freem(m);
968 return (error);
969 }
970
971 /*
972 * Get name of peer for connected socket.
973 */
974 /* ARGSUSED */
975 int
976 sys_getpeername(p, v, retval)
977 struct proc *p;
978 void *v;
979 register_t *retval;
980 {
981 register struct sys_getpeername_args /* {
982 syscallarg(int) fdes;
983 syscallarg(struct sockaddr *) asa;
984 syscallarg(unsigned int *) alen;
985 } */ *uap = v;
986 struct file *fp;
987 register struct socket *so;
988 struct mbuf *m;
989 unsigned int len;
990 int error;
991
992 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
993 return (error);
994 so = (struct socket *)fp->f_data;
995 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
996 return (ENOTCONN);
997 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
998 if (error)
999 return (error);
1000 m = m_getclr(M_WAIT, MT_SONAME);
1001 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
1002 m, (struct mbuf *)0, (struct proc *)0);
1003 if (error)
1004 goto bad;
1005 if (len > m->m_len)
1006 len = m->m_len;
1007 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1008 if (error)
1009 goto bad;
1010 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1011 bad:
1012 m_freem(m);
1013 return (error);
1014 }
1015
1016 /*
1017 * XXX In a perfect world, we wouldn't pass around socket control
1018 * XXX arguments in mbufs, and this could go away.
1019 */
1020 int
1021 sockargs(mp, buf, buflen, type)
1022 struct mbuf **mp;
1023 const void *buf;
1024 int buflen, type;
1025 {
1026 register struct sockaddr *sa;
1027 register struct mbuf *m;
1028 int error;
1029
1030 /*
1031 * We can't allow socket names > UCHAR_MAX in length, since that
1032 * will overflow sa_len.
1033 */
1034 if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
1035 return (EINVAL);
1036
1037 /* Allocate an mbuf to hold the arguments. */
1038 m = m_get(M_WAIT, type);
1039 if ((u_int)buflen > MLEN) {
1040 /*
1041 * Won't fit into a regular mbuf, so we allocate just
1042 * enough external storage to hold the argument.
1043 */
1044 MEXTMALLOC(m, buflen, M_WAITOK);
1045 }
1046 m->m_len = buflen;
1047 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1048 if (error) {
1049 (void) m_free(m);
1050 return (error);
1051 }
1052 *mp = m;
1053 if (type == MT_SONAME) {
1054 sa = mtod(m, struct sockaddr *);
1055
1056 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1057 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1058 sa->sa_family = sa->sa_len;
1059 #endif
1060 sa->sa_len = buflen;
1061 }
1062 return (0);
1063 }
1064
1065 int
1066 getsock(fdp, fdes, fpp)
1067 struct filedesc *fdp;
1068 int fdes;
1069 struct file **fpp;
1070 {
1071 register struct file *fp;
1072
1073 if ((unsigned)fdes >= fdp->fd_nfiles ||
1074 (fp = fdp->fd_ofiles[fdes]) == NULL)
1075 return (EBADF);
1076 if (fp->f_type != DTYPE_SOCKET)
1077 return (ENOTSOCK);
1078 *fpp = fp;
1079 return (0);
1080 }
1081