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