[BACK]Return to uipc_syscalls.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/uipc_syscalls.c, Revision 1.154.2.1

1.154.2.1! riz         1: /*     $NetBSD: uipc_syscalls.c,v 1.154 2012/01/25 16:56:13 christos Exp $     */
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.154.2.1! riz        64: __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.154 2012/01/25 16:56:13 christos Exp $");
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;
                    237:        error = soaccept(so2, nam);
1.139     elad      238:        so2->so_cred = kauth_cred_dup(so->so_cred);
1.129     ad        239:        sounlock(so);
1.49      mycroft   240:        if (error) {
1.113     dsl       241:                /* an error occurred, free the file descriptor and mbuf */
                    242:                m_freem(nam);
1.128     ad        243:                mutex_enter(&fp2->f_lock);
                    244:                fp2->f_count++;
                    245:                mutex_exit(&fp2->f_lock);
                    246:                closef(fp2);
                    247:                fd_abort(curproc, NULL, fd);
1.99      christos  248:        } else {
1.144     christos  249:                fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
1.128     ad        250:                fd_affix(curproc, fp2, fd);
1.113     dsl       251:                *name = nam;
1.49      mycroft   252:        }
1.129     ad        253:        fd_putfile(sock);
1.144     christos  254:        if (__predict_false(mask))
                    255:                sigsuspendteardown(l);
1.128     ad        256:        return (error);
                    257:  bad:
1.129     ad        258:        sounlock(so);
1.128     ad        259:        m_freem(nam);
1.129     ad        260:        fd_putfile(sock);
1.128     ad        261:        fd_abort(curproc, fp2, fd);
1.144     christos  262:        if (__predict_false(mask))
                    263:                sigsuspendteardown(l);
1.128     ad        264:        return (error);
1.1       cgd       265: }
                    266:
1.113     dsl       267: int
1.125     dsl       268: sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval)
1.113     dsl       269: {
1.125     dsl       270:        /* {
1.113     dsl       271:                syscallarg(int)                 s;
                    272:                syscallarg(struct sockaddr *)   name;
                    273:                syscallarg(unsigned int *)      anamelen;
1.125     dsl       274:        } */
1.128     ad        275:        int error, fd;
1.113     dsl       276:        struct mbuf *name;
                    277:
1.144     christos  278:        error = do_sys_accept(l, SCARG(uap, s), &name, retval, NULL, 0, 0);
                    279:        if (error != 0)
                    280:                return error;
                    281:        error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
                    282:            MSG_LENUSRSPACE, name);
                    283:        if (name != NULL)
                    284:                m_free(name);
                    285:        if (error != 0) {
                    286:                fd = (int)*retval;
                    287:                if (fd_getfile(fd) != NULL)
                    288:                        (void)fd_close(fd);
                    289:        }
                    290:        return error;
                    291: }
                    292:
                    293: int
                    294: sys_paccept(struct lwp *l, const struct sys_paccept_args *uap,
                    295:     register_t *retval)
                    296: {
                    297:        /* {
                    298:                syscallarg(int)                 s;
                    299:                syscallarg(struct sockaddr *)   name;
                    300:                syscallarg(unsigned int *)      anamelen;
                    301:                syscallarg(const sigset_t *)    mask;
                    302:                syscallarg(int)                 flags;
                    303:        } */
                    304:        int error, fd;
                    305:        struct mbuf *name;
                    306:        sigset_t *mask, amask;
                    307:
                    308:        if (SCARG(uap, mask) != NULL) {
                    309:                error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
                    310:                if (error)
                    311:                        return error;
                    312:                mask = &amask;
                    313:        } else
                    314:                mask = NULL;
                    315:
                    316:        error = do_sys_accept(l, SCARG(uap, s), &name, retval, mask,
                    317:            SCARG(uap, flags), FNONBLOCK);
1.113     dsl       318:        if (error != 0)
                    319:                return error;
                    320:        error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
                    321:            MSG_LENUSRSPACE, name);
                    322:        if (name != NULL)
                    323:                m_free(name);
1.128     ad        324:        if (error != 0) {
                    325:                fd = (int)*retval;
                    326:                if (fd_getfile(fd) != NULL)
                    327:                        (void)fd_close(fd);
                    328:        }
1.113     dsl       329:        return error;
                    330: }
                    331:
1.1       cgd       332: /* ARGSUSED */
1.7       mycroft   333: int
1.125     dsl       334: sys_connect(struct lwp *l, const struct sys_connect_args *uap, register_t *retval)
1.15      thorpej   335: {
1.125     dsl       336:        /* {
1.57      lukem     337:                syscallarg(int)                         s;
                    338:                syscallarg(const struct sockaddr *)     name;
                    339:                syscallarg(unsigned int)                namelen;
1.125     dsl       340:        } */
1.111     dsl       341:        int             error;
                    342:        struct mbuf     *nam;
                    343:
1.112     enami     344:        error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
                    345:            MT_SONAME);
1.111     dsl       346:        if (error)
                    347:                return error;
                    348:        return do_sys_connect(l,  SCARG(uap, s), nam);
                    349: }
                    350:
                    351: int
1.128     ad        352: do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
1.111     dsl       353: {
1.57      lukem     354:        struct socket   *so;
1.111     dsl       355:        int             error;
1.87      ragge     356:        int             interrupted = 0;
1.1       cgd       357:
1.128     ad        358:        if ((error = fd_getsock(fd, &so)) != 0) {
1.111     dsl       359:                m_freem(nam);
1.1       cgd       360:                return (error);
1.111     dsl       361:        }
1.129     ad        362:        solock(so);
1.111     dsl       363:        MCLAIM(nam, so->so_mowner);
1.136     ad        364:        if ((so->so_state & SS_ISCONNECTING) != 0) {
1.62      jdolecek  365:                error = EALREADY;
                    366:                goto out;
                    367:        }
1.111     dsl       368:
1.95      christos  369:        error = soconnect(so, nam, l);
1.1       cgd       370:        if (error)
                    371:                goto bad;
1.150     christos  372:        if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) ==
                    373:            (SS_NBIO|SS_ISCONNECTING)) {
1.62      jdolecek  374:                error = EINPROGRESS;
                    375:                goto out;
1.1       cgd       376:        }
1.136     ad        377:        while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
1.135     yamt      378:                error = sowait(so, true, 0);
1.137     dsl       379:                if (__predict_false((so->so_state & SS_ISABORTING) != 0)) {
1.136     ad        380:                        error = EPIPE;
                    381:                        interrupted = 1;
                    382:                        break;
                    383:                }
1.87      ragge     384:                if (error) {
                    385:                        if (error == EINTR || error == ERESTART)
                    386:                                interrupted = 1;
1.1       cgd       387:                        break;
1.87      ragge     388:                }
1.18      christos  389:        }
1.1       cgd       390:        if (error == 0) {
                    391:                error = so->so_error;
                    392:                so->so_error = 0;
                    393:        }
1.57      lukem     394:  bad:
1.87      ragge     395:        if (!interrupted)
                    396:                so->so_state &= ~SS_ISCONNECTING;
1.1       cgd       397:        if (error == ERESTART)
                    398:                error = EINTR;
1.62      jdolecek  399:  out:
1.129     ad        400:        sounlock(so);
1.128     ad        401:        fd_putfile(fd);
1.111     dsl       402:        m_freem(nam);
1.1       cgd       403:        return (error);
                    404: }
                    405:
1.148     christos  406: static int
                    407: makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type,
                    408:     int domain, int proto, struct socket *soo)
                    409: {
                    410:        int error;
                    411:        struct socket *so;
                    412:
                    413:        if ((error = socreate(domain, &so, type, proto, l, soo)) != 0)
                    414:                return error;
                    415:
                    416:        if ((error = fd_allocfile(fp, fd)) != 0) {
                    417:                soclose(so);
                    418:                return error;
                    419:        }
                    420:        fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
1.151     christos  421:        (*fp)->f_flag = FREAD|FWRITE|
                    422:            ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
                    423:            ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
1.148     christos  424:        (*fp)->f_type = DTYPE_SOCKET;
                    425:        (*fp)->f_ops = &socketops;
                    426:        (*fp)->f_data = so;
                    427:        return 0;
                    428: }
                    429:
1.7       mycroft   430: int
1.148     christos  431: sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap,
                    432:     register_t *retval)
1.15      thorpej   433: {
1.125     dsl       434:        /* {
1.57      lukem     435:                syscallarg(int)         domain;
                    436:                syscallarg(int)         type;
                    437:                syscallarg(int)         protocol;
                    438:                syscallarg(int *)       rsv;
1.125     dsl       439:        } */
1.128     ad        440:        file_t          *fp1, *fp2;
1.57      lukem     441:        struct socket   *so1, *so2;
                    442:        int             fd, error, sv[2];
1.128     ad        443:        proc_t          *p;
1.144     christos  444:        int             flags = SCARG(uap, type) & SOCK_FLAGS_MASK;
                    445:        int             type = SCARG(uap, type) & ~SOCK_FLAGS_MASK;
1.148     christos  446:        int             domain = SCARG(uap, domain);
                    447:        int             proto = SCARG(uap, protocol);
1.1       cgd       448:
1.128     ad        449:        p = curproc;
1.148     christos  450:
                    451:        error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL);
1.18      christos  452:        if (error)
1.148     christos  453:                return error;
                    454:        so1 = fp1->f_data;
                    455:        sv[0] = fd;
                    456:
                    457:        error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1);
1.18      christos  458:        if (error)
1.148     christos  459:                goto out;
                    460:        so2 = fp2->f_data;
1.1       cgd       461:        sv[1] = fd;
1.148     christos  462:
1.129     ad        463:        solock(so1);
                    464:        error = soconnect2(so1, so2);
1.148     christos  465:        if (error == 0 && type == SOCK_DGRAM) {
1.1       cgd       466:                /*
                    467:                 * Datagram socket connection is asymmetric.
                    468:                 */
1.129     ad        469:                error = soconnect2(so2, so1);
                    470:        }
                    471:        sounlock(so1);
1.148     christos  472:
1.129     ad        473:        if (error == 0)
1.148     christos  474:                error = copyout(sv, SCARG(uap, rsv), sizeof(sv));
1.129     ad        475:        if (error == 0) {
                    476:                fd_affix(p, fp2, sv[1]);
                    477:                fd_affix(p, fp1, sv[0]);
1.148     christos  478:                return 0;
1.1       cgd       479:        }
1.128     ad        480:        fd_abort(p, fp2, sv[1]);
1.148     christos  481:        (void)soclose(so2);
                    482: out:
1.128     ad        483:        fd_abort(p, fp1, sv[0]);
1.1       cgd       484:        (void)soclose(so1);
1.148     christos  485:        return error;
1.1       cgd       486: }
                    487:
1.7       mycroft   488: int
1.125     dsl       489: sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, register_t *retval)
1.15      thorpej   490: {
1.125     dsl       491:        /* {
1.57      lukem     492:                syscallarg(int)                         s;
                    493:                syscallarg(const void *)                buf;
                    494:                syscallarg(size_t)                      len;
                    495:                syscallarg(int)                         flags;
                    496:                syscallarg(const struct sockaddr *)     to;
                    497:                syscallarg(unsigned int)                tolen;
1.125     dsl       498:        } */
1.57      lukem     499:        struct msghdr   msg;
                    500:        struct iovec    aiov;
1.1       cgd       501:
1.91      christos  502:        msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */
1.9       cgd       503:        msg.msg_namelen = SCARG(uap, tolen);
1.1       cgd       504:        msg.msg_iov = &aiov;
                    505:        msg.msg_iovlen = 1;
1.121     christos  506:        msg.msg_control = NULL;
1.1       cgd       507:        msg.msg_flags = 0;
1.91      christos  508:        aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
1.9       cgd       509:        aiov.iov_len = SCARG(uap, len);
1.111     dsl       510:        return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1       cgd       511: }
                    512:
1.7       mycroft   513: int
1.125     dsl       514: sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retval)
1.15      thorpej   515: {
1.125     dsl       516:        /* {
1.57      lukem     517:                syscallarg(int)                         s;
                    518:                syscallarg(const struct msghdr *)       msg;
                    519:                syscallarg(int)                         flags;
1.125     dsl       520:        } */
1.57      lukem     521:        struct msghdr   msg;
                    522:        int             error;
1.1       cgd       523:
1.110     dsl       524:        error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
1.18      christos  525:        if (error)
1.1       cgd       526:                return (error);
1.111     dsl       527:
                    528:        msg.msg_flags = MSG_IOVUSRSPACE;
                    529:        return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1       cgd       530: }
                    531:
1.7       mycroft   532: int
1.111     dsl       533: do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
                    534:                register_t *retsize)
1.1       cgd       535: {
1.141     rmind     536:        struct iovec    aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
1.57      lukem     537:        struct mbuf     *to, *control;
                    538:        struct socket   *so;
1.151     christos  539:        file_t          *fp;
1.141     rmind     540:        struct uio      auio;
                    541:        size_t          len, iovsz;
                    542:        int             i, error;
1.90      perry     543:
1.117     dsl       544:        ktrkuser("msghdr", mp, sizeof *mp);
                    545:
1.141     rmind     546:        /* If the caller passed us stuff in mbufs, we must free them. */
                    547:        to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL;
                    548:        control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL;
                    549:        iovsz = mp->msg_iovlen * sizeof(struct iovec);
1.111     dsl       550:
                    551:        if (mp->msg_flags & MSG_IOVUSRSPACE) {
                    552:                if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
                    553:                        if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
                    554:                                error = EMSGSIZE;
                    555:                                goto bad;
                    556:                        }
1.141     rmind     557:                        iov = kmem_alloc(iovsz, KM_SLEEP);
1.111     dsl       558:                }
                    559:                if (mp->msg_iovlen != 0) {
1.141     rmind     560:                        error = copyin(mp->msg_iov, iov, iovsz);
1.111     dsl       561:                        if (error)
                    562:                                goto bad;
                    563:                }
                    564:                mp->msg_iov = iov;
                    565:        }
                    566:
1.1       cgd       567:        auio.uio_iov = mp->msg_iov;
                    568:        auio.uio_iovcnt = mp->msg_iovlen;
                    569:        auio.uio_rw = UIO_WRITE;
                    570:        auio.uio_offset = 0;                    /* XXX */
                    571:        auio.uio_resid = 0;
1.97      yamt      572:        KASSERT(l == curlwp);
                    573:        auio.uio_vmspace = l->l_proc->p_vmspace;
1.111     dsl       574:
                    575:        for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) {
1.33      thorpej   576:                /*
                    577:                 * Writes return ssize_t because -1 is returned on error.
                    578:                 * Therefore, we must restrict the length to SSIZE_MAX to
                    579:                 * avoid garbage return values.
                    580:                 */
1.111     dsl       581:                auio.uio_resid += tiov->iov_len;
                    582:                if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
1.43      thorpej   583:                        error = EINVAL;
1.111     dsl       584:                        goto bad;
1.43      thorpej   585:                }
1.1       cgd       586:        }
1.111     dsl       587:
1.112     enami     588:        if (mp->msg_name && to == NULL) {
1.63      jdolecek  589:                error = sockargs(&to, mp->msg_name, mp->msg_namelen,
1.112     enami     590:                    MT_SONAME);
1.63      jdolecek  591:                if (error)
1.111     dsl       592:                        goto bad;
                    593:        }
                    594:
1.1       cgd       595:        if (mp->msg_control) {
1.104     elad      596:                if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
1.1       cgd       597:                        error = EINVAL;
                    598:                        goto bad;
                    599:                }
1.112     enami     600:                if (control == NULL) {
1.111     dsl       601:                        error = sockargs(&control, mp->msg_control,
1.112     enami     602:                            mp->msg_controllen, MT_CONTROL);
1.111     dsl       603:                        if (error)
                    604:                                goto bad;
                    605:                }
                    606:        }
                    607:
1.154.2.1! riz       608:        if (ktrpoint(KTR_GENIO) && iovsz > 0) {
1.141     rmind     609:                ktriov = kmem_alloc(iovsz, KM_SLEEP);
                    610:                memcpy(ktriov, auio.uio_iov, iovsz);
1.1       cgd       611:        }
1.111     dsl       612:
1.151     christos  613:        if ((error = fd_getsock1(s, &so, &fp)) != 0)
1.111     dsl       614:                goto bad;
                    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.128     ad        626:        fd_putfile(s);
1.111     dsl       627:
1.18      christos  628:        if (error) {
1.1       cgd       629:                if (auio.uio_resid != len && (error == ERESTART ||
                    630:                    error == EINTR || error == EWOULDBLOCK))
                    631:                        error = 0;
1.151     christos  632:                if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 &&
                    633:                    (flags & MSG_NOSIGNAL) == 0) {
1.130     ad        634:                        mutex_enter(proc_lock);
1.111     dsl       635:                        psignal(l->l_proc, SIGPIPE);
1.130     ad        636:                        mutex_exit(proc_lock);
1.106     ad        637:                }
1.1       cgd       638:        }
                    639:        if (error == 0)
                    640:                *retsize = len - auio.uio_resid;
1.111     dsl       641:
1.119     rmind     642: bad:
1.154.2.1! riz       643:        if (ktrpoint(KTR_GENIO)) {
1.116     ad        644:                ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error);
1.154.2.1! riz       645:                if (ktriov != NULL)
        !           646:                        kmem_free(ktriov, iovsz);
1.1       cgd       647:        }
1.111     dsl       648:
1.119     rmind     649:        if (iov != aiov)
1.141     rmind     650:                kmem_free(iov, iovsz);
1.1       cgd       651:        if (to)
                    652:                m_freem(to);
1.121     christos  653:        if (control)
1.111     dsl       654:                m_freem(control);
                    655:
1.1       cgd       656:        return (error);
                    657: }
                    658:
1.7       mycroft   659: int
1.125     dsl       660: sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval)
1.15      thorpej   661: {
1.125     dsl       662:        /* {
1.57      lukem     663:                syscallarg(int)                 s;
                    664:                syscallarg(void *)              buf;
                    665:                syscallarg(size_t)              len;
                    666:                syscallarg(int)                 flags;
                    667:                syscallarg(struct sockaddr *)   from;
                    668:                syscallarg(unsigned int *)      fromlenaddr;
1.125     dsl       669:        } */
1.57      lukem     670:        struct msghdr   msg;
                    671:        struct iovec    aiov;
                    672:        int             error;
1.113     dsl       673:        struct mbuf     *from;
1.1       cgd       674:
1.121     christos  675:        msg.msg_name = NULL;
1.1       cgd       676:        msg.msg_iov = &aiov;
                    677:        msg.msg_iovlen = 1;
1.9       cgd       678:        aiov.iov_base = SCARG(uap, buf);
                    679:        aiov.iov_len = SCARG(uap, len);
1.113     dsl       680:        msg.msg_control = NULL;
                    681:        msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
                    682:
                    683:        error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
                    684:        if (error != 0)
                    685:                return error;
                    686:
                    687:        error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr),
                    688:            MSG_LENUSRSPACE, from);
                    689:        if (from != NULL)
                    690:                m_free(from);
                    691:        return error;
1.1       cgd       692: }
                    693:
1.7       mycroft   694: int
1.125     dsl       695: sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retval)
1.15      thorpej   696: {
1.125     dsl       697:        /* {
1.57      lukem     698:                syscallarg(int)                 s;
                    699:                syscallarg(struct msghdr *)     msg;
                    700:                syscallarg(int)                 flags;
1.125     dsl       701:        } */
1.81      fvdl      702:        struct msghdr   msg;
1.57      lukem     703:        int             error;
1.113     dsl       704:        struct mbuf     *from, *control;
1.1       cgd       705:
1.110     dsl       706:        error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
1.18      christos  707:        if (error)
1.1       cgd       708:                return (error);
1.113     dsl       709:
                    710:        msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
                    711:
                    712:        error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
                    713:            msg.msg_control != NULL ? &control : NULL, retval);
                    714:        if (error != 0)
                    715:                return error;
                    716:
                    717:        if (msg.msg_control != NULL)
                    718:                error = copyout_msg_control(l, &msg, control);
                    719:
                    720:        if (error == 0)
                    721:                error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
                    722:                        from);
                    723:        if (from != NULL)
                    724:                m_free(from);
1.117     dsl       725:        if (error == 0) {
                    726:                ktrkuser("msghdr", &msg, sizeof msg);
1.110     dsl       727:                error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
1.117     dsl       728:        }
1.113     dsl       729:
1.1       cgd       730:        return (error);
                    731: }
                    732:
1.92      martin    733: /*
1.113     dsl       734:  * Adjust for a truncated SCM_RIGHTS control message.
                    735:  *  This means closing any file descriptors that aren't present
                    736:  *  in the returned buffer.
                    737:  *  m is the mbuf holding the (already externalized) SCM_RIGHTS message.
1.92      martin    738:  */
1.93      martin    739: static void
1.128     ad        740: free_rights(struct mbuf *m)
1.92      martin    741: {
                    742:        int nfd;
                    743:        int i;
                    744:        int *fdv;
                    745:
1.94      martin    746:        nfd = m->m_len < CMSG_SPACE(sizeof(int)) ? 0
                    747:            : (m->m_len - CMSG_SPACE(sizeof(int))) / sizeof(int) + 1;
1.92      martin    748:        fdv = (int *) CMSG_DATA(mtod(m,struct cmsghdr *));
1.128     ad        749:        for (i = 0; i < nfd; i++) {
                    750:                if (fd_getfile(fdv[i]) != NULL)
                    751:                        (void)fd_close(fdv[i]);
                    752:        }
1.113     dsl       753: }
                    754:
                    755: void
                    756: free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied)
                    757: {
                    758:        struct mbuf *next;
1.114     dsl       759:        struct cmsghdr *cmsg;
1.113     dsl       760:        bool do_free_rights = false;
                    761:
                    762:        while (control != NULL) {
1.114     dsl       763:                cmsg = mtod(control, struct cmsghdr *);
1.113     dsl       764:                if (control == uncopied)
                    765:                        do_free_rights = true;
1.114     dsl       766:                if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET
                    767:                    && cmsg->cmsg_type == SCM_RIGHTS)
1.128     ad        768:                        free_rights(control);
1.113     dsl       769:                next = control->m_next;
                    770:                m_free(control);
                    771:                control = next;
                    772:        }
                    773: }
                    774:
                    775: /* Copy socket control/CMSG data to user buffer, frees the mbuf */
                    776: int
                    777: copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
                    778: {
                    779:        int i, len, error = 0;
1.114     dsl       780:        struct cmsghdr *cmsg;
1.113     dsl       781:        struct mbuf *m;
                    782:        char *q;
                    783:
                    784:        len = mp->msg_controllen;
                    785:        if (len <= 0 || control == 0) {
                    786:                mp->msg_controllen = 0;
                    787:                free_control_mbuf(l, control, control);
                    788:                return 0;
                    789:        }
                    790:
                    791:        q = (char *)mp->msg_control;
                    792:
                    793:        for (m = control; m != NULL; ) {
1.114     dsl       794:                cmsg = mtod(m, struct cmsghdr *);
1.113     dsl       795:                i = m->m_len;
                    796:                if (len < i) {
                    797:                        mp->msg_flags |= MSG_CTRUNC;
1.114     dsl       798:                        if (cmsg->cmsg_level == SOL_SOCKET
                    799:                            && cmsg->cmsg_type == SCM_RIGHTS)
1.113     dsl       800:                                /* Do not truncate me ... */
                    801:                                break;
                    802:                        i = len;
                    803:                }
                    804:                error = copyout(mtod(m, void *), q, i);
1.117     dsl       805:                ktrkuser("msgcontrol", mtod(m, void *), i);
1.113     dsl       806:                if (error != 0) {
                    807:                        /* We must free all the SCM_RIGHTS */
                    808:                        m = control;
                    809:                        break;
                    810:                }
                    811:                m = m->m_next;
                    812:                if (m)
                    813:                        i = ALIGN(i);
                    814:                q += i;
                    815:                len -= i;
                    816:                if (len <= 0)
                    817:                        break;
                    818:        }
                    819:
                    820:        free_control_mbuf(l, control, m);
                    821:
                    822:        mp->msg_controllen = q - (char *)mp->msg_control;
                    823:        return error;
1.92      martin    824: }
                    825:
1.7       mycroft   826: int
1.113     dsl       827: do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
                    828:     struct mbuf **control, register_t *retsize)
1.1       cgd       829: {
1.154.2.1! riz       830:        struct iovec    aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
1.141     rmind     831:        struct socket   *so;
1.57      lukem     832:        struct uio      auio;
1.141     rmind     833:        size_t          len, iovsz;
                    834:        int             i, error;
1.57      lukem     835:
1.117     dsl       836:        ktrkuser("msghdr", mp, sizeof *mp);
                    837:
1.113     dsl       838:        *from = NULL;
                    839:        if (control != NULL)
                    840:                *control = NULL;
1.90      perry     841:
1.128     ad        842:        if ((error = fd_getsock(s, &so)) != 0)
1.1       cgd       843:                return (error);
1.113     dsl       844:
1.141     rmind     845:        iovsz = mp->msg_iovlen * sizeof(struct iovec);
                    846:
1.113     dsl       847:        if (mp->msg_flags & MSG_IOVUSRSPACE) {
                    848:                if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
                    849:                        if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
                    850:                                error = EMSGSIZE;
                    851:                                goto out;
                    852:                        }
1.141     rmind     853:                        iov = kmem_alloc(iovsz, KM_SLEEP);
1.113     dsl       854:                }
                    855:                if (mp->msg_iovlen != 0) {
1.141     rmind     856:                        error = copyin(mp->msg_iov, iov, iovsz);
1.113     dsl       857:                        if (error)
                    858:                                goto out;
                    859:                }
                    860:                auio.uio_iov = iov;
                    861:        } else
                    862:                auio.uio_iov = mp->msg_iov;
1.1       cgd       863:        auio.uio_iovcnt = mp->msg_iovlen;
                    864:        auio.uio_rw = UIO_READ;
                    865:        auio.uio_offset = 0;                    /* XXX */
                    866:        auio.uio_resid = 0;
1.97      yamt      867:        KASSERT(l == curlwp);
                    868:        auio.uio_vmspace = l->l_proc->p_vmspace;
1.113     dsl       869:
                    870:        tiov = auio.uio_iov;
                    871:        for (i = 0; i < mp->msg_iovlen; i++, tiov++) {
1.33      thorpej   872:                /*
                    873:                 * Reads return ssize_t because -1 is returned on error.
                    874:                 * Therefore we must restrict the length to SSIZE_MAX to
                    875:                 * avoid garbage return values.
                    876:                 */
1.113     dsl       877:                auio.uio_resid += tiov->iov_len;
                    878:                if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
1.43      thorpej   879:                        error = EINVAL;
1.113     dsl       880:                        goto out;
1.43      thorpej   881:                }
1.1       cgd       882:        }
                    883:
1.154.2.1! riz       884:        if (ktrpoint(KTR_GENIO) && iovsz > 0) {
1.141     rmind     885:                ktriov = kmem_alloc(iovsz, KM_SLEEP);
                    886:                memcpy(ktriov, auio.uio_iov, iovsz);
1.1       cgd       887:        }
1.113     dsl       888:
1.1       cgd       889:        len = auio.uio_resid;
1.115     dsl       890:        mp->msg_flags &= MSG_USERFLAGS;
1.113     dsl       891:        error = (*so->so_receive)(so, from, &auio, NULL, control,
1.129     ad        892:            &mp->msg_flags);
1.113     dsl       893:        len -= auio.uio_resid;
                    894:        *retsize = len;
                    895:        if (error != 0 && len != 0
                    896:            && (error == ERESTART || error == EINTR || error == EWOULDBLOCK))
                    897:                /* Some data transferred */
                    898:                error = 0;
1.116     ad        899:
1.154.2.1! riz       900:        if (ktrpoint(KTR_GENIO)) {
1.116     ad        901:                ktrgeniov(s, UIO_READ, ktriov, len, error);
1.154.2.1! riz       902:                if (ktriov != NULL)
        !           903:                        kmem_free(ktriov, iovsz);
1.1       cgd       904:        }
1.116     ad        905:
1.113     dsl       906:        if (error != 0) {
                    907:                m_freem(*from);
                    908:                *from = NULL;
                    909:                if (control != NULL) {
                    910:                        free_control_mbuf(l, *control, *control);
                    911:                        *control = NULL;
1.1       cgd       912:                }
                    913:        }
1.43      thorpej   914:  out:
1.113     dsl       915:        if (iov != aiov)
1.141     rmind     916:                kmem_free(iov, iovsz);
1.128     ad        917:        fd_putfile(s);
1.1       cgd       918:        return (error);
                    919: }
                    920:
1.113     dsl       921:
1.1       cgd       922: /* ARGSUSED */
1.7       mycroft   923: int
1.125     dsl       924: sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)
1.15      thorpej   925: {
1.125     dsl       926:        /* {
1.57      lukem     927:                syscallarg(int) s;
                    928:                syscallarg(int) how;
1.125     dsl       929:        } */
1.128     ad        930:        struct socket   *so;
1.57      lukem     931:        int             error;
1.1       cgd       932:
1.128     ad        933:        if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1       cgd       934:                return (error);
1.129     ad        935:        solock(so);
1.128     ad        936:        error = soshutdown(so, SCARG(uap, how));
1.129     ad        937:        sounlock(so);
1.128     ad        938:        fd_putfile(SCARG(uap, s));
1.43      thorpej   939:        return (error);
1.1       cgd       940: }
                    941:
                    942: /* ARGSUSED */
1.7       mycroft   943: int
1.125     dsl       944: sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval)
1.15      thorpej   945: {
1.125     dsl       946:        /* {
1.57      lukem     947:                syscallarg(int)                 s;
                    948:                syscallarg(int)                 level;
                    949:                syscallarg(int)                 name;
                    950:                syscallarg(const void *)        val;
                    951:                syscallarg(unsigned int)        valsize;
1.125     dsl       952:        } */
1.134     plunky    953:        struct sockopt  sopt;
1.76      matt      954:        struct socket   *so;
1.151     christos  955:        file_t          *fp;
1.57      lukem     956:        int             error;
1.75      thorpej   957:        unsigned int    len;
1.1       cgd       958:
1.134     plunky    959:        len = SCARG(uap, valsize);
                    960:        if (len > 0 && SCARG(uap, val) == NULL)
                    961:                return (EINVAL);
                    962:
                    963:        if (len > MCLBYTES)
                    964:                return (EINVAL);
                    965:
1.151     christos  966:        if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1.1       cgd       967:                return (error);
1.134     plunky    968:
                    969:        sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
                    970:
                    971:        if (len > 0) {
                    972:                error = copyin(SCARG(uap, val), sopt.sopt_data, len);
                    973:                if (error)
1.43      thorpej   974:                        goto out;
1.1       cgd       975:        }
1.134     plunky    976:
                    977:        error = sosetopt(so, &sopt);
1.151     christos  978:        if (so->so_options & SO_NOSIGPIPE)
1.152     christos  979:                atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
1.151     christos  980:        else
1.152     christos  981:                atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);
1.134     plunky    982:
1.43      thorpej   983:  out:
1.134     plunky    984:        sockopt_destroy(&sopt);
1.128     ad        985:        fd_putfile(SCARG(uap, s));
1.43      thorpej   986:        return (error);
1.1       cgd       987: }
                    988:
                    989: /* ARGSUSED */
1.7       mycroft   990: int
1.125     dsl       991: sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval)
1.15      thorpej   992: {
1.125     dsl       993:        /* {
1.57      lukem     994:                syscallarg(int)                 s;
                    995:                syscallarg(int)                 level;
                    996:                syscallarg(int)                 name;
                    997:                syscallarg(void *)              val;
                    998:                syscallarg(unsigned int *)      avalsize;
1.125     dsl       999:        } */
1.134     plunky   1000:        struct sockopt  sopt;
1.128     ad       1001:        struct socket   *so;
1.151     christos 1002:        file_t          *fp;
1.134     plunky   1003:        unsigned int    valsize, len;
1.57      lukem    1004:        int             error;
1.1       cgd      1005:
1.134     plunky   1006:        if (SCARG(uap, val) != NULL) {
                   1007:                error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
                   1008:                if (error)
                   1009:                        return (error);
                   1010:        } else
                   1011:                valsize = 0;
                   1012:
1.151     christos 1013:        if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1.1       cgd      1014:                return (error);
1.134     plunky   1015:
                   1016:        sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
                   1017:
1.151     christos 1018:        if (fp->f_flag & FNOSIGPIPE)
1.154     christos 1019:                so->so_options |= SO_NOSIGPIPE;
1.151     christos 1020:        else
1.154     christos 1021:                so->so_options &= ~SO_NOSIGPIPE;
1.134     plunky   1022:        error = sogetopt(so, &sopt);
                   1023:        if (error)
                   1024:                goto out;
                   1025:
                   1026:        if (valsize > 0) {
                   1027:                len = min(valsize, sopt.sopt_size);
                   1028:                error = copyout(sopt.sopt_data, SCARG(uap, val), len);
                   1029:                if (error)
                   1030:                        goto out;
                   1031:
                   1032:                error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
1.18      christos 1033:                if (error)
1.43      thorpej  1034:                        goto out;
1.1       cgd      1035:        }
1.134     plunky   1036:
1.43      thorpej  1037:  out:
1.134     plunky   1038:        sockopt_destroy(&sopt);
1.128     ad       1039:        fd_putfile(SCARG(uap, s));
1.1       cgd      1040:        return (error);
                   1041: }
                   1042:
1.68      jdolecek 1043: #ifdef PIPE_SOCKETPAIR
1.1       cgd      1044: /* ARGSUSED */
1.7       mycroft  1045: int
1.142     christos 1046: pipe1(struct lwp *l, register_t *retval, int flags)
1.1       cgd      1047: {
1.128     ad       1048:        file_t          *rf, *wf;
1.57      lukem    1049:        struct socket   *rso, *wso;
                   1050:        int             fd, error;
1.128     ad       1051:        proc_t          *p;
1.1       cgd      1052:
1.151     christos 1053:        if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
1.145     christos 1054:                return EINVAL;
1.128     ad       1055:        p = curproc;
1.129     ad       1056:        if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
1.1       cgd      1057:                return (error);
1.129     ad       1058:        if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
1.1       cgd      1059:                goto free1;
1.58      manu     1060:        /* remember this socket pair implements a pipe */
                   1061:        wso->so_state |= SS_ISAPIPE;
                   1062:        rso->so_state |= SS_ISAPIPE;
1.128     ad       1063:        if ((error = fd_allocfile(&rf, &fd)) != 0)
1.1       cgd      1064:                goto free2;
                   1065:        retval[0] = fd;
1.142     christos 1066:        rf->f_flag = FREAD | flags;
1.1       cgd      1067:        rf->f_type = DTYPE_SOCKET;
                   1068:        rf->f_ops = &socketops;
1.110     dsl      1069:        rf->f_data = rso;
1.128     ad       1070:        if ((error = fd_allocfile(&wf, &fd)) != 0)
1.1       cgd      1071:                goto free3;
1.142     christos 1072:        wf->f_flag = FWRITE | flags;
1.1       cgd      1073:        wf->f_type = DTYPE_SOCKET;
                   1074:        wf->f_ops = &socketops;
1.110     dsl      1075:        wf->f_data = wso;
1.1       cgd      1076:        retval[1] = fd;
1.129     ad       1077:        solock(wso);
                   1078:        error = unp_connect2(wso, rso, PRU_CONNECT2);
                   1079:        sounlock(wso);
                   1080:        if (error != 0)
1.1       cgd      1081:                goto free4;
1.128     ad       1082:        fd_affix(p, wf, (int)retval[1]);
                   1083:        fd_affix(p, rf, (int)retval[0]);
1.1       cgd      1084:        return (0);
1.57      lukem    1085:  free4:
1.128     ad       1086:        fd_abort(p, wf, (int)retval[1]);
1.57      lukem    1087:  free3:
1.128     ad       1088:        fd_abort(p, rf, (int)retval[0]);
1.57      lukem    1089:  free2:
1.1       cgd      1090:        (void)soclose(wso);
1.57      lukem    1091:  free1:
1.1       cgd      1092:        (void)soclose(rso);
                   1093:        return (error);
                   1094: }
1.68      jdolecek 1095: #endif /* PIPE_SOCKETPAIR */
1.1       cgd      1096:
                   1097: /*
                   1098:  * Get socket name.
                   1099:  */
1.13      christos 1100: /* ARGSUSED */
1.7       mycroft  1101: int
1.113     dsl      1102: do_sys_getsockname(struct lwp *l, int fd, int which, struct mbuf **nam)
1.15      thorpej  1103: {
1.57      lukem    1104:        struct socket   *so;
                   1105:        struct mbuf     *m;
                   1106:        int             error;
1.1       cgd      1107:
1.128     ad       1108:        if ((error = fd_getsock(fd, &so)) != 0)
1.113     dsl      1109:                return error;
                   1110:
1.129     ad       1111:        m = m_getclr(M_WAIT, MT_SONAME);
                   1112:        MCLAIM(m, so->so_mowner);
                   1113:
                   1114:        solock(so);
1.113     dsl      1115:        if (which == PRU_PEERADDR
                   1116:            && (so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) {
                   1117:                error = ENOTCONN;
1.129     ad       1118:        } else {
                   1119:                *nam = m;
                   1120:                error = (*so->so_proto->pr_usrreq)(so, which, NULL, m, NULL,
                   1121:                    NULL);
1.113     dsl      1122:        }
1.129     ad       1123:        sounlock(so);
1.113     dsl      1124:        if (error != 0)
                   1125:                m_free(m);
1.128     ad       1126:        fd_putfile(fd);
1.113     dsl      1127:        return error;
                   1128: }
                   1129:
                   1130: int
                   1131: copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags,
                   1132:     struct mbuf *addr)
                   1133: {
                   1134:        int len;
                   1135:        int error;
                   1136:
                   1137:        if (asa == NULL)
                   1138:                /* Assume application not interested */
                   1139:                return 0;
                   1140:
                   1141:        if (flags & MSG_LENUSRSPACE) {
                   1142:                error = copyin(alen, &len, sizeof(len));
                   1143:                if (error)
                   1144:                        return error;
                   1145:        } else
                   1146:                len = *alen;
1.118     dsl      1147:        if (len < 0)
1.113     dsl      1148:                return EINVAL;
                   1149:
                   1150:        if (addr == NULL) {
                   1151:                len = 0;
                   1152:                error = 0;
                   1153:        } else {
                   1154:                if (len > addr->m_len)
                   1155:                        len = addr->m_len;
                   1156:                /* Maybe this ought to copy a chain ? */
1.117     dsl      1157:                ktrkuser("sockname", mtod(addr, void *), len);
1.113     dsl      1158:                error = copyout(mtod(addr, void *), asa, len);
                   1159:        }
                   1160:
                   1161:        if (error == 0) {
                   1162:                if (flags & MSG_LENUSRSPACE)
                   1163:                        error = copyout(&len, alen, sizeof(len));
                   1164:                else
                   1165:                        *alen = len;
                   1166:        }
                   1167:
                   1168:        return error;
                   1169: }
                   1170:
                   1171: /*
                   1172:  * Get socket name.
                   1173:  */
                   1174: /* ARGSUSED */
                   1175: int
1.125     dsl      1176: sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, register_t *retval)
1.113     dsl      1177: {
1.125     dsl      1178:        /* {
1.113     dsl      1179:                syscallarg(int)                 fdes;
                   1180:                syscallarg(struct sockaddr *)   asa;
                   1181:                syscallarg(unsigned int *)      alen;
1.125     dsl      1182:        } */
1.113     dsl      1183:        struct mbuf     *m;
                   1184:        int             error;
                   1185:
                   1186:        error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m);
                   1187:        if (error != 0)
                   1188:                return error;
                   1189:
                   1190:        error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
                   1191:            MSG_LENUSRSPACE, m);
                   1192:        if (m != NULL)
                   1193:                m_free(m);
                   1194:        return error;
1.1       cgd      1195: }
                   1196:
                   1197: /*
                   1198:  * Get name of peer for connected socket.
                   1199:  */
1.13      christos 1200: /* ARGSUSED */
1.7       mycroft  1201: int
1.125     dsl      1202: sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, register_t *retval)
1.15      thorpej  1203: {
1.125     dsl      1204:        /* {
1.57      lukem    1205:                syscallarg(int)                 fdes;
                   1206:                syscallarg(struct sockaddr *)   asa;
                   1207:                syscallarg(unsigned int *)      alen;
1.125     dsl      1208:        } */
1.57      lukem    1209:        struct mbuf     *m;
                   1210:        int             error;
1.1       cgd      1211:
1.113     dsl      1212:        error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m);
                   1213:        if (error != 0)
                   1214:                return error;
                   1215:
                   1216:        error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
                   1217:            MSG_LENUSRSPACE, m);
                   1218:        if (m != NULL)
                   1219:                m_free(m);
                   1220:        return error;
1.1       cgd      1221: }
                   1222:
1.24      thorpej  1223: /*
                   1224:  * XXX In a perfect world, we wouldn't pass around socket control
                   1225:  * XXX arguments in mbufs, and this could go away.
                   1226:  */
1.7       mycroft  1227: int
1.91      christos 1228: sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type)
1.1       cgd      1229: {
1.57      lukem    1230:        struct sockaddr *sa;
                   1231:        struct mbuf     *m;
                   1232:        int             error;
1.1       cgd      1233:
1.24      thorpej  1234:        /*
1.25      thorpej  1235:         * We can't allow socket names > UCHAR_MAX in length, since that
1.64      matt     1236:         * will overflow sa_len.  Control data more than a page size in
                   1237:         * length is just too much.
1.24      thorpej  1238:         */
1.64      matt     1239:        if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1.24      thorpej  1240:                return (EINVAL);
                   1241:
                   1242:        /* Allocate an mbuf to hold the arguments. */
                   1243:        m = m_get(M_WAIT, type);
1.76      matt     1244:        /* can't claim.  don't who to assign it to. */
1.64      matt     1245:        if (buflen > MLEN) {
1.24      thorpej  1246:                /*
                   1247:                 * Won't fit into a regular mbuf, so we allocate just
                   1248:                 * enough external storage to hold the argument.
                   1249:                 */
                   1250:                MEXTMALLOC(m, buflen, M_WAITOK);
1.1       cgd      1251:        }
                   1252:        m->m_len = buflen;
1.107     christos 1253:        error = copyin(bf, mtod(m, void *), buflen);
1.1       cgd      1254:        if (error) {
                   1255:                (void) m_free(m);
1.7       mycroft  1256:                return (error);
1.1       cgd      1257:        }
1.147     christos 1258:        ktrkuser(mbuftypes[type], mtod(m, void *), buflen);
1.1       cgd      1259:        *mp = m;
                   1260:        if (type == MT_SONAME) {
1.7       mycroft  1261:                sa = mtod(m, struct sockaddr *);
1.65      jdolecek 1262: #if BYTE_ORDER != BIG_ENDIAN
                   1263:                /*
                   1264:                 * 4.3BSD compat thing - need to stay, since bind(2),
                   1265:                 * connect(2), sendto(2) were not versioned for COMPAT_43.
                   1266:                 */
1.1       cgd      1267:                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                   1268:                        sa->sa_family = sa->sa_len;
                   1269: #endif
                   1270:                sa->sa_len = buflen;
                   1271:        }
                   1272:        return (0);
                   1273: }

CVSweb <webmaster@jp.NetBSD.org>