[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.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>