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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1982, 1986, 1989, 1990, 1993
                     24:  *     The Regents of the University of California.  All rights reserved.
                     25:  *
                     26:  * sendfile(2) and related extensions:
                     27:  * Copyright (c) 1998, David Greenman. All rights reserved. 
                     28:  *
                     29:  * Redistribution and use in source and binary forms, with or without
                     30:  * modification, are permitted provided that the following conditions
                     31:  * are met:
                     32:  * 1. Redistributions of source code must retain the above copyright
                     33:  *    notice, this list of conditions and the following disclaimer.
                     34:  * 2. Redistributions in binary form must reproduce the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer in the
                     36:  *    documentation and/or other materials provided with the distribution.
                     37:  * 3. All advertising materials mentioning features or use of this software
                     38:  *    must display the following acknowledgement:
                     39:  *     This product includes software developed by the University of
                     40:  *     California, Berkeley and its contributors.
                     41:  * 4. Neither the name of the University nor the names of its contributors
                     42:  *    may be used to endorse or promote products derived from this software
                     43:  *    without specific prior written permission.
                     44:  *
                     45:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     46:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     47:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     48:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     49:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     50:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     51:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     52:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     53:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     54:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     55:  * SUCH DAMAGE.
                     56:  *
                     57:  *     @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
                     58:  */
                     59: 
                     60: 
                     61: 
                     62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/filedesc.h>
                     65: #include <sys/proc.h>
                     66: #include <sys/file.h>
                     67: #include <sys/buf.h>
                     68: #include <sys/malloc.h>
                     69: #include <sys/mbuf.h>
                     70: #include <sys/protosw.h>
                     71: #include <sys/socket.h>
                     72: #include <sys/socketvar.h>
                     73: #if KTRACE
                     74: #include <sys/ktrace.h>
                     75: #endif
                     76: #include <sys/kernel.h>
                     77: 
                     78: #if NEXT
                     79: #import <sys/kdebug.h>
                     80: 
                     81: #if KDEBUG
                     82: 
                     83: #define DBG_LAYER_IN_BEG       NETDBG_CODE(DBG_NETSOCK, 0)
                     84: #define DBG_LAYER_IN_END       NETDBG_CODE(DBG_NETSOCK, 2)
                     85: #define DBG_LAYER_OUT_BEG      NETDBG_CODE(DBG_NETSOCK, 1)
                     86: #define DBG_LAYER_OUT_END      NETDBG_CODE(DBG_NETSOCK, 3)
                     87: #define DBG_FNC_SENDMSG                NETDBG_CODE(DBG_NETSOCK, (1 << 8) | 1)
                     88: #define DBG_FNC_SENDTO         NETDBG_CODE(DBG_NETSOCK, (2 << 8) | 1)
                     89: #define DBG_FNC_SENDIT         NETDBG_CODE(DBG_NETSOCK, (3 << 8) | 1)
                     90: #define DBG_FNC_RECVFROM       NETDBG_CODE(DBG_NETSOCK, (5 << 8))
                     91: #define DBG_FNC_RECVMSG                NETDBG_CODE(DBG_NETSOCK, (6 << 8))
                     92: #define DBG_FNC_RECVIT         NETDBG_CODE(DBG_NETSOCK, (7 << 8))
                     93: 
                     94: 
                     95: #endif
                     96: 
                     97: #endif
                     98: 
                     99: struct getsockname_args  {
                    100:     int        fdes;
                    101:     caddr_t    asa;
                    102:     int        *alen;
                    103: };
                    104: 
                    105: struct getsockopt_args  {
                    106:     int        s;
                    107:     int        level;
                    108:     int        name;
                    109:     caddr_t    val;
                    110:     int        *avalsize;
                    111: } ;
                    112: 
                    113: struct accept_args {
                    114:        int     s;
                    115:        caddr_t name;
                    116:        int     *anamelen;
                    117: };
                    118: 
                    119: struct getpeername_args {
                    120:        int     fdes;
                    121:        caddr_t asa;
                    122:        int     *alen;
                    123: };
                    124: 
                    125: 
                    126: /* ARGSUSED */
                    127: 
                    128: #if SENDFILE
                    129: static void sf_buf_init(void *arg);
                    130: SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL)
                    131: static struct sf_buf *sf_buf_alloc(void);
                    132: static void sf_buf_ref(caddr_t addr, u_int size);
                    133: static void sf_buf_free(caddr_t addr, u_int size);
                    134: 
                    135: static SLIST_HEAD(, sf_buf) sf_freelist;
                    136: static vm_offset_t sf_base;
                    137: static struct sf_buf *sf_bufs;
                    138: static int sf_buf_alloc_want;
                    139: #endif
                    140: 
                    141: static int sendit __P((struct proc *p, int s, struct msghdr *mp, int flags, register_t *retval));
                    142: static int recvit __P((struct proc *p, int s, struct msghdr *mp,
                    143:                       caddr_t namelenp, register_t *retval));
                    144:   
                    145: static int accept1 __P((struct proc *p, struct accept_args *uap, register_t *retval, int compat));
                    146: static int getsockname1 __P((struct proc *p, struct getsockname_args *uap,
                    147:                             register_t *retval, int compat));
                    148: static int getpeername1 __P((struct proc *p, struct getpeername_args *uap,
                    149:                             register_t *retval, int compat));
                    150: 
                    151: /*
                    152:  * System call interface to the socket abstraction.
                    153:  */
                    154: #if COMPAT_43 || defined(COMPAT_SUNOS)
                    155: #define COMPAT_OLDSOCK
                    156: #endif
                    157: 
                    158: extern struct fileops socketops;
                    159: 
                    160: struct socket_args {
                    161:        int     domain;
                    162:        int     type;
                    163:        int     protocol;
                    164: };
                    165: int
                    166: socket(p, uap, retval)
                    167:        struct proc *p;
                    168:        register struct socket_args *uap;
                    169:        register_t *retval;
                    170: {
                    171:        struct filedesc *fdp = p->p_fd;
                    172:        struct socket *so;
                    173:        struct file *fp;
                    174:        int fd, error;
                    175: 
                    176:        error = falloc(p, &fp, &fd);
                    177:        if (error)
                    178:                return (error);
                    179:        fp->f_flag = FREAD|FWRITE;
                    180:        fp->f_type = DTYPE_SOCKET;
                    181:        fp->f_ops = &socketops;
                    182:        if (error = socreate(uap->domain, &so, uap->type,
                    183:            uap->protocol)) {
                    184:                fdrelse(p, fd);
                    185:                ffree(fp);
                    186:        } else {
                    187:                fp->f_data = (caddr_t)so;
                    188:                *fdflags(p, fd) &= ~UF_RESERVED;
                    189:                *retval = fd;
                    190:        }
                    191:        return (error);
                    192: }
                    193: 
                    194: struct bind_args {
                    195:        int     s;
                    196:        caddr_t name;
                    197:        int     namelen;
                    198: };
                    199: 
                    200: /* ARGSUSED */
                    201: int
                    202: bind(p, uap, retval)
                    203:        struct proc *p;
                    204:        register struct bind_args *uap;
                    205:        register_t *retval;
                    206: {
                    207:        struct file *fp;
                    208:        struct sockaddr *sa;
                    209:        int error;
                    210: 
                    211:        error = getsock(p->p_fd, uap->s, &fp);
                    212:        if (error)
                    213:                return (error);
                    214:        error = getsockaddr(&sa, uap->name, uap->namelen);
                    215:        if (error)
                    216:                return (error);
                    217:        error = sobind((struct socket *)fp->f_data, sa);
                    218:        FREE(sa, M_SONAME);
                    219:        return (error);
                    220: }
                    221: 
                    222: struct listen_args {
                    223:        int     s;
                    224:        int     backlog;
                    225: };
                    226: 
                    227: 
                    228: 
                    229: int
                    230: listen(p, uap, retval)
                    231:        struct proc *p;
                    232:        register struct listen_args *uap;
                    233:        register_t *retval;
                    234: {
                    235:        struct file *fp;
                    236:        int error;
                    237: 
                    238:        error = getsock(p->p_fd, uap->s, &fp);
                    239:        if (error)
                    240:                return (error);
                    241:        return (solisten((struct socket *)fp->f_data, uap->backlog));
                    242: }
                    243: 
                    244: #ifndef COMPAT_OLDSOCK
                    245: #define        accept1 accept
                    246: #endif
                    247: 
                    248: 
                    249: 
                    250: int
                    251: accept1(p, uap, retval, compat)
                    252:        struct proc *p;
                    253:        register struct accept_args *uap;
                    254:        register_t *retval;
                    255:        int compat;
                    256: {
                    257:        struct file *fp;
                    258:        struct sockaddr *sa;
                    259:        int namelen, error, s;
                    260:        struct socket *head, *so;
                    261:        int fd;
                    262:        short fflag;            /* type must match fp->f_flag */
                    263:        int tmpfd;
                    264: 
                    265:        if (uap->name) {
                    266:                error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
                    267:                        sizeof (namelen));
                    268:                if(error)
                    269:                        return (error);
                    270:        }
                    271:        error = getsock(p->p_fd, uap->s, &fp);
                    272:        if (error)
                    273:                return (error);
                    274:        s = splnet();
                    275:        head = (struct socket *)fp->f_data;
                    276:        if ((head->so_options & SO_ACCEPTCONN) == 0) {
                    277:                splx(s);
                    278:                return (EINVAL);
                    279:        }
                    280:        if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
                    281:                splx(s);
                    282:                return (EWOULDBLOCK);
                    283:        }
                    284:        while (head->so_comp.tqh_first == NULL && head->so_error == 0) {
                    285:                if (head->so_state & SS_CANTRCVMORE) {
                    286:                        head->so_error = ECONNABORTED;
                    287:                        break;
                    288:                }
                    289:                error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
                    290:                    "accept", 0);
                    291:                if (error) {
                    292:                        splx(s);
                    293:                        return (error);
                    294:                }
                    295:        }
                    296:        if (head->so_error) {
                    297:                error = head->so_error;
                    298:                head->so_error = 0;
                    299:                splx(s);
                    300:                return (error);
                    301:        }
                    302: 
                    303: 
                    304:        /*
                    305:         * At this point we know that there is at least one connection
                    306:         * ready to be accepted. Remove it from the queue prior to
                    307:         * allocating the file descriptor for it since falloc() may
                    308:         * block allowing another process to accept the connection
                    309:         * instead.
                    310:         */
                    311:        so = head->so_comp.tqh_first;
                    312:        TAILQ_REMOVE(&head->so_comp, so, so_list);
                    313:        head->so_qlen--;
                    314: 
                    315:        fflag = fp->f_flag;
                    316:        error = falloc(p, &fp, &fd);
                    317:        if (error) {
                    318:                /*
                    319:                 * Probably ran out of file descriptors. Put the
                    320:                 * unaccepted connection back onto the queue and
                    321:                 * do another wakeup so some other process might
                    322:                 * have a chance at it.
                    323:                 */
                    324:                TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
                    325:                head->so_qlen++;
                    326:                wakeup_one(&head->so_timeo);
                    327:                splx(s);
                    328:                return (error);
                    329:        } else {
                    330:                *fdflags(p, fd) &= ~UF_RESERVED;
                    331:                *retval = fd;
                    332:        }
                    333: 
                    334:        so->so_state &= ~SS_COMP;
                    335:        so->so_head = NULL;
                    336: #if ISFB31
                    337:        if (head->so_pgid != NULL)
                    338:                fsetown(fgetown(head->so_pgid), &so->so_pgid);
                    339: #endif
                    340:        fp->f_type = DTYPE_SOCKET;
                    341:        fp->f_flag = fflag;
                    342:        fp->f_ops = &socketops;
                    343:        fp->f_data = (caddr_t)so;
                    344:        sa = 0;
                    345:        (void) soaccept(so, &sa);
                    346:        if (sa == 0) {
                    347:                namelen = 0;
                    348:                if (uap->name)
                    349:                        goto gotnoname;
                    350:                return 0;
                    351:        }
                    352:        if (uap->name) {
                    353:                /* check sa_len before it is destroyed */
                    354:                if (namelen > sa->sa_len)
                    355:                        namelen = sa->sa_len;
                    356: #ifdef COMPAT_OLDSOCK
                    357:                if (compat)
                    358:                        ((struct osockaddr *)sa)->sa_family =
                    359:                            sa->sa_family;
                    360: #endif
                    361:                error = copyout(sa, (caddr_t)uap->name, (u_int)namelen);
                    362:                if (!error)
                    363: gotnoname:
                    364:                        error = copyout((caddr_t)&namelen,
                    365:                            (caddr_t)uap->anamelen, sizeof (*uap->anamelen));
                    366:        }
                    367:        FREE(sa, M_SONAME);
                    368:        splx(s);
                    369:        return (error);
                    370: }
                    371: 
                    372: int
                    373: accept(p, uap, retval)
                    374:        struct proc *p;
                    375:        struct accept_args *uap;
                    376:        register_t *retval;
                    377: {
                    378: 
                    379:        return (accept1(p, uap, retval, 0));
                    380: }
                    381: 
                    382: #ifdef COMPAT_OLDSOCK
                    383: int
                    384: oaccept(p, uap, retval)
                    385:        struct proc *p;
                    386:        struct accept_args *uap;
                    387:        register_t *retval;
                    388: {
                    389: 
                    390:        return (accept1(p, uap, retval, 1));
                    391: }
                    392: #endif /* COMPAT_OLDSOCK */
                    393: 
                    394: struct connect_args {
                    395:        int s;
                    396:        caddr_t name;
                    397:        int     namelen;
                    398: };
                    399: /* ARGSUSED */
                    400: int
                    401: connect(p, uap, retval)
                    402:        struct proc *p;
                    403:        register struct connect_args *uap;
                    404:        register_t *retval;
                    405: {
                    406:        struct file *fp;
                    407:        register struct socket *so;
                    408:        struct sockaddr *sa;
                    409:        int error, s;
                    410: 
                    411:        error = getsock(p->p_fd, uap->s, &fp);
                    412:        if (error)
                    413:                return (error);
                    414:        so = (struct socket *)fp->f_data;
                    415:        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
                    416:                return (EALREADY);
                    417:        error = getsockaddr(&sa, uap->name, uap->namelen);
                    418:        if (error)
                    419:                return (error);
                    420:        error = soconnect(so, sa);
                    421:        if (error)
                    422:                goto bad;
                    423:        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
                    424:                FREE(sa, M_SONAME);
                    425:                return (EINPROGRESS);
                    426:        }
                    427:        s = splnet();
                    428:        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
                    429:                error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
                    430:                    "connec", 0);
                    431:                if (error)
                    432:                        break;
                    433:        }
                    434:        if (error == 0) {
                    435:                error = so->so_error;
                    436:                so->so_error = 0;
                    437:        }
                    438:        splx(s);
                    439: bad:
                    440:        so->so_state &= ~SS_ISCONNECTING;
                    441:        FREE(sa, M_SONAME);
                    442:        if (error == ERESTART)
                    443:                error = EINTR;
                    444:        return (error);
                    445: }
                    446: 
                    447: struct socketpair_args {
                    448:        int     domain;
                    449:        int     type;
                    450:        int     protocol;
                    451:        int     *rsv;
                    452: };
                    453: int
                    454: socketpair(p, uap, retval)
                    455:        struct proc *p;
                    456:        register struct socketpair_args *uap;
                    457:        register_t *retval;
                    458: {
                    459:        register struct filedesc *fdp = p->p_fd;
                    460:        struct file *fp1, *fp2;
                    461:        struct socket *so1, *so2;
                    462:        int fd, error, sv[2];
                    463: 
                    464:        error = socreate(uap->domain, &so1, uap->type, uap->protocol);
                    465:        if (error)
                    466:                return (error);
                    467:        error = socreate(uap->domain, &so2, uap->type, uap->protocol);
                    468:        if (error)
                    469:                goto free1;
                    470:        error = falloc(p, &fp1, &fd);
                    471:        if (error)
                    472:                goto free2;
                    473:        sv[0] = fd;
                    474:        fp1->f_flag = FREAD|FWRITE;
                    475:        fp1->f_type = DTYPE_SOCKET;
                    476:        fp1->f_ops = &socketops;
                    477:        fp1->f_data = (caddr_t)so1;
                    478:        error = falloc(p, &fp2, &fd);
                    479:        if (error)
                    480:                goto free3;
                    481:        fp2->f_flag = FREAD|FWRITE;
                    482:        fp2->f_type = DTYPE_SOCKET;
                    483:        fp2->f_ops = &socketops;
                    484:        fp2->f_data = (caddr_t)so2;
                    485:        sv[1] = fd;
                    486:        error = soconnect2(so1, so2);
                    487:        if (error)
                    488:                goto free4;
                    489:        if (uap->type == SOCK_DGRAM) {
                    490:                /*
                    491:                 * Datagram socket connection is asymmetric.
                    492:                 */
                    493:                 error = soconnect2(so2, so1);
                    494:                 if (error)
                    495:                        goto free4;
                    496:        }
                    497:        *fdflags(p, sv[0]) &= ~UF_RESERVED;
                    498:        *fdflags(p, sv[1]) &= ~UF_RESERVED;
                    499:        error = copyout((caddr_t)sv, (caddr_t)uap->rsv,
                    500:            2 * sizeof (int));
                    501: #if 0   /* old pipe(2) syscall compatability, unused these days */
                    502:        retval[0] = sv[0];              /* XXX ??? */
                    503:        retval[1] = sv[1];              /* XXX ??? */
                    504: #endif /* 0 */
                    505:        return (error);
                    506: free4:
                    507:        fdrelse(p, sv[1]);
                    508:        ffree(fp2);
                    509: free3:
                    510:        fdrelse(p, sv[0]);
                    511:        ffree(fp1);
                    512: free2:
                    513:        (void)soclose(so2);
                    514: free1:
                    515:        (void)soclose(so1);
                    516:        return (error);
                    517: }
                    518: 
                    519: static int
                    520: sendit(p, s, mp, flags, retsize)
                    521:        register struct proc *p;
                    522:        int s;
                    523:        register struct msghdr *mp;
                    524:        int flags;
                    525:        register_t *retsize;
                    526: {
                    527:        struct file *fp;
                    528:        struct uio auio;
                    529:        register struct iovec *iov;
                    530:        register int i;
                    531:        struct mbuf *control;
                    532:        struct sockaddr *to;
                    533:        int len, error;
                    534:        struct socket *so;
                    535: #if KTRACE
                    536:        struct iovec *ktriov = NULL;
                    537: #endif
                    538:        
                    539:        KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_START, 0,0,0,0,0);
                    540: 
                    541:        if (error = getsock(p->p_fd, s, &fp))
                    542:        {
                    543:            KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
                    544:            return (error);
                    545:        }
                    546: 
                    547:        auio.uio_iov = mp->msg_iov;
                    548:        auio.uio_iovcnt = mp->msg_iovlen;
                    549:        auio.uio_segflg = UIO_USERSPACE;
                    550:        auio.uio_rw = UIO_WRITE;
                    551:        auio.uio_procp = p;
                    552:        auio.uio_offset = 0;                    /* XXX */
                    553:        auio.uio_resid = 0;
                    554:        iov = mp->msg_iov;
                    555:        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                    556:                if (iov->iov_len < 0)
                    557:                {
                    558:                    KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, EINVAL,0,0,0,0);
                    559:                    return (EINVAL);
                    560:                }
                    561: 
                    562:                if ((auio.uio_resid += iov->iov_len) < 0)
                    563:                {
                    564:                    KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, EINVAL,0,0,0,0);
                    565:                    return (EINVAL);
                    566:                }
                    567:        }
                    568:        if (mp->msg_name) {
                    569:                error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
                    570:                if (error)
                    571:                        return (error);
                    572:        } else
                    573:                to = 0;
                    574:        if (mp->msg_control) {
                    575:                if (mp->msg_controllen < sizeof(struct cmsghdr)
                    576: #ifdef COMPAT_OLDSOCK
                    577:                    && mp->msg_flags != MSG_COMPAT
                    578: #endif
                    579:                ) {
                    580:                        error = EINVAL;
                    581:                        goto bad;
                    582:                }
                    583:                error = sockargs(&control, mp->msg_control,
                    584:                    mp->msg_controllen, MT_CONTROL);
                    585:                if (error)
                    586:                        goto bad;
                    587: #ifdef COMPAT_OLDSOCK
                    588:                if (mp->msg_flags == MSG_COMPAT) {
                    589:                        register struct cmsghdr *cm;
                    590: 
                    591:                        M_PREPEND(control, sizeof(*cm), M_WAIT);
                    592:                        if (control == 0) {
                    593:                                error = ENOBUFS;
                    594:                                goto bad;
                    595:                        } else {
                    596:                                cm = mtod(control, struct cmsghdr *);
                    597:                                cm->cmsg_len = control->m_len;
                    598:                                cm->cmsg_level = SOL_SOCKET;
                    599:                                cm->cmsg_type = SCM_RIGHTS;
                    600:                        }
                    601:                }
                    602: #endif
                    603:        } else
                    604:                control = 0;
                    605: 
                    606:        len = auio.uio_resid;
                    607:        so = (struct socket *)fp->f_data;
                    608:        error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
                    609:                                                     flags);
                    610:        if (error) {
                    611:                if (auio.uio_resid != len && (error == ERESTART ||
                    612:                    error == EINTR || error == EWOULDBLOCK))
                    613:                        error = 0;
                    614:                if (error == EPIPE)
                    615:                        psignal(p, SIGPIPE);
                    616:        }
                    617:        if (error == 0)
                    618:                *retsize = len - auio.uio_resid;
                    619: #if KTRACE
                    620:        if (ktriov != NULL) {
                    621:                if (error == 0)
                    622:                        ktrgenio(p->p_tracep, s, UIO_WRITE,
                    623:                                ktriov, *retsize, error);
                    624:                FREE(ktriov, M_TEMP);
                    625:        }
                    626: #endif
                    627: bad:
                    628:        if (to)
                    629:                FREE(to, M_SONAME);
                    630:        return (error);
                    631: }
                    632: 
                    633: 
                    634: struct sendto_args {
                    635:        int s;
                    636:        caddr_t buf;
                    637:        size_t len;
                    638:        int flags;
                    639:        caddr_t to;
                    640:        int tolen;
                    641: };
                    642: 
                    643: int
                    644: sendto(p, uap, retval)
                    645:        struct proc *p;
                    646:        register struct sendto_args /* {
                    647:                int     s;
                    648:                caddr_t buf;
                    649:                size_t  len;
                    650:                int     flags;
                    651:                caddr_t to;
                    652:                int     tolen;
                    653:        } */ *uap;
                    654:        register_t *retval;
                    655: 
                    656: {
                    657:        struct msghdr msg;
                    658:        struct iovec aiov;
                    659: 
                    660:        msg.msg_name = uap->to;
                    661:        msg.msg_namelen = uap->tolen;
                    662:        msg.msg_iov = &aiov;
                    663:        msg.msg_iovlen = 1;
                    664:        msg.msg_control = 0;
                    665: #ifdef COMPAT_OLDSOCK
                    666:        msg.msg_flags = 0;
                    667: #endif
                    668:        aiov.iov_base = uap->buf;
                    669:        aiov.iov_len = uap->len;
                    670:        KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_END, stat, *retval,0,0,0);
                    671:        return (sendit(p, uap->s, &msg, uap->flags, retval));
                    672: }
                    673: 
                    674: #ifdef COMPAT_OLDSOCK
                    675: struct osend_args {
                    676:        int s;
                    677:        caddr_t buf;
                    678:        int len;
                    679:        int flags;
                    680: };
                    681: 
                    682: int
                    683: osend(p, uap, retval)
                    684:        struct proc *p;
                    685:        register struct osend_args /* {
                    686:                int     s;
                    687:                caddr_t buf;
                    688:                int     len;
                    689:                int     flags;
                    690:        } */ *uap;
                    691:        register_t *retval;
                    692: 
                    693: {
                    694:        struct msghdr msg;
                    695:        struct iovec aiov;
                    696: 
                    697:        msg.msg_name = 0;
                    698:        msg.msg_namelen = 0;
                    699:        msg.msg_iov = &aiov;
                    700:        msg.msg_iovlen = 1;
                    701:        aiov.iov_base = uap->buf;
                    702:        aiov.iov_len = uap->len;
                    703:        msg.msg_control = 0;
                    704:        msg.msg_flags = 0;
                    705:        return (sendit(p, uap->s, &msg, uap->flags, retval));
                    706: }
                    707: struct osendmsg_args {
                    708:        int s;
                    709:        caddr_t msg;
                    710:        int flags;
                    711: };
                    712: 
                    713: int
                    714: osendmsg(p, uap, retval)
                    715:        struct proc *p;
                    716:        register struct osendmsg_args /* {
                    717:                int     s;
                    718:                caddr_t msg;
                    719:                int     flags;
                    720:        } */ *uap;
                    721:        register_t *retval;
                    722: 
                    723: {
                    724:        struct msghdr msg;
                    725:        struct iovec aiov[UIO_SMALLIOV], *iov;
                    726:        int error;
                    727: 
                    728:        error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
                    729:        if (error)
                    730:                return (error);
                    731:        if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
                    732:                if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
                    733:                        return (EMSGSIZE);
                    734:                MALLOC(iov, struct iovec *,
                    735:                      sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
                    736:                      M_WAITOK);
                    737:        } else
                    738:                iov = aiov;
                    739:        error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
                    740:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
                    741:        if (error)
                    742:                goto done;
                    743:        msg.msg_flags = MSG_COMPAT;
                    744:        msg.msg_iov = iov;
                    745:        error = sendit(p, uap->s, &msg, uap->flags, retval);
                    746: done:
                    747:        if (iov != aiov)
                    748:                FREE(iov, M_IOV);
                    749:        return (error);
                    750: }
                    751: #endif
                    752: 
                    753: struct sendmsg_args {
                    754:        int s;
                    755:        caddr_t msg;
                    756:        int flags;
                    757: };
                    758: 
                    759: int
                    760: sendmsg(p, uap, retval)
                    761:        struct proc *p;
                    762:        register struct sendmsg_args *uap;
                    763:        register_t *retval;
                    764: {
                    765:        struct msghdr msg;
                    766:        struct iovec aiov[UIO_SMALLIOV], *iov;
                    767:        int error;
                    768: 
                    769:        error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
                    770:        if (error)
                    771:                return (error);
                    772:        if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
                    773:                if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
                    774:                        return (EMSGSIZE);
                    775:                MALLOC(iov, struct iovec *,
                    776:                       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
                    777:                       M_WAITOK);
                    778:        } else
                    779:                iov = aiov;
                    780:        if (msg.msg_iovlen &&
                    781:            (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
                    782:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
                    783:                goto done;
                    784:        msg.msg_iov = iov;
                    785: #ifdef COMPAT_OLDSOCK
                    786:        msg.msg_flags = 0;
                    787: #endif
                    788:        error = sendit(p, uap->s, &msg, uap->flags, retval);
                    789: done:
                    790:        if (iov != aiov)
                    791:                FREE(iov, M_IOV);
                    792:        return (error);
                    793: }
                    794: 
                    795: static int
                    796: recvit(p, s, mp, namelenp, retval)
                    797:        register struct proc *p;
                    798:        int s;
                    799:        register struct msghdr *mp;
                    800:        caddr_t namelenp;
                    801:        register_t *retval;
                    802: {
                    803:        struct file *fp;
                    804:        struct uio auio;
                    805:        register struct iovec *iov;
                    806:        register int i;
                    807:        int len, error;
                    808:        struct mbuf *m, *control = 0;
                    809:        caddr_t ctlbuf;
                    810:        struct socket *so;
                    811:        struct sockaddr *fromsa = 0;
                    812: #if KTRACE
                    813:        struct iovec *ktriov = NULL;
                    814: #endif
                    815: 
                    816:        error = getsock(p->p_fd, s, &fp);
                    817:        if (error)
                    818:                return (error);
                    819:        auio.uio_iov = mp->msg_iov;
                    820:        auio.uio_iovcnt = mp->msg_iovlen;
                    821:        auio.uio_segflg = UIO_USERSPACE;
                    822:        auio.uio_rw = UIO_READ;
                    823:        auio.uio_procp = p;
                    824:        auio.uio_offset = 0;                    /* XXX */
                    825:        auio.uio_resid = 0;
                    826:        iov = mp->msg_iov;
                    827:        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                    828:                if ((auio.uio_resid += iov->iov_len) < 0)
                    829:                        return (EINVAL);
                    830:        }
                    831: #if KTRACE
                    832:        if (KTRPOINT(p, KTR_GENIO)) {
                    833:                int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
                    834: 
                    835:                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                    836:                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
                    837:        }
                    838: #endif
                    839:        len = auio.uio_resid;
                    840:        so = (struct socket *)fp->f_data;
                    841:        error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
                    842:            (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
                    843:            &mp->msg_flags);
                    844:        if (error) {
                    845:                if (auio.uio_resid != len && (error == ERESTART ||
                    846:                    error == EINTR || error == EWOULDBLOCK))
                    847:                        error = 0;
                    848:        }
                    849: #if KTRACE
                    850:        if (ktriov != NULL) {
                    851:                if (error == 0)
                    852:                        ktrgenio(p->p_tracep, s, UIO_WRITE,
                    853:                                ktriov, len - auio.uio_resid, error);
                    854:                FREE(ktriov, M_TEMP);
                    855:        }
                    856: #endif
                    857:        if (error)
                    858:                goto out;
                    859:        *retval = len - auio.uio_resid;
                    860:        if (mp->msg_name) {
                    861:                len = mp->msg_namelen;
                    862:                if (len <= 0 || fromsa == 0)
                    863:                        len = 0;
                    864:                else {
                    865: #ifndef MIN
                    866: #define MIN(a,b) ((a)>(b)?(b):(a))
                    867: #endif
                    868:                        /* save sa_len before it is destroyed by MSG_COMPAT */
                    869:                        len = MIN(len, fromsa->sa_len);
                    870: #ifdef COMPAT_OLDSOCK
                    871:                        if (mp->msg_flags & MSG_COMPAT)
                    872:                                ((struct osockaddr *)fromsa)->sa_family =
                    873:                                    fromsa->sa_family;
                    874: #endif
                    875:                        error = copyout(fromsa,
                    876:                            (caddr_t)mp->msg_name, (unsigned)len);
                    877:                        if (error)
                    878:                                goto out;
                    879:                }
                    880:                mp->msg_namelen = len;
                    881:                if (namelenp &&
                    882:                    (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
                    883: #ifdef COMPAT_OLDSOCK
                    884:                        if (mp->msg_flags & MSG_COMPAT)
                    885:                                error = 0;      /* old recvfrom didn't check */
                    886:                        else
                    887: #endif
                    888:                        goto out;
                    889:                }
                    890:        }
                    891:        if (mp->msg_control) {
                    892: #ifdef COMPAT_OLDSOCK
                    893:                /*
                    894:                 * We assume that old recvmsg calls won't receive access
                    895:                 * rights and other control info, esp. as control info
                    896:                 * is always optional and those options didn't exist in 4.3.
                    897:                 * If we receive rights, trim the cmsghdr; anything else
                    898:                 * is tossed.
                    899:                 */
                    900:                if (control && mp->msg_flags & MSG_COMPAT) {
                    901:                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
                    902:                            SOL_SOCKET ||
                    903:                            mtod(control, struct cmsghdr *)->cmsg_type !=
                    904:                            SCM_RIGHTS) {
                    905:                                mp->msg_controllen = 0;
                    906:                                goto out;
                    907:                        }
                    908:                        control->m_len -= sizeof (struct cmsghdr);
                    909:                        control->m_data += sizeof (struct cmsghdr);
                    910:                }
                    911: #endif
                    912:                len = mp->msg_controllen;
                    913:                m = control;
                    914:                mp->msg_controllen = 0;
                    915:                ctlbuf = (caddr_t) mp->msg_control;
                    916: 
                    917:                while (m && len > 0) {
                    918:                        unsigned int tocopy;
                    919: 
                    920:                        if (len >= m->m_len) 
                    921:                                tocopy = m->m_len;
                    922:                        else {
                    923:                                mp->msg_flags |= MSG_CTRUNC;
                    924:                                tocopy = len;
                    925:                        }
                    926:                
                    927:                        if (error = copyout((caddr_t)mtod(m, caddr_t),
                    928:                                        ctlbuf, tocopy))
                    929:                                goto out;
                    930: 
                    931:                        ctlbuf += tocopy;
                    932:                        len -= tocopy;
                    933:                        m = m->m_next;
                    934:                }
                    935:                mp->msg_controllen = ctlbuf - mp->msg_control;
                    936:        }
                    937: out:
                    938:        if (fromsa)
                    939:                FREE(fromsa, M_SONAME);
                    940:        if (control)
                    941:                m_freem(control);
                    942:        return (error);
                    943: }
                    944: 
                    945: 
                    946: struct recvfrom_args  {
                    947:     int        s;
                    948:     caddr_t    buf;
                    949:     size_t     len;
                    950:     int        flags;
                    951:     caddr_t    from;
                    952:     int        *fromlenaddr;
                    953: };
                    954: 
                    955: int
                    956: recvfrom(p, uap, retval)
                    957:        struct proc *p;
                    958:        register struct recvfrom_args /* {
                    959:                int     s;
                    960:                caddr_t buf;
                    961:                size_t  len;
                    962:                int     flags;
                    963:                caddr_t from;
                    964:                int     *fromlenaddr;
                    965:        } */ *uap;
                    966:        register_t *retval;
                    967: {
                    968:        struct msghdr msg;
                    969:        struct iovec aiov;
                    970:        int error;
                    971: 
                    972:        if (uap->fromlenaddr) {
                    973:                error = copyin((caddr_t)uap->fromlenaddr,
                    974:                    (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen));
                    975:                if (error)
                    976:                        return (error);
                    977:        } else
                    978:                msg.msg_namelen = 0;
                    979:        msg.msg_name = uap->from;
                    980:        msg.msg_iov = &aiov;
                    981:        msg.msg_iovlen = 1;
                    982:        aiov.iov_base = uap->buf;
                    983:        aiov.iov_len = uap->len;
                    984:        msg.msg_control = 0;
                    985:        msg.msg_flags = uap->flags;
                    986:        return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval));
                    987: }
                    988: 
                    989: #ifdef COMPAT_OLDSOCK
                    990: int
                    991: orecvfrom(p, uap, retval)
                    992:        struct proc *p;
                    993:        struct recvfrom_args *uap;
                    994:        register_t *retval;
                    995: {
                    996: 
                    997:        uap->flags |= MSG_COMPAT;
                    998:        return (recvfrom(p, uap));
                    999: }
                   1000: #endif
                   1001: 
                   1002: 
                   1003: #ifdef COMPAT_OLDSOCK
                   1004: int
                   1005: orecv(p, uap, retval)
                   1006:        struct proc *p;
                   1007:        register struct orecv_args  {
                   1008:                int     s;
                   1009:                caddr_t buf;
                   1010:                int     len;
                   1011:                int     flags;
                   1012:        }  *uap;
                   1013:        register_t *retval;
                   1014: {
                   1015:        struct msghdr msg;
                   1016:        struct iovec aiov;
                   1017: 
                   1018:        msg.msg_name = 0;
                   1019:        msg.msg_namelen = 0;
                   1020:        msg.msg_iov = &aiov;
                   1021:        msg.msg_iovlen = 1;
                   1022:        aiov.iov_base = uap->buf;
                   1023:        aiov.iov_len = uap->len;
                   1024:        msg.msg_control = 0;
                   1025:        msg.msg_flags = uap->flags;
                   1026:        return (recvit(p, uap->s, &msg, (caddr_t)0, retval));
                   1027: }
                   1028: 
                   1029: /*
                   1030:  * Old recvmsg.  This code takes advantage of the fact that the old msghdr
                   1031:  * overlays the new one, missing only the flags, and with the (old) access
                   1032:  * rights where the control fields are now.
                   1033:  */
                   1034: int
                   1035: orecvmsg(p, uap, retval)
                   1036:        struct proc *p;
                   1037:        register struct orecvmsg_args  {
                   1038:                int     s;
                   1039:                struct  omsghdr *msg;
                   1040:                int     flags;
                   1041:        }  *uap;
                   1042:        register_t *retval;
                   1043: {
                   1044:        struct msghdr msg;
                   1045:        struct iovec aiov[UIO_SMALLIOV], *iov;
                   1046:        int error;
                   1047: 
                   1048:        error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
                   1049:            sizeof (struct omsghdr));
                   1050:        if (error)
                   1051:                return (error);
                   1052:        if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
                   1053:                if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
                   1054:                        return (EMSGSIZE);
                   1055:                MALLOC(iov, struct iovec *,
                   1056:                      sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
                   1057:                      M_WAITOK);
                   1058:        } else
                   1059:                iov = aiov;
                   1060:        msg.msg_flags = uap->flags | MSG_COMPAT;
                   1061:        error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
                   1062:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
                   1063:        if (error)
                   1064:                goto done;
                   1065:        msg.msg_iov = iov;
                   1066:        error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval);
                   1067: 
                   1068:        if (msg.msg_controllen && error == 0)
                   1069:                error = copyout((caddr_t)&msg.msg_controllen,
                   1070:                    (caddr_t)&uap->msg->msg_accrightslen, sizeof (int));
                   1071: done:
                   1072:        if (iov != aiov)
                   1073:                FREE(iov, M_IOV);
                   1074:        return (error);
                   1075: }
                   1076: #endif
                   1077: 
                   1078: int
                   1079: recvmsg(p, uap, retval)
                   1080:        struct proc *p;
                   1081:        register struct recvmsg_args  {
                   1082:                int     s;
                   1083:                struct  msghdr *msg;
                   1084:                int     flags;
                   1085:        }  *uap;
                   1086:        register_t *retval;
                   1087: {
                   1088:        struct msghdr msg;
                   1089:        struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
                   1090:        register int error;
                   1091: 
                   1092:        error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
                   1093:        if (error)
                   1094:                return (error);
                   1095:        if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
                   1096:                if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
                   1097:                        return (EMSGSIZE);
                   1098:                MALLOC(iov, struct iovec *,
                   1099:                       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
                   1100:                       M_WAITOK);
                   1101:        } else
                   1102:                iov = aiov;
                   1103: #ifdef COMPAT_OLDSOCK
                   1104:        msg.msg_flags = uap->flags &~ MSG_COMPAT;
                   1105: #else
                   1106:        msg.msg_flags = uap->flags;
                   1107: #endif
                   1108:        uiov = msg.msg_iov;
                   1109:        msg.msg_iov = iov;
                   1110:        error = copyin((caddr_t)uiov, (caddr_t)iov,
                   1111:            (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
                   1112:        if (error)
                   1113:                goto done;
                   1114:        error = recvit(p, uap->s, &msg, (caddr_t)0, retval);
                   1115:        if (!error) {
                   1116:                msg.msg_iov = uiov;
                   1117:                error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
                   1118:        }
                   1119: done:
                   1120:        if (iov != aiov)
                   1121:                FREE(iov, M_IOV);
                   1122:        return (error);
                   1123: }
                   1124: 
                   1125: /* ARGSUSED */
                   1126: int
                   1127: shutdown(p, uap, retval)
                   1128:        struct proc *p;
                   1129:        register struct shutdown_args  {
                   1130:                int     s;
                   1131:                int     how;
                   1132:        }  *uap;
                   1133:        register_t *retval;
                   1134: {
                   1135:        struct file *fp;
                   1136:        int error;
                   1137: 
                   1138:        error = getsock(p->p_fd, uap->s, &fp);
                   1139:        if (error)
                   1140:                return (error);
                   1141:        return (soshutdown((struct socket *)fp->f_data, uap->how));
                   1142: }
                   1143: 
                   1144: 
                   1145: 
                   1146: 
                   1147: 
                   1148: /* ARGSUSED */
                   1149: int
                   1150: setsockopt(p, uap, retval)
                   1151:        struct proc *p;
                   1152:        register struct setsockopt_args  {
                   1153:                int     s;
                   1154:                int     level;
                   1155:                int     name;
                   1156:                caddr_t val;
                   1157:                int     valsize;
                   1158:        }  *uap;
                   1159:        register_t *retval;
                   1160: {
                   1161:        struct file *fp;
                   1162:        struct sockopt sopt;
                   1163:        int error;
                   1164: 
                   1165:        if (uap->val == 0 && uap->valsize != 0)
                   1166:                return (EFAULT);
                   1167:        if (uap->valsize < 0)
                   1168:                return (EINVAL);
                   1169: 
                   1170:        error = getsock(p->p_fd, uap->s, &fp);
                   1171:        if (error)
                   1172:                return (error);
                   1173: 
                   1174:        sopt.sopt_dir = SOPT_SET;
                   1175:        sopt.sopt_level = uap->level;
                   1176:        sopt.sopt_name = uap->name;
                   1177:        sopt.sopt_val = uap->val;
                   1178:        sopt.sopt_valsize = uap->valsize;
                   1179:        sopt.sopt_p = p;
                   1180: 
                   1181:        return (sosetopt((struct socket *)fp->f_data, &sopt));
                   1182: }
                   1183: 
                   1184: 
                   1185: 
                   1186: int
                   1187: getsockopt(p, uap, retval)
                   1188:        struct proc *p;
                   1189:        struct getsockopt_args  *uap;
                   1190:        register_t *retval;
                   1191: {
                   1192:        int     valsize, error;
                   1193:        struct  file *fp;
                   1194:        struct  sockopt sopt;
                   1195: 
                   1196:        error = getsock(p->p_fd, uap->s, &fp);
                   1197:        if (error)
                   1198:                return (error);
                   1199:        if (uap->val) {
                   1200:                error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
                   1201:                    sizeof (valsize));
                   1202:                if (error)
                   1203:                        return (error);
                   1204:                if (valsize < 0)
                   1205:                        return (EINVAL);
                   1206:        } else
                   1207:                valsize = 0;
                   1208: 
                   1209:        sopt.sopt_dir = SOPT_GET;
                   1210:        sopt.sopt_level = uap->level;
                   1211:        sopt.sopt_name = uap->name;
                   1212:        sopt.sopt_val = uap->val;
                   1213:        sopt.sopt_valsize = (size_t)valsize; /* checked non-negative above */
                   1214:        sopt.sopt_p = p;
                   1215: 
                   1216:        error = sogetopt((struct socket *)fp->f_data, &sopt);
                   1217:        if (error == 0) {
                   1218:                valsize = sopt.sopt_valsize;
                   1219:                error = copyout((caddr_t)&valsize,
                   1220:                                (caddr_t)uap->avalsize, sizeof (valsize));
                   1221:        }
                   1222:        return (error);
                   1223: }
                   1224: 
                   1225: 
                   1226: 
                   1227: struct pipe_args {
                   1228:        int     dummy;
                   1229: };
                   1230: /* ARGSUSED */
                   1231: int
                   1232: pipe(p, uap, retval)
                   1233:        struct proc *p;
                   1234:        struct pipe_args *uap;
                   1235:        register_t *retval;
                   1236: {
                   1237:        struct file *rf, *wf;
                   1238:        struct socket *rso, *wso;
                   1239:        int fd, error;
                   1240: 
                   1241:        if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0))
                   1242:                return (error);
                   1243:        if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0))
                   1244:                goto free1;
                   1245:        if (error = falloc(p, &rf, &fd))
                   1246:                goto free2;
                   1247:        retval[0] = fd;
                   1248:        rf->f_flag = FREAD;
                   1249:        rf->f_type = DTYPE_SOCKET;
                   1250:        rf->f_ops = &socketops;
                   1251:        rf->f_data = (caddr_t)rso;
                   1252:        if (error = falloc(p, &wf, &fd))
                   1253:                goto free3;
                   1254:        wf->f_flag = FWRITE;
                   1255:        wf->f_type = DTYPE_SOCKET;
                   1256:        wf->f_ops = &socketops;
                   1257:        wf->f_data = (caddr_t)wso;
                   1258:        retval[1] = fd;
                   1259:        if (error = unp_connect2(wso, rso))
                   1260:                goto free4;
                   1261:        *fdflags(p, retval[0]) &= ~UF_RESERVED;
                   1262:        *fdflags(p, retval[1]) &= ~UF_RESERVED;
                   1263:        return (0);
                   1264: free4:
                   1265:        fdrelse(p, retval[1]);
                   1266:        ffree(wf);
                   1267: free3:
                   1268:        fdrelse(p, retval[0]);
                   1269:        ffree(rf);
                   1270: free2:
                   1271:        (void)soclose(wso);
                   1272: free1:
                   1273:        (void)soclose(rso);
                   1274:        return (error);
                   1275: }
                   1276: 
                   1277: 
                   1278: /*
                   1279:  * Get socket name.
                   1280:  */
                   1281: /* ARGSUSED */
                   1282: static int
                   1283: getsockname1(p, uap, retval, compat)
                   1284:        struct proc *p;
                   1285:        register struct getsockname_args *uap;
                   1286:        register_t *retval;
                   1287:        int compat;
                   1288: {
                   1289:        struct file *fp;
                   1290:        register struct socket *so;
                   1291:        struct sockaddr *sa;
                   1292:        int len, error;
                   1293: 
                   1294:        error = getsock(p->p_fd, uap->fdes, &fp);
                   1295:        if (error)
                   1296:                return (error);
                   1297:        error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
                   1298:        if (error)
                   1299:                return (error);
                   1300:        so = (struct socket *)fp->f_data;
                   1301:        sa = 0;
                   1302:        error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
                   1303:        if (error)
                   1304:                goto bad;
                   1305:        if (sa == 0) {
                   1306:                len = 0;
                   1307:                goto gotnothing;
                   1308:        }
                   1309: 
                   1310:        len = MIN(len, sa->sa_len);
                   1311: #ifdef COMPAT_OLDSOCK
                   1312:        if (compat)
                   1313:                ((struct osockaddr *)sa)->sa_family = sa->sa_family;
                   1314: #endif
                   1315:        error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
                   1316:        if (error == 0)
                   1317: gotnothing:
                   1318:                error = copyout((caddr_t)&len, (caddr_t)uap->alen,
                   1319:                    sizeof (len));
                   1320: bad:
                   1321:        if (sa)
                   1322:                FREE(sa, M_SONAME);
                   1323:        return (error);
                   1324: }
                   1325: 
                   1326: int
                   1327: getsockname(p, uap, retval)
                   1328:        struct proc *p;
                   1329:        struct getsockname_args *uap;
                   1330:        register_t *retval;
                   1331: {
                   1332: 
                   1333:        return (getsockname1(p, uap, retval, 0));
                   1334: }
                   1335: 
                   1336: #ifdef COMPAT_OLDSOCK
                   1337: int
                   1338: ogetsockname(p, uap, retval)
                   1339:        struct proc *p;
                   1340:        struct getsockname_args *uap;
                   1341:        register_t *retval;
                   1342: {
                   1343: 
                   1344:        return (getsockname1(p, uap, retval, 1));
                   1345: }
                   1346: #endif /* COMPAT_OLDSOCK */
                   1347: 
                   1348: /*
                   1349:  * Get name of peer for connected socket.
                   1350:  */
                   1351: /* ARGSUSED */
                   1352: int
                   1353: getpeername1(p, uap, retval, compat)
                   1354:        struct proc *p;
                   1355:        register struct getpeername_args *uap;
                   1356:        register_t *retval;
                   1357:        int compat;
                   1358: {
                   1359:        struct file *fp;
                   1360:        register struct socket *so;
                   1361:        struct sockaddr *sa;
                   1362:        int len, error;
                   1363: 
                   1364:        error = getsock(p->p_fd, uap->fdes, &fp);
                   1365:        if (error)
                   1366:                return (error);
                   1367:        so = (struct socket *)fp->f_data;
                   1368:        if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
                   1369:                return (ENOTCONN);
                   1370:        error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
                   1371:        if (error)
                   1372:                return (error);
                   1373:        sa = 0;
                   1374:        error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
                   1375:        if (error)
                   1376:                goto bad;
                   1377:        if (sa == 0) {
                   1378:                len = 0;
                   1379:                goto gotnothing;
                   1380:        }
                   1381:        len = MIN(len, sa->sa_len);
                   1382: #ifdef COMPAT_OLDSOCK
                   1383:        if (compat)
                   1384:                ((struct osockaddr *)sa)->sa_family =
                   1385:                    sa->sa_family;
                   1386: #endif
                   1387:        error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
                   1388:        if (error)
                   1389:                goto bad;
                   1390: gotnothing:
                   1391:        error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
                   1392: bad:
                   1393:        if (sa) FREE(sa, M_SONAME);
                   1394:        return (error);
                   1395: }
                   1396: 
                   1397: int
                   1398: getpeername(p, uap, retval)
                   1399:        struct proc *p;
                   1400:        struct getpeername_args *uap;
                   1401:        register_t *retval;
                   1402: {
                   1403: 
                   1404:        return (getpeername1(p, uap, retval, 0));
                   1405: }
                   1406: 
                   1407: #ifdef COMPAT_OLDSOCK
                   1408: int
                   1409: ogetpeername(p, uap, retval)
                   1410:        struct proc *p;
                   1411:        struct ogetpeername_args *uap;
                   1412:        register_t *retval;
                   1413: {
                   1414: 
                   1415:        /* XXX uap should have type `getpeername_args *' to begin with. */
                   1416:        return (getpeername1(p, (struct getpeername_args *)uap, retval, 1));
                   1417: }
                   1418: #endif /* COMPAT_OLDSOCK */
                   1419: 
                   1420: int
                   1421: sockargs(mp, buf, buflen, type)
                   1422:        struct mbuf **mp;
                   1423:        caddr_t buf;
                   1424:        int buflen, type;
                   1425: {
                   1426:        register struct sockaddr *sa;
                   1427:        register struct mbuf *m;
                   1428:        int error;
                   1429: 
                   1430:        if ((u_int)buflen > MLEN) {
                   1431: #ifdef COMPAT_OLDSOCK
                   1432:                if (type == MT_SONAME && (u_int)buflen <= 112)
                   1433:                        buflen = MLEN;          /* unix domain compat. hack */
                   1434:                else
                   1435: #endif
                   1436:                return (EINVAL);
                   1437:        }
                   1438:        m = m_get(M_WAIT, type);
                   1439:        if (m == NULL)
                   1440:                return (ENOBUFS);
                   1441:        m->m_len = buflen;
                   1442:        error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
                   1443:        if (error)
                   1444:                (void) m_free(m);
                   1445:        else {
                   1446:                *mp = m;
                   1447:                if (type == MT_SONAME) {
                   1448:                        sa = mtod(m, struct sockaddr *);
                   1449: 
                   1450: #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
                   1451:                        if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                   1452:                                sa->sa_family = sa->sa_len;
                   1453: #endif
                   1454:                        sa->sa_len = buflen;
                   1455:                }
                   1456:        }
                   1457:        return (error);
                   1458: }
                   1459: 
                   1460: int
                   1461: getsockaddr(namp, uaddr, len)
                   1462:        struct sockaddr **namp;
                   1463:        caddr_t uaddr;
                   1464:        size_t len;
                   1465: {
                   1466:        struct sockaddr *sa;
                   1467:        int error;
                   1468: 
                   1469:        if (len > SOCK_MAXADDRLEN)
                   1470:                return ENAMETOOLONG;
                   1471:        MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
                   1472:        error = copyin(uaddr, sa, len);
                   1473:        if (error) {
                   1474:                FREE(sa, M_SONAME);
                   1475:        } else {
                   1476: #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
                   1477:                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                   1478:                        sa->sa_family = sa->sa_len;
                   1479: #endif
                   1480:                sa->sa_len = len;
                   1481:                *namp = sa;
                   1482:        }
                   1483:        return error;
                   1484: }
                   1485: 
                   1486: int
                   1487: getsock(fdp, fdes, fpp)
                   1488:        struct filedesc *fdp;
                   1489:        int fdes;
                   1490:        struct file **fpp;
                   1491: {
                   1492:        register struct file *fp;
                   1493: 
                   1494:        if ((unsigned)fdes >= fdp->fd_nfiles ||
                   1495:            (fp = fdp->fd_ofiles[fdes]) == NULL ||
                   1496:            (fdp->fd_ofileflags[fdes] & UF_RESERVED))
                   1497:                return (EBADF);
                   1498:        if (fp->f_type != DTYPE_SOCKET)
                   1499:                return (ENOTSOCK);
                   1500:        *fpp = fp;
                   1501:        return (0);
                   1502: }
                   1503: 
                   1504: #if SENDFILE
                   1505: /*
                   1506:  * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
                   1507:  * XXX - The sf_buf functions are currently private to sendfile(2), so have
                   1508:  * been made static, but may be useful in the future for doing zero-copy in
                   1509:  * other parts of the networking code. 
                   1510:  */
                   1511: static void
                   1512: sf_buf_init(void *arg)
                   1513: {
                   1514:        int i;
                   1515: 
                   1516:        SLIST_INIT(&sf_freelist);
                   1517:        sf_base = kmem_alloc_pageable(kernel_map, nsfbufs * PAGE_SIZE);
                   1518:        sf_bufs = _MALLOC(nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT);
                   1519:        bzero(sf_bufs, nsfbufs * sizeof(struct sf_buf));
                   1520:        for (i = 0; i < nsfbufs; i++) {
                   1521:                sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
                   1522:                SLIST_INSERT_HEAD(&sf_freelist, &sf_bufs[i], free_list);
                   1523:        }
                   1524: }
                   1525: 
                   1526: /*
                   1527:  * Get an sf_buf from the freelist. Will block if none are available.
                   1528:  */
                   1529: static struct sf_buf *
                   1530: sf_buf_alloc()
                   1531: {
                   1532:        struct sf_buf *sf;
                   1533:        int s;
                   1534: 
                   1535:        s = splimp();
                   1536:        while ((sf = SLIST_FIRST(&sf_freelist)) == NULL) {
                   1537:                sf_buf_alloc_want = 1;
                   1538:                tsleep(&sf_freelist, PVM, "sfbufa", 0);
                   1539:        }
                   1540:        SLIST_REMOVE_HEAD(&sf_freelist, free_list);
                   1541:        splx(s);
                   1542:        sf->refcnt = 1;
                   1543:        return (sf);
                   1544: }
                   1545: 
                   1546: #define dtosf(x)       (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT])
                   1547: static void
                   1548: sf_buf_ref(caddr_t addr, u_int size)
                   1549: {
                   1550:        struct sf_buf *sf;
                   1551: 
                   1552:        sf = dtosf(addr);
                   1553:        if (sf->refcnt == 0)
                   1554:                panic("sf_buf_ref: referencing a free sf_buf");
                   1555:        sf->refcnt++;
                   1556: }
                   1557: 
                   1558: /*
                   1559:  * Lose a reference to an sf_buf. When none left, detach mapped page
                   1560:  * and release resources back to the system.
                   1561:  *
                   1562:  * Must be called at splimp.
                   1563:  */
                   1564: static void
                   1565: sf_buf_free(caddr_t addr, u_int size)
                   1566: {
                   1567:        struct sf_buf *sf;
                   1568:        struct vm_page *m;
                   1569:        int s;
                   1570: 
                   1571:        sf = dtosf(addr);
                   1572:        if (sf->refcnt == 0)
                   1573:                panic("sf_buf_free: freeing free sf_buf");
                   1574:        sf->refcnt--;
                   1575:        if (sf->refcnt == 0) {
                   1576:                pmap_qremove((vm_offset_t)addr, 1);
                   1577:                m = sf->m;
                   1578:                s = splvm();
                   1579:                vm_page_unwire(m, 0);
                   1580:                /*
                   1581:                 * Check for the object going away on us. This can
                   1582:                 * happen since we don't hold a reference to it.
                   1583:                 * If so, we're responsible for freeing the page.
                   1584:                 */
                   1585:                if (m->wire_count == 0 && m->object == NULL)
                   1586:                        vm_page_free(m);
                   1587:                splx(s);
                   1588:                sf->m = NULL;
                   1589:                SLIST_INSERT_HEAD(&sf_freelist, sf, free_list);
                   1590:                if (sf_buf_alloc_want) {
                   1591:                        sf_buf_alloc_want = 0;
                   1592:                        wakeup(&sf_freelist);
                   1593:                }
                   1594:        }
                   1595: }
                   1596: 
                   1597: /*
                   1598:  * sendfile(2).
                   1599:  * int sendfile(int fd, int s, off_t offset, size_t nbytes,
                   1600:  *      struct sf_hdtr *hdtr, off_t *sbytes, int flags)
                   1601:  *
                   1602:  * Send a file specified by 'fd' and starting at 'offset' to a socket
                   1603:  * specified by 's'. Send only 'nbytes' of the file or until EOF if
                   1604:  * nbytes == 0. Optionally add a header and/or trailer to the socket
                   1605:  * output. If specified, write the total number of bytes sent into *sbytes.
                   1606:  */
                   1607: int
                   1608: sendfile(struct proc *p, struct sendfile_args *uap)
                   1609: {
                   1610:        struct file *fp;
                   1611:        struct filedesc *fdp = p->p_fd;
                   1612:        struct vnode *vp;
                   1613:        struct vm_object *obj;
                   1614:        struct socket *so;
                   1615:        struct mbuf *m;
                   1616:        struct sf_buf *sf;
                   1617:        struct vm_page *pg;
                   1618:        struct writev_args nuap;
                   1619:        struct sf_hdtr hdtr;
                   1620:        off_t off, xfsize, sbytes = 0;
                   1621:        int error = 0, s;
                   1622: 
                   1623:        /*
                   1624:         * Do argument checking. Must be a regular file in, stream
                   1625:         * type and connected socket out, positive offset.
                   1626:         */
                   1627:        if (((u_int)uap->fd) >= fdp->fd_nfiles ||
                   1628:            (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
                   1629:            (fp->f_flag & FREAD) == 0) {
                   1630:                error = EBADF;
                   1631:                goto done;
                   1632:        }
                   1633:        if (fp->f_type != DTYPE_VNODE) {
                   1634:                error = EINVAL;
                   1635:                goto done;
                   1636:        }
                   1637:        vp = (struct vnode *)fp->f_data;
                   1638:        obj = vp->v_object;
                   1639:        if (vp->v_type != VREG || obj == NULL) {
                   1640:                error = EINVAL;
                   1641:                goto done;
                   1642:        }
                   1643:        error = getsock(p->p_fd, uap->s, &fp);
                   1644:        if (error)
                   1645:                goto done;
                   1646:        so = (struct socket *)fp->f_data;
                   1647:        if (so->so_type != SOCK_STREAM) {
                   1648:                error = EINVAL;
                   1649:                goto done;
                   1650:        }
                   1651:        if ((so->so_state & SS_ISCONNECTED) == 0) {
                   1652:                error = ENOTCONN;
                   1653:                goto done;
                   1654:        }
                   1655:        if (uap->offset < 0) {
                   1656:                error = EINVAL;
                   1657:                goto done;
                   1658:        }
                   1659: 
                   1660:        /*
                   1661:         * If specified, get the pointer to the sf_hdtr struct for
                   1662:         * any headers/trailers.
                   1663:         */
                   1664:        if (uap->hdtr != NULL) {
                   1665:                error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
                   1666:                if (error)
                   1667:                        goto done;
                   1668:                /*
                   1669:                 * Send any headers. Wimp out and use writev(2).
                   1670:                 */
                   1671:                if (hdtr.headers != NULL) {
                   1672:                        nuap.fd = uap->s;
                   1673:                        nuap.iovp = hdtr.headers;
                   1674:                        nuap.iovcnt = hdtr.hdr_cnt;
                   1675:                        error = writev(p, &nuap);
                   1676:                        if (error)
                   1677:                                goto done;
                   1678:                        sbytes += p->p_retval[0];
                   1679:                }
                   1680:        }
                   1681: 
                   1682:        /*
                   1683:         * Protect against multiple writers to the socket.
                   1684:         */
                   1685:        (void) sblock(&so->so_snd, M_WAIT);
                   1686: 
                   1687:        /*
                   1688:         * Loop through the pages in the file, starting with the requested
                   1689:         * offset. Get a file page (do I/O if necessary), map the file page
                   1690:         * into an sf_buf, attach an mbuf header to the sf_buf, and queue
                   1691:         * it on the socket.
                   1692:         */
                   1693:        for (off = uap->offset; ; off += xfsize, sbytes += xfsize) {
                   1694:                vm_pindex_t pindex;
                   1695:                vm_offset_t pgoff;
                   1696: 
                   1697:                pindex = OFF_TO_IDX(off);
                   1698: retry_lookup:
                   1699:                /*
                   1700:                 * Calculate the amount to transfer. Not to exceed a page,
                   1701:                 * the EOF, or the passed in nbytes.
                   1702:                 */
                   1703:                xfsize = obj->un_pager.vnp.vnp_size - off;
                   1704:                if (xfsize > PAGE_SIZE)
                   1705:                        xfsize = PAGE_SIZE;
                   1706:                pgoff = (vm_offset_t)(off & PAGE_MASK);
                   1707:                if (PAGE_SIZE - pgoff < xfsize)
                   1708:                        xfsize = PAGE_SIZE - pgoff;
                   1709:                if (uap->nbytes && xfsize > (uap->nbytes - sbytes))
                   1710:                        xfsize = uap->nbytes - sbytes;
                   1711:                if (xfsize <= 0)
                   1712:                        break;
                   1713:                /*
                   1714:                 * Optimize the non-blocking case by looking at the socket space
                   1715:                 * before going to the extra work of constituting the sf_buf.
                   1716:                 */
                   1717:                if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) {
                   1718:                        if (so->so_state & SS_CANTSENDMORE)
                   1719:                                error = EPIPE;
                   1720:                        else
                   1721:                                error = EAGAIN;
                   1722:                        sbunlock(&so->so_snd);
                   1723:                        goto done;
                   1724:                }
                   1725:                /*
                   1726:                 * Attempt to look up the page. If the page doesn't exist or the
                   1727:                 * part we're interested in isn't valid, then read it from disk.
                   1728:                 * If some other part of the kernel has this page (i.e. it's busy),
                   1729:                 * then disk I/O may be occuring on it, so wait and retry.
                   1730:                 */
                   1731:                pg = vm_page_lookup(obj, pindex);
                   1732:                if (pg == NULL || (!(pg->flags & PG_BUSY) && !pg->busy &&
                   1733:                    !vm_page_is_valid(pg, pgoff, xfsize))) {
                   1734:                        struct uio auio;
                   1735:                        struct iovec aiov;
                   1736:                        int bsize;
                   1737: 
                   1738:                        if (pg == NULL) {
                   1739:                                pg = vm_page_alloc(obj, pindex, VM_ALLOC_NORMAL);
                   1740:                                if (pg == NULL) {
                   1741:                                        VM_WAIT;
                   1742:                                        goto retry_lookup;
                   1743:                                }
                   1744:                                /*
                   1745:                                 * don't just clear PG_BUSY manually -
                   1746:                                 * vm_page_alloc() should be considered opaque,
                   1747:                                 * use the VM routine provided to clear
                   1748:                                 * PG_BUSY.
                   1749:                                 */
                   1750:                                vm_page_wakeup(pg);
                   1751: 
                   1752:                        }
                   1753:                        /*
                   1754:                         * Ensure that our page is still around when the I/O completes.
                   1755:                         */
                   1756:                        vm_page_io_start(pg);
                   1757:                        vm_page_wire(pg);
                   1758:                        /*
                   1759:                         * Get the page from backing store.
                   1760:                         */
                   1761:                        bsize = vp->v_mount->mnt_stat.f_iosize;
                   1762:                        auio.uio_iov = &aiov;
                   1763:                        auio.uio_iovcnt = 1;
                   1764:                        aiov.iov_base = 0;
                   1765:                        aiov.iov_len = MAXBSIZE;
                   1766:                        auio.uio_resid = MAXBSIZE;
                   1767:                        auio.uio_offset = trunc_page(off);
                   1768:                        auio.uio_segflg = UIO_NOCOPY;
                   1769:                        auio.uio_rw = UIO_READ;
                   1770:                        auio.uio_procp = p;
                   1771:                        vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, p);
                   1772:                        error = VOP_READ(vp, &auio, IO_VMIO | ((MAXBSIZE / bsize) << 16),
                   1773:                                p->p_ucred);
                   1774:                        VOP_UNLOCK(vp, 0, p);
                   1775:                        vm_page_flag_clear(pg, PG_ZERO);
                   1776:                        vm_page_io_finish(pg);
                   1777:                        if (error) {
                   1778:                                vm_page_unwire(pg, 0);
                   1779:                                /*
                   1780:                                 * See if anyone else might know about this page.
                   1781:                                 * If not and it is not valid, then free it.
                   1782:                                 */
                   1783:                                if (pg->wire_count == 0 && pg->valid == 0 &&
                   1784:                                    pg->busy == 0 && !(pg->flags & PG_BUSY) &&
                   1785:                                    pg->hold_count == 0)
                   1786:                                        vm_page_free(pg);
                   1787:                                sbunlock(&so->so_snd);
                   1788:                                goto done;
                   1789:                        }
                   1790:                } else {
                   1791:                        if ((pg->flags & PG_BUSY) || pg->busy)  {
                   1792:                                s = splvm();
                   1793:                                if ((pg->flags & PG_BUSY) || pg->busy) {
                   1794:                                        /*
                   1795:                                         * Page is busy. Wait and retry.
                   1796:                                         */
                   1797:                                        vm_page_flag_set(pg, PG_WANTED);
                   1798:                                        tsleep(pg, PVM, "sfpbsy", 0);
                   1799:                                        splx(s);
                   1800:                                        goto retry_lookup;
                   1801:                                }
                   1802:                                splx(s);
                   1803:                        }
                   1804:                        /*
                   1805:                         * Protect from having the page ripped out from beneath us.
                   1806:                         */
                   1807:                        vm_page_wire(pg);
                   1808:                }
                   1809:                /*
                   1810:                 * Allocate a kernel virtual page and insert the physical page
                   1811:                 * into it.
                   1812:                 */
                   1813:                sf = sf_buf_alloc();
                   1814:                sf->m = pg;
                   1815:                pmap_qenter(sf->kva, &pg, 1);
                   1816:                /*
                   1817:                 * Get an mbuf header and set it up as having external storage.
                   1818:                 */
                   1819:                MGETHDR(m, M_WAIT, MT_DATA);
                   1820:                m->m_ext.ext_free = sf_buf_free;
                   1821:                m->m_ext.ext_ref = sf_buf_ref;
                   1822:                m->m_ext.ext_buf = (void *)sf->kva;
                   1823:                m->m_ext.ext_size = PAGE_SIZE;
                   1824:                m->m_data = (char *) sf->kva + pgoff;
                   1825:                m->m_flags |= M_EXT;
                   1826:                m->m_pkthdr.len = m->m_len = xfsize;
                   1827:                /*
                   1828:                 * Add the buffer to the socket buffer chain.
                   1829:                 */
                   1830:                s = splnet();
                   1831: retry_space:
                   1832:                /*
                   1833:                 * Make sure that the socket is still able to take more data.
                   1834:                 * CANTSENDMORE being true usually means that the connection
                   1835:                 * was closed. so_error is true when an error was sensed after
                   1836:                 * a previous send.
                   1837:                 * The state is checked after the page mapping and buffer
                   1838:                 * allocation above since those operations may block and make
                   1839:                 * any socket checks stale. From this point forward, nothing
                   1840:                 * blocks before the pru_send (or more accurately, any blocking
                   1841:                 * results in a loop back to here to re-check).
                   1842:                 */
                   1843:                if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
                   1844:                        if (so->so_state & SS_CANTSENDMORE) {
                   1845:                                error = EPIPE;
                   1846:                        } else {
                   1847:                                error = so->so_error;
                   1848:                                so->so_error = 0;
                   1849:                        }
                   1850:                        m_freem(m);
                   1851:                        sbunlock(&so->so_snd);
                   1852:                        splx(s);
                   1853:                        goto done;
                   1854:                }
                   1855:                /*
                   1856:                 * Wait for socket space to become available. We do this just
                   1857:                 * after checking the connection state above in order to avoid
                   1858:                 * a race condition with sbwait().
                   1859:                 */
                   1860:                if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
                   1861:                        if (so->so_state & SS_NBIO) {
                   1862:                                m_freem(m);
                   1863:                                sbunlock(&so->so_snd);
                   1864:                                splx(s);
                   1865:                                error = EAGAIN;
                   1866:                                goto done;
                   1867:                        }
                   1868:                        error = sbwait(&so->so_snd);
                   1869:                        /*
                   1870:                         * An error from sbwait usually indicates that we've
                   1871:                         * been interrupted by a signal. If we've sent anything
                   1872:                         * then return bytes sent, otherwise return the error.
                   1873:                         */
                   1874:                        if (error) {
                   1875:                                m_freem(m);
                   1876:                                sbunlock(&so->so_snd);
                   1877:                                splx(s);
                   1878:                                goto done;
                   1879:                        }
                   1880:                        goto retry_space;
                   1881:                }
                   1882:                error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, p);
                   1883:                splx(s);
                   1884:                if (error) {
                   1885:                        sbunlock(&so->so_snd);
                   1886:                        goto done;
                   1887:                }
                   1888:        }
                   1889:        sbunlock(&so->so_snd);
                   1890: 
                   1891:        /*
                   1892:         * Send trailers. Wimp out and use writev(2).
                   1893:         */
                   1894:        if (uap->hdtr != NULL && hdtr.trailers != NULL) {
                   1895:                        nuap.fd = uap->s;
                   1896:                        nuap.iovp = hdtr.trailers;
                   1897:                        nuap.iovcnt = hdtr.trl_cnt;
                   1898:                        error = writev(p, &nuap);
                   1899:                        if (error)
                   1900:                                goto done;
                   1901:                        sbytes += p->p_retval[0];
                   1902:        }
                   1903: 
                   1904: done:
                   1905:        if (uap->sbytes != NULL) {
                   1906:                copyout(&sbytes, uap->sbytes, sizeof(off_t));
                   1907:        }
                   1908:        return (error);
                   1909: }
                   1910: 
                   1911: #endif

unix.superglobalmegacorp.com

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