Annotation of kernel/bsd/kern/uipc_syscalls.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1982, 1986, 1989, 1990, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  *
                     30:  * Redistribution and use in source and binary forms, with or without
                     31:  * modification, are permitted provided that the following conditions
                     32:  * are met:
                     33:  * 1. Redistributions of source code must retain the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer.
                     35:  * 2. Redistributions in binary form must reproduce the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer in the
                     37:  *    documentation and/or other materials provided with the distribution.
                     38:  * 3. All advertising materials mentioning features or use of this software
                     39:  *    must display the following acknowledgement:
                     40:  *     This product includes software developed by the University of
                     41:  *     California, Berkeley and its contributors.
                     42:  * 4. Neither the name of the University nor the names of its contributors
                     43:  *    may be used to endorse or promote products derived from this software
                     44:  *    without specific prior written permission.
                     45:  *
                     46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     56:  * SUCH DAMAGE.
                     57:  *
                     58:  *     @(#)uipc_syscalls.c     8.6 (Berkeley) 2/14/95
                     59:  */
                     60: 
                     61: #include <sys/param.h>
                     62: #include <sys/systm.h>
                     63: #include <sys/filedesc.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/file.h>
                     66: #include <sys/buf.h>
                     67: #include <sys/malloc.h>
                     68: #include <sys/mbuf.h>
                     69: #include <sys/protosw.h>
                     70: #include <sys/socket.h>
                     71: #include <sys/socketvar.h>
                     72: #if KTRACE
                     73: #include <sys/ktrace.h>
                     74: #endif
                     75: #include <sys/kernel.h>
                     76: 
                     77: #if NEXT
                     78: #import <kern/kdebug.h>
                     79: 
                     80: #if KDEBUG
                     81: 
                     82: #define DBG_LAYER_IN_BEG       NETDBG_CODE(DBG_NETSOCK, 0)
                     83: #define DBG_LAYER_IN_END       NETDBG_CODE(DBG_NETSOCK, 2)
                     84: #define DBG_LAYER_OUT_BEG      NETDBG_CODE(DBG_NETSOCK, 1)
                     85: #define DBG_LAYER_OUT_END      NETDBG_CODE(DBG_NETSOCK, 3)
                     86: #define DBG_FNC_SENDMSG                NETDBG_CODE(DBG_NETSOCK, (1 << 8) | 1)
                     87: #define DBG_FNC_SENDTO         NETDBG_CODE(DBG_NETSOCK, (2 << 8) | 1)
                     88: #define DBG_FNC_SENDIT         NETDBG_CODE(DBG_NETSOCK, (3 << 8) | 1)
                     89: #define DBG_FNC_RECVFROM       NETDBG_CODE(DBG_NETSOCK, (5 << 8))
                     90: #define DBG_FNC_RECVMSG                NETDBG_CODE(DBG_NETSOCK, (6 << 8))
                     91: #define DBG_FNC_RECVIT         NETDBG_CODE(DBG_NETSOCK, (7 << 8))
                     92: 
                     93: 
                     94: #endif
                     95: 
                     96: #endif
                     97: 
                     98: 
                     99: 
                    100: /*
                    101:  * System call interface to the socket abstraction.
                    102:  */
                    103: #if COMPAT_43
                    104: #define COMPAT_OLDSOCK
                    105: #endif
                    106: 
                    107: extern struct fileops socketops;
                    108: 
                    109: struct socket_args {
                    110:        int     domain;
                    111:        int     type;
                    112:        int     protocol;
                    113: };
                    114: int
                    115: socket(p, uap, retval)
                    116:        struct proc *p;
                    117:        register struct socket_args *uap;
                    118:        register_t *retval;
                    119: {
                    120:        struct socket *so;
                    121:        struct file *fp;
                    122:        int fd, error;
                    123: 
                    124:        if (error = falloc(p, &fp, &fd))
                    125:                return (error);
                    126:        fp->f_flag = FREAD|FWRITE;
                    127:        fp->f_type = DTYPE_SOCKET;
                    128:        fp->f_ops = &socketops;
                    129:        if (error = socreate(uap->domain, &so, uap->type,
                    130:            uap->protocol)) {
                    131:                fdrelse(p, fd);
                    132:                ffree(fp);
                    133:        } else {
                    134:                fp->f_data = (caddr_t)so;
                    135:                *fdflags(p, fd) &= ~UF_RESERVED;
                    136:                *retval = fd;
                    137:        }
                    138:        return (error);
                    139: }
                    140: 
                    141: struct bind_args {
                    142:        int     s;
                    143:        caddr_t name;
                    144:        int     namelen;
                    145: };
                    146: 
                    147: /* ARGSUSED */
                    148: int
                    149: bind(p, uap, retval)
                    150:        struct proc *p;
                    151:        register struct bind_args *uap;
                    152:        register_t *retval;
                    153: {
                    154:        struct file *fp;
                    155:        struct mbuf *nam;
                    156:        int error;
                    157: 
                    158:        if (error = getsock(p, uap->s, &fp))
                    159:                return (error);
                    160:        if (error = sockargs(&nam, uap->name, uap->namelen,
                    161:            MT_SONAME))
                    162:                return (error);
                    163:        error = sobind((struct socket *)fp->f_data, nam);
                    164:        m_freem(nam);
                    165:        return (error);
                    166: }
                    167: 
                    168: struct listen_args {
                    169:        int     s;
                    170:        int     backlog;
                    171: };
                    172: /* ARGSUSED */
                    173: int
                    174: listen(p, uap, retval)
                    175:        struct proc *p;
                    176:        register struct listen_args *uap;
                    177:        register_t *retval;
                    178: {
                    179:        struct file *fp;
                    180:        int error;
                    181: 
                    182:        if (error = getsock(p, uap->s, &fp))
                    183:                return (error);
                    184:        return (solisten((struct socket *)fp->f_data, uap->backlog));
                    185: }
                    186: 
                    187: struct accept_args {
                    188:        int     s;
                    189:        caddr_t name;
                    190:        int     *anamelen;
                    191: };
                    192: #ifdef COMPAT_OLDSOCK
                    193: int
                    194: accept(p, uap, retval)
                    195:        struct proc *p;
                    196:        struct accept_args *uap;
                    197:        register_t *retval;
                    198: {
                    199: 
                    200:        return (accept1(p, uap, retval, 0));
                    201: }
                    202: 
                    203: int
                    204: oaccept(p, uap, retval)
                    205:        struct proc *p;
                    206:        struct accept_args *uap;
                    207:        register_t *retval;
                    208: {
                    209: 
                    210:        return (accept1(p, uap, retval, 1));
                    211: }
                    212: #else /* COMPAT_OLDSOCK */
                    213: 
                    214: #define        accept1 accept
                    215: #endif
                    216: 
                    217: int
                    218: accept1(p, uap, retval, compat_43)
                    219:        struct proc *p;
                    220:        register struct accept_args *uap;
                    221:        register_t *retval;
                    222:        int compat_43;
                    223: {
                    224:        struct file *fp;
                    225:        struct mbuf *nam;
                    226:        u_int namelen;
                    227:        int error, s, tmpfd;
                    228:        register struct socket *so;
                    229: 
                    230:        if (uap->name && (error = copyin((caddr_t)uap->anamelen,
                    231:            (caddr_t)&namelen, sizeof (namelen))))
                    232:                return (error);
                    233:        if (error = getsock(p, uap->s, &fp))
                    234:                return (error);
                    235:        s = splnet();
                    236:        so = (struct socket *)fp->f_data;
                    237:        if ((so->so_options & SO_ACCEPTCONN) == 0) {
                    238:                splx(s);
                    239:                return (EINVAL);
                    240:        }
                    241:        if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
                    242:                splx(s);
                    243:                return (EWOULDBLOCK);
                    244:        }
                    245:        /*
                    246:         * Move the falloc before tsleep so that we can correctly have 
                    247:         * multiple accept().
                    248:         */
                    249:        if (error = falloc(p, &fp, &tmpfd)) {
                    250:                splx(s);
                    251:                return (error);
                    252:        }
                    253:        while (so->so_qlen == 0 && so->so_error == 0) {
                    254:                if (so->so_state & SS_CANTRCVMORE) {
                    255:                        so->so_error = ECONNABORTED;
                    256:                        break;
                    257:                }
                    258:                if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
                    259:                    netcon, 0)) {
                    260:                        goto ffreeout;
                    261:                }
                    262:        }
                    263:        if (so->so_error) {
                    264:                error = so->so_error;
                    265:                so->so_error = 0;
                    266:                goto ffreeout;
                    267:        }
                    268:        *fdflags(p, tmpfd) &= ~UF_RESERVED;
                    269:        *retval = tmpfd;
                    270:        { struct socket *aso = so->so_q;
                    271:          if (soqremque(aso, 1) == 0)
                    272:                panic("accept");
                    273:          so = aso;
                    274:        }
                    275:        fp->f_type = DTYPE_SOCKET;
                    276:        fp->f_flag = FREAD|FWRITE;
                    277:        fp->f_ops = &socketops;
                    278:        fp->f_data = (caddr_t)so;
                    279:        nam = m_get(M_WAIT, MT_SONAME);
                    280:        (void) soaccept(so, nam);
                    281:        if (uap->name) {
                    282: #ifdef COMPAT_OLDSOCK
                    283:                if (compat_43)
                    284:                        mtod(nam, struct osockaddr *)->sa_family =
                    285:                            mtod(nam, struct sockaddr *)->sa_family;
                    286: #endif
                    287:                if (namelen > nam->m_len)
                    288:                        namelen = nam->m_len;
                    289:                /* SHOULD COPY OUT A CHAIN HERE */
                    290:                if ((error = copyout(mtod(nam, caddr_t),
                    291:                    (caddr_t)uap->name, (u_int)namelen)) == 0)
                    292:                        error = copyout((caddr_t)&namelen,
                    293:                            (caddr_t)uap->anamelen,
                    294:                            sizeof (*uap->anamelen));
                    295:        }
                    296:        m_freem(nam);
                    297:        splx(s);
                    298:        return (error);
                    299: 
                    300: ffreeout:
                    301:        fdrelse(p, tmpfd);
                    302:        ffree(fp);
                    303:        splx(s);
                    304:        return (error);
                    305: }
                    306: 
                    307: struct connect_args {
                    308:        int s;
                    309:        caddr_t name;
                    310:        int     namelen;
                    311: };
                    312: /* ARGSUSED */
                    313: int
                    314: connect(p, uap, retval)
                    315:        struct proc *p;
                    316:        register struct connect_args *uap;
                    317:        register_t *retval;
                    318: {
                    319:        struct file *fp;
                    320:        register struct socket *so;
                    321:        struct mbuf *nam;
                    322:        int error, s;
                    323: 
                    324:        if (error = getsock(p, uap->s, &fp))
                    325:                return (error);
                    326:        so = (struct socket *)fp->f_data;
                    327:        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
                    328:                return (EALREADY);
                    329:        if (error = sockargs(&nam, uap->name, uap->namelen,
                    330:            MT_SONAME))
                    331:                return (error);
                    332:        error = soconnect(so, nam);
                    333:        if (error)
                    334:                goto bad;
                    335:        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
                    336:                m_freem(nam);
                    337:                return (EINPROGRESS);
                    338:        }
                    339:        s = splnet();
                    340:        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
                    341:                if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
                    342:                    netcon, 0))
                    343:                        break;
                    344:        if (error == 0) {
                    345:                error = so->so_error;
                    346:                so->so_error = 0;
                    347:        }
                    348:        splx(s);
                    349: bad:
                    350:        so->so_state &= ~SS_ISCONNECTING;
                    351:        m_freem(nam);
                    352:        if (error == ERESTART)
                    353:                error = EINTR;
                    354:        return (error);
                    355: }
                    356: 
                    357: struct socketpair_args {
                    358:        int     domain;
                    359:        int     type;
                    360:        int     protocol;
                    361:        int     *rsv;
                    362: };
                    363: int
                    364: socketpair(p, uap, retval)
                    365:        struct proc *p;
                    366:        register struct socketpair_args *uap;
                    367:        register_t *retval;
                    368: {
                    369:        struct file *fp1, *fp2;
                    370:        struct socket *so1, *so2;
                    371:        int fd, error, sv[2];
                    372: 
                    373:        if (error = socreate(uap->domain, &so1, uap->type,
                    374:            uap->protocol))
                    375:                return (error);
                    376:        if (error = socreate(uap->domain, &so2, uap->type,
                    377:            uap->protocol))
                    378:                goto free1;
                    379:        if (error = falloc(p, &fp1, &fd))
                    380:                goto free2;
                    381:        sv[0] = fd;
                    382:        fp1->f_flag = FREAD|FWRITE;
                    383:        fp1->f_type = DTYPE_SOCKET;
                    384:        fp1->f_ops = &socketops;
                    385:        fp1->f_data = (caddr_t)so1;
                    386:        if (error = falloc(p, &fp2, &fd))
                    387:                goto free3;
                    388:        fp2->f_flag = FREAD|FWRITE;
                    389:        fp2->f_type = DTYPE_SOCKET;
                    390:        fp2->f_ops = &socketops;
                    391:        fp2->f_data = (caddr_t)so2;
                    392:        sv[1] = fd;
                    393:        if (error = soconnect2(so1, so2))
                    394:                goto free4;
                    395:        if (uap->type == SOCK_DGRAM) {
                    396:                /*
                    397:                 * Datagram socket connection is asymmetric.
                    398:                 */
                    399:                 if (error = soconnect2(so2, so1))
                    400:                        goto free4;
                    401:        }
                    402:        *fdflags(p, sv[0]) &= ~UF_RESERVED;
                    403:        *fdflags(p, sv[1]) &= ~UF_RESERVED;
                    404:        error = copyout((caddr_t)sv, (caddr_t)uap->rsv,
                    405:            2 * sizeof (int));
                    406: #if 0   /* old pipe(2) syscall compatability, unused these days */
                    407:        retval[0] = sv[0];              /* XXX ??? */
                    408:        retval[1] = sv[1];              /* XXX ??? */
                    409: #endif /* 0 */
                    410:        return (error);
                    411: free4:
                    412:        fdrelse(p, sv[1]);
                    413:        ffree(fp2);
                    414: free3:
                    415:        fdrelse(p, sv[0]);
                    416:        ffree(fp1);
                    417: free2:
                    418:        (void)soclose(so2);
                    419: free1:
                    420:        (void)soclose(so1);
                    421:        return (error);
                    422: }
                    423: 
                    424: int sendit(struct proc *, int, struct msghdr *, int, register_t *);
                    425: 
                    426: struct sendto_args {
                    427:        int s;
                    428:        caddr_t buf;
                    429:        size_t len;
                    430:        int flags;
                    431:        caddr_t to;
                    432:        int tolen;
                    433: };
                    434: int
                    435: sendto(p, uap, retval)
                    436:        struct proc *p;
                    437:        register struct sendto_args *uap;
                    438:        register_t *retval;
                    439: {
                    440:        struct msghdr msg;
                    441:        struct iovec aiov;
                    442:        int          stat;
                    443: 
                    444:        KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_START, 0,0,0,0,0);
                    445: 
                    446:        msg.msg_name = uap->to;
                    447:        msg.msg_namelen = uap->tolen;
                    448:        msg.msg_iov = &aiov;
                    449:        msg.msg_iovlen = 1;
                    450:        msg.msg_control = 0;
                    451: #ifdef COMPAT_OLDSOCK
                    452:        msg.msg_flags = 0;
                    453: #endif
                    454:        aiov.iov_base = uap->buf;
                    455:        aiov.iov_len = uap->len;
                    456: 
                    457:        stat = sendit(p, uap->s, &msg, uap->flags, retval);
                    458:        KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_END, stat, *retval,0,0,0);
                    459:        return (stat);
                    460: }
                    461: 
                    462: #ifdef COMPAT_OLDSOCK
                    463: struct osend_args {
                    464:        int s;
                    465:        caddr_t buf;
                    466:        int len;
                    467:        int flags;
                    468: };
                    469: int
                    470: osend(p, uap, retval)
                    471:        struct proc *p;
                    472:        register struct osend_args *uap;
                    473:        register_t *retval;
                    474: {
                    475:        struct msghdr msg;
                    476:        struct iovec aiov;
                    477: 
                    478:        msg.msg_name = 0;
                    479:        msg.msg_namelen = 0;
                    480:        msg.msg_iov = &aiov;
                    481:        msg.msg_iovlen = 1;
                    482:        aiov.iov_base = uap->buf;
                    483:        aiov.iov_len = uap->len;
                    484:        msg.msg_control = 0;
                    485:        msg.msg_flags = 0;
                    486:        return (sendit(p, uap->s, &msg, uap->flags, retval));
                    487: }
                    488: 
                    489: #define MSG_COMPAT     0x8000
                    490: struct osendmsg_args {
                    491:        int s;
                    492:        caddr_t msg;
                    493:        int flags;
                    494: };
                    495: int
                    496: osendmsg(p, uap, retval)
                    497:        struct proc *p;
                    498:        register struct osendmsg_args *uap;
                    499:        register_t *retval;
                    500: {
                    501:        struct msghdr msg;
                    502:        struct iovec aiov[UIO_SMALLIOV], *iov;
                    503:        int error;
                    504:        u_int iovlen;
                    505: 
                    506:        if (error = copyin(uap->msg, (caddr_t)&msg,
                    507:            sizeof (struct omsghdr)))
                    508:                return (error);
                    509:        iovlen = (u_int)msg.msg_iovlen;
                    510:        if (iovlen >= UIO_SMALLIOV) {
                    511:                if (iovlen >= UIO_MAXIOV)
                    512:                        return (EMSGSIZE);
                    513:                MALLOC_ZONE(iov, struct iovec *,
                    514:                        sizeof(struct iovec) * iovlen, M_IOV, M_WAITOK);
                    515:        } else
                    516:                iov = aiov;
                    517:        if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
                    518:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
                    519:                goto done;
                    520:        msg.msg_flags = MSG_COMPAT;
                    521:        msg.msg_iov = iov;
                    522:        error = sendit(p, uap->s, &msg, uap->flags, retval);
                    523: done:
                    524:        if (iov != aiov)
                    525:                FREE_ZONE(iov, sizeof (struct iovec) * iovlen, M_IOV);
                    526:        return (error);
                    527: }
                    528: #endif
                    529: 
                    530: struct sendmsg_args {
                    531:        int s;
                    532:        caddr_t msg;
                    533:        int flags;
                    534: };
                    535: int
                    536: sendmsg(p, uap, retval)
                    537:        struct proc *p;
                    538:        register struct sendmsg_args *uap;
                    539:        register_t *retval;
                    540: {
                    541:        struct msghdr msg;
                    542:        struct iovec aiov[UIO_SMALLIOV], *iov;
                    543:        int error;
                    544:        u_int iovlen;
                    545: 
                    546:        KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_START, 0,0,0,0,0);
                    547:        if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)))
                    548:        {
                    549:            KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, error,0,0,0,0);
                    550:            return (error);
                    551:        }
                    552: 
                    553:        iovlen = (u_int)msg.msg_iovlen;
                    554:        if (iovlen >= UIO_SMALLIOV) {
                    555:                if (iovlen >= UIO_MAXIOV)
                    556:                {
                    557:                    KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, EMSGSIZE,0,0,0,0);
                    558:                    return (EMSGSIZE);
                    559:                }
                    560: 
                    561:                MALLOC_ZONE(iov, struct iovec *,
                    562:                        sizeof(struct iovec) * iovlen, M_IOV, M_WAITOK);
                    563:        } else
                    564:                iov = aiov;
                    565:        if (msg.msg_iovlen &&
                    566:            (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
                    567:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
                    568:                goto done;
                    569:        msg.msg_iov = iov;
                    570: #ifdef COMPAT_OLDSOCK
                    571:        msg.msg_flags = 0;
                    572: #endif
                    573:        error = sendit(p, uap->s, &msg, uap->flags, retval);
                    574: done:
                    575:        if (iov != aiov)
                    576:                FREE_ZONE(iov, sizeof (struct iovec) * iovlen, M_IOV);
                    577:        KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, error,0,0,0,0);
                    578:        return (error);
                    579: }
                    580: 
                    581: int
                    582: sendit(p, s, mp, flags, retsize)
                    583:        register struct proc *p;
                    584:        int s;
                    585:        register struct msghdr *mp;
                    586:        int flags;
                    587:        register_t *retsize;
                    588: {
                    589:        struct file *fp;
                    590:        struct uio auio;
                    591:        register struct iovec *iov;
                    592:        register int i;
                    593:        struct mbuf *to, *control;
                    594:        int len, error;
                    595: #if KTRACE
                    596:        struct iovec *ktriov = NULL;
                    597: #endif
                    598:        
                    599:        KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_START, 0,0,0,0,0);
                    600: 
                    601:        if (error = getsock(p, s, &fp))
                    602:        {
                    603:            KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
                    604:            return (error);
                    605:        }
                    606: 
                    607:        auio.uio_iov = mp->msg_iov;
                    608:        auio.uio_iovcnt = mp->msg_iovlen;
                    609:        auio.uio_segflg = UIO_USERSPACE;
                    610:        auio.uio_rw = UIO_WRITE;
                    611:        auio.uio_procp = p;
                    612:        auio.uio_offset = 0;                    /* XXX */
                    613:        auio.uio_resid = 0;
                    614:        iov = mp->msg_iov;
                    615:        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                    616:                if (iov->iov_len < 0)
                    617:                {
                    618:                    KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, EINVAL,0,0,0,0);
                    619:                    return (EINVAL);
                    620:                }
                    621: 
                    622:                if ((auio.uio_resid += iov->iov_len) < 0)
                    623:                {
                    624:                    KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, EINVAL,0,0,0,0);
                    625:                    return (EINVAL);
                    626:                }
                    627:        }
                    628:        if (mp->msg_name) {
                    629:                if (error = sockargs(&to, mp->msg_name, mp->msg_namelen,
                    630:                    MT_SONAME))
                    631:                {
                    632:                    KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
                    633:                    return (error);
                    634:                }
                    635:        } else
                    636:                to = 0;
                    637:        if (mp->msg_control) {
                    638:                if (mp->msg_controllen < sizeof(struct cmsghdr)
                    639: #ifdef COMPAT_OLDSOCK
                    640:                    && mp->msg_flags != MSG_COMPAT
                    641: #endif
                    642:                ) {
                    643:                        error = EINVAL;
                    644:                        goto bad;
                    645:                }
                    646:                if (error = sockargs(&control, mp->msg_control,
                    647:                    mp->msg_controllen, MT_CONTROL))
                    648:                        goto bad;
                    649: #ifdef COMPAT_OLDSOCK
                    650:                if (mp->msg_flags == MSG_COMPAT) {
                    651:                        register struct cmsghdr *cm;
                    652: 
                    653:                        M_PREPEND(control, sizeof(*cm), M_WAIT);
                    654:                        if (control == 0) {
                    655:                                error = ENOBUFS;
                    656:                                goto bad;
                    657:                        } else {
                    658:                                cm = mtod(control, struct cmsghdr *);
                    659:                                cm->cmsg_len = control->m_len;
                    660:                                cm->cmsg_level = SOL_SOCKET;
                    661:                                cm->cmsg_type = SCM_RIGHTS;
                    662:                        }
                    663:                }
                    664: #endif
                    665:        } else
                    666:                control = 0;
                    667: #if KTRACE
                    668:        if (KTRPOINT(p, KTR_GENIO)) {
                    669:                int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
                    670: 
                    671:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    672:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    673:        }
                    674: #endif
                    675:        len = auio.uio_resid;
                    676:        if (error = sosend((struct socket *)fp->f_data, to, &auio,
                    677:            (struct mbuf *)0, control, flags)) {
                    678:                if (auio.uio_resid != len && (error == ERESTART ||
                    679:                    error == EINTR || error == EWOULDBLOCK))
                    680:                        error = 0;
                    681:                if (error == EPIPE)
                    682:                        psignal(p, SIGPIPE);
                    683:        }
                    684:        if (error == 0)
                    685:                *retsize = len - auio.uio_resid;
                    686: #if KTRACE
                    687:        if (ktriov != NULL) {
                    688:                if (error == 0)
                    689:                        ktrgenio(p->p_tracep, s, UIO_WRITE,
                    690:                                ktriov, *retsize, error);
                    691:                FREE(ktriov, M_TEMP);
                    692:        }
                    693: #endif
                    694: bad:
                    695:        if (to)
                    696:                m_freem(to);
                    697: 
                    698:        KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
                    699:        return (error);
                    700: }
                    701: 
                    702: struct recvfrom_args {
                    703:        int     s;
                    704:        caddr_t buf;
                    705:        size_t  len;
                    706:        int     flags;
                    707:        caddr_t from;
                    708:        int     *fromlenaddr;
                    709: };
                    710: #ifdef COMPAT_OLDSOCK
                    711: int
                    712: orecvfrom(p, uap, retval)
                    713:        struct proc *p;
                    714:        struct recvfrom_args *uap;
                    715:        register_t *retval;
                    716: {
                    717: 
                    718:        uap->flags |= MSG_COMPAT;
                    719:        return (recvfrom(p, uap, retval));
                    720: }
                    721: #endif
                    722: 
                    723: int
                    724: recvfrom(p, uap, retval)
                    725:        struct proc *p;
                    726:        register struct recvfrom_args *uap;
                    727:        register_t *retval;
                    728: {
                    729:        struct msghdr msg;
                    730:        struct iovec aiov;
                    731:        int error;
                    732: 
                    733: 
                    734:        KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_START, 0,0,0,0,0);
                    735: 
                    736:        if (uap->fromlenaddr) {
                    737:                if (error = copyin((caddr_t)uap->fromlenaddr,
                    738:                    (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)))
                    739:                {
                    740:                    KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_END, error,0,0,0,0);
                    741:                    return (error);
                    742:                }
                    743:        } else
                    744:                msg.msg_namelen = 0;
                    745:        msg.msg_name = uap->from;
                    746:        msg.msg_iov = &aiov;
                    747:        msg.msg_iovlen = 1;
                    748:        aiov.iov_base = uap->buf;
                    749:        aiov.iov_len = uap->len;
                    750:        msg.msg_control = 0;
                    751:        msg.msg_flags = uap->flags;
                    752:        error = recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval);
                    753:        KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_END, error,0,0,0,0);
                    754:        return (error);
                    755: }
                    756: 
                    757: #ifdef COMPAT_OLDSOCK
                    758: struct orecv_args {
                    759:        int     s;
                    760:        caddr_t buf;
                    761:        int     len;
                    762:        int     flags;
                    763: };
                    764: int
                    765: orecv(p, uap, retval)
                    766:        struct proc *p;
                    767:        register struct orecv_args *uap;
                    768:        register_t *retval;
                    769: {
                    770:        struct msghdr msg;
                    771:        struct iovec aiov;
                    772: 
                    773:        msg.msg_name = 0;
                    774:        msg.msg_namelen = 0;
                    775:        msg.msg_iov = &aiov;
                    776:        msg.msg_iovlen = 1;
                    777:        aiov.iov_base = uap->buf;
                    778:        aiov.iov_len = uap->len;
                    779:        msg.msg_control = 0;
                    780:        msg.msg_flags = uap->flags;
                    781:        return (recvit(p, uap->s, &msg, (caddr_t)0, retval));
                    782: }
                    783: 
                    784: /*
                    785:  * Old recvmsg.  This code takes advantage of the fact that the old msghdr
                    786:  * overlays the new one, missing only the flags, and with the (old) access
                    787:  * rights where the control fields are now.
                    788:  */
                    789: struct orecvmsg_args {
                    790:        int     s;
                    791:        struct  omsghdr *msg;
                    792:        int     flags;
                    793: };
                    794: int
                    795: orecvmsg(p, uap, retval)
                    796:        struct proc *p;
                    797:        register struct orecvmsg_args *uap;
                    798:        register_t *retval;
                    799: {
                    800:        struct msghdr msg;
                    801:        struct iovec aiov[UIO_SMALLIOV], *iov;
                    802:        int error;
                    803:        u_int iovlen;
                    804: 
                    805:        if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
                    806:            sizeof (struct omsghdr)))
                    807:                return (error);
                    808:        iovlen = (u_int)msg.msg_iovlen;
                    809:        if (iovlen >= UIO_SMALLIOV) {
                    810:                if (iovlen >= UIO_MAXIOV)
                    811:                        return (EMSGSIZE);
                    812:                MALLOC_ZONE(iov, struct iovec *,
                    813:                        sizeof(struct iovec) * iovlen, M_IOV, M_WAITOK);
                    814:        } else
                    815:                iov = aiov;
                    816:        msg.msg_flags = uap->flags | MSG_COMPAT;
                    817:        if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
                    818:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
                    819:                goto done;
                    820:        msg.msg_iov = iov;
                    821:        error = recvit(p, uap->s, &msg,
                    822:            (caddr_t)&uap->msg->msg_namelen, retval);
                    823: 
                    824:        if (msg.msg_controllen && error == 0)
                    825:                error = copyout((caddr_t)&msg.msg_controllen,
                    826:                    (caddr_t)&uap->msg->msg_accrightslen, sizeof (int));
                    827: done:
                    828:        if (iov != aiov)
                    829:                FREE_ZONE(iov, sizeof (struct iovec) * iovlen, M_IOV);
                    830:        return (error);
                    831: }
                    832: #endif
                    833: 
                    834: struct recvmsg_args {
                    835:        int     s;
                    836:        struct  msghdr *msg;
                    837:        int     flags;
                    838: };
                    839: int
                    840: recvmsg(p, uap, retval)
                    841:        struct proc *p;
                    842:        register struct recvmsg_args *uap;
                    843:        register_t *retval;
                    844: {
                    845:        struct msghdr msg;
                    846:        struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
                    847:        register int error;
                    848:        u_int iovlen;
                    849: 
                    850:        KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_START, 0,0,0,0,0);
                    851:        if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
                    852:            sizeof (msg)))
                    853:        {
                    854:                KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error,0,0,0,0);
                    855:                return (error);
                    856:        }
                    857: 
                    858:        iovlen = (u_int)msg.msg_iovlen;
                    859:        if (iovlen >= UIO_SMALLIOV) {
                    860:                if (iovlen >= UIO_MAXIOV)
                    861:                {
                    862:                    KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error,0,0,0,0);
                    863:                    return (EMSGSIZE);
                    864:                }
                    865: 
                    866:                MALLOC_ZONE(iov, struct iovec *,
                    867:                        sizeof(struct iovec) * iovlen, M_IOV, M_WAITOK);
                    868:        } else
                    869:                iov = aiov;
                    870: #ifdef COMPAT_OLDSOCK
                    871:        msg.msg_flags = uap->flags &~ MSG_COMPAT;
                    872: #else
                    873:        msg.msg_flags = uap->flags;
                    874: #endif
                    875:        uiov = msg.msg_iov;
                    876:        msg.msg_iov = iov;
                    877:        if (error = copyin((caddr_t)uiov, (caddr_t)iov,
                    878:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
                    879:                goto done;
                    880:        if ((error = recvit(p, uap->s, &msg, (caddr_t)0, retval)) == 0) {
                    881:                msg.msg_iov = uiov;
                    882:                error = copyout((caddr_t)&msg, (caddr_t)uap->msg,
                    883:                    sizeof(msg));
                    884:        }
                    885: done:
                    886:        if (iov != aiov)
                    887:                FREE_ZONE(iov, sizeof (struct iovec) * iovlen, M_IOV);
                    888: 
                    889:        KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error,0,0,0,0);
                    890:        return (error);
                    891: }
                    892: 
                    893: int
                    894: recvit(p, s, mp, namelenp, retsize)
                    895:        register struct proc *p;
                    896:        int s;
                    897:        register struct msghdr *mp;
                    898:        caddr_t namelenp;
                    899:        register_t *retsize;
                    900: {
                    901:        struct file *fp;
                    902:        struct uio auio;
                    903:        register struct iovec *iov;
                    904:        register int i;
                    905:        int len, error;
                    906:        struct mbuf *from = 0, *control = 0;
                    907: #if KTRACE
                    908:        struct iovec *ktriov = NULL;
                    909: #endif
                    910:        
                    911:        KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_START, 0,0,0,0,0);
                    912:        if (error = getsock(p, s, &fp))
                    913:        {
                    914:            KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, error,0,0,0,0);
                    915:            return (error);
                    916:        }
                    917: 
                    918:        auio.uio_iov = mp->msg_iov;
                    919:        auio.uio_iovcnt = mp->msg_iovlen;
                    920:        auio.uio_segflg = UIO_USERSPACE;
                    921:        auio.uio_rw = UIO_READ;
                    922:        auio.uio_procp = p;
                    923:        auio.uio_offset = 0;                    /* XXX */
                    924:        auio.uio_resid = 0;
                    925:        iov = mp->msg_iov;
                    926:        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                    927:                if (iov->iov_len < 0)
                    928:                {
                    929:                    KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, EINVAL,0,0,0,0);
                    930:                    return (EINVAL);
                    931:                }
                    932:                if ((auio.uio_resid += iov->iov_len) < 0)
                    933:                {
                    934:                    KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, EINVAL,0,0,0,0);
                    935:                    return (EINVAL);
                    936:                }
                    937: 
                    938:        }
                    939: #if KTRACE
                    940:        if (KTRPOINT(p, KTR_GENIO)) {
                    941:                int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
                    942: 
                    943:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    944:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    945:        }
                    946: #endif
                    947:        len = auio.uio_resid;
                    948:        if (error = soreceive((struct socket *)fp->f_data, &from, &auio,
                    949:            (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
                    950:            &mp->msg_flags)) {
                    951:                if (auio.uio_resid != len && (error == ERESTART ||
                    952:                    error == EINTR || error == EWOULDBLOCK))
                    953:                        error = 0;
                    954:        }
                    955: #if KTRACE
                    956:        if (ktriov != NULL) {
                    957:                if (error == 0)
                    958:                        ktrgenio(p->p_tracep, s, UIO_READ,
                    959:                                ktriov, len - auio.uio_resid, error);
                    960:                FREE(ktriov, M_TEMP);
                    961:        }
                    962: #endif
                    963:        if (error)
                    964:                goto out;
                    965:        *retsize = len - auio.uio_resid;
                    966:        if (mp->msg_name) {
                    967:                len = mp->msg_namelen;
                    968:                if (len <= 0 || from == 0)
                    969:                        len = 0;
                    970:                else {
                    971: #ifdef COMPAT_OLDSOCK
                    972:                        if (mp->msg_flags & MSG_COMPAT)
                    973:                                mtod(from, struct osockaddr *)->sa_family =
                    974:                                    mtod(from, struct sockaddr *)->sa_family;
                    975: #endif
                    976:                        if (len > from->m_len)
                    977:                                len = from->m_len;
                    978:                        /* else if len < from->m_len ??? */
                    979:                        if (error = copyout(mtod(from, caddr_t),
                    980:                            (caddr_t)mp->msg_name, (unsigned)len))
                    981:                                goto out;
                    982:                }
                    983:                mp->msg_namelen = len;
                    984:                if (namelenp &&
                    985:                    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
                    986: #ifdef COMPAT_OLDSOCK
                    987:                        if (mp->msg_flags & MSG_COMPAT)
                    988:                                error = 0;      /* old recvfrom didn't check */
                    989:                        else
                    990: #endif
                    991:                        goto out;
                    992:                }
                    993:        }
                    994:        if (mp->msg_control) {
                    995: #ifdef COMPAT_OLDSOCK
                    996:                /*
                    997:                 * We assume that old recvmsg calls won't receive access
                    998:                 * rights and other control info, esp. as control info
                    999:                 * is always optional and those options didn't exist in 4.3.
                   1000:                 * If we receive rights, trim the cmsghdr; anything else
                   1001:                 * is tossed.
                   1002:                 */
                   1003:                if (control && mp->msg_flags & MSG_COMPAT) {
                   1004:                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
                   1005:                            SOL_SOCKET ||
                   1006:                            mtod(control, struct cmsghdr *)->cmsg_type !=
                   1007:                            SCM_RIGHTS) {
                   1008:                                mp->msg_controllen = 0;
                   1009:                                goto out;
                   1010:                        }
                   1011:                        control->m_len -= sizeof (struct cmsghdr);
                   1012:                        control->m_data += sizeof (struct cmsghdr);
                   1013:                }
                   1014: #endif
                   1015:                len = 0;
                   1016:                if (mp->msg_controllen <= 0 || control == 0)
                   1017:                        ;
                   1018:                else {
                   1019:                        struct mbuf * c = control;
                   1020:                        
                   1021:                        for (c = control; 
                   1022:                             c && len < mp->msg_controllen && !error;
                   1023:                             c = c->m_next) {
                   1024:                                int clen;
                   1025:                                clen = c->m_len;
                   1026:                                if ((len + clen) > mp->msg_controllen) {
                   1027:                                        clen = mp->msg_controllen - len;
                   1028:                                        mp->msg_flags |= MSG_CTRUNC;
                   1029:                                }
                   1030:                                error = copyout((caddr_t)mtod(c, caddr_t),
                   1031:                                                (caddr_t)mp->msg_control + len,
                   1032:                                                (unsigned)clen);
                   1033:                                len += clen;
                   1034:                        }
                   1035:                }
                   1036:                mp->msg_controllen = len;
                   1037:        }
                   1038: out:
                   1039:        if (from)
                   1040:                m_freem(from);
                   1041:        if (control)
                   1042:                m_freem(control);
                   1043: 
                   1044:        KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, error,0,0,0,0);
                   1045:        return (error);
                   1046: }
                   1047: 
                   1048: struct shutdown_args {
                   1049:        int     s;
                   1050:        int     how;
                   1051: };
                   1052: /* ARGSUSED */
                   1053: int
                   1054: shutdown(p, uap, retval)
                   1055:        struct proc *p;
                   1056:        register struct shutdown_args *uap;
                   1057:        register_t *retval;
                   1058: {
                   1059:        struct file *fp;
                   1060:        int error;
                   1061: 
                   1062:        if (error = getsock(p, uap->s, &fp))
                   1063:                return (error);
                   1064:        return (soshutdown((struct socket *)fp->f_data, uap->how));
                   1065: }
                   1066: 
                   1067: struct setsockopt_args {
                   1068:        int     s;
                   1069:        int     level;
                   1070:        int     name;
                   1071:        caddr_t val;
                   1072:        int     valsize;
                   1073: };
                   1074: /* ARGSUSED */
                   1075: int
                   1076: setsockopt(p, uap, retval)
                   1077:        struct proc *p;
                   1078:        register struct setsockopt_args *uap;
                   1079:        register_t *retval;
                   1080: {
                   1081:        struct file *fp;
                   1082:        struct mbuf *m = NULL;
                   1083:        int error;
                   1084: 
                   1085:        if (error = getsock(p, uap->s, &fp))
                   1086:                return (error);
                   1087:        if (uap->valsize > MLEN)
                   1088:                return (EINVAL);
                   1089:        if (uap->val) {
                   1090:                m = m_get(M_WAIT, MT_SOOPTS);
                   1091:                if (m == NULL)
                   1092:                        return (ENOBUFS);
                   1093:                if (error = copyin(uap->val, mtod(m, caddr_t),
                   1094:                    (u_int)uap->valsize)) {
                   1095:                        (void) m_free(m);
                   1096:                        return (error);
                   1097:                }
                   1098:                m->m_len = uap->valsize;
                   1099:        }
                   1100:        return (sosetopt((struct socket *)fp->f_data, uap->level,
                   1101:            uap->name, m));
                   1102: }
                   1103: 
                   1104: struct getsockopt_args {
                   1105:        int     s;
                   1106:        int     level;
                   1107:        int     name;
                   1108:        caddr_t val;
                   1109:        int     *avalsize;
                   1110: };
                   1111: /* ARGSUSED */
                   1112: int
                   1113: getsockopt(p, uap, retval)
                   1114:        struct proc *p;
                   1115:        register struct getsockopt_args *uap;
                   1116:        register_t *retval;
                   1117: {
                   1118:        struct file *fp;
                   1119:        struct mbuf *m = NULL;
                   1120:        int valsize, error;
                   1121: 
                   1122:        if (error = getsock(p, uap->s, &fp))
                   1123:                return (error);
                   1124:        if (uap->val) {
                   1125:                if (error = copyin((caddr_t)uap->avalsize,
                   1126:                    (caddr_t)&valsize, sizeof (valsize)))
                   1127:                        return (error);
                   1128:        } else
                   1129:                valsize = 0;
                   1130:        if ((error = sogetopt((struct socket *)fp->f_data, uap->level,
                   1131:            uap->name, &m)) == 0 && uap->val && valsize &&
                   1132:            m != NULL) {
                   1133:                if (valsize > m->m_len)
                   1134:                        valsize = m->m_len;
                   1135:                error = copyout(mtod(m, caddr_t), uap->val,
                   1136:                    (u_int)valsize);
                   1137:                if (error == 0)
                   1138:                        error = copyout((caddr_t)&valsize,
                   1139:                            (caddr_t)uap->avalsize, sizeof (valsize));
                   1140:        }
                   1141:        if (m != NULL)
                   1142:                (void) m_free(m);
                   1143:        return (error);
                   1144: }
                   1145: 
                   1146: struct pipe_args {
                   1147:        int     dummy;
                   1148: };
                   1149: /* ARGSUSED */
                   1150: int
                   1151: pipe(p, uap, retval)
                   1152:        struct proc *p;
                   1153:        struct pipe_args *uap;
                   1154:        register_t *retval;
                   1155: {
                   1156:        struct file *rf, *wf;
                   1157:        struct socket *rso, *wso;
                   1158:        int fd, error;
                   1159: 
                   1160:        if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0))
                   1161:                return (error);
                   1162:        if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0))
                   1163:                goto free1;
                   1164:        if (error = falloc(p, &rf, &fd))
                   1165:                goto free2;
                   1166:        retval[0] = fd;
                   1167:        rf->f_flag = FREAD;
                   1168:        rf->f_type = DTYPE_SOCKET;
                   1169:        rf->f_ops = &socketops;
                   1170:        rf->f_data = (caddr_t)rso;
                   1171:        if (error = falloc(p, &wf, &fd))
                   1172:                goto free3;
                   1173:        wf->f_flag = FWRITE;
                   1174:        wf->f_type = DTYPE_SOCKET;
                   1175:        wf->f_ops = &socketops;
                   1176:        wf->f_data = (caddr_t)wso;
                   1177:        retval[1] = fd;
                   1178:        if (error = unp_connect2(wso, rso))
                   1179:                goto free4;
                   1180:        *fdflags(p, retval[0]) &= ~UF_RESERVED;
                   1181:        *fdflags(p, retval[1]) &= ~UF_RESERVED;
                   1182:        return (0);
                   1183: free4:
                   1184:        fdrelse(p, retval[1]);
                   1185:        ffree(wf);
                   1186: free3:
                   1187:        fdrelse(p, retval[0]);
                   1188:        ffree(rf);
                   1189: free2:
                   1190:        (void)soclose(wso);
                   1191: free1:
                   1192:        (void)soclose(rso);
                   1193:        return (error);
                   1194: }
                   1195: 
                   1196: /*
                   1197:  * Get socket name.
                   1198:  */
                   1199: struct getsockname_args {
                   1200:        int     fdes;
                   1201:        caddr_t asa;
                   1202:        int     *alen;
                   1203: };
                   1204: #ifdef COMPAT_OLDSOCK
                   1205: int
                   1206: getsockname(p, uap, retval)
                   1207:        struct proc *p;
                   1208:        struct getsockname_args *uap;
                   1209:        register_t *retval;
                   1210: {
                   1211:        return (getsockname1(p, uap, retval, 0));
                   1212: }
                   1213: 
                   1214: int
                   1215: ogetsockname(p, uap, retval)
                   1216:        struct proc *p;
                   1217:        struct getsockname_args *uap;
                   1218:        register_t *retval;
                   1219: {
                   1220:        return (getsockname1(p, uap, retval, 1));
                   1221: }
                   1222: #else /* COMPAT_OLDSOCK */
                   1223: 
                   1224: #define        getsockname1    getsockname
                   1225: #endif
                   1226: 
                   1227: /* ARGSUSED */
                   1228: int
                   1229: getsockname1(p, uap, retval, compat_43)
                   1230:        struct proc *p;
                   1231:        register struct getsockname_args *uap;
                   1232:        register_t *retval;
                   1233:        int compat_43;
                   1234: {
                   1235:        struct file *fp;
                   1236:        register struct socket *so;
                   1237:        struct mbuf *m;
                   1238:        int len, error;
                   1239: 
                   1240:        if (error = getsock(p, uap->fdes, &fp))
                   1241:                return (error);
                   1242:        if (error = copyin((caddr_t)uap->alen, (caddr_t)&len,
                   1243:            sizeof (len)))
                   1244:                return (error);
                   1245:        so = (struct socket *)fp->f_data;
                   1246:        m = m_getclr(M_WAIT, MT_SONAME);
                   1247:        if (m == NULL)
                   1248:                return (ENOBUFS);
                   1249:        if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
                   1250:                goto bad;
                   1251:        if (len > m->m_len)
                   1252:                len = m->m_len;
                   1253: #ifdef COMPAT_OLDSOCK
                   1254:        if (compat_43)
                   1255:                mtod(m, struct osockaddr *)->sa_family =
                   1256:                    mtod(m, struct sockaddr *)->sa_family;
                   1257: #endif
                   1258:        error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
                   1259:        if (error == 0)
                   1260:                error = copyout((caddr_t)&len, (caddr_t)uap->alen,
                   1261:                    sizeof (len));
                   1262: bad:
                   1263:        m_freem(m);
                   1264:        return (error);
                   1265: }
                   1266: 
                   1267: /*
                   1268:  * Get name of peer for connected socket.
                   1269:  */
                   1270: struct getpeername_args {
                   1271:        int     fdes;
                   1272:        caddr_t asa;
                   1273:        int     *alen;
                   1274: };
                   1275: #ifdef COMPAT_OLDSOCK
                   1276: int
                   1277: getpeername(p, uap, retval)
                   1278:        struct proc *p;
                   1279:        struct getpeername_args *uap;
                   1280:        register_t *retval;
                   1281: {
                   1282:        return (getpeername1(p, uap, retval, 0));
                   1283: }
                   1284: 
                   1285: int
                   1286: ogetpeername(p, uap, retval)
                   1287:        struct proc *p;
                   1288:        struct getpeername_args *uap;
                   1289:        register_t *retval;
                   1290: {
                   1291: 
                   1292:        return (getpeername1(p, uap, retval, 1));
                   1293: }
                   1294: #else /* COMPAT_OLDSOCK */
                   1295: 
                   1296: #define        getpeername1    getpeername
                   1297: #endif
                   1298: 
                   1299: /* ARGSUSED */
                   1300: int
                   1301: getpeername1(p, uap, retval, compat_43)
                   1302:        struct proc *p;
                   1303:        register struct getpeername_args *uap;
                   1304:        register_t *retval;
                   1305:        int compat_43;
                   1306: {
                   1307:        struct file *fp;
                   1308:        register struct socket *so;
                   1309:        struct mbuf *m;
                   1310:        int len, error;
                   1311: 
                   1312:        if (error = getsock(p, uap->fdes, &fp))
                   1313:                return (error);
                   1314:        so = (struct socket *)fp->f_data;
                   1315:        if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
                   1316:                return (ENOTCONN);
                   1317:        if (error =
                   1318:            copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)))
                   1319:                return (error);
                   1320:        m = m_getclr(M_WAIT, MT_SONAME);
                   1321:        if (m == NULL)
                   1322:                return (ENOBUFS);
                   1323:        if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
                   1324:                goto bad;
                   1325:        if (len > m->m_len)
                   1326:                len = m->m_len;
                   1327: #ifdef COMPAT_OLDSOCK
                   1328:        if (compat_43)
                   1329:                mtod(m, struct osockaddr *)->sa_family =
                   1330:                    mtod(m, struct sockaddr *)->sa_family;
                   1331: #endif
                   1332:        if (error =
                   1333:            copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len))
                   1334:                goto bad;
                   1335:        error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
                   1336: bad:
                   1337:        m_freem(m);
                   1338:        return (error);
                   1339: }
                   1340: 
                   1341: int
                   1342: sockargs(mp, buf, buflen, type)
                   1343:        struct mbuf **mp;
                   1344:        caddr_t buf;
                   1345:        int buflen, type;
                   1346: {
                   1347:        register struct sockaddr *sa;
                   1348:        register struct mbuf *m;
                   1349:        int error;
                   1350: 
                   1351:        if ((u_int)buflen > MLEN) {
                   1352: #ifdef COMPAT_OLDSOCK
                   1353:                if (type == MT_SONAME && (u_int)buflen <= 112)
                   1354:                        buflen = MLEN;          /* unix domain compat. hack */
                   1355:                else
                   1356: #endif
                   1357:                return (EINVAL);
                   1358:        }
                   1359:        m = m_get(M_WAIT, type);
                   1360:        if (m == NULL)
                   1361:                return (ENOBUFS);
                   1362:        m->m_len = buflen;
                   1363:        error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
                   1364:        if (error) {
                   1365:                (void) m_free(m);
                   1366:                return (error);
                   1367:        }
                   1368:        *mp = m;
                   1369:        if (type == MT_SONAME) {
                   1370:                sa = mtod(m, struct sockaddr *);
                   1371: 
                   1372: #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
                   1373:                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                   1374:                        sa->sa_family = sa->sa_len;
                   1375: #endif
                   1376:                sa->sa_len = buflen;
                   1377:        }
                   1378:        return (0);
                   1379: }
                   1380: 
                   1381: int
                   1382: getsock(p, fdes, fpp)
                   1383:        struct proc *p;
                   1384:        int fdes;
                   1385:        struct file **fpp;
                   1386: {
                   1387:        struct file *fp;
                   1388:        int error;
                   1389: 
                   1390:        if (error = fdgetf(p, fdes, &fp))
                   1391:                return (error);
                   1392:        if (fp->f_type != DTYPE_SOCKET)
                   1393:                return (ENOTSOCK);
                   1394:        *fpp = fp;
                   1395:        return (0);
                   1396: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.