uipc_syscalls.c revision 1.41.6.1 1 /* $NetBSD: uipc_syscalls.c,v 1.41.6.1 1999/06/28 06:36:53 itojun 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) > MCLBYTES)
823 return (EINVAL);
824 if (SCARG(uap, val)) {
825 m = m_get(M_WAIT, MT_SOOPTS);
826 if (SCARG(uap, valsize) > MLEN) {
827 MCLGET(m, M_DONTWAIT);
828 if ((m->m_flags & M_EXT) == 0) {
829 m_freem(m);
830 return (ENOBUFS);
831 }
832 }
833 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
834 SCARG(uap, valsize));
835 if (error) {
836 (void) m_free(m);
837 return (error);
838 }
839 m->m_len = SCARG(uap, valsize);
840 }
841 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
842 SCARG(uap, name), m));
843 }
844
845 /* ARGSUSED */
846 int
847 sys_getsockopt(p, v, retval)
848 struct proc *p;
849 void *v;
850 register_t *retval;
851 {
852 register struct sys_getsockopt_args /* {
853 syscallarg(int) s;
854 syscallarg(int) level;
855 syscallarg(int) name;
856 syscallarg(void *) val;
857 syscallarg(unsigned int *) avalsize;
858 } */ *uap = v;
859 struct file *fp;
860 struct mbuf *m = NULL, *m0;
861 unsigned int op, i, valsize;
862 int error;
863
864 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
865 return (error);
866 if (SCARG(uap, val)) {
867 error = copyin((caddr_t)SCARG(uap, avalsize),
868 (caddr_t)&valsize, sizeof(valsize));
869 if (error)
870 return (error);
871 } else
872 valsize = 0;
873 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
874 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
875 m != NULL) {
876 op = 0;
877 while (m && !error && op < valsize) {
878 i = min(m->m_len, (valsize - op));
879 error = copyout(mtod(m, caddr_t), SCARG(uap, val), i);
880 op += i;
881 SCARG(uap, val) = ((u_int8_t *)SCARG(uap, val)) + i;
882 m0 = m;
883 MFREE(m0, m);
884 }
885 valsize = op;
886 if (error == 0)
887 error = copyout(&valsize,
888 SCARG(uap, avalsize), sizeof(valsize));
889 }
890 if (m != NULL)
891 (void) m_free(m);
892 return (error);
893 }
894
895 /* ARGSUSED */
896 int
897 sys_pipe(p, v, retval)
898 struct proc *p;
899 void *v;
900 register_t *retval;
901 {
902 register struct filedesc *fdp = p->p_fd;
903 struct file *rf, *wf;
904 struct socket *rso, *wso;
905 int fd, error;
906
907 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
908 return (error);
909 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
910 goto free1;
911 if ((error = falloc(p, &rf, &fd)) != 0)
912 goto free2;
913 retval[0] = fd;
914 rf->f_flag = FREAD;
915 rf->f_type = DTYPE_SOCKET;
916 rf->f_ops = &socketops;
917 rf->f_data = (caddr_t)rso;
918 if ((error = falloc(p, &wf, &fd)) != 0)
919 goto free3;
920 wf->f_flag = FWRITE;
921 wf->f_type = DTYPE_SOCKET;
922 wf->f_ops = &socketops;
923 wf->f_data = (caddr_t)wso;
924 retval[1] = fd;
925 if ((error = unp_connect2(wso, rso)) != 0)
926 goto free4;
927 return (0);
928 free4:
929 ffree(wf);
930 fdp->fd_ofiles[retval[1]] = 0;
931 free3:
932 ffree(rf);
933 fdp->fd_ofiles[retval[0]] = 0;
934 free2:
935 (void)soclose(wso);
936 free1:
937 (void)soclose(rso);
938 return (error);
939 }
940
941 /*
942 * Get socket name.
943 */
944 /* ARGSUSED */
945 int
946 sys_getsockname(p, v, retval)
947 struct proc *p;
948 void *v;
949 register_t *retval;
950 {
951 register struct sys_getsockname_args /* {
952 syscallarg(int) fdes;
953 syscallarg(struct sockaddr *) asa;
954 syscallarg(unsigned int *) alen;
955 } */ *uap = v;
956 struct file *fp;
957 register struct socket *so;
958 struct mbuf *m;
959 unsigned int len;
960 int error;
961
962 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
963 return (error);
964 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
965 if (error)
966 return (error);
967 so = (struct socket *)fp->f_data;
968 m = m_getclr(M_WAIT, MT_SONAME);
969 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
970 m, (struct mbuf *)0, (struct proc *)0);
971 if (error)
972 goto bad;
973 if (len > m->m_len)
974 len = m->m_len;
975 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
976 if (error == 0)
977 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
978 sizeof(len));
979 bad:
980 m_freem(m);
981 return (error);
982 }
983
984 /*
985 * Get name of peer for connected socket.
986 */
987 /* ARGSUSED */
988 int
989 sys_getpeername(p, v, retval)
990 struct proc *p;
991 void *v;
992 register_t *retval;
993 {
994 register struct sys_getpeername_args /* {
995 syscallarg(int) fdes;
996 syscallarg(struct sockaddr *) asa;
997 syscallarg(unsigned int *) alen;
998 } */ *uap = v;
999 struct file *fp;
1000 register struct socket *so;
1001 struct mbuf *m;
1002 unsigned int len;
1003 int error;
1004
1005 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1006 return (error);
1007 so = (struct socket *)fp->f_data;
1008 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
1009 return (ENOTCONN);
1010 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1011 if (error)
1012 return (error);
1013 m = m_getclr(M_WAIT, MT_SONAME);
1014 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
1015 m, (struct mbuf *)0, (struct proc *)0);
1016 if (error)
1017 goto bad;
1018 if (len > m->m_len)
1019 len = m->m_len;
1020 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1021 if (error)
1022 goto bad;
1023 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1024 bad:
1025 m_freem(m);
1026 return (error);
1027 }
1028
1029 /*
1030 * XXX In a perfect world, we wouldn't pass around socket control
1031 * XXX arguments in mbufs, and this could go away.
1032 */
1033 int
1034 sockargs(mp, buf, buflen, type)
1035 struct mbuf **mp;
1036 const void *buf;
1037 int buflen, type;
1038 {
1039 register struct sockaddr *sa;
1040 register struct mbuf *m;
1041 int error;
1042
1043 /*
1044 * We can't allow socket names > UCHAR_MAX in length, since that
1045 * will overflow sa_len.
1046 */
1047 if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
1048 return (EINVAL);
1049
1050 /* Allocate an mbuf to hold the arguments. */
1051 m = m_get(M_WAIT, type);
1052 if ((u_int)buflen > MLEN) {
1053 /*
1054 * Won't fit into a regular mbuf, so we allocate just
1055 * enough external storage to hold the argument.
1056 */
1057 MEXTMALLOC(m, buflen, M_WAITOK);
1058 }
1059 m->m_len = buflen;
1060 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1061 if (error) {
1062 (void) m_free(m);
1063 return (error);
1064 }
1065 *mp = m;
1066 if (type == MT_SONAME) {
1067 sa = mtod(m, struct sockaddr *);
1068
1069 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1070 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1071 sa->sa_family = sa->sa_len;
1072 #endif
1073 sa->sa_len = buflen;
1074 }
1075 return (0);
1076 }
1077
1078 int
1079 getsock(fdp, fdes, fpp)
1080 struct filedesc *fdp;
1081 int fdes;
1082 struct file **fpp;
1083 {
1084 register struct file *fp;
1085
1086 if ((unsigned)fdes >= fdp->fd_nfiles ||
1087 (fp = fdp->fd_ofiles[fdes]) == NULL)
1088 return (EBADF);
1089 if (fp->f_type != DTYPE_SOCKET)
1090 return (ENOTSOCK);
1091 *fpp = fp;
1092 return (0);
1093 }
1094