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