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