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

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

CVSweb <webmaster@jp.NetBSD.org>