Annotation of src/sys/kern/uipc_syscalls.c, Revision 1.156.2.2
1.156.2.2! tls 1: /* $NetBSD$ */
1.129 ad 2:
3: /*-
1.136 ad 4: * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
1.129 ad 5: * All rights reserved.
6: *
1.136 ad 7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Andrew Doran.
9: *
1.129 ad 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: */
1.8 cgd 31:
1.1 cgd 32: /*
1.7 mycroft 33: * Copyright (c) 1982, 1986, 1989, 1990, 1993
34: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.82 agc 44: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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: *
1.29 fvdl 60: * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
1.1 cgd 61: */
1.67 lukem 62:
63: #include <sys/cdefs.h>
1.156.2.2! tls 64: __KERNEL_RCSID(0, "$NetBSD$");
1.31 thorpej 65:
1.68 jdolecek 66: #include "opt_pipe.h"
1.55 jdolecek 67:
1.6 mycroft 68: #include <sys/param.h>
1.9 cgd 69: #include <sys/systm.h>
1.6 mycroft 70: #include <sys/filedesc.h>
71: #include <sys/proc.h>
72: #include <sys/file.h>
73: #include <sys/buf.h>
1.147 christos 74: #define MBUFTYPES
1.6 mycroft 75: #include <sys/mbuf.h>
76: #include <sys/protosw.h>
77: #include <sys/socket.h>
78: #include <sys/socketvar.h>
1.18 christos 79: #include <sys/signalvar.h>
80: #include <sys/un.h>
1.6 mycroft 81: #include <sys/ktrace.h>
1.71 jdolecek 82: #include <sys/event.h>
1.153 christos 83: #include <sys/atomic.h>
1.139 elad 84: #include <sys/kauth.h>
1.1 cgd 85:
1.9 cgd 86: #include <sys/mount.h>
87: #include <sys/syscallargs.h>
88:
1.1 cgd 89: /*
90: * System call interface to the socket abstraction.
91: */
1.89 christos 92: extern const struct fileops socketops;
1.1 cgd 93:
1.7 mycroft 94: int
1.125 dsl 95: sys___socket30(struct lwp *l, const struct sys___socket30_args *uap, register_t *retval)
1.15 thorpej 96: {
1.125 dsl 97: /* {
1.57 lukem 98: syscallarg(int) domain;
99: syscallarg(int) type;
100: syscallarg(int) protocol;
1.125 dsl 101: } */
1.57 lukem 102: int fd, error;
1.1 cgd 103:
1.120 dyoung 104: error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
105: SCARG(uap, protocol), l, &fd);
106: if (error == 0)
1.1 cgd 107: *retval = fd;
1.120 dyoung 108: return error;
1.1 cgd 109: }
110:
111: /* ARGSUSED */
1.7 mycroft 112: int
1.125 dsl 113: sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval)
1.15 thorpej 114: {
1.125 dsl 115: /* {
1.57 lukem 116: syscallarg(int) s;
117: syscallarg(const struct sockaddr *) name;
118: syscallarg(unsigned int) namelen;
1.125 dsl 119: } */
1.111 dsl 120: struct mbuf *nam;
121: int error;
122:
1.112 enami 123: error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
124: MT_SONAME);
1.111 dsl 125: if (error)
126: return error;
127:
128: return do_sys_bind(l, SCARG(uap, s), nam);
129: }
130:
131: int
1.128 ad 132: do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
1.111 dsl 133: {
1.128 ad 134: struct socket *so;
1.57 lukem 135: int error;
1.1 cgd 136:
1.128 ad 137: if ((error = fd_getsock(fd, &so)) != 0) {
1.111 dsl 138: m_freem(nam);
1.1 cgd 139: return (error);
1.43 thorpej 140: }
1.128 ad 141: MCLAIM(nam, so->so_mowner);
142: error = sobind(so, nam, l);
1.1 cgd 143: m_freem(nam);
1.128 ad 144: fd_putfile(fd);
1.111 dsl 145: return error;
1.1 cgd 146: }
147:
148: /* ARGSUSED */
1.7 mycroft 149: int
1.125 dsl 150: sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval)
1.15 thorpej 151: {
1.125 dsl 152: /* {
1.57 lukem 153: syscallarg(int) s;
154: syscallarg(int) backlog;
1.125 dsl 155: } */
1.128 ad 156: struct socket *so;
1.57 lukem 157: int error;
1.1 cgd 158:
1.128 ad 159: if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1 cgd 160: return (error);
1.128 ad 161: error = solisten(so, SCARG(uap, backlog), l);
162: fd_putfile(SCARG(uap, s));
1.111 dsl 163: return error;
1.1 cgd 164: }
165:
1.7 mycroft 166: int
1.144 christos 167: do_sys_accept(struct lwp *l, int sock, struct mbuf **name, register_t *new_sock,
168: const sigset_t *mask, int flags, int clrflags)
1.15 thorpej 169: {
1.128 ad 170: file_t *fp, *fp2;
1.57 lukem 171: struct mbuf *nam;
1.129 ad 172: int error, fd;
1.128 ad 173: struct socket *so, *so2;
1.138 dsl 174: short wakeup_state = 0;
1.1 cgd 175:
1.128 ad 176: if ((fp = fd_getfile(sock)) == NULL)
177: return (EBADF);
1.132 rmind 178: if (fp->f_type != DTYPE_SOCKET) {
179: fd_putfile(sock);
1.128 ad 180: return (ENOTSOCK);
1.132 rmind 181: }
182: if ((error = fd_allocfile(&fp2, &fd)) != 0) {
183: fd_putfile(sock);
1.1 cgd 184: return (error);
1.132 rmind 185: }
1.128 ad 186: nam = m_get(M_WAIT, MT_SONAME);
187: *new_sock = fd;
188: so = fp->f_data;
1.129 ad 189: solock(so);
1.144 christos 190:
191: if (__predict_false(mask))
192: sigsuspendsetup(l, mask);
193:
1.44 darrenr 194: if (!(so->so_proto->pr_flags & PR_LISTEN)) {
1.128 ad 195: error = EOPNOTSUPP;
196: goto bad;
1.44 darrenr 197: }
1.1 cgd 198: if ((so->so_options & SO_ACCEPTCONN) == 0) {
1.128 ad 199: error = EINVAL;
200: goto bad;
1.1 cgd 201: }
1.149 christos 202: if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
1.128 ad 203: error = EWOULDBLOCK;
204: goto bad;
1.1 cgd 205: }
206: while (so->so_qlen == 0 && so->so_error == 0) {
207: if (so->so_state & SS_CANTRCVMORE) {
208: so->so_error = ECONNABORTED;
209: break;
210: }
1.138 dsl 211: if (wakeup_state & SS_RESTARTSYS) {
212: error = ERESTART;
213: goto bad;
214: }
1.135 yamt 215: error = sowait(so, true, 0);
1.18 christos 216: if (error) {
1.128 ad 217: goto bad;
1.1 cgd 218: }
1.138 dsl 219: wakeup_state = so->so_state;
1.1 cgd 220: }
221: if (so->so_error) {
222: error = so->so_error;
223: so->so_error = 0;
1.128 ad 224: goto bad;
1.1 cgd 225: }
1.71 jdolecek 226: /* connection has been removed from the listen queue */
1.129 ad 227: KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT);
1.128 ad 228: so2 = TAILQ_FIRST(&so->so_q);
229: if (soqremque(so2, 1) == 0)
1.1 cgd 230: panic("accept");
1.128 ad 231: fp2->f_type = DTYPE_SOCKET;
1.144 christos 232: fp2->f_flag = (fp->f_flag & ~clrflags) |
1.151 christos 233: ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
234: ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
1.128 ad 235: fp2->f_ops = &socketops;
236: fp2->f_data = so2;
1.156.2.1 tls 237: if (flags & SOCK_NONBLOCK)
238: so2->so_state |= SS_NBIO;
1.128 ad 239: error = soaccept(so2, nam);
1.139 elad 240: so2->so_cred = kauth_cred_dup(so->so_cred);
1.129 ad 241: sounlock(so);
1.49 mycroft 242: if (error) {
1.113 dsl 243: /* an error occurred, free the file descriptor and mbuf */
244: m_freem(nam);
1.128 ad 245: mutex_enter(&fp2->f_lock);
246: fp2->f_count++;
247: mutex_exit(&fp2->f_lock);
248: closef(fp2);
249: fd_abort(curproc, NULL, fd);
1.99 christos 250: } else {
1.144 christos 251: fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
1.128 ad 252: fd_affix(curproc, fp2, fd);
1.113 dsl 253: *name = nam;
1.49 mycroft 254: }
1.129 ad 255: fd_putfile(sock);
1.144 christos 256: if (__predict_false(mask))
257: sigsuspendteardown(l);
1.128 ad 258: return (error);
259: bad:
1.129 ad 260: sounlock(so);
1.128 ad 261: m_freem(nam);
1.129 ad 262: fd_putfile(sock);
1.128 ad 263: fd_abort(curproc, fp2, fd);
1.144 christos 264: if (__predict_false(mask))
265: sigsuspendteardown(l);
1.128 ad 266: return (error);
1.1 cgd 267: }
268:
1.113 dsl 269: int
1.125 dsl 270: sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval)
1.113 dsl 271: {
1.125 dsl 272: /* {
1.113 dsl 273: syscallarg(int) s;
274: syscallarg(struct sockaddr *) name;
275: syscallarg(unsigned int *) anamelen;
1.125 dsl 276: } */
1.128 ad 277: int error, fd;
1.113 dsl 278: struct mbuf *name;
279:
1.144 christos 280: error = do_sys_accept(l, SCARG(uap, s), &name, retval, NULL, 0, 0);
281: if (error != 0)
282: return error;
283: error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
284: MSG_LENUSRSPACE, name);
285: if (name != NULL)
286: m_free(name);
287: if (error != 0) {
288: fd = (int)*retval;
289: if (fd_getfile(fd) != NULL)
290: (void)fd_close(fd);
291: }
292: return error;
293: }
294:
295: int
296: sys_paccept(struct lwp *l, const struct sys_paccept_args *uap,
297: register_t *retval)
298: {
299: /* {
300: syscallarg(int) s;
301: syscallarg(struct sockaddr *) name;
302: syscallarg(unsigned int *) anamelen;
303: syscallarg(const sigset_t *) mask;
304: syscallarg(int) flags;
305: } */
306: int error, fd;
307: struct mbuf *name;
308: sigset_t *mask, amask;
309:
310: if (SCARG(uap, mask) != NULL) {
311: error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
312: if (error)
313: return error;
314: mask = &amask;
315: } else
316: mask = NULL;
317:
318: error = do_sys_accept(l, SCARG(uap, s), &name, retval, mask,
319: SCARG(uap, flags), FNONBLOCK);
1.113 dsl 320: if (error != 0)
321: return error;
322: error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
323: MSG_LENUSRSPACE, name);
324: if (name != NULL)
325: m_free(name);
1.128 ad 326: if (error != 0) {
327: fd = (int)*retval;
328: if (fd_getfile(fd) != NULL)
329: (void)fd_close(fd);
330: }
1.113 dsl 331: return error;
332: }
333:
1.1 cgd 334: /* ARGSUSED */
1.7 mycroft 335: int
1.125 dsl 336: sys_connect(struct lwp *l, const struct sys_connect_args *uap, register_t *retval)
1.15 thorpej 337: {
1.125 dsl 338: /* {
1.57 lukem 339: syscallarg(int) s;
340: syscallarg(const struct sockaddr *) name;
341: syscallarg(unsigned int) namelen;
1.125 dsl 342: } */
1.111 dsl 343: int error;
344: struct mbuf *nam;
345:
1.112 enami 346: error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
347: MT_SONAME);
1.111 dsl 348: if (error)
349: return error;
350: return do_sys_connect(l, SCARG(uap, s), nam);
351: }
352:
353: int
1.128 ad 354: do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
1.111 dsl 355: {
1.57 lukem 356: struct socket *so;
1.111 dsl 357: int error;
1.87 ragge 358: int interrupted = 0;
1.1 cgd 359:
1.128 ad 360: if ((error = fd_getsock(fd, &so)) != 0) {
1.111 dsl 361: m_freem(nam);
1.1 cgd 362: return (error);
1.111 dsl 363: }
1.129 ad 364: solock(so);
1.111 dsl 365: MCLAIM(nam, so->so_mowner);
1.136 ad 366: if ((so->so_state & SS_ISCONNECTING) != 0) {
1.62 jdolecek 367: error = EALREADY;
368: goto out;
369: }
1.111 dsl 370:
1.95 christos 371: error = soconnect(so, nam, l);
1.1 cgd 372: if (error)
373: goto bad;
1.150 christos 374: if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) ==
375: (SS_NBIO|SS_ISCONNECTING)) {
1.62 jdolecek 376: error = EINPROGRESS;
377: goto out;
1.1 cgd 378: }
1.136 ad 379: while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
1.135 yamt 380: error = sowait(so, true, 0);
1.137 dsl 381: if (__predict_false((so->so_state & SS_ISABORTING) != 0)) {
1.136 ad 382: error = EPIPE;
383: interrupted = 1;
384: break;
385: }
1.87 ragge 386: if (error) {
387: if (error == EINTR || error == ERESTART)
388: interrupted = 1;
1.1 cgd 389: break;
1.87 ragge 390: }
1.18 christos 391: }
1.1 cgd 392: if (error == 0) {
393: error = so->so_error;
394: so->so_error = 0;
395: }
1.57 lukem 396: bad:
1.87 ragge 397: if (!interrupted)
398: so->so_state &= ~SS_ISCONNECTING;
1.1 cgd 399: if (error == ERESTART)
400: error = EINTR;
1.62 jdolecek 401: out:
1.129 ad 402: sounlock(so);
1.128 ad 403: fd_putfile(fd);
1.111 dsl 404: m_freem(nam);
1.1 cgd 405: return (error);
406: }
407:
1.148 christos 408: static int
409: makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type,
410: int domain, int proto, struct socket *soo)
411: {
412: int error;
413: struct socket *so;
414:
415: if ((error = socreate(domain, &so, type, proto, l, soo)) != 0)
416: return error;
417:
418: if ((error = fd_allocfile(fp, fd)) != 0) {
419: soclose(so);
420: return error;
421: }
422: fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
1.151 christos 423: (*fp)->f_flag = FREAD|FWRITE|
424: ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
425: ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
1.148 christos 426: (*fp)->f_type = DTYPE_SOCKET;
427: (*fp)->f_ops = &socketops;
428: (*fp)->f_data = so;
1.156.2.1 tls 429: if (flags & SOCK_NONBLOCK)
430: so->so_state |= SS_NBIO;
1.148 christos 431: return 0;
432: }
433:
1.7 mycroft 434: int
1.148 christos 435: sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap,
436: register_t *retval)
1.15 thorpej 437: {
1.125 dsl 438: /* {
1.57 lukem 439: syscallarg(int) domain;
440: syscallarg(int) type;
441: syscallarg(int) protocol;
442: syscallarg(int *) rsv;
1.125 dsl 443: } */
1.128 ad 444: file_t *fp1, *fp2;
1.57 lukem 445: struct socket *so1, *so2;
446: int fd, error, sv[2];
1.128 ad 447: proc_t *p;
1.144 christos 448: int flags = SCARG(uap, type) & SOCK_FLAGS_MASK;
449: int type = SCARG(uap, type) & ~SOCK_FLAGS_MASK;
1.148 christos 450: int domain = SCARG(uap, domain);
451: int proto = SCARG(uap, protocol);
1.1 cgd 452:
1.128 ad 453: p = curproc;
1.148 christos 454:
455: error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL);
1.18 christos 456: if (error)
1.148 christos 457: return error;
458: so1 = fp1->f_data;
459: sv[0] = fd;
460:
461: error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1);
1.18 christos 462: if (error)
1.148 christos 463: goto out;
464: so2 = fp2->f_data;
1.1 cgd 465: sv[1] = fd;
1.148 christos 466:
1.129 ad 467: solock(so1);
468: error = soconnect2(so1, so2);
1.148 christos 469: if (error == 0 && type == SOCK_DGRAM) {
1.1 cgd 470: /*
471: * Datagram socket connection is asymmetric.
472: */
1.129 ad 473: error = soconnect2(so2, so1);
474: }
475: sounlock(so1);
1.148 christos 476:
1.129 ad 477: if (error == 0)
1.148 christos 478: error = copyout(sv, SCARG(uap, rsv), sizeof(sv));
1.129 ad 479: if (error == 0) {
480: fd_affix(p, fp2, sv[1]);
481: fd_affix(p, fp1, sv[0]);
1.148 christos 482: return 0;
1.1 cgd 483: }
1.128 ad 484: fd_abort(p, fp2, sv[1]);
1.148 christos 485: (void)soclose(so2);
486: out:
1.128 ad 487: fd_abort(p, fp1, sv[0]);
1.1 cgd 488: (void)soclose(so1);
1.148 christos 489: return error;
1.1 cgd 490: }
491:
1.7 mycroft 492: int
1.125 dsl 493: sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, register_t *retval)
1.15 thorpej 494: {
1.125 dsl 495: /* {
1.57 lukem 496: syscallarg(int) s;
497: syscallarg(const void *) buf;
498: syscallarg(size_t) len;
499: syscallarg(int) flags;
500: syscallarg(const struct sockaddr *) to;
501: syscallarg(unsigned int) tolen;
1.125 dsl 502: } */
1.57 lukem 503: struct msghdr msg;
504: struct iovec aiov;
1.1 cgd 505:
1.91 christos 506: msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */
1.9 cgd 507: msg.msg_namelen = SCARG(uap, tolen);
1.1 cgd 508: msg.msg_iov = &aiov;
509: msg.msg_iovlen = 1;
1.121 christos 510: msg.msg_control = NULL;
1.1 cgd 511: msg.msg_flags = 0;
1.91 christos 512: aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
1.9 cgd 513: aiov.iov_len = SCARG(uap, len);
1.111 dsl 514: return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1 cgd 515: }
516:
1.7 mycroft 517: int
1.125 dsl 518: sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retval)
1.15 thorpej 519: {
1.125 dsl 520: /* {
1.57 lukem 521: syscallarg(int) s;
522: syscallarg(const struct msghdr *) msg;
523: syscallarg(int) flags;
1.125 dsl 524: } */
1.57 lukem 525: struct msghdr msg;
526: int error;
1.1 cgd 527:
1.110 dsl 528: error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
1.18 christos 529: if (error)
1.1 cgd 530: return (error);
1.111 dsl 531:
532: msg.msg_flags = MSG_IOVUSRSPACE;
533: return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1 cgd 534: }
535:
1.155 christos 536: static int
537: do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp,
538: struct msghdr *mp, int flags, register_t *retsize)
1.1 cgd 539: {
1.155 christos 540:
1.141 rmind 541: struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
1.57 lukem 542: struct mbuf *to, *control;
1.141 rmind 543: struct uio auio;
544: size_t len, iovsz;
545: int i, error;
1.90 perry 546:
1.117 dsl 547: ktrkuser("msghdr", mp, sizeof *mp);
548:
1.141 rmind 549: /* If the caller passed us stuff in mbufs, we must free them. */
550: to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL;
551: control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL;
552: iovsz = mp->msg_iovlen * sizeof(struct iovec);
1.111 dsl 553:
554: if (mp->msg_flags & MSG_IOVUSRSPACE) {
555: if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
556: if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
557: error = EMSGSIZE;
558: goto bad;
559: }
1.141 rmind 560: iov = kmem_alloc(iovsz, KM_SLEEP);
1.111 dsl 561: }
562: if (mp->msg_iovlen != 0) {
1.141 rmind 563: error = copyin(mp->msg_iov, iov, iovsz);
1.111 dsl 564: if (error)
565: goto bad;
566: }
567: mp->msg_iov = iov;
568: }
569:
1.1 cgd 570: auio.uio_iov = mp->msg_iov;
571: auio.uio_iovcnt = mp->msg_iovlen;
572: auio.uio_rw = UIO_WRITE;
573: auio.uio_offset = 0; /* XXX */
574: auio.uio_resid = 0;
1.97 yamt 575: KASSERT(l == curlwp);
576: auio.uio_vmspace = l->l_proc->p_vmspace;
1.111 dsl 577:
578: for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) {
1.33 thorpej 579: /*
580: * Writes return ssize_t because -1 is returned on error.
581: * Therefore, we must restrict the length to SSIZE_MAX to
582: * avoid garbage return values.
583: */
1.111 dsl 584: auio.uio_resid += tiov->iov_len;
585: if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
1.43 thorpej 586: error = EINVAL;
1.111 dsl 587: goto bad;
1.43 thorpej 588: }
1.1 cgd 589: }
1.111 dsl 590:
1.112 enami 591: if (mp->msg_name && to == NULL) {
1.63 jdolecek 592: error = sockargs(&to, mp->msg_name, mp->msg_namelen,
1.112 enami 593: MT_SONAME);
1.63 jdolecek 594: if (error)
1.111 dsl 595: goto bad;
596: }
597:
1.1 cgd 598: if (mp->msg_control) {
1.104 elad 599: if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
1.1 cgd 600: error = EINVAL;
601: goto bad;
602: }
1.112 enami 603: if (control == NULL) {
1.111 dsl 604: error = sockargs(&control, mp->msg_control,
1.112 enami 605: mp->msg_controllen, MT_CONTROL);
1.111 dsl 606: if (error)
607: goto bad;
608: }
609: }
610:
1.156 njoly 611: if (ktrpoint(KTR_GENIO) && iovsz > 0) {
1.141 rmind 612: ktriov = kmem_alloc(iovsz, KM_SLEEP);
613: memcpy(ktriov, auio.uio_iov, iovsz);
1.1 cgd 614: }
1.111 dsl 615:
616: if (mp->msg_name)
617: MCLAIM(to, so->so_mowner);
618: if (mp->msg_control)
619: MCLAIM(control, so->so_mowner);
620:
1.1 cgd 621: len = auio.uio_resid;
1.95 christos 622: error = (*so->so_send)(so, to, &auio, NULL, control, flags, l);
1.111 dsl 623: /* Protocol is responsible for freeing 'control' */
624: control = NULL;
625:
1.18 christos 626: if (error) {
1.1 cgd 627: if (auio.uio_resid != len && (error == ERESTART ||
628: error == EINTR || error == EWOULDBLOCK))
629: error = 0;
1.151 christos 630: if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 &&
631: (flags & MSG_NOSIGNAL) == 0) {
1.130 ad 632: mutex_enter(proc_lock);
1.111 dsl 633: psignal(l->l_proc, SIGPIPE);
1.130 ad 634: mutex_exit(proc_lock);
1.106 ad 635: }
1.1 cgd 636: }
637: if (error == 0)
638: *retsize = len - auio.uio_resid;
1.111 dsl 639:
1.119 rmind 640: bad:
1.156.2.1 tls 641: if (ktriov != NULL) {
1.116 ad 642: ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error);
1.156.2.1 tls 643: kmem_free(ktriov, iovsz);
1.1 cgd 644: }
1.111 dsl 645:
1.119 rmind 646: if (iov != aiov)
1.141 rmind 647: kmem_free(iov, iovsz);
1.1 cgd 648: if (to)
649: m_freem(to);
1.121 christos 650: if (control)
1.111 dsl 651: m_freem(control);
652:
1.1 cgd 653: return (error);
654: }
655:
1.7 mycroft 656: int
1.155 christos 657: do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
658: register_t *retsize)
659: {
660: int error;
661: struct socket *so;
662: file_t *fp;
663:
664: if ((error = fd_getsock1(s, &so, &fp)) != 0)
665: return error;
666: error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize);
667: fd_putfile(s);
668: return error;
669: }
670:
671: int
1.125 dsl 672: sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval)
1.15 thorpej 673: {
1.125 dsl 674: /* {
1.57 lukem 675: syscallarg(int) s;
676: syscallarg(void *) buf;
677: syscallarg(size_t) len;
678: syscallarg(int) flags;
679: syscallarg(struct sockaddr *) from;
680: syscallarg(unsigned int *) fromlenaddr;
1.125 dsl 681: } */
1.57 lukem 682: struct msghdr msg;
683: struct iovec aiov;
684: int error;
1.113 dsl 685: struct mbuf *from;
1.1 cgd 686:
1.121 christos 687: msg.msg_name = NULL;
1.1 cgd 688: msg.msg_iov = &aiov;
689: msg.msg_iovlen = 1;
1.9 cgd 690: aiov.iov_base = SCARG(uap, buf);
691: aiov.iov_len = SCARG(uap, len);
1.113 dsl 692: msg.msg_control = NULL;
693: msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
694:
695: error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
696: if (error != 0)
697: return error;
698:
699: error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr),
700: MSG_LENUSRSPACE, from);
701: if (from != NULL)
702: m_free(from);
703: return error;
1.1 cgd 704: }
705:
1.7 mycroft 706: int
1.125 dsl 707: sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retval)
1.15 thorpej 708: {
1.125 dsl 709: /* {
1.57 lukem 710: syscallarg(int) s;
711: syscallarg(struct msghdr *) msg;
712: syscallarg(int) flags;
1.125 dsl 713: } */
1.81 fvdl 714: struct msghdr msg;
1.57 lukem 715: int error;
1.113 dsl 716: struct mbuf *from, *control;
1.1 cgd 717:
1.110 dsl 718: error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
1.18 christos 719: if (error)
1.1 cgd 720: return (error);
1.113 dsl 721:
722: msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
723:
724: error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
725: msg.msg_control != NULL ? &control : NULL, retval);
726: if (error != 0)
727: return error;
728:
729: if (msg.msg_control != NULL)
730: error = copyout_msg_control(l, &msg, control);
731:
732: if (error == 0)
733: error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
734: from);
735: if (from != NULL)
736: m_free(from);
1.117 dsl 737: if (error == 0) {
738: ktrkuser("msghdr", &msg, sizeof msg);
1.110 dsl 739: error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
1.117 dsl 740: }
1.113 dsl 741:
1.1 cgd 742: return (error);
743: }
744:
1.155 christos 745: int
746: sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap,
747: register_t *retval)
748: {
749: /* {
750: syscallarg(int) s;
751: syscallarg(struct mmsghdr *) mmsg;
752: syscallarg(unsigned int) vlen;
753: syscallarg(unsigned int) flags;
754: } */
755: struct mmsghdr mmsg;
756: struct socket *so;
757: file_t *fp;
758: struct msghdr *msg = &mmsg.msg_hdr;
759: int error, s;
760: unsigned int vlen, flags, dg;
761:
762: s = SCARG(uap, s);
763: if ((error = fd_getsock1(s, &so, &fp)) != 0)
764: return error;
765:
766: vlen = SCARG(uap, vlen);
767: if (vlen > 1024)
768: vlen = 1024;
769:
770: flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
771:
772: for (dg = 0; dg < vlen;) {
773: error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
774: if (error)
775: break;
776:
777: msg->msg_flags = flags;
778:
779: error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
780: if (error)
781: break;
782:
783: ktrkuser("msghdr", msg, sizeof *msg);
784: mmsg.msg_len = *retval;
785: error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
786: if (error)
787: break;
788: dg++;
789:
790: }
791:
792: *retval = dg;
793: if (error)
794: so->so_error = error;
795:
796: fd_putfile(s);
797:
798: /*
799: * If we succeeded at least once, return 0, hopefully so->so_error
800: * will catch it next time.
801: */
802: if (dg)
803: return 0;
804: return error;
805: }
806:
1.92 martin 807: /*
1.113 dsl 808: * Adjust for a truncated SCM_RIGHTS control message.
809: * This means closing any file descriptors that aren't present
810: * in the returned buffer.
811: * m is the mbuf holding the (already externalized) SCM_RIGHTS message.
1.92 martin 812: */
1.93 martin 813: static void
1.128 ad 814: free_rights(struct mbuf *m)
1.92 martin 815: {
1.156.2.1 tls 816: struct cmsghdr *cm;
1.92 martin 817: int *fdv;
1.156.2.1 tls 818: unsigned int nfds, i;
1.92 martin 819:
1.156.2.1 tls 820: KASSERT(sizeof(*cm) <= m->m_len);
821: cm = mtod(m, struct cmsghdr *);
822:
823: KASSERT(CMSG_ALIGN(sizeof(*cm)) <= cm->cmsg_len);
824: KASSERT(cm->cmsg_len <= m->m_len);
825: nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int);
826: fdv = (int *)CMSG_DATA(cm);
827:
828: for (i = 0; i < nfds; i++)
1.128 ad 829: if (fd_getfile(fdv[i]) != NULL)
830: (void)fd_close(fdv[i]);
1.113 dsl 831: }
832:
833: void
834: free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied)
835: {
836: struct mbuf *next;
1.114 dsl 837: struct cmsghdr *cmsg;
1.113 dsl 838: bool do_free_rights = false;
839:
840: while (control != NULL) {
1.114 dsl 841: cmsg = mtod(control, struct cmsghdr *);
1.113 dsl 842: if (control == uncopied)
843: do_free_rights = true;
1.114 dsl 844: if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET
845: && cmsg->cmsg_type == SCM_RIGHTS)
1.128 ad 846: free_rights(control);
1.113 dsl 847: next = control->m_next;
848: m_free(control);
849: control = next;
850: }
851: }
852:
853: /* Copy socket control/CMSG data to user buffer, frees the mbuf */
854: int
855: copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
856: {
857: int i, len, error = 0;
1.114 dsl 858: struct cmsghdr *cmsg;
1.113 dsl 859: struct mbuf *m;
860: char *q;
861:
862: len = mp->msg_controllen;
863: if (len <= 0 || control == 0) {
864: mp->msg_controllen = 0;
865: free_control_mbuf(l, control, control);
866: return 0;
867: }
868:
869: q = (char *)mp->msg_control;
870:
871: for (m = control; m != NULL; ) {
1.114 dsl 872: cmsg = mtod(m, struct cmsghdr *);
1.113 dsl 873: i = m->m_len;
874: if (len < i) {
875: mp->msg_flags |= MSG_CTRUNC;
1.114 dsl 876: if (cmsg->cmsg_level == SOL_SOCKET
877: && cmsg->cmsg_type == SCM_RIGHTS)
1.113 dsl 878: /* Do not truncate me ... */
879: break;
880: i = len;
881: }
882: error = copyout(mtod(m, void *), q, i);
1.117 dsl 883: ktrkuser("msgcontrol", mtod(m, void *), i);
1.113 dsl 884: if (error != 0) {
885: /* We must free all the SCM_RIGHTS */
886: m = control;
887: break;
888: }
889: m = m->m_next;
890: if (m)
891: i = ALIGN(i);
892: q += i;
893: len -= i;
894: if (len <= 0)
895: break;
896: }
897:
898: free_control_mbuf(l, control, m);
899:
900: mp->msg_controllen = q - (char *)mp->msg_control;
901: return error;
1.92 martin 902: }
903:
1.155 christos 904: static int
905: do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
906: struct mbuf **from, struct mbuf **control, register_t *retsize)
1.1 cgd 907: {
1.156 njoly 908: struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
1.57 lukem 909: struct uio auio;
1.141 rmind 910: size_t len, iovsz;
911: int i, error;
1.57 lukem 912:
1.117 dsl 913: ktrkuser("msghdr", mp, sizeof *mp);
914:
1.113 dsl 915: *from = NULL;
916: if (control != NULL)
917: *control = NULL;
1.90 perry 918:
1.141 rmind 919: iovsz = mp->msg_iovlen * sizeof(struct iovec);
920:
1.113 dsl 921: if (mp->msg_flags & MSG_IOVUSRSPACE) {
922: if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
923: if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
924: error = EMSGSIZE;
925: goto out;
926: }
1.141 rmind 927: iov = kmem_alloc(iovsz, KM_SLEEP);
1.113 dsl 928: }
929: if (mp->msg_iovlen != 0) {
1.141 rmind 930: error = copyin(mp->msg_iov, iov, iovsz);
1.113 dsl 931: if (error)
932: goto out;
933: }
934: auio.uio_iov = iov;
935: } else
936: auio.uio_iov = mp->msg_iov;
1.1 cgd 937: auio.uio_iovcnt = mp->msg_iovlen;
938: auio.uio_rw = UIO_READ;
939: auio.uio_offset = 0; /* XXX */
940: auio.uio_resid = 0;
1.97 yamt 941: KASSERT(l == curlwp);
942: auio.uio_vmspace = l->l_proc->p_vmspace;
1.113 dsl 943:
944: tiov = auio.uio_iov;
945: for (i = 0; i < mp->msg_iovlen; i++, tiov++) {
1.33 thorpej 946: /*
947: * Reads return ssize_t because -1 is returned on error.
948: * Therefore we must restrict the length to SSIZE_MAX to
949: * avoid garbage return values.
950: */
1.113 dsl 951: auio.uio_resid += tiov->iov_len;
952: if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
1.43 thorpej 953: error = EINVAL;
1.113 dsl 954: goto out;
1.43 thorpej 955: }
1.1 cgd 956: }
957:
1.156 njoly 958: if (ktrpoint(KTR_GENIO) && iovsz > 0) {
1.141 rmind 959: ktriov = kmem_alloc(iovsz, KM_SLEEP);
960: memcpy(ktriov, auio.uio_iov, iovsz);
1.1 cgd 961: }
1.113 dsl 962:
1.1 cgd 963: len = auio.uio_resid;
1.115 dsl 964: mp->msg_flags &= MSG_USERFLAGS;
1.113 dsl 965: error = (*so->so_receive)(so, from, &auio, NULL, control,
1.129 ad 966: &mp->msg_flags);
1.113 dsl 967: len -= auio.uio_resid;
968: *retsize = len;
969: if (error != 0 && len != 0
970: && (error == ERESTART || error == EINTR || error == EWOULDBLOCK))
971: /* Some data transferred */
972: error = 0;
1.116 ad 973:
1.156.2.1 tls 974: if (ktriov != NULL) {
1.116 ad 975: ktrgeniov(s, UIO_READ, ktriov, len, error);
1.156.2.1 tls 976: kmem_free(ktriov, iovsz);
1.1 cgd 977: }
1.116 ad 978:
1.113 dsl 979: if (error != 0) {
980: m_freem(*from);
981: *from = NULL;
982: if (control != NULL) {
983: free_control_mbuf(l, *control, *control);
984: *control = NULL;
1.1 cgd 985: }
986: }
1.43 thorpej 987: out:
1.113 dsl 988: if (iov != aiov)
1.141 rmind 989: kmem_free(iov, iovsz);
1.155 christos 990: return (error);
991: }
992:
993:
994: int
995: do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
996: struct mbuf **control, register_t *retsize)
997: {
998: int error;
999: struct socket *so;
1000:
1001: if ((error = fd_getsock(s, &so)) != 0)
1002: return error;
1003: error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize);
1.128 ad 1004: fd_putfile(s);
1.155 christos 1005: return error;
1.1 cgd 1006: }
1007:
1.155 christos 1008: int
1009: sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap,
1010: register_t *retval)
1011: {
1012: /* {
1013: syscallarg(int) s;
1014: syscallarg(struct mmsghdr *) mmsg;
1015: syscallarg(unsigned int) vlen;
1016: syscallarg(unsigned int) flags;
1017: syscallarg(struct timespec *) timeout;
1018: } */
1019: struct mmsghdr mmsg;
1020: struct socket *so;
1021: struct msghdr *msg = &mmsg.msg_hdr;
1022: int error, s;
1023: struct mbuf *from, *control;
1024: struct timespec ts, now;
1025: unsigned int vlen, flags, dg;
1026:
1027: if (SCARG(uap, timeout)) {
1028: if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0)
1029: return error;
1030: getnanotime(&now);
1031: timespecadd(&now, &ts, &ts);
1032: }
1033:
1034: s = SCARG(uap, s);
1035: if ((error = fd_getsock(s, &so)) != 0)
1036: return error;
1037:
1038: vlen = SCARG(uap, vlen);
1039: if (vlen > 1024)
1040: vlen = 1024;
1041:
1042: from = NULL;
1043: flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
1044:
1045: for (dg = 0; dg < vlen;) {
1046: error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
1047: if (error)
1048: break;
1049:
1050: msg->msg_flags = flags & ~MSG_WAITFORONE;
1051:
1052: if (from != NULL) {
1053: m_free(from);
1054: from = NULL;
1055: }
1056:
1057: error = do_sys_recvmsg_so(l, s, so, msg, &from,
1058: msg->msg_control != NULL ? &control : NULL, retval);
1059: if (error)
1060: break;
1061:
1062: if (msg->msg_control != NULL)
1063: error = copyout_msg_control(l, msg, control);
1064: if (error)
1065: break;
1066:
1067: error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
1068: from);
1069: if (error)
1070: break;
1071:
1072: ktrkuser("msghdr", msg, sizeof *msg);
1073: mmsg.msg_len = *retval;
1074:
1075: error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
1076: if (error)
1077: break;
1078:
1079: dg++;
1080: if (msg->msg_flags & MSG_OOB)
1081: break;
1082:
1083: if (SCARG(uap, timeout)) {
1084: getnanotime(&now);
1085: timespecsub(&now, &ts, &now);
1086: if (now.tv_sec > 0)
1087: break;
1088: }
1089:
1090: if (flags & MSG_WAITFORONE)
1091: flags |= MSG_DONTWAIT;
1092:
1093: }
1094:
1095: if (from != NULL)
1096: m_free(from);
1097:
1098: *retval = dg;
1099: if (error)
1100: so->so_error = error;
1101:
1102: fd_putfile(s);
1103:
1104: /*
1105: * If we succeeded at least once, return 0, hopefully so->so_error
1106: * will catch it next time.
1107: */
1108: if (dg)
1109: return 0;
1110:
1111: return error;
1112: }
1.113 dsl 1113:
1.1 cgd 1114: /* ARGSUSED */
1.7 mycroft 1115: int
1.125 dsl 1116: sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)
1.15 thorpej 1117: {
1.125 dsl 1118: /* {
1.57 lukem 1119: syscallarg(int) s;
1120: syscallarg(int) how;
1.125 dsl 1121: } */
1.128 ad 1122: struct socket *so;
1.57 lukem 1123: int error;
1.1 cgd 1124:
1.128 ad 1125: if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1 cgd 1126: return (error);
1.129 ad 1127: solock(so);
1.128 ad 1128: error = soshutdown(so, SCARG(uap, how));
1.129 ad 1129: sounlock(so);
1.128 ad 1130: fd_putfile(SCARG(uap, s));
1.43 thorpej 1131: return (error);
1.1 cgd 1132: }
1133:
1134: /* ARGSUSED */
1.7 mycroft 1135: int
1.125 dsl 1136: sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval)
1.15 thorpej 1137: {
1.125 dsl 1138: /* {
1.57 lukem 1139: syscallarg(int) s;
1140: syscallarg(int) level;
1141: syscallarg(int) name;
1142: syscallarg(const void *) val;
1143: syscallarg(unsigned int) valsize;
1.125 dsl 1144: } */
1.134 plunky 1145: struct sockopt sopt;
1.76 matt 1146: struct socket *so;
1.151 christos 1147: file_t *fp;
1.57 lukem 1148: int error;
1.75 thorpej 1149: unsigned int len;
1.1 cgd 1150:
1.134 plunky 1151: len = SCARG(uap, valsize);
1152: if (len > 0 && SCARG(uap, val) == NULL)
1153: return (EINVAL);
1154:
1155: if (len > MCLBYTES)
1156: return (EINVAL);
1157:
1.151 christos 1158: if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1.1 cgd 1159: return (error);
1.134 plunky 1160:
1161: sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
1162:
1163: if (len > 0) {
1164: error = copyin(SCARG(uap, val), sopt.sopt_data, len);
1165: if (error)
1.43 thorpej 1166: goto out;
1.1 cgd 1167: }
1.134 plunky 1168:
1169: error = sosetopt(so, &sopt);
1.151 christos 1170: if (so->so_options & SO_NOSIGPIPE)
1.152 christos 1171: atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
1.151 christos 1172: else
1.152 christos 1173: atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);
1.134 plunky 1174:
1.43 thorpej 1175: out:
1.134 plunky 1176: sockopt_destroy(&sopt);
1.128 ad 1177: fd_putfile(SCARG(uap, s));
1.43 thorpej 1178: return (error);
1.1 cgd 1179: }
1180:
1181: /* ARGSUSED */
1.7 mycroft 1182: int
1.125 dsl 1183: sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval)
1.15 thorpej 1184: {
1.125 dsl 1185: /* {
1.57 lukem 1186: syscallarg(int) s;
1187: syscallarg(int) level;
1188: syscallarg(int) name;
1189: syscallarg(void *) val;
1190: syscallarg(unsigned int *) avalsize;
1.125 dsl 1191: } */
1.134 plunky 1192: struct sockopt sopt;
1.128 ad 1193: struct socket *so;
1.151 christos 1194: file_t *fp;
1.134 plunky 1195: unsigned int valsize, len;
1.57 lukem 1196: int error;
1.1 cgd 1197:
1.134 plunky 1198: if (SCARG(uap, val) != NULL) {
1199: error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
1200: if (error)
1201: return (error);
1202: } else
1203: valsize = 0;
1204:
1.151 christos 1205: if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1.1 cgd 1206: return (error);
1.134 plunky 1207:
1208: sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
1209:
1.151 christos 1210: if (fp->f_flag & FNOSIGPIPE)
1.154 christos 1211: so->so_options |= SO_NOSIGPIPE;
1.151 christos 1212: else
1.154 christos 1213: so->so_options &= ~SO_NOSIGPIPE;
1.134 plunky 1214: error = sogetopt(so, &sopt);
1215: if (error)
1216: goto out;
1217:
1218: if (valsize > 0) {
1219: len = min(valsize, sopt.sopt_size);
1220: error = copyout(sopt.sopt_data, SCARG(uap, val), len);
1221: if (error)
1222: goto out;
1223:
1224: error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
1.18 christos 1225: if (error)
1.43 thorpej 1226: goto out;
1.1 cgd 1227: }
1.134 plunky 1228:
1.43 thorpej 1229: out:
1.134 plunky 1230: sockopt_destroy(&sopt);
1.128 ad 1231: fd_putfile(SCARG(uap, s));
1.1 cgd 1232: return (error);
1233: }
1234:
1.68 jdolecek 1235: #ifdef PIPE_SOCKETPAIR
1.1 cgd 1236: /* ARGSUSED */
1.7 mycroft 1237: int
1.142 christos 1238: pipe1(struct lwp *l, register_t *retval, int flags)
1.1 cgd 1239: {
1.128 ad 1240: file_t *rf, *wf;
1.57 lukem 1241: struct socket *rso, *wso;
1242: int fd, error;
1.128 ad 1243: proc_t *p;
1.1 cgd 1244:
1.151 christos 1245: if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
1.145 christos 1246: return EINVAL;
1.128 ad 1247: p = curproc;
1.129 ad 1248: if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
1.1 cgd 1249: return (error);
1.129 ad 1250: if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
1.1 cgd 1251: goto free1;
1.58 manu 1252: /* remember this socket pair implements a pipe */
1253: wso->so_state |= SS_ISAPIPE;
1254: rso->so_state |= SS_ISAPIPE;
1.128 ad 1255: if ((error = fd_allocfile(&rf, &fd)) != 0)
1.1 cgd 1256: goto free2;
1257: retval[0] = fd;
1.142 christos 1258: rf->f_flag = FREAD | flags;
1.1 cgd 1259: rf->f_type = DTYPE_SOCKET;
1260: rf->f_ops = &socketops;
1.110 dsl 1261: rf->f_data = rso;
1.128 ad 1262: if ((error = fd_allocfile(&wf, &fd)) != 0)
1.1 cgd 1263: goto free3;
1.142 christos 1264: wf->f_flag = FWRITE | flags;
1.1 cgd 1265: wf->f_type = DTYPE_SOCKET;
1266: wf->f_ops = &socketops;
1.110 dsl 1267: wf->f_data = wso;
1.1 cgd 1268: retval[1] = fd;
1.129 ad 1269: solock(wso);
1270: error = unp_connect2(wso, rso, PRU_CONNECT2);
1271: sounlock(wso);
1272: if (error != 0)
1.1 cgd 1273: goto free4;
1.128 ad 1274: fd_affix(p, wf, (int)retval[1]);
1275: fd_affix(p, rf, (int)retval[0]);
1.1 cgd 1276: return (0);
1.57 lukem 1277: free4:
1.128 ad 1278: fd_abort(p, wf, (int)retval[1]);
1.57 lukem 1279: free3:
1.128 ad 1280: fd_abort(p, rf, (int)retval[0]);
1.57 lukem 1281: free2:
1.1 cgd 1282: (void)soclose(wso);
1.57 lukem 1283: free1:
1.1 cgd 1284: (void)soclose(rso);
1285: return (error);
1286: }
1.68 jdolecek 1287: #endif /* PIPE_SOCKETPAIR */
1.1 cgd 1288:
1289: /*
1290: * Get socket name.
1291: */
1.13 christos 1292: /* ARGSUSED */
1.7 mycroft 1293: int
1.113 dsl 1294: do_sys_getsockname(struct lwp *l, int fd, int which, struct mbuf **nam)
1.15 thorpej 1295: {
1.57 lukem 1296: struct socket *so;
1297: struct mbuf *m;
1298: int error;
1.1 cgd 1299:
1.128 ad 1300: if ((error = fd_getsock(fd, &so)) != 0)
1.113 dsl 1301: return error;
1302:
1.129 ad 1303: m = m_getclr(M_WAIT, MT_SONAME);
1304: MCLAIM(m, so->so_mowner);
1305:
1306: solock(so);
1.113 dsl 1307: if (which == PRU_PEERADDR
1308: && (so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) {
1309: error = ENOTCONN;
1.129 ad 1310: } else {
1311: *nam = m;
1312: error = (*so->so_proto->pr_usrreq)(so, which, NULL, m, NULL,
1313: NULL);
1.113 dsl 1314: }
1.129 ad 1315: sounlock(so);
1.113 dsl 1316: if (error != 0)
1317: m_free(m);
1.128 ad 1318: fd_putfile(fd);
1.113 dsl 1319: return error;
1320: }
1321:
1322: int
1323: copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags,
1324: struct mbuf *addr)
1325: {
1326: int len;
1327: int error;
1328:
1329: if (asa == NULL)
1330: /* Assume application not interested */
1331: return 0;
1332:
1333: if (flags & MSG_LENUSRSPACE) {
1334: error = copyin(alen, &len, sizeof(len));
1335: if (error)
1336: return error;
1337: } else
1338: len = *alen;
1.118 dsl 1339: if (len < 0)
1.113 dsl 1340: return EINVAL;
1341:
1342: if (addr == NULL) {
1343: len = 0;
1344: error = 0;
1345: } else {
1346: if (len > addr->m_len)
1347: len = addr->m_len;
1348: /* Maybe this ought to copy a chain ? */
1.156.2.2! tls 1349: ktrkuser(mbuftypes[MT_SONAME], mtod(addr, void *), len);
1.113 dsl 1350: error = copyout(mtod(addr, void *), asa, len);
1351: }
1352:
1353: if (error == 0) {
1354: if (flags & MSG_LENUSRSPACE)
1355: error = copyout(&len, alen, sizeof(len));
1356: else
1357: *alen = len;
1358: }
1359:
1360: return error;
1361: }
1362:
1363: /*
1364: * Get socket name.
1365: */
1366: /* ARGSUSED */
1367: int
1.125 dsl 1368: sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, register_t *retval)
1.113 dsl 1369: {
1.125 dsl 1370: /* {
1.113 dsl 1371: syscallarg(int) fdes;
1372: syscallarg(struct sockaddr *) asa;
1373: syscallarg(unsigned int *) alen;
1.125 dsl 1374: } */
1.113 dsl 1375: struct mbuf *m;
1376: int error;
1377:
1378: error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m);
1379: if (error != 0)
1380: return error;
1381:
1382: error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1383: MSG_LENUSRSPACE, m);
1384: if (m != NULL)
1385: m_free(m);
1386: return error;
1.1 cgd 1387: }
1388:
1389: /*
1390: * Get name of peer for connected socket.
1391: */
1.13 christos 1392: /* ARGSUSED */
1.7 mycroft 1393: int
1.125 dsl 1394: sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, register_t *retval)
1.15 thorpej 1395: {
1.125 dsl 1396: /* {
1.57 lukem 1397: syscallarg(int) fdes;
1398: syscallarg(struct sockaddr *) asa;
1399: syscallarg(unsigned int *) alen;
1.125 dsl 1400: } */
1.57 lukem 1401: struct mbuf *m;
1402: int error;
1.1 cgd 1403:
1.113 dsl 1404: error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m);
1405: if (error != 0)
1406: return error;
1407:
1408: error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1409: MSG_LENUSRSPACE, m);
1410: if (m != NULL)
1411: m_free(m);
1412: return error;
1.1 cgd 1413: }
1414:
1.24 thorpej 1415: /*
1416: * XXX In a perfect world, we wouldn't pass around socket control
1417: * XXX arguments in mbufs, and this could go away.
1418: */
1.7 mycroft 1419: int
1.91 christos 1420: sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type)
1.1 cgd 1421: {
1.57 lukem 1422: struct sockaddr *sa;
1423: struct mbuf *m;
1424: int error;
1.1 cgd 1425:
1.24 thorpej 1426: /*
1.25 thorpej 1427: * We can't allow socket names > UCHAR_MAX in length, since that
1.64 matt 1428: * will overflow sa_len. Control data more than a page size in
1429: * length is just too much.
1.24 thorpej 1430: */
1.64 matt 1431: if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1.24 thorpej 1432: return (EINVAL);
1433:
1434: /* Allocate an mbuf to hold the arguments. */
1435: m = m_get(M_WAIT, type);
1.76 matt 1436: /* can't claim. don't who to assign it to. */
1.64 matt 1437: if (buflen > MLEN) {
1.24 thorpej 1438: /*
1439: * Won't fit into a regular mbuf, so we allocate just
1440: * enough external storage to hold the argument.
1441: */
1442: MEXTMALLOC(m, buflen, M_WAITOK);
1.1 cgd 1443: }
1444: m->m_len = buflen;
1.107 christos 1445: error = copyin(bf, mtod(m, void *), buflen);
1.1 cgd 1446: if (error) {
1447: (void) m_free(m);
1.7 mycroft 1448: return (error);
1.1 cgd 1449: }
1.147 christos 1450: ktrkuser(mbuftypes[type], mtod(m, void *), buflen);
1.1 cgd 1451: *mp = m;
1452: if (type == MT_SONAME) {
1.7 mycroft 1453: sa = mtod(m, struct sockaddr *);
1.65 jdolecek 1454: #if BYTE_ORDER != BIG_ENDIAN
1455: /*
1456: * 4.3BSD compat thing - need to stay, since bind(2),
1457: * connect(2), sendto(2) were not versioned for COMPAT_43.
1458: */
1.1 cgd 1459: if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1460: sa->sa_family = sa->sa_len;
1461: #endif
1462: sa->sa_len = buflen;
1463: }
1464: return (0);
1465: }
CVSweb <webmaster@jp.NetBSD.org>