[BACK]Return to linux_socket.c CVS log [TXT][DIR] Up to [local] / sys / compat / linux

Annotation of sys/compat/linux/linux_socket.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: linux_socket.c,v 1.36 2007/06/06 09:59:21 henning Exp $       */
        !             2: /*     $NetBSD: linux_socket.c,v 1.14 1996/04/05 00:01:50 christos Exp $       */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Frank van der Linden
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *      This product includes software developed for the NetBSD Project
        !            19:  *      by Frank van der Linden
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  */
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/kernel.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/buf.h>
        !            39: #include <sys/malloc.h>
        !            40: #include <sys/ioctl.h>
        !            41: #include <sys/tty.h>
        !            42: #include <sys/file.h>
        !            43: #include <sys/filedesc.h>
        !            44: #include <sys/selinfo.h>
        !            45: #include <sys/socket.h>
        !            46: #include <sys/socketvar.h>
        !            47: #include <net/if.h>
        !            48: #include <net/if_types.h>
        !            49: #include <net/if_dl.h>
        !            50: #include <netinet/in.h>
        !            51: #include <netinet/in_systm.h>
        !            52: #include <netinet/ip.h>
        !            53: #include <netinet/tcp.h>
        !            54: #include <sys/mount.h>
        !            55: #include <sys/proc.h>
        !            56: #include <sys/vnode.h>
        !            57: #include <sys/device.h>
        !            58:
        !            59: #include <sys/syscallargs.h>
        !            60:
        !            61: #include <compat/linux/linux_types.h>
        !            62: #include <compat/linux/linux_util.h>
        !            63: #include <compat/linux/linux_signal.h>
        !            64: #include <compat/linux/linux_syscallargs.h>
        !            65: #include <compat/linux/linux_ioctl.h>
        !            66: #include <compat/linux/linux_socket.h>
        !            67: #include <compat/linux/linux_socketcall.h>
        !            68: #include <compat/linux/linux_sockio.h>
        !            69:
        !            70: /*
        !            71:  * All the calls in this file are entered via one common system
        !            72:  * call in Linux, represented here by linux_socketcall()
        !            73:  * Arguments for the various calls are on the user stack. A pointer
        !            74:  * to them is the only thing that is passed. It is up to the various
        !            75:  * calls to copy them in themselves. To make it look better, they
        !            76:  * are copied to structures.
        !            77:  */
        !            78:
        !            79: static int linux_to_bsd_domain (int);
        !            80: static int bsd_to_linux_domain(int);
        !            81:
        !            82: int linux_socket(struct proc *, void *, register_t *);
        !            83: int linux_bind(struct proc *, void *, register_t *);
        !            84: int linux_connect(struct proc *, void *, register_t *);
        !            85: int linux_listen(struct proc *, void *, register_t *);
        !            86: int linux_accept(struct proc *, void *, register_t *);
        !            87: int linux_getsockname(struct proc *, void *, register_t *);
        !            88: int linux_getpeername(struct proc *, void *, register_t *);
        !            89: int linux_socketpair(struct proc *, void *, register_t *);
        !            90: int linux_send(struct proc *, void *, register_t *);
        !            91: int linux_recv(struct proc *, void *, register_t *);
        !            92: int linux_sendto(struct proc *, void *, register_t *);
        !            93: int linux_recvfrom(struct proc *, void *, register_t *);
        !            94: int linux_shutdown(struct proc *, void *, register_t *);
        !            95: int linux_to_bsd_sopt_level(int);
        !            96: int linux_to_bsd_so_sockopt(int);
        !            97: int linux_to_bsd_ip_sockopt(int);
        !            98: int linux_to_bsd_tcp_sockopt(int);
        !            99: int linux_to_bsd_udp_sockopt(int);
        !           100: int linux_setsockopt(struct proc *, void *, register_t *);
        !           101: int linux_getsockopt(struct proc *, void *, register_t *);
        !           102: int linux_recvmsg(struct proc *, void *, register_t *);
        !           103: int linux_sendmsg(struct proc *, void *, register_t *);
        !           104:
        !           105: int linux_check_hdrincl(struct proc *, int, register_t *, caddr_t *);
        !           106: int linux_sendto_hdrincl(struct proc *, struct sys_sendto_args *,
        !           107:     register_t *, caddr_t *);
        !           108:
        !           109: int linux_sa_get(struct proc *, caddr_t *, struct sockaddr **,
        !           110:     const struct osockaddr *, int *);
        !           111: int linux_sa_put(struct osockaddr *);
        !           112:
        !           113: static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
        !           114:        AF_UNSPEC,
        !           115:        AF_UNIX,
        !           116:        AF_INET,
        !           117:        -1,             /* LINUX_AF_AX25 */
        !           118:        -1,             /* IPX */
        !           119:        AF_APPLETALK,
        !           120:        -1,             /* LINUX_AF_NETROM */
        !           121:        -1,             /* LINUX_AF_BRIDGE */
        !           122:        -1,             /* LINUX_AF_ATMPVC */
        !           123:        -1,             /* LINUX_AF_X25 */
        !           124:        AF_INET6,
        !           125:        -1,             /* LINUX_AF_ROSE */
        !           126:        AF_DECnet,
        !           127:        -1,             /* LINUX_AF_NETBEUI */
        !           128:        -1,             /* LINUX_AF_SECURITY */
        !           129:        -1,             /* pseudo_AF_KEY */
        !           130:        AF_ROUTE,       /* LINUX_AF_NETLINK */
        !           131:        -1,             /* LINUX_AF_PACKET */
        !           132:        -1,             /* LINUX_AF_ASH */
        !           133:        -1,             /* LINUX_AF_ECONET */
        !           134:        -1,             /* LINUX_AF_ATMSVC */
        !           135:        AF_SNA,
        !           136:        /* rest up to LINUX_AF_MAX-1 is not allocated */
        !           137:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !           138: };
        !           139:
        !           140: static const int bsd_to_linux_domain_[AF_MAX] = {
        !           141:        LINUX_AF_UNSPEC,
        !           142:        LINUX_AF_UNIX,
        !           143:        LINUX_AF_INET,
        !           144:        -1,             /* AF_IMPLINK */
        !           145:        -1,             /* AF_PUP */
        !           146:        -1,             /* AF_CHAOS */
        !           147:        -1,             /* AF_NS */
        !           148:        -1,             /* AF_ISO */
        !           149:        -1,             /* AF_ECMA */
        !           150:        -1,             /* AF_DATAKIT */
        !           151:        -1,             /* AF_CCITT */
        !           152:        -1,             /* LINUX_AF_SNA */
        !           153:        -1,             /* LINUX_AF_DECnet */
        !           154:        -1,             /* AF_DLI */
        !           155:        -1,             /* AF_LAT */
        !           156:        -1,             /* AF_HYLINK */
        !           157:        LINUX_AF_APPLETALK,
        !           158:        -1,             /* LINUX_AF_NETLINK */
        !           159:        -1,             /* AF_LINK */
        !           160:        -1,             /* AF_XTP */
        !           161:        -1,             /* AF_COIP */
        !           162:        -1,             /* AF_CNT */
        !           163:        -1,             /* pseudo_AF_RTIP */
        !           164:        LINUX_AF_IPX,
        !           165:        LINUX_AF_INET6,
        !           166:        -1,             /* pseudo_AF_PIP */
        !           167:        -1,             /* AF_ISDN */
        !           168:        -1,             /* AF_NATM */
        !           169:        -1,             /* AF_ARP */
        !           170:        -1,             /* LINUX_pseudo_AF_KEY */
        !           171:        -1,             /* pseudo_AF_HDRCMPLT */
        !           172: };
        !           173:
        !           174: /*
        !           175:  * Convert between Linux and BSD socket domain values
        !           176:  */
        !           177: static int
        !           178: linux_to_bsd_domain(ldom)
        !           179:        int ldom;
        !           180: {
        !           181:        if (ldom < 0 || ldom >= LINUX_AF_MAX)
        !           182:                return (-1);
        !           183:
        !           184:        return linux_to_bsd_domain_[ldom];
        !           185: }
        !           186:
        !           187: /*
        !           188:  * Convert between BSD and Linux socket domain values
        !           189:  */
        !           190: static int
        !           191: bsd_to_linux_domain(bdom)
        !           192:        int bdom;
        !           193: {
        !           194:        if (bdom < 0 || bdom >= AF_MAX)
        !           195:                return (-1);
        !           196:
        !           197:        return bsd_to_linux_domain_[bdom];
        !           198: }
        !           199:
        !           200: int
        !           201: linux_socket(p, v, retval)
        !           202:        struct proc *p;
        !           203:        void *v;
        !           204:        register_t *retval;
        !           205: {
        !           206:        struct linux_socket_args /* {
        !           207:                syscallarg(int) domain;
        !           208:                syscallarg(int) type;
        !           209:                syscallarg(int) protocol;
        !           210:        } */ *uap = v;
        !           211:        struct linux_socket_args lsa;
        !           212:        struct sys_socket_args bsa;
        !           213:        int error;
        !           214:
        !           215:        if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
        !           216:                return error;
        !           217:
        !           218:        SCARG(&bsa, protocol) = lsa.protocol;
        !           219:        SCARG(&bsa, type) = lsa.type;
        !           220:        SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
        !           221:        if (SCARG(&bsa, domain) == -1)
        !           222:                return EINVAL;
        !           223:        return sys_socket(p, &bsa, retval);
        !           224: }
        !           225:
        !           226: int
        !           227: linux_bind(p, v, retval)
        !           228:        struct proc *p;
        !           229:        void *v;
        !           230:        register_t *retval;
        !           231: {
        !           232:        struct linux_bind_args /* {
        !           233:                syscallarg(int) s;
        !           234:                syscallarg(struct sockaddr *) name;
        !           235:                syscallarg(int) namelen;
        !           236:        } */ *uap = v;
        !           237:        struct linux_bind_args lba;
        !           238:        struct sys_bind_args bba;
        !           239:        int error;
        !           240:        int namlen;
        !           241:
        !           242:        if ((error = copyin((caddr_t) uap, (caddr_t) &lba, sizeof lba)))
        !           243:                return error;
        !           244:
        !           245:        SCARG(&bba, s) = lba.s;
        !           246:        namlen = lba.namelen;
        !           247:        if (lba.name) {
        !           248:                struct sockaddr *sa;
        !           249:                caddr_t sg = stackgap_init(p->p_emul);
        !           250:
        !           251:                error = linux_sa_get(p, &sg, &sa, lba.name, &namlen);
        !           252:                if (error)
        !           253:                        return (error);
        !           254:                SCARG(&bba, name) = sa;
        !           255:        } else
        !           256:                SCARG(&bba, name) = NULL;
        !           257:        SCARG(&bba, namelen) = namlen;
        !           258:
        !           259:        return sys_bind(p, &bba, retval);
        !           260: }
        !           261:
        !           262: int
        !           263: linux_connect(p, v, retval)
        !           264:        struct proc *p;
        !           265:        void *v;
        !           266:        register_t *retval;
        !           267: {
        !           268:        struct linux_connect_args /* {
        !           269:                syscallarg(int) s;
        !           270:                syscallarg(struct osockaddr *) name;
        !           271:                syscallarg(int) namelen;
        !           272:        } */ *uap = v;
        !           273:        struct linux_connect_args lca;
        !           274:        struct sys_connect_args bca;
        !           275:        struct sockaddr *sa;
        !           276:        caddr_t sg = stackgap_init(p->p_emul);
        !           277:        int namlen;
        !           278:        int error;
        !           279:
        !           280:        if ((error = copyin((caddr_t) uap, (caddr_t) &lca, sizeof lca)))
        !           281:                return error;
        !           282:
        !           283:        namlen = lca.namelen;
        !           284:        error = linux_sa_get(p, &sg, &sa, lca.name, &namlen);
        !           285:        if (error)
        !           286:                return (error);
        !           287:
        !           288:        SCARG(&bca, s) = lca.s;
        !           289:        SCARG(&bca, name) = sa;
        !           290:        SCARG(&bca, namelen) = (unsigned int)namlen;
        !           291:
        !           292:        error = sys_connect(p, &bca, retval);
        !           293:
        !           294:        if (error == EISCONN) {
        !           295:                struct sys_getsockopt_args bga;
        !           296: #if 0
        !           297:                struct sys_fcntl_args fca;
        !           298: #endif
        !           299:                void *status, *statusl;
        !           300:                int stat, statl = sizeof stat;
        !           301:
        !           302: #if 0
        !           303:                SCARG(&fca, fd) = lca.s;
        !           304:                SCARG(&fca, cmd) = F_GETFL;
        !           305:                SCARG(&fca, arg) = 0;
        !           306:                if (sys_fcntl(p, &fca, retval) == -1 ||
        !           307:                    (*retval & O_NONBLOCK) == 0)
        !           308:                        return error;
        !           309: #endif
        !           310:
        !           311:                status = stackgap_alloc(&sg, sizeof stat);
        !           312:                statusl = stackgap_alloc(&sg, sizeof statusl);
        !           313:
        !           314:                if ((error = copyout(&statl, statusl, sizeof statl)))
        !           315:                        return error;
        !           316:
        !           317:                SCARG(&bga, s) = lca.s;
        !           318:                SCARG(&bga, level) = SOL_SOCKET;
        !           319:                SCARG(&bga, name) = SO_ERROR;
        !           320:                SCARG(&bga, val) = status;
        !           321:                SCARG(&bga, avalsize) = statusl;
        !           322:
        !           323:                error = sys_getsockopt(p, &bga, retval);
        !           324:                if (error)
        !           325:                        return error;
        !           326:                if ((error = copyin(status, &stat, sizeof stat)))
        !           327:                        return error;
        !           328:                return stat;
        !           329:        }
        !           330:        return error;
        !           331: }
        !           332:
        !           333: int
        !           334: linux_listen(p, v, retval)
        !           335:        struct proc *p;
        !           336:        void *v;
        !           337:        register_t *retval;
        !           338: {
        !           339:        struct linux_listen_args /* {
        !           340:                syscallarg(int) s;
        !           341:                syscallarg(int) backlog;
        !           342:        } */ *uap = v;
        !           343:        struct linux_listen_args lla;
        !           344:        struct sys_listen_args bla;
        !           345:        int error;
        !           346:
        !           347:        if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
        !           348:                return error;
        !           349:
        !           350:        SCARG(&bla, s) = lla.s;
        !           351:        SCARG(&bla, backlog) = lla.backlog;
        !           352:
        !           353:        return sys_listen(p, &bla, retval);
        !           354: }
        !           355:
        !           356: int
        !           357: linux_accept(p, v, retval)
        !           358:        struct proc *p;
        !           359:        void *v;
        !           360:        register_t *retval;
        !           361: {
        !           362:        struct linux_accept_args /* {
        !           363:                syscallarg(int) s;
        !           364:                syscallarg(struct sockaddr *) addr;
        !           365:                syscallarg(int *) namelen;
        !           366:        } */ *uap = v;
        !           367:        struct linux_accept_args laa;
        !           368:        struct compat_43_sys_accept_args baa;
        !           369:        struct sys_fcntl_args fca;
        !           370:        int error;
        !           371:
        !           372:        if ((error = copyin((caddr_t) uap, (caddr_t) &laa, sizeof laa)))
        !           373:                return error;
        !           374:
        !           375:        SCARG(&baa, s) = laa.s;
        !           376:        SCARG(&baa, name) = (caddr_t) laa.addr;
        !           377:        SCARG(&baa, anamelen) = laa.namelen;
        !           378:
        !           379:        error = compat_43_sys_accept(p, &baa, retval);
        !           380:        if (error)
        !           381:                return (error);
        !           382:
        !           383:        /*
        !           384:         * linux appears not to copy flags from the parent socket to the
        !           385:         * accepted one, so we must clear the flags in the new descriptor.
        !           386:         * Ignore any errors, because we already have an open fd.
        !           387:         */
        !           388:        SCARG(&fca, fd) = *retval;
        !           389:        SCARG(&fca, cmd) = F_SETFL;
        !           390:        SCARG(&fca, arg) = 0;
        !           391:        (void)sys_fcntl(p, &fca, retval);
        !           392:        *retval = SCARG(&fca, fd);
        !           393:        return (0);
        !           394: }
        !           395:
        !           396: int
        !           397: linux_getsockname(p, v, retval)
        !           398:        struct proc *p;
        !           399:        void *v;
        !           400:        register_t *retval;
        !           401: {
        !           402:        struct linux_getsockname_args /* {
        !           403:                syscallarg(int) s;
        !           404:                syscallarg(caddr_t) addr;
        !           405:                syscallarg(int *) namelen;
        !           406:        } */ *uap = v;
        !           407:        struct linux_getsockname_args lga;
        !           408:        struct sys_getsockname_args bga;
        !           409:        int error;
        !           410:
        !           411:        if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
        !           412:                return error;
        !           413:
        !           414:        SCARG(&bga, fdes) = lga.s;
        !           415:        SCARG(&bga, asa) = (struct sockaddr *) lga.addr;
        !           416:        SCARG(&bga, alen) = lga.namelen;
        !           417:
        !           418:        error = sys_getsockname(p, &bga, retval);
        !           419:        if (error)
        !           420:                return (error);
        !           421:
        !           422:        if ((error = linux_sa_put((struct osockaddr *)lga.addr)))
        !           423:                return (error);
        !           424:
        !           425:        return (0);
        !           426: }
        !           427:
        !           428: int
        !           429: linux_getpeername(p, v, retval)
        !           430:        struct proc *p;
        !           431:        void *v;
        !           432:        register_t *retval;
        !           433: {
        !           434:        struct linux_getpeername_args /* {
        !           435:                syscallarg(int) s;
        !           436:                syscallarg(struct sockaddr *) addr;
        !           437:                syscallarg(int *) namelen;
        !           438:        } */ *uap = v;
        !           439:        struct linux_getpeername_args lga;
        !           440:        struct sys_getpeername_args bga;
        !           441:        int error;
        !           442:
        !           443:        if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
        !           444:                return error;
        !           445:
        !           446:        SCARG(&bga, fdes) = lga.s;
        !           447:        SCARG(&bga, asa) = (struct sockaddr *) lga.addr;
        !           448:        SCARG(&bga, alen) = lga.namelen;
        !           449:
        !           450:        error = sys_getpeername(p, &bga, retval);
        !           451:        if (error)
        !           452:                return (error);
        !           453:
        !           454:        if ((error = linux_sa_put((struct osockaddr *)lga.addr)))
        !           455:                return (error);
        !           456:
        !           457:        return (0);
        !           458: }
        !           459:
        !           460: int
        !           461: linux_socketpair(p, v, retval)
        !           462:        struct proc *p;
        !           463:        void *v;
        !           464:        register_t *retval;
        !           465: {
        !           466:        struct linux_socketpair_args /* {
        !           467:                syscallarg(int) domain;
        !           468:                syscallarg(int) type;
        !           469:                syscallarg(int) protocol;
        !           470:                syscallarg(int *) rsv;
        !           471:        } */ *uap = v;
        !           472:        struct linux_socketpair_args lsa;
        !           473:        struct sys_socketpair_args bsa;
        !           474:        int error;
        !           475:
        !           476:        if ((error = copyin((caddr_t) uap, &lsa, sizeof lsa)))
        !           477:                return error;
        !           478:
        !           479:        SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
        !           480:        if (SCARG(&bsa, domain) == -1)
        !           481:                return EINVAL;
        !           482:        SCARG(&bsa, type) = lsa.type;
        !           483:        SCARG(&bsa, protocol) = lsa.protocol;
        !           484:        SCARG(&bsa, rsv) = lsa.rsv;
        !           485:
        !           486:        return sys_socketpair(p, &bsa, retval);
        !           487: }
        !           488:
        !           489: int
        !           490: linux_send(p, v, retval)
        !           491:        struct proc *p;
        !           492:        void *v;
        !           493:        register_t *retval;
        !           494: {
        !           495:        struct linux_send_args /* {
        !           496:                syscallarg(int) s;
        !           497:                syscallarg(void *) msg;
        !           498:                syscallarg(int) len;
        !           499:                syscallarg(int) flags;
        !           500:        } */ *uap = v;
        !           501:        struct linux_send_args lsa;
        !           502:        struct compat_43_sys_send_args bsa;
        !           503:        int error;
        !           504:
        !           505:        if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
        !           506:                return error;
        !           507:
        !           508:        SCARG(&bsa, s) = lsa.s;
        !           509:        SCARG(&bsa, buf) = lsa.msg;
        !           510:        SCARG(&bsa, len) = lsa.len;
        !           511:        SCARG(&bsa, flags) = lsa.flags;
        !           512:
        !           513:        return compat_43_sys_send(p, &bsa, retval);
        !           514: }
        !           515:
        !           516: int
        !           517: linux_recv(p, v, retval)
        !           518:        struct proc *p;
        !           519:        void *v;
        !           520:        register_t *retval;
        !           521: {
        !           522:        struct linux_recv_args /* {
        !           523:                syscallarg(int) s;
        !           524:                syscallarg(void *) msg;
        !           525:                syscallarg(int) len;
        !           526:                syscallarg(int) flags;
        !           527:        } */ *uap = v;
        !           528:        struct linux_recv_args lra;
        !           529:        struct compat_43_sys_recv_args bra;
        !           530:        int error;
        !           531:
        !           532:        if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
        !           533:                return error;
        !           534:
        !           535:        SCARG(&bra, s) = lra.s;
        !           536:        SCARG(&bra, buf) = lra.msg;
        !           537:        SCARG(&bra, len) = lra.len;
        !           538:        SCARG(&bra, flags) = lra.flags;
        !           539:
        !           540:        return compat_43_sys_recv(p, &bra, retval);
        !           541: }
        !           542:
        !           543: int
        !           544: linux_check_hdrincl(p, fd, retval, sgp)
        !           545:        struct proc *p;
        !           546:        int fd;
        !           547:        register_t *retval;
        !           548:        caddr_t *sgp;
        !           549: {
        !           550:        struct sys_getsockopt_args /* {
        !           551:                int s;
        !           552:                int level;
        !           553:                int name;
        !           554:                caddr_t val;
        !           555:                int *avalsize;
        !           556:        } */ gsa;
        !           557:        int error;
        !           558:        caddr_t val;
        !           559:        int *valsize;
        !           560:        int size_val = sizeof val;
        !           561:        int optval;
        !           562:
        !           563:        val = stackgap_alloc(sgp, sizeof(optval));
        !           564:        valsize = stackgap_alloc(sgp, sizeof(size_val));
        !           565:
        !           566:        if ((error = copyout(&size_val, valsize, sizeof(size_val))))
        !           567:                return (error);
        !           568:        SCARG(&gsa, s) = fd;
        !           569:        SCARG(&gsa, level) = IPPROTO_IP;
        !           570:        SCARG(&gsa, name) = IP_HDRINCL;
        !           571:        SCARG(&gsa, val) = val;
        !           572:        SCARG(&gsa, avalsize) = valsize;
        !           573:
        !           574:        if ((error = sys_getsockopt(p, &gsa, retval)))
        !           575:                return (error);
        !           576:        if ((error = copyin(val, &optval, sizeof(optval))))
        !           577:                return (error);
        !           578:        return (optval == 0);
        !           579: }
        !           580:
        !           581: /*
        !           582:  * linux_ip_copysize defines how many bytes we should copy
        !           583:  * from the beginning of the IP packet before we customize it for BSD.
        !           584:  * It should include all the fields we modify (ip_len and ip_off)
        !           585:  * and be as small as possible to minimize copying overhead.
        !           586:  */
        !           587: #define linux_ip_copysize      8
        !           588:
        !           589: int
        !           590: linux_sendto_hdrincl(p, bsa, retval, sgp)
        !           591:        struct proc *p;
        !           592:        struct sys_sendto_args *bsa;
        !           593:        register_t *retval;
        !           594:        caddr_t *sgp;
        !           595: {
        !           596:        struct sys_sendmsg_args ssa;
        !           597:        struct ip *packet, rpacket;
        !           598:        struct msghdr *msg, rmsg;
        !           599:        struct iovec *iov, riov[2];
        !           600:        int error;
        !           601:
        !           602:        /* Check the packet isn't too small before we mess with it */
        !           603:        if (SCARG(bsa, len) < linux_ip_copysize)
        !           604:                return EINVAL;
        !           605:
        !           606:        /*
        !           607:         * Tweaking the user buffer in place would be bad manners.
        !           608:         * We create a corrected IP header with just the needed length,
        !           609:         * then use an iovec to glue it to the rest of the user packet
        !           610:         * when calling sendmsg().
        !           611:         */
        !           612:        packet = (struct ip *)stackgap_alloc(sgp, linux_ip_copysize);
        !           613:        msg = (struct msghdr *)stackgap_alloc(sgp, sizeof(*msg));
        !           614:        iov = (struct iovec *)stackgap_alloc(sgp, sizeof(*iov)*2);
        !           615:
        !           616:        /* Make a copy of the beginning of the packet to be sent */
        !           617:        if ((error = copyin(SCARG(bsa, buf), (caddr_t)&rpacket,
        !           618:            linux_ip_copysize)))
        !           619:                return error;
        !           620:
        !           621:        /* Convert fields from Linux to BSD raw IP socket format */
        !           622:        rpacket.ip_len = SCARG(bsa, len);
        !           623:        error = copyout(&rpacket, packet, linux_ip_copysize);
        !           624:        if (error)
        !           625:                return (error);
        !           626:
        !           627:        riov[0].iov_base = (char *)packet;
        !           628:        riov[0].iov_len = linux_ip_copysize;
        !           629:        riov[1].iov_base = (caddr_t)SCARG(bsa, buf) + linux_ip_copysize;
        !           630:        riov[1].iov_len = SCARG(bsa, len) - linux_ip_copysize;
        !           631:
        !           632:        error = copyout(&riov[0], iov, sizeof(riov));
        !           633:        if (error)
        !           634:                return (error);
        !           635:
        !           636:        /* Prepare the msghdr and iovec structures describing the new packet */
        !           637:        rmsg.msg_name = (void *)SCARG(bsa, to);
        !           638:        rmsg.msg_namelen = SCARG(bsa, tolen);
        !           639:        rmsg.msg_iov = iov;
        !           640:        rmsg.msg_iovlen = 2;
        !           641:        rmsg.msg_control = NULL;
        !           642:        rmsg.msg_controllen = 0;
        !           643:        rmsg.msg_flags = 0;
        !           644:
        !           645:        error = copyout(&riov[0], iov, sizeof(riov));
        !           646:        if (error)
        !           647:                return (error);
        !           648:
        !           649:        SCARG(&ssa, s) = SCARG(bsa, s);
        !           650:        SCARG(&ssa, msg) = msg;
        !           651:        SCARG(&ssa, flags) = SCARG(bsa, flags);
        !           652:        return sys_sendmsg(p, &ssa, retval);
        !           653: }
        !           654:
        !           655: int
        !           656: linux_sendto(p, v, retval)
        !           657:        struct proc *p;
        !           658:        void *v;
        !           659:        register_t *retval;
        !           660: {
        !           661:        struct linux_sendto_args /* {
        !           662:                syscallarg(int) s;
        !           663:                syscallarg(void *) msg;
        !           664:                syscallarg(int) len;
        !           665:                syscallarg(int) flags;
        !           666:                syscallarg(osockaddr *) to;
        !           667:                syscallarg(int) tolen;
        !           668:        } */ *uap = v;
        !           669:        struct linux_sendto_args lsa;
        !           670:        struct sys_sendto_args bsa;
        !           671:        int error;
        !           672:        int tolen;
        !           673:        caddr_t sg = stackgap_init(p->p_emul);
        !           674:
        !           675:        if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
        !           676:                return error;
        !           677:
        !           678:        SCARG(&bsa, s) = lsa.s;
        !           679:        SCARG(&bsa, buf) = lsa.msg;
        !           680:        SCARG(&bsa, len) = lsa.len;
        !           681:        SCARG(&bsa, flags) = lsa.flags;
        !           682:        tolen = lsa.tolen;
        !           683:        if (lsa.to) {
        !           684:                struct sockaddr *sa;
        !           685:
        !           686:                if ((error = linux_sa_get(p, &sg, &sa, lsa.to, &tolen)))
        !           687:                        return (error);
        !           688:                SCARG(&bsa, to) = sa;
        !           689:        } else
        !           690:                SCARG(&bsa, to) = NULL;
        !           691:        SCARG(&bsa, tolen) = tolen;
        !           692:
        !           693:        if (linux_check_hdrincl(p, lsa.s, retval, &sg) == 0)
        !           694:                return linux_sendto_hdrincl(p, &bsa, retval, &sg);
        !           695:        return sys_sendto(p, &bsa, retval);
        !           696: }
        !           697:
        !           698: int
        !           699: linux_recvfrom(p, v, retval)
        !           700:        struct proc *p;
        !           701:        void *v;
        !           702:        register_t *retval;
        !           703: {
        !           704:        struct linux_recvfrom_args /* {
        !           705:                syscallarg(int) s;
        !           706:                syscallarg(void *) buf;
        !           707:                syscallarg(int) len;
        !           708:                syscallarg(int) flags;
        !           709:                syscallarg(struct osockaddr *) from;
        !           710:                syscallarg(int *) fromlen;
        !           711:        } */ *uap = v;
        !           712:        struct linux_recvfrom_args lra;
        !           713:        struct sys_recvfrom_args bra;
        !           714:        int error;
        !           715:
        !           716:        if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
        !           717:                return error;
        !           718:
        !           719:        SCARG(&bra, s) = lra.s;
        !           720:        SCARG(&bra, buf) = lra.buf;
        !           721:        SCARG(&bra, len) = lra.len;
        !           722:        SCARG(&bra, flags) = lra.flags;
        !           723:        SCARG(&bra, from) = (struct sockaddr *) lra.from;
        !           724:        SCARG(&bra, fromlenaddr) = lra.fromlen;
        !           725:
        !           726:        if ((error = sys_recvfrom(p, &bra, retval)))
        !           727:                return (error);
        !           728:
        !           729:        if (lra.from && (error = linux_sa_put(lra.from)))
        !           730:                return (error);
        !           731:
        !           732:        return (0);
        !           733: }
        !           734:
        !           735: int
        !           736: linux_shutdown(p, v, retval)
        !           737:        struct proc *p;
        !           738:        void *v;
        !           739:        register_t *retval;
        !           740: {
        !           741:        struct linux_shutdown_args /* {
        !           742:                syscallarg(int) s;
        !           743:                syscallarg(int) how;
        !           744:        } */ *uap = v;
        !           745:        struct linux_shutdown_args lsa;
        !           746:        struct sys_shutdown_args bsa;
        !           747:        int error;
        !           748:
        !           749:        if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
        !           750:                return error;
        !           751:
        !           752:        SCARG(&bsa, s) = lsa.s;
        !           753:        SCARG(&bsa, how) = lsa.how;
        !           754:
        !           755:        return sys_shutdown(p, &bsa, retval);
        !           756: }
        !           757:
        !           758: /*
        !           759:  * Convert socket option level from Linux to OpenBSD value. Only SOL_SOCKET
        !           760:  * is different, the rest matches IPPROTO_* on both systems.
        !           761:  */
        !           762: int
        !           763: linux_to_bsd_sopt_level(llevel)
        !           764:        int llevel;
        !           765: {
        !           766:
        !           767:        switch (llevel) {
        !           768:        case LINUX_SOL_SOCKET:
        !           769:                return SOL_SOCKET;
        !           770:        case LINUX_SOL_IP:
        !           771:                return IPPROTO_IP;
        !           772:        case LINUX_SOL_TCP:
        !           773:                return IPPROTO_TCP;
        !           774:        case LINUX_SOL_UDP:
        !           775:                return IPPROTO_UDP;
        !           776:        default:
        !           777:                return -1;
        !           778:        }
        !           779: }
        !           780:
        !           781: /*
        !           782:  * Convert Linux socket level socket option numbers to OpenBSD values.
        !           783:  */
        !           784: int
        !           785: linux_to_bsd_so_sockopt(lopt)
        !           786:        int lopt;
        !           787: {
        !           788:
        !           789:        switch (lopt) {
        !           790:        case LINUX_SO_DEBUG:
        !           791:                return SO_DEBUG;
        !           792:        case LINUX_SO_REUSEADDR:
        !           793:                /*
        !           794:                 * Linux does not implement SO_REUSEPORT, but allows reuse
        !           795:                 * of a host:port pair through SO_REUSEADDR even if the
        !           796:                 * address is not a multicast-address.  Effectively, this
        !           797:                 * means that we should use SO_REUSEPORT to allow Linux
        !           798:                 * applications to not exit with EADDRINUSE.
        !           799:                 */
        !           800:                return SO_REUSEPORT;
        !           801:        case LINUX_SO_TYPE:
        !           802:                return SO_TYPE;
        !           803:        case LINUX_SO_ERROR:
        !           804:                return SO_ERROR;
        !           805:        case LINUX_SO_DONTROUTE:
        !           806:                return SO_DONTROUTE;
        !           807:        case LINUX_SO_BROADCAST:
        !           808:                return SO_BROADCAST;
        !           809:        case LINUX_SO_SNDBUF:
        !           810:                return SO_SNDBUF;
        !           811:        case LINUX_SO_RCVBUF:
        !           812:                return SO_RCVBUF;
        !           813:        case LINUX_SO_KEEPALIVE:
        !           814:                return SO_KEEPALIVE;
        !           815:        case LINUX_SO_OOBINLINE:
        !           816:                return SO_OOBINLINE;
        !           817:        case LINUX_SO_LINGER:
        !           818:                return SO_LINGER;
        !           819:        case LINUX_SO_PRIORITY:
        !           820:        case LINUX_SO_NO_CHECK:
        !           821:        default:
        !           822:                return -1;
        !           823:        }
        !           824: }
        !           825:
        !           826: /*
        !           827:  * Convert Linux IP level socket option number to OpenBSD values.
        !           828:  */
        !           829: int
        !           830: linux_to_bsd_ip_sockopt(lopt)
        !           831:        int lopt;
        !           832: {
        !           833:
        !           834:        switch (lopt) {
        !           835:        case LINUX_IP_TOS:
        !           836:                return IP_TOS;
        !           837:        case LINUX_IP_TTL:
        !           838:                return IP_TTL;
        !           839:        case LINUX_IP_MULTICAST_TTL:
        !           840:                return IP_MULTICAST_TTL;
        !           841:        case LINUX_IP_MULTICAST_LOOP:
        !           842:                return IP_MULTICAST_LOOP;
        !           843:        case LINUX_IP_MULTICAST_IF:
        !           844:                return IP_MULTICAST_IF;
        !           845:        case LINUX_IP_ADD_MEMBERSHIP:
        !           846:                return IP_ADD_MEMBERSHIP;
        !           847:        case LINUX_IP_DROP_MEMBERSHIP:
        !           848:                return IP_DROP_MEMBERSHIP;
        !           849:        case LINUX_IP_HDRINCL:
        !           850:                return IP_HDRINCL;
        !           851:        default:
        !           852:                return -1;
        !           853:        }
        !           854: }
        !           855:
        !           856: /*
        !           857:  * Convert Linux TCP level socket option number to OpenBSD values.
        !           858:  */
        !           859: int
        !           860: linux_to_bsd_tcp_sockopt(lopt)
        !           861:        int lopt;
        !           862: {
        !           863:
        !           864:        switch (lopt) {
        !           865:        case LINUX_TCP_NODELAY:
        !           866:                return TCP_NODELAY;
        !           867:        case LINUX_TCP_MAXSEG:
        !           868:                return TCP_MAXSEG;
        !           869:        default:
        !           870:                return -1;
        !           871:        }
        !           872: }
        !           873:
        !           874: /*
        !           875:  * Convert Linux UDP level socket option number to OpenBSD values.
        !           876:  */
        !           877: int
        !           878: linux_to_bsd_udp_sockopt(lopt)
        !           879:        int lopt;
        !           880: {
        !           881:
        !           882:        switch (lopt) {
        !           883:        default:
        !           884:                return -1;
        !           885:        }
        !           886: }
        !           887:
        !           888: /*
        !           889:  * Another reasonably straightforward function: setsockopt(2).
        !           890:  * The level and option numbers are converted; the values passed
        !           891:  * are not (yet) converted, the ones currently implemented don't
        !           892:  * need conversion, as they are the same on both systems.
        !           893:  */
        !           894: int
        !           895: linux_setsockopt(p, v, retval)
        !           896:        struct proc *p;
        !           897:        void *v;
        !           898:        register_t *retval;
        !           899: {
        !           900:        struct linux_setsockopt_args /* {
        !           901:                syscallarg(int) s;
        !           902:                syscallarg(int) level;
        !           903:                syscallarg(int) optname;
        !           904:                syscallarg(void *) optval;
        !           905:                syscallarg(int) optlen;
        !           906:        } */ *uap = v;
        !           907:        struct linux_setsockopt_args lsa;
        !           908:        struct sys_setsockopt_args bsa;
        !           909:        int error, name;
        !           910:
        !           911:        if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
        !           912:                return error;
        !           913:
        !           914:        SCARG(&bsa, s) = lsa.s;
        !           915:        SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level);
        !           916:        SCARG(&bsa, val) = lsa.optval;
        !           917:        SCARG(&bsa, valsize) = lsa.optlen;
        !           918:
        !           919:        switch (SCARG(&bsa, level)) {
        !           920:        case SOL_SOCKET:
        !           921:                name = linux_to_bsd_so_sockopt(lsa.optname);
        !           922:                break;
        !           923:        case IPPROTO_IP:
        !           924:                name = linux_to_bsd_ip_sockopt(lsa.optname);
        !           925:                break;
        !           926:        case IPPROTO_TCP:
        !           927:                name = linux_to_bsd_tcp_sockopt(lsa.optname);
        !           928:                break;
        !           929:        case IPPROTO_UDP:
        !           930:                name = linux_to_bsd_udp_sockopt(lsa.optname);
        !           931:                break;
        !           932:        default:
        !           933:                return EINVAL;
        !           934:        }
        !           935:
        !           936:        if (name == -1)
        !           937:                return EINVAL;
        !           938:        SCARG(&bsa, name) = name;
        !           939:
        !           940:        return sys_setsockopt(p, &bsa, retval);
        !           941: }
        !           942:
        !           943: /*
        !           944:  * getsockopt(2) is very much the same as setsockopt(2) (see above)
        !           945:  */
        !           946: int
        !           947: linux_getsockopt(p, v, retval)
        !           948:        struct proc *p;
        !           949:        void *v;
        !           950:        register_t *retval;
        !           951: {
        !           952:        struct linux_getsockopt_args /* {
        !           953:                syscallarg(int) s;
        !           954:                syscallarg(int) level;
        !           955:                syscallarg(int) optname;
        !           956:                syscallarg(void *) optval;
        !           957:                syscallarg(int) *optlen;
        !           958:        } */ *uap = v;
        !           959:        struct linux_getsockopt_args lga;
        !           960:        struct sys_getsockopt_args bga;
        !           961:        int error, name;
        !           962:
        !           963:        if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
        !           964:                return error;
        !           965:
        !           966:        SCARG(&bga, s) = lga.s;
        !           967:        SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
        !           968:        SCARG(&bga, val) = lga.optval;
        !           969:        SCARG(&bga, avalsize) = lga.optlen;
        !           970:
        !           971:        switch (SCARG(&bga, level)) {
        !           972:        case SOL_SOCKET:
        !           973:                name = linux_to_bsd_so_sockopt(lga.optname);
        !           974:                break;
        !           975:        case IPPROTO_IP:
        !           976:                name = linux_to_bsd_ip_sockopt(lga.optname);
        !           977:                break;
        !           978:        case IPPROTO_TCP:
        !           979:                name = linux_to_bsd_tcp_sockopt(lga.optname);
        !           980:                break;
        !           981:        case IPPROTO_UDP:
        !           982:                name = linux_to_bsd_udp_sockopt(lga.optname);
        !           983:                break;
        !           984:        default:
        !           985:                return EINVAL;
        !           986:        }
        !           987:
        !           988:        if (name == -1)
        !           989:                return EINVAL;
        !           990:        SCARG(&bga, name) = name;
        !           991:
        !           992:        return sys_getsockopt(p, &bga, retval);
        !           993: }
        !           994:
        !           995: int
        !           996: linux_recvmsg(p, v, retval)
        !           997:        struct proc *p;
        !           998:        void *v;
        !           999:        register_t *retval;
        !          1000: {
        !          1001:        struct linux_recvmsg_args /* {
        !          1002:                syscallarg(int) s;
        !          1003:                syscallarg(caddr_t) msg;
        !          1004:                syscallarg(int) flags;
        !          1005:        } */ *uap = v;
        !          1006:        struct linux_recvmsg_args lla;
        !          1007:        struct sys_recvmsg_args bla;
        !          1008:        struct msghdr msg;
        !          1009:        int error;
        !          1010:
        !          1011:        if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
        !          1012:                return error;
        !          1013:
        !          1014:        SCARG(&bla, s) = lla.s;
        !          1015:        SCARG(&bla, msg) = (struct msghdr *)lla.msg;
        !          1016:        SCARG(&bla, flags) = lla.flags;
        !          1017:
        !          1018:        error = sys_recvmsg(p, &bla, retval);
        !          1019:        if (error)
        !          1020:                return (error);
        !          1021:
        !          1022:        error = copyin(lla.msg, (caddr_t)&msg, sizeof(msg));
        !          1023:
        !          1024:        if (!error && msg.msg_name && msg.msg_namelen > 2)
        !          1025:                error = linux_sa_put(msg.msg_name);
        !          1026:
        !          1027:        return (error);
        !          1028: }
        !          1029:
        !          1030: int
        !          1031: linux_sendmsg(p, v, retval)
        !          1032:        struct proc *p;
        !          1033:        void *v;
        !          1034:        register_t *retval;
        !          1035: {
        !          1036:        struct linux_sendmsg_args /* {
        !          1037:                syscallarg(int) s;
        !          1038:                syscallarg(struct msghdr *) msg;
        !          1039:                syscallarg(int) flags;
        !          1040:        } */ *uap = v;
        !          1041:        struct linux_sendmsg_args lla;
        !          1042:        struct sys_sendmsg_args bla;
        !          1043:        struct msghdr msg, *nmsg = NULL;
        !          1044:        int error;
        !          1045:        caddr_t control;
        !          1046:        int level;
        !          1047:
        !          1048:        if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
        !          1049:                return error;
        !          1050:
        !          1051:        if ((error = copyin(lla.msg, (caddr_t) &msg, sizeof(msg))))
        !          1052:                return (error);
        !          1053:
        !          1054:        if (msg.msg_name) {
        !          1055:                struct sockaddr *sa;
        !          1056:                caddr_t sg = stackgap_init(p->p_emul);
        !          1057:
        !          1058:                nmsg = (struct msghdr *)stackgap_alloc(&sg,
        !          1059:                    sizeof(struct msghdr));
        !          1060:                if (!nmsg)
        !          1061:                        return (ENOMEM);
        !          1062:
        !          1063:                error = linux_sa_get(p, &sg, &sa,
        !          1064:                    (struct osockaddr *)msg.msg_name, &msg.msg_namelen);
        !          1065:                if (error)
        !          1066:                        return (error);
        !          1067:
        !          1068:                msg.msg_name = (struct sockaddr *)sa;
        !          1069:                if ((error = copyout(&msg, nmsg, sizeof(struct msghdr))))
        !          1070:                        return (error);
        !          1071:                lla.msg = nmsg;
        !          1072:        }
        !          1073:
        !          1074:        SCARG(&bla, s) = lla.s;
        !          1075:        SCARG(&bla, msg) = lla.msg;
        !          1076:        SCARG(&bla, flags) = lla.flags;
        !          1077:
        !          1078:        error = copyin(lla.msg->msg_control, &control, sizeof(caddr_t));
        !          1079:        if (error)
        !          1080:                return error;
        !          1081:        if (control == NULL)
        !          1082:                goto done;
        !          1083:        error = copyin(&((struct cmsghdr *)control)->cmsg_level,
        !          1084:            &level, sizeof(int));
        !          1085:        if (error)
        !          1086:                return error;
        !          1087:        if (level == 1) {
        !          1088:                /*
        !          1089:                 * Linux thinks that SOL_SOCKET is 1; we know that it's really
        !          1090:                 * 0xffff, of course.
        !          1091:                 */
        !          1092:                level = SOL_SOCKET;
        !          1093:                /*
        !          1094:                 * XXX should use stack gap!
        !          1095:                 * We don't because the control header is variable length
        !          1096:                 * up to 2048 bytes, and there's only 512 bytes of gap.
        !          1097:                 */
        !          1098:                error = copyout(&level, &((struct cmsghdr *)control)->
        !          1099:                    cmsg_level, sizeof(int));
        !          1100:                if (error)
        !          1101:                        return error;
        !          1102:        }
        !          1103: done:
        !          1104:        error = sys_sendmsg(p, &bla, retval);
        !          1105:        /* replace level, just in case somebody cares. */
        !          1106:        if (level == SOL_SOCKET) {
        !          1107:                level = 1;
        !          1108:                /* don't worry about the error */
        !          1109:                copyout(&level, &((struct cmsghdr *)control)->cmsg_level,
        !          1110:                    sizeof(int));
        !          1111:        }
        !          1112:        return (error);
        !          1113: }
        !          1114:
        !          1115: /*
        !          1116:  * Copy the osockaddr structure pointed to by osa to kernel, adjust
        !          1117:  * family and convert to sockaddr, allocate stackgap and put the
        !          1118:  * the converted structure there, address on stackgap returned in sap.
        !          1119:  */
        !          1120: int
        !          1121: linux_sa_get(p, sgp, sap, osa, osalen)
        !          1122:        struct proc *p;
        !          1123:        caddr_t *sgp;
        !          1124:        struct sockaddr **sap;
        !          1125:        const struct osockaddr *osa;
        !          1126:        int *osalen;
        !          1127: {
        !          1128:        int error=0, bdom;
        !          1129:        struct sockaddr *sa, *usa;
        !          1130:        struct osockaddr *kosa;
        !          1131:        int alloclen;
        !          1132: #ifdef INET6
        !          1133:        int oldv6size;
        !          1134:        struct sockaddr_in6 *sin6;
        !          1135: #endif
        !          1136:
        !          1137:        if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
        !          1138:                return (EINVAL);
        !          1139:        }
        !          1140:
        !          1141:        alloclen = *osalen;
        !          1142: #ifdef INET6
        !          1143:        oldv6size = 0;
        !          1144:        /*
        !          1145:         * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
        !          1146:         * if it's a v4-mapped address, so reserve the proper space
        !          1147:         * for it.
        !          1148:         */
        !          1149:        if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
        !          1150:                alloclen = sizeof (struct sockaddr_in6);
        !          1151:                oldv6size = 1;
        !          1152:        }
        !          1153: #endif
        !          1154:
        !          1155:        kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
        !          1156:
        !          1157:        if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
        !          1158:                goto out;
        !          1159:        }
        !          1160:
        !          1161:        bdom = linux_to_bsd_domain(kosa->sa_family);
        !          1162:        if (bdom == -1) {
        !          1163:                error = EINVAL;
        !          1164:                goto out;
        !          1165:        }
        !          1166:
        !          1167: #ifdef INET6
        !          1168:        /*
        !          1169:         * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
        !          1170:         * which lacks the scope id compared with RFC2553 one. If we detect
        !          1171:         * the situation, reject the address.
        !          1172:         *
        !          1173:         * Still accept addresses for which the scope id is not used.
        !          1174:         */
        !          1175:        if (oldv6size && bdom == AF_INET6) {
        !          1176:                sin6 = (struct sockaddr_in6 *)kosa;
        !          1177:                if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
        !          1178:                    (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
        !          1179:                     !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
        !          1180:                     !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
        !          1181:                     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
        !          1182:                     !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
        !          1183:                        sin6->sin6_scope_id = 0;
        !          1184:                } else {
        !          1185:                        error = EINVAL;
        !          1186:                        goto out;
        !          1187:                }
        !          1188:        } else
        !          1189: #endif
        !          1190:        if (bdom == AF_INET) {
        !          1191:                alloclen = sizeof(struct sockaddr_in);
        !          1192:        }
        !          1193:
        !          1194:        sa = (struct sockaddr *) kosa;
        !          1195:        sa->sa_family = bdom;
        !          1196:        sa->sa_len = alloclen;
        !          1197:
        !          1198:        usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen);
        !          1199:        if (!usa) {
        !          1200:                error = ENOMEM;
        !          1201:                goto out;
        !          1202:        }
        !          1203:
        !          1204:        if ((error = copyout(sa, usa, alloclen))) {
        !          1205:                goto out;
        !          1206:        }
        !          1207:
        !          1208:        *sap = usa;
        !          1209:
        !          1210:     out:
        !          1211:        *osalen = alloclen;
        !          1212:        free(kosa, M_TEMP);
        !          1213:        return (error);
        !          1214: }
        !          1215:
        !          1216: int
        !          1217: linux_sa_put(osa)
        !          1218:        struct osockaddr *osa;
        !          1219: {
        !          1220:        struct sockaddr sa;
        !          1221:        struct osockaddr *kosa;
        !          1222:        int error, bdom, len;
        !          1223:
        !          1224:        /*
        !          1225:         * Only read/write the sockaddr family and length part, the rest is
        !          1226:         * not changed.
        !          1227:         */
        !          1228:        len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
        !          1229:
        !          1230:        error = copyin((caddr_t) osa, (caddr_t) &sa, len);
        !          1231:        if (error)
        !          1232:                return (error);
        !          1233:
        !          1234:        bdom = bsd_to_linux_domain(sa.sa_family);
        !          1235:        if (bdom == -1)
        !          1236:                return (EINVAL);
        !          1237:
        !          1238:        /* Note: we convert from sockaddr to osockaddr here, too */
        !          1239:        kosa = (struct osockaddr *) &sa;
        !          1240:        kosa->sa_family = bdom;
        !          1241:        error = copyout(kosa, osa, len);
        !          1242:        if (error)
        !          1243:                return (error);
        !          1244:
        !          1245:        return (0);
        !          1246: }
        !          1247:
        !          1248: /*
        !          1249:  * Entry point to all Linux socket calls. Just check which call to
        !          1250:  * make and take appropriate action.
        !          1251:  */
        !          1252: int
        !          1253: linux_sys_socketcall(p, v, retval)
        !          1254:        struct proc *p;
        !          1255:        void *v;
        !          1256:        register_t *retval;
        !          1257: {
        !          1258:        struct linux_sys_socketcall_args /* {
        !          1259:                syscallarg(int) what;
        !          1260:                syscallarg(void *) args;
        !          1261:        } */ *uap = v;
        !          1262:
        !          1263:        switch (SCARG(uap, what)) {
        !          1264:        case LINUX_SYS_socket:
        !          1265:                return linux_socket(p, SCARG(uap, args), retval);
        !          1266:        case LINUX_SYS_bind:
        !          1267:                return linux_bind(p, SCARG(uap, args), retval);
        !          1268:        case LINUX_SYS_connect:
        !          1269:                return linux_connect(p, SCARG(uap, args), retval);
        !          1270:        case LINUX_SYS_listen:
        !          1271:                return linux_listen(p, SCARG(uap, args), retval);
        !          1272:        case LINUX_SYS_accept:
        !          1273:                return linux_accept(p, SCARG(uap, args), retval);
        !          1274:        case LINUX_SYS_getsockname:
        !          1275:                return linux_getsockname(p, SCARG(uap, args), retval);
        !          1276:        case LINUX_SYS_getpeername:
        !          1277:                return linux_getpeername(p, SCARG(uap, args), retval);
        !          1278:        case LINUX_SYS_socketpair:
        !          1279:                return linux_socketpair(p, SCARG(uap, args), retval);
        !          1280:        case LINUX_SYS_send:
        !          1281:                return linux_send(p, SCARG(uap, args), retval);
        !          1282:        case LINUX_SYS_recv:
        !          1283:                return linux_recv(p, SCARG(uap, args), retval);
        !          1284:        case LINUX_SYS_sendto:
        !          1285:                return linux_sendto(p, SCARG(uap, args), retval);
        !          1286:        case LINUX_SYS_recvfrom:
        !          1287:                return linux_recvfrom(p, SCARG(uap, args), retval);
        !          1288:        case LINUX_SYS_shutdown:
        !          1289:                return linux_shutdown(p, SCARG(uap, args), retval);
        !          1290:        case LINUX_SYS_setsockopt:
        !          1291:                return linux_setsockopt(p, SCARG(uap, args), retval);
        !          1292:        case LINUX_SYS_getsockopt:
        !          1293:                return linux_getsockopt(p, SCARG(uap, args), retval);
        !          1294:        case LINUX_SYS_sendmsg:
        !          1295:                return linux_sendmsg(p, SCARG(uap, args), retval);
        !          1296:        case LINUX_SYS_recvmsg:
        !          1297:                return linux_recvmsg(p, SCARG(uap, args), retval);
        !          1298:        default:
        !          1299:                return ENOSYS;
        !          1300:        }
        !          1301: }
        !          1302:
        !          1303: int
        !          1304: linux_ioctl_socket(p, v, retval)
        !          1305:        register struct proc *p;
        !          1306:        void *v;
        !          1307:        register_t *retval;
        !          1308: {
        !          1309:        struct linux_sys_ioctl_args /* {
        !          1310:                syscallarg(int) fd;
        !          1311:                syscallarg(u_long) com;
        !          1312:                syscallarg(caddr_t) data;
        !          1313:        } */ *uap = v;
        !          1314:        u_long com;
        !          1315:        struct sys_ioctl_args ia;
        !          1316:        struct file *fp;
        !          1317:        struct filedesc *fdp;
        !          1318:        struct vnode *vp;
        !          1319:        int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
        !          1320:        struct ioctl_pt pt;
        !          1321:        int error = 0, isdev = 0, dosys = 1;
        !          1322:
        !          1323:        fdp = p->p_fd;
        !          1324:        if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
        !          1325:                return (EBADF);
        !          1326:        FREF(fp);
        !          1327:
        !          1328:        if (fp->f_type == DTYPE_VNODE) {
        !          1329:                vp = (struct vnode *)fp->f_data;
        !          1330:                isdev = vp->v_type == VCHR;
        !          1331:        }
        !          1332:
        !          1333:        /*
        !          1334:         * Don't try to interpret socket ioctl calls that are done
        !          1335:         * on a device filedescriptor, just pass them through, to
        !          1336:         * emulate Linux behaviour. Use PTIOCLINUX so that the
        !          1337:         * device will only handle these if it's prepared to do
        !          1338:         * so, to avoid unexpected things from happening.
        !          1339:         */
        !          1340:        if (isdev) {
        !          1341:                dosys = 0;
        !          1342:                ioctlf = fp->f_ops->fo_ioctl;
        !          1343:                pt.com = SCARG(uap, com);
        !          1344:                pt.data = SCARG(uap, data);
        !          1345:                error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
        !          1346:                /*
        !          1347:                 * XXX hack: if the function returns EJUSTRETURN,
        !          1348:                 * it has stuffed a sysctl return value in pt.data.
        !          1349:                 */
        !          1350:                if (error == EJUSTRETURN) {
        !          1351:                        retval[0] = (register_t)pt.data;
        !          1352:                        error = 0;
        !          1353:                }
        !          1354:                goto out;
        !          1355:        }
        !          1356:
        !          1357:        com = SCARG(uap, com);
        !          1358:        retval[0] = 0;
        !          1359:
        !          1360:        switch (com) {
        !          1361:        case LINUX_FIOSETOWN:
        !          1362:                SCARG(&ia, com) = FIOSETOWN;
        !          1363:                break;
        !          1364:        case LINUX_SIOCSPGRP:
        !          1365:                SCARG(&ia, com) = SIOCSPGRP;
        !          1366:                break;
        !          1367:        case LINUX_FIOGETOWN:
        !          1368:                SCARG(&ia, com) = FIOGETOWN;
        !          1369:                break;
        !          1370:        case LINUX_SIOCGPGRP:
        !          1371:                SCARG(&ia, com) = SIOCGPGRP;
        !          1372:                break;
        !          1373:        case LINUX_SIOCATMARK:
        !          1374:                SCARG(&ia, com) = SIOCATMARK;
        !          1375:                break;
        !          1376: #if 0
        !          1377:        case LINUX_SIOCGSTAMP:
        !          1378:                SCARG(&ia, com) = SIOCGSTAMP;
        !          1379:                break;
        !          1380: #endif
        !          1381:        case LINUX_SIOCGIFCONF:
        !          1382:                SCARG(&ia, com) = OSIOCGIFCONF;
        !          1383:                break;
        !          1384:        case LINUX_SIOCGIFFLAGS:
        !          1385:                SCARG(&ia, com) = SIOCGIFFLAGS;
        !          1386:                break;
        !          1387:        case LINUX_SIOCGIFADDR:
        !          1388:                SCARG(&ia, com) = OSIOCGIFADDR;
        !          1389:                break;
        !          1390:        case LINUX_SIOCGIFDSTADDR:
        !          1391:                SCARG(&ia, com) = OSIOCGIFDSTADDR;
        !          1392:                break;
        !          1393:        case LINUX_SIOCGIFBRDADDR:
        !          1394:                SCARG(&ia, com) = OSIOCGIFBRDADDR;
        !          1395:                break;
        !          1396:        case LINUX_SIOCGIFNETMASK:
        !          1397:                SCARG(&ia, com) = OSIOCGIFNETMASK;
        !          1398:                break;
        !          1399:        case LINUX_SIOCGIFMETRIC:
        !          1400:                SCARG(&ia, com) = SIOCGIFMETRIC;
        !          1401:                break;
        !          1402:        case LINUX_SIOCGIFMTU:
        !          1403:                SCARG(&ia, com) = SIOCGIFMTU;
        !          1404:                break;
        !          1405:        case LINUX_SIOCADDMULTI:
        !          1406:                SCARG(&ia, com) = SIOCADDMULTI;
        !          1407:                break;
        !          1408:        case LINUX_SIOCDELMULTI:
        !          1409:                SCARG(&ia, com) = SIOCDELMULTI;
        !          1410:                break;
        !          1411:        case LINUX_SIOCGIFHWADDR: {
        !          1412:                struct linux_ifreq *ifr = (struct linux_ifreq *)SCARG(uap, data);
        !          1413:                struct sockaddr_dl *sdl;
        !          1414:                struct ifnet *ifp;
        !          1415:                struct ifaddr *ifa;
        !          1416:
        !          1417:                /*
        !          1418:                 * Note that we don't actually respect the name in the ifreq
        !          1419:                 * structure, as Linux interface names are all different.
        !          1420:                 */
        !          1421:                TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !          1422:                        if (ifp->if_type != IFT_ETHER)
        !          1423:                                continue;
        !          1424:                        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !          1425:                                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
        !          1426:                                    (sdl->sdl_family == AF_LINK) &&
        !          1427:                                    (sdl->sdl_type == IFT_ETHER)) {
        !          1428:                                        error = copyout(LLADDR(sdl),
        !          1429:                                            (caddr_t)&ifr->ifr_hwaddr.sa_data,
        !          1430:                                            LINUX_IFHWADDRLEN);
        !          1431:                                        dosys = 0;
        !          1432:                                        goto out;
        !          1433:                                }
        !          1434:                        }
        !          1435:                }
        !          1436:                error = ENOENT;
        !          1437:                break;
        !          1438:            }
        !          1439:        default:
        !          1440:                error = EINVAL;
        !          1441:        }
        !          1442:
        !          1443: out:
        !          1444:        if (error == 0 && dosys) {
        !          1445:                SCARG(&ia, fd) = SCARG(uap, fd);
        !          1446:                SCARG(&ia, data) = SCARG(uap, data);
        !          1447:                error = sys_ioctl(p, &ia, retval);
        !          1448:        }
        !          1449:
        !          1450:        FRELE(fp);
        !          1451:        return (error);
        !          1452: }

CVSweb