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