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