uipc_syscalls.c revision 1.81.2.2 1 /* $NetBSD: uipc_syscalls.c,v 1.81.2.2 2004/08/03 10:52:58 skrll 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.81.2.2 2004/08/03 10:52:58 skrll 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), l);
94 if (error) {
95 FILE_UNUSE(fp, l);
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, l);
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, l);
129 return (error);
130 }
131 MCLAIM(nam, ((struct socket *)fp->f_data)->so_mowner);
132 error = sobind((struct socket *)fp->f_data, nam, l);
133 m_freem(nam);
134 FILE_UNUSE(fp, l);
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, l);
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, l);
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, l);
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, l);
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, l);
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), l);
344 if (error)
345 return (error);
346 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
347 SCARG(uap, protocol), l);
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, l);
379 FILE_UNUSE(fp2, l);
380 return (error);
381 free4:
382 FILE_UNUSE(fp2, l);
383 ffree(fp2);
384 fdremove(fdp, sv[1]);
385 free3:
386 FILE_UNUSE(fp1, l);
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 msghdr msg;
408 struct iovec aiov;
409
410 msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
411 msg.msg_namelen = SCARG(uap, tolen);
412 msg.msg_iov = &aiov;
413 msg.msg_iovlen = 1;
414 msg.msg_control = 0;
415 msg.msg_flags = 0;
416 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
417 aiov.iov_len = SCARG(uap, len);
418 return (sendit(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
419 }
420
421 int
422 sys_sendmsg(struct lwp *l, void *v, register_t *retval)
423 {
424 struct sys_sendmsg_args /* {
425 syscallarg(int) s;
426 syscallarg(const struct msghdr *) msg;
427 syscallarg(int) flags;
428 } */ *uap = v;
429 struct msghdr msg;
430 struct iovec aiov[UIO_SMALLIOV], *iov;
431 int error;
432
433 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
434 if (error)
435 return (error);
436 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
437 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
438 return (EMSGSIZE);
439 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
440 M_IOV, M_WAITOK);
441 } else
442 iov = aiov;
443 if ((unsigned int)msg.msg_iovlen > 0) {
444 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
445 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
446 if (error)
447 goto done;
448 }
449 msg.msg_iov = iov;
450 msg.msg_flags = 0;
451 error = sendit(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
452 done:
453 if (iov != aiov)
454 free(iov, M_IOV);
455 return (error);
456 }
457
458 int
459 sendit(struct lwp *l, int s, struct msghdr *mp, int flags, register_t *retsize)
460 {
461 struct proc *p;
462 struct file *fp;
463 struct uio auio;
464 struct iovec *iov;
465 int i, len, error;
466 struct mbuf *to, *control;
467 struct socket *so;
468 #ifdef KTRACE
469 struct iovec *ktriov;
470 #endif
471
472 #ifdef KTRACE
473 ktriov = NULL;
474 #endif
475 p = l->l_proc;
476 /* getsock() will use the descriptor for us */
477 if ((error = getsock(p->p_fd, s, &fp)) != 0)
478 return (error);
479 so = (struct socket *)fp->f_data;
480 auio.uio_iov = mp->msg_iov;
481 auio.uio_iovcnt = mp->msg_iovlen;
482 auio.uio_segflg = UIO_USERSPACE;
483 auio.uio_rw = UIO_WRITE;
484 auio.uio_lwp = l;
485 auio.uio_offset = 0; /* XXX */
486 auio.uio_resid = 0;
487 iov = mp->msg_iov;
488 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
489 #if 0
490 /* cannot happen; iov_len is unsigned */
491 if (iov->iov_len < 0) {
492 error = EINVAL;
493 goto out;
494 }
495 #endif
496 /*
497 * Writes return ssize_t because -1 is returned on error.
498 * Therefore, we must restrict the length to SSIZE_MAX to
499 * avoid garbage return values.
500 */
501 auio.uio_resid += iov->iov_len;
502 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
503 error = EINVAL;
504 goto out;
505 }
506 }
507 if (mp->msg_name) {
508 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
509 MT_SONAME);
510 if (error)
511 goto out;
512 MCLAIM(to, so->so_mowner);
513 } else
514 to = 0;
515 if (mp->msg_control) {
516 if (mp->msg_controllen < sizeof(struct cmsghdr)) {
517 error = EINVAL;
518 goto bad;
519 }
520 error = sockargs(&control, mp->msg_control,
521 mp->msg_controllen, MT_CONTROL);
522 if (error)
523 goto bad;
524 MCLAIM(control, so->so_mowner);
525 } else
526 control = 0;
527 #ifdef KTRACE
528 if (KTRPOINT(p, KTR_GENIO)) {
529 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
530
531 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
532 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
533 }
534 #endif
535 len = auio.uio_resid;
536 error = (*so->so_send)(so, to, &auio, NULL, control, flags, l);
537 if (error) {
538 if (auio.uio_resid != len && (error == ERESTART ||
539 error == EINTR || error == EWOULDBLOCK))
540 error = 0;
541 if (error == EPIPE)
542 psignal(p, SIGPIPE);
543 }
544 if (error == 0)
545 *retsize = len - auio.uio_resid;
546 #ifdef KTRACE
547 if (ktriov != NULL) {
548 if (error == 0)
549 ktrgenio(l, s, UIO_WRITE, ktriov, *retsize, error);
550 free(ktriov, M_TEMP);
551 }
552 #endif
553 bad:
554 if (to)
555 m_freem(to);
556 out:
557 FILE_UNUSE(fp, l);
558 return (error);
559 }
560
561 int
562 sys_recvfrom(struct lwp *l, void *v, register_t *retval)
563 {
564 struct sys_recvfrom_args /* {
565 syscallarg(int) s;
566 syscallarg(void *) buf;
567 syscallarg(size_t) len;
568 syscallarg(int) flags;
569 syscallarg(struct sockaddr *) from;
570 syscallarg(unsigned int *) fromlenaddr;
571 } */ *uap = v;
572 struct msghdr msg;
573 struct iovec aiov;
574 int error;
575
576 if (SCARG(uap, fromlenaddr)) {
577 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
578 (caddr_t)&msg.msg_namelen,
579 sizeof(msg.msg_namelen));
580 if (error)
581 return (error);
582 } else
583 msg.msg_namelen = 0;
584 msg.msg_name = (caddr_t)SCARG(uap, from);
585 msg.msg_iov = &aiov;
586 msg.msg_iovlen = 1;
587 aiov.iov_base = SCARG(uap, buf);
588 aiov.iov_len = SCARG(uap, len);
589 msg.msg_control = 0;
590 msg.msg_flags = SCARG(uap, flags);
591 return (recvit(l, SCARG(uap, s), &msg,
592 (caddr_t)SCARG(uap, fromlenaddr), retval));
593 }
594
595 int
596 sys_recvmsg(struct lwp *l, void *v, register_t *retval)
597 {
598 struct sys_recvmsg_args /* {
599 syscallarg(int) s;
600 syscallarg(struct msghdr *) msg;
601 syscallarg(int) flags;
602 } */ *uap = v;
603 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
604 struct msghdr msg;
605 int error;
606
607 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
608 sizeof(msg));
609 if (error)
610 return (error);
611 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
612 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
613 return (EMSGSIZE);
614 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
615 M_IOV, M_WAITOK);
616 } else
617 iov = aiov;
618 if ((unsigned int)msg.msg_iovlen > 0) {
619 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
620 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
621 if (error)
622 goto done;
623 }
624 uiov = msg.msg_iov;
625 msg.msg_iov = iov;
626 msg.msg_flags = SCARG(uap, flags);
627 if ((error = recvit(l, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
628 msg.msg_iov = uiov;
629 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
630 sizeof(msg));
631 }
632 done:
633 if (iov != aiov)
634 free(iov, M_IOV);
635 return (error);
636 }
637
638 int
639 recvit(struct lwp *l, int s, struct msghdr *mp, caddr_t namelenp,
640 register_t *retsize)
641 {
642 struct proc *p;
643 struct file *fp;
644 struct uio auio;
645 struct iovec *iov;
646 int i, len, error;
647 struct mbuf *from, *control;
648 struct socket *so;
649 #ifdef KTRACE
650 struct iovec *ktriov;
651 #endif
652
653 p = l->l_proc;
654 from = 0;
655 control = 0;
656 #ifdef KTRACE
657 ktriov = NULL;
658 #endif
659
660 /* getsock() will use the descriptor for us */
661 if ((error = getsock(p->p_fd, s, &fp)) != 0)
662 return (error);
663 so = (struct socket *)fp->f_data;
664 auio.uio_iov = mp->msg_iov;
665 auio.uio_iovcnt = mp->msg_iovlen;
666 auio.uio_segflg = UIO_USERSPACE;
667 auio.uio_rw = UIO_READ;
668 auio.uio_lwp = l;
669 auio.uio_offset = 0; /* XXX */
670 auio.uio_resid = 0;
671 iov = mp->msg_iov;
672 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
673 #if 0
674 /* cannot happen iov_len is unsigned */
675 if (iov->iov_len < 0) {
676 error = EINVAL;
677 goto out1;
678 }
679 #endif
680 /*
681 * Reads return ssize_t because -1 is returned on error.
682 * Therefore we must restrict the length to SSIZE_MAX to
683 * avoid garbage return values.
684 */
685 auio.uio_resid += iov->iov_len;
686 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
687 error = EINVAL;
688 goto out1;
689 }
690 }
691 #ifdef KTRACE
692 if (KTRPOINT(p, KTR_GENIO)) {
693 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
694
695 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
696 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
697 }
698 #endif
699 len = auio.uio_resid;
700 error = (*so->so_receive)(so, &from, &auio, NULL,
701 mp->msg_control ? &control : NULL, &mp->msg_flags);
702 if (error) {
703 if (auio.uio_resid != len && (error == ERESTART ||
704 error == EINTR || error == EWOULDBLOCK))
705 error = 0;
706 }
707 #ifdef KTRACE
708 if (ktriov != NULL) {
709 if (error == 0)
710 ktrgenio(l, s, UIO_READ, ktriov,
711 len - auio.uio_resid, error);
712 free(ktriov, M_TEMP);
713 }
714 #endif
715 if (error)
716 goto out;
717 *retsize = len - auio.uio_resid;
718 if (mp->msg_name) {
719 len = mp->msg_namelen;
720 if (len <= 0 || from == 0)
721 len = 0;
722 else {
723 if (len > from->m_len)
724 len = from->m_len;
725 /* else if len < from->m_len ??? */
726 error = copyout(mtod(from, caddr_t),
727 (caddr_t)mp->msg_name, (unsigned)len);
728 if (error)
729 goto out;
730 }
731 mp->msg_namelen = len;
732 if (namelenp &&
733 (error = copyout((caddr_t)&len, namelenp, sizeof(int))))
734 goto out;
735 }
736 if (mp->msg_control) {
737 len = mp->msg_controllen;
738 if (len <= 0 || control == 0)
739 len = 0;
740 else {
741 struct mbuf *m = control;
742 caddr_t p = (caddr_t)mp->msg_control;
743
744 do {
745 i = m->m_len;
746 if (len < i) {
747 mp->msg_flags |= MSG_CTRUNC;
748 i = len;
749 }
750 error = copyout(mtod(m, caddr_t), p,
751 (unsigned)i);
752 if (m->m_next)
753 i = ALIGN(i);
754 p += i;
755 len -= i;
756 if (error != 0 || len <= 0)
757 break;
758 } while ((m = m->m_next) != NULL);
759 len = p - (caddr_t)mp->msg_control;
760 }
761 mp->msg_controllen = len;
762 }
763 out:
764 if (from)
765 m_freem(from);
766 if (control)
767 m_freem(control);
768 out1:
769 FILE_UNUSE(fp, l);
770 return (error);
771 }
772
773 /* ARGSUSED */
774 int
775 sys_shutdown(struct lwp *l, void *v, register_t *retval)
776 {
777 struct sys_shutdown_args /* {
778 syscallarg(int) s;
779 syscallarg(int) how;
780 } */ *uap = v;
781 struct proc *p;
782 struct file *fp;
783 int error;
784
785 p = l->l_proc;
786 /* getsock() will use the descriptor for us */
787 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
788 return (error);
789 error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how));
790 FILE_UNUSE(fp, l);
791 return (error);
792 }
793
794 /* ARGSUSED */
795 int
796 sys_setsockopt(struct lwp *l, void *v, register_t *retval)
797 {
798 struct sys_setsockopt_args /* {
799 syscallarg(int) s;
800 syscallarg(int) level;
801 syscallarg(int) name;
802 syscallarg(const void *) val;
803 syscallarg(unsigned int) valsize;
804 } */ *uap = v;
805 struct proc *p;
806 struct file *fp;
807 struct mbuf *m;
808 struct socket *so;
809 int error;
810 unsigned int len;
811
812 p = l->l_proc;
813 m = NULL;
814 /* getsock() will use the descriptor for us */
815 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
816 return (error);
817 so = (struct socket *)fp->f_data;
818 len = SCARG(uap, valsize);
819 if (len > MCLBYTES) {
820 error = EINVAL;
821 goto out;
822 }
823 if (SCARG(uap, val)) {
824 m = m_get(M_WAIT, MT_SOOPTS);
825 MCLAIM(m, so->so_mowner);
826 if (len > MLEN)
827 m_clget(m, M_WAIT);
828 error = copyin(SCARG(uap, val), mtod(m, caddr_t), len);
829 if (error) {
830 (void) m_free(m);
831 goto out;
832 }
833 m->m_len = SCARG(uap, valsize);
834 }
835 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
836 out:
837 FILE_UNUSE(fp, l);
838 return (error);
839 }
840
841 /* ARGSUSED */
842 int
843 sys_getsockopt(struct lwp *l, void *v, register_t *retval)
844 {
845 struct sys_getsockopt_args /* {
846 syscallarg(int) s;
847 syscallarg(int) level;
848 syscallarg(int) name;
849 syscallarg(void *) val;
850 syscallarg(unsigned int *) avalsize;
851 } */ *uap = v;
852 struct proc *p;
853 struct file *fp;
854 struct mbuf *m;
855 unsigned int op, i, valsize;
856 int error;
857
858 p = l->l_proc;
859 m = NULL;
860 /* getsock() will use the descriptor for us */
861 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
862 return (error);
863 if (SCARG(uap, val)) {
864 error = copyin((caddr_t)SCARG(uap, avalsize),
865 (caddr_t)&valsize, sizeof(valsize));
866 if (error)
867 goto out;
868 } else
869 valsize = 0;
870 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
871 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
872 m != NULL) {
873 op = 0;
874 while (m && !error && op < valsize) {
875 i = min(m->m_len, (valsize - op));
876 error = copyout(mtod(m, caddr_t), SCARG(uap, val), i);
877 op += i;
878 SCARG(uap, val) = ((u_int8_t *)SCARG(uap, val)) + i;
879 m = m_free(m);
880 }
881 valsize = op;
882 if (error == 0)
883 error = copyout(&valsize,
884 SCARG(uap, avalsize), sizeof(valsize));
885 }
886 if (m != NULL)
887 (void) m_freem(m);
888 out:
889 FILE_UNUSE(fp, l);
890 return (error);
891 }
892
893 #ifdef PIPE_SOCKETPAIR
894 /* ARGSUSED */
895 int
896 sys_pipe(struct lwp *l, void *v, register_t *retval)
897 {
898 struct proc *p;
899 struct filedesc *fdp;
900 struct file *rf, *wf;
901 struct socket *rso, *wso;
902 int fd, error;
903
904 p = l->l_proc;
905 fdp = p->p_fd;
906 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, p)) != 0)
907 return (error);
908 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, p)) != 0)
909 goto free1;
910 /* remember this socket pair implements a pipe */
911 wso->so_state |= SS_ISAPIPE;
912 rso->so_state |= SS_ISAPIPE;
913 /* falloc() will use the descriptor for us */
914 if ((error = falloc(p, &rf, &fd)) != 0)
915 goto free2;
916 retval[0] = fd;
917 rf->f_flag = FREAD;
918 rf->f_type = DTYPE_SOCKET;
919 rf->f_ops = &socketops;
920 rf->f_data = (caddr_t)rso;
921 if ((error = falloc(p, &wf, &fd)) != 0)
922 goto free3;
923 wf->f_flag = FWRITE;
924 wf->f_type = DTYPE_SOCKET;
925 wf->f_ops = &socketops;
926 wf->f_data = (caddr_t)wso;
927 retval[1] = fd;
928 if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0)
929 goto free4;
930 FILE_SET_MATURE(rf);
931 FILE_SET_MATURE(wf);
932 FILE_UNUSE(rf, l);
933 FILE_UNUSE(wf, l);
934 return (0);
935 free4:
936 FILE_UNUSE(wf, l);
937 ffree(wf);
938 fdremove(fdp, retval[1]);
939 free3:
940 FILE_UNUSE(rf, l);
941 ffree(rf);
942 fdremove(fdp, retval[0]);
943 free2:
944 (void)soclose(wso);
945 free1:
946 (void)soclose(rso);
947 return (error);
948 }
949 #endif /* PIPE_SOCKETPAIR */
950
951 /*
952 * Get socket name.
953 */
954 /* ARGSUSED */
955 int
956 sys_getsockname(struct lwp *l, void *v, register_t *retval)
957 {
958 struct sys_getsockname_args /* {
959 syscallarg(int) fdes;
960 syscallarg(struct sockaddr *) asa;
961 syscallarg(unsigned int *) alen;
962 } */ *uap = v;
963 struct proc *p;
964 struct file *fp;
965 struct socket *so;
966 struct mbuf *m;
967 unsigned int len;
968 int error;
969
970 p = l->l_proc;
971 /* getsock() will use the descriptor for us */
972 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
973 return (error);
974 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
975 if (error)
976 goto out;
977 so = (struct socket *)fp->f_data;
978 m = m_getclr(M_WAIT, MT_SONAME);
979 MCLAIM(m, so->so_mowner);
980 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
981 m, (struct mbuf *)0, (struct lwp *)0);
982 if (error)
983 goto bad;
984 if (len > m->m_len)
985 len = m->m_len;
986 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
987 if (error == 0)
988 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
989 sizeof(len));
990 bad:
991 m_freem(m);
992 out:
993 FILE_UNUSE(fp, l);
994 return (error);
995 }
996
997 /*
998 * Get name of peer for connected socket.
999 */
1000 /* ARGSUSED */
1001 int
1002 sys_getpeername(struct lwp *l, void *v, register_t *retval)
1003 {
1004 struct sys_getpeername_args /* {
1005 syscallarg(int) fdes;
1006 syscallarg(struct sockaddr *) asa;
1007 syscallarg(unsigned int *) alen;
1008 } */ *uap = v;
1009 struct proc *p;
1010 struct file *fp;
1011 struct socket *so;
1012 struct mbuf *m;
1013 unsigned int len;
1014 int error;
1015
1016 p = l->l_proc;
1017 /* getsock() will use the descriptor for us */
1018 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1019 return (error);
1020 so = (struct socket *)fp->f_data;
1021 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1022 error = ENOTCONN;
1023 goto out;
1024 }
1025 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1026 if (error)
1027 goto out;
1028 m = m_getclr(M_WAIT, MT_SONAME);
1029 MCLAIM(m, so->so_mowner);
1030 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
1031 m, (struct mbuf *)0, (struct lwp *)0);
1032 if (error)
1033 goto bad;
1034 if (len > m->m_len)
1035 len = m->m_len;
1036 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1037 if (error)
1038 goto bad;
1039 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1040 bad:
1041 m_freem(m);
1042 out:
1043 FILE_UNUSE(fp, l);
1044 return (error);
1045 }
1046
1047 /*
1048 * XXX In a perfect world, we wouldn't pass around socket control
1049 * XXX arguments in mbufs, and this could go away.
1050 */
1051 int
1052 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1053 {
1054 struct sockaddr *sa;
1055 struct mbuf *m;
1056 int error;
1057
1058 /*
1059 * We can't allow socket names > UCHAR_MAX in length, since that
1060 * will overflow sa_len. Control data more than a page size in
1061 * length is just too much.
1062 */
1063 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1064 return (EINVAL);
1065
1066 /* Allocate an mbuf to hold the arguments. */
1067 m = m_get(M_WAIT, type);
1068 /* can't claim. don't who to assign it to. */
1069 if (buflen > MLEN) {
1070 /*
1071 * Won't fit into a regular mbuf, so we allocate just
1072 * enough external storage to hold the argument.
1073 */
1074 MEXTMALLOC(m, buflen, M_WAITOK);
1075 }
1076 m->m_len = buflen;
1077 error = copyin(buf, mtod(m, caddr_t), buflen);
1078 if (error) {
1079 (void) m_free(m);
1080 return (error);
1081 }
1082 *mp = m;
1083 if (type == MT_SONAME) {
1084 sa = mtod(m, struct sockaddr *);
1085 #if BYTE_ORDER != BIG_ENDIAN
1086 /*
1087 * 4.3BSD compat thing - need to stay, since bind(2),
1088 * connect(2), sendto(2) were not versioned for COMPAT_43.
1089 */
1090 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1091 sa->sa_family = sa->sa_len;
1092 #endif
1093 sa->sa_len = buflen;
1094 }
1095 return (0);
1096 }
1097
1098 int
1099 getsock(struct filedesc *fdp, int fdes, struct file **fpp)
1100 {
1101 struct file *fp;
1102
1103 if ((fp = fd_getfile(fdp, fdes)) == NULL)
1104 return (EBADF);
1105
1106 FILE_USE(fp);
1107
1108 if (fp->f_type != DTYPE_SOCKET) {
1109 FILE_UNUSE(fp, NULL);
1110 return (ENOTSOCK);
1111 }
1112 *fpp = fp;
1113 return (0);
1114 }
1115