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