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