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