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