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