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