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