Annotation of kernel/bsd/kern/sys_generic.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1982, 1986, 1989, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  * (c) UNIX System Laboratories, Inc.
                     30:  * All or some portions of this file are derived from material licensed
                     31:  * to the University of California by American Telephone and Telegraph
                     32:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     33:  * the permission of UNIX System Laboratories, Inc.
                     34:  *
                     35:  * Redistribution and use in source and binary forms, with or without
                     36:  * modification, are permitted provided that the following conditions
                     37:  * are met:
                     38:  * 1. Redistributions of source code must retain the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer.
                     40:  * 2. Redistributions in binary form must reproduce the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer in the
                     42:  *    documentation and/or other materials provided with the distribution.
                     43:  * 3. All advertising materials mentioning features or use of this software
                     44:  *    must display the following acknowledgement:
                     45:  *     This product includes software developed by the University of
                     46:  *     California, Berkeley and its contributors.
                     47:  * 4. Neither the name of the University nor the names of its contributors
                     48:  *    may be used to endorse or promote products derived from this software
                     49:  *    without specific prior written permission.
                     50:  *
                     51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     61:  * SUCH DAMAGE.
                     62:  *
                     63:  *     @(#)sys_generic.c       8.9 (Berkeley) 2/14/95
                     64:  */
                     65: #include <sys/param.h>
                     66: #include <sys/systm.h>
1.1.1.2 ! root       67: #include <sys/malloc.h>
        !            68: #include <sys/mbuf.h>
        !            69: #include <sys/protosw.h>
        !            70: #include <sys/socket.h>
        !            71: #include <sys/socketvar.h>
        !            72: #include <sys/errno.h>
        !            73: #include <sys/ev.h>
        !            74: 
        !            75: #include <net/if.h>
        !            76: #include <net/route.h>
        !            77: 
        !            78: #include <netinet/in.h>
        !            79: #include <netinet/in_systm.h>
        !            80: #include <netinet/ip.h>
        !            81: #include <netinet/in_pcb.h>
        !            82: #include <netinet/ip_var.h>
        !            83: #include <netinet/tcp.h>
        !            84: #include <netinet/tcp_fsm.h>
        !            85: #include <netinet/tcp_seq.h>
        !            86: #include <netinet/tcp_timer.h>
        !            87: #include <netinet/tcp_var.h>
        !            88: #include <netinet/tcpip.h>
        !            89: #include <netinet/tcp_debug.h>
        !            90: #include <sys/ev.h>
        !            91: 
1.1       root       92: #include <sys/filedesc.h>
                     93: #include <sys/ioctl.h>
                     94: #include <sys/file.h>
                     95: #include <sys/proc.h>
                     96: #include <sys/uio.h>
                     97: #include <sys/kernel.h>
                     98: #include <sys/stat.h>
1.1.1.2 ! root       99: 
1.1       root      100: #if KTRACE
                    101: #include <sys/ktrace.h>
                    102: #endif
                    103: 
                    104: #include <sys/mount.h>
                    105: #include <sys/protosw.h>
                    106: #include <sys/ev.h>
                    107: #include <sys/user.h>
                    108: #include <kern/kdebug.h>
                    109: 
                    110: /*
                    111:  * Read system call.
                    112:  */
                    113: struct read_args {
                    114:        int fd;
                    115:        char *cbuf;
                    116:        u_int nbyte;
                    117: };
                    118: /* ARGSUSED */
                    119: read(p, uap, retval)
                    120:        struct proc *p;
                    121:        register struct read_args *uap;
                    122:        register_t *retval;
                    123: {
                    124:        struct uio auio;
                    125:        struct iovec aiov;
                    126: 
                    127:        aiov.iov_base = (caddr_t)uap->cbuf;
                    128:        aiov.iov_len = uap->nbyte;
                    129:        auio.uio_iov = &aiov;
                    130:        auio.uio_iovcnt = 1;
                    131:        auio.uio_rw = UIO_READ;
                    132:        return (rwuio(p, uap->fd, &auio, UIO_READ, retval));    
                    133: }
                    134: 
                    135: struct readv_args {
                    136:        int fd;
                    137:        struct iovec *iovp;
                    138:        u_int iovcnt;
                    139: };
                    140: readv(p, uap, retval)
                    141:        struct proc *p;
                    142:        register struct readv_args *uap;
                    143:        int *retval;
                    144: {
                    145:        struct uio auio;
                    146:        register struct iovec *iov;
                    147:        int error;
                    148:        struct iovec aiov[UIO_SMALLIOV];
                    149: 
                    150:        if (uap->iovcnt > UIO_SMALLIOV) {
                    151:                if (uap->iovcnt > UIO_MAXIOV)
                    152:                        return (EINVAL);        
                    153:                if ((iov = (struct iovec *)
                    154:                            kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
                    155:                        return (ENOMEM);
                    156:        } else
                    157:                iov = aiov;
                    158:        auio.uio_iov = iov;
                    159:        auio.uio_iovcnt = uap->iovcnt;
                    160:        auio.uio_rw = UIO_READ;
                    161:        error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
                    162:            uap->iovcnt * sizeof (struct iovec));
                    163:        if (!error)
                    164:                error = rwuio(p, uap->fd, &auio, UIO_READ, retval);
                    165:        if (uap->iovcnt > UIO_SMALLIOV)
                    166:                kfree(iov, sizeof(struct iovec)*uap->iovcnt);
                    167:        return (error);
                    168: }
                    169: 
                    170: /*
                    171:  * Write system call
                    172:  */
                    173: struct write_args {
                    174:        int fd;
                    175:        char *cbuf;
                    176:        u_int nbyte;
                    177: };
                    178: write(p, uap, retval)
                    179:        struct proc *p;
                    180:        register struct write_args *uap;
                    181:        int *retval;
                    182: {
                    183:        struct uio auio;
                    184:        struct iovec aiov;
                    185: 
                    186:        aiov.iov_base = uap->cbuf;
                    187:        aiov.iov_len = uap->nbyte;
                    188:        auio.uio_iov = &aiov;
                    189:        auio.uio_iovcnt = 1;
                    190:        auio.uio_rw = UIO_WRITE;
                    191:        return (rwuio(p, uap->fd, &auio, UIO_WRITE, retval));
                    192: }
                    193: 
                    194: struct writev_args {
                    195:        int fd;
                    196:        struct iovec *iovp;
                    197:        u_int iovcnt;
                    198: };
                    199: writev(p, uap, retval)
                    200:        struct proc *p;
                    201:        register struct writev_args *uap;
                    202:        int *retval;
                    203: {
                    204:        struct uio auio;
                    205:        register struct iovec *iov;
                    206:        int error;
                    207:        struct iovec aiov[UIO_SMALLIOV];
                    208: 
                    209:        if (uap->iovcnt > UIO_SMALLIOV) {
                    210:                if (uap->iovcnt > UIO_MAXIOV)
                    211:                        return (EINVAL);        
                    212:                if ((iov = (struct iovec *)
                    213:                            kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
                    214:                        return (ENOMEM);
                    215:        } else
                    216:                iov = aiov;
                    217:        auio.uio_iov = iov;
                    218:        auio.uio_iovcnt = uap->iovcnt;
                    219:        auio.uio_rw = UIO_WRITE;
                    220:        error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
                    221:            uap->iovcnt * sizeof (struct iovec));
                    222:        if (!error)
                    223:                error = rwuio(p, uap->fd, &auio, UIO_WRITE, retval);
                    224:        if (uap->iovcnt > UIO_SMALLIOV)
                    225:                kfree(iov, sizeof(struct iovec)*uap->iovcnt);
                    226:        return (error);
                    227: }
                    228: 
                    229: rwuio(p, fdes, uio, rw, retval)
                    230:        struct proc *p;
                    231:        int fdes;
                    232:        register struct uio *uio;
                    233:        enum uio_rw rw;
                    234:        int *retval;
                    235: {
                    236:        register struct file *fp;
                    237:        register struct iovec *iov;
                    238:        int i, count, flag, error;
                    239: 
                    240:        if (error = fdgetf(p, fdes, &fp))
                    241:                return (error);
                    242: 
                    243:        if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
                    244:                return(EBADF);
                    245:        }
                    246:        uio->uio_resid = 0;
                    247:        uio->uio_segflg = UIO_USERSPACE;
                    248:        uio->uio_procp = p;
                    249:        iov = uio->uio_iov;
                    250:        for (i = 0; i < uio->uio_iovcnt; i++) {
                    251:                if (iov->iov_len < 0) {
                    252:                        return(EINVAL);
                    253:                }
                    254:                uio->uio_resid += iov->iov_len;
                    255:                if (uio->uio_resid < 0) {
                    256:                        return(EINVAL);
                    257:                }
                    258:                iov++;
                    259:        }
                    260:        count = uio->uio_resid;
                    261:        if (rw == UIO_READ) {
                    262:                if (error = (*fp->f_ops->fo_read)(fp, uio, fp->f_cred))
                    263:                                if (uio->uio_resid != count && (error == ERESTART ||
                    264:                                        error == EINTR || error == EWOULDBLOCK))
                    265:                                                error = 0;
                    266:        } else {
                    267:                if (error = (*fp->f_ops->fo_write)(fp, uio, fp->f_cred)) {
                    268:                        if (uio->uio_resid != count && (error == ERESTART ||
                    269:                        error == EINTR || error == EWOULDBLOCK))
                    270:                                error = 0;
                    271:                        if (error == EPIPE)
                    272:                                psignal(p, SIGPIPE);
                    273:                }
                    274:        }
                    275:        *retval = count - uio->uio_resid;
                    276:        return(error);
                    277: }
                    278: 
                    279: /*
                    280:  * Ioctl system call
                    281:  */
                    282: struct ioctl_args {
                    283:        int fd;
                    284:        u_long com;
                    285:        caddr_t data;
                    286: };
                    287: /* ARGSUSED */
                    288: ioctl(p, uap, retval)
                    289:        struct proc *p;
                    290:        register struct ioctl_args *uap;
                    291:        register_t *retval;
                    292: {
                    293:        register struct file *fp;
                    294:        register u_long com;
                    295:        register int error;
                    296:        register u_int size;
                    297:        caddr_t data, memp;
                    298:        int tmp;
                    299: #define STK_PARAMS     128
                    300:        char stkbuf[STK_PARAMS];
                    301: 
                    302:        if (error = fdgetf(p, uap->fd, &fp))
                    303:                return (error);
                    304: 
                    305:        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
                    306:                return (EBADF);
                    307:                
                    308:        /*### LD 6/11/97 Hack Alert: this is to get AppleTalk to work
                    309:         * while implementing an ATioctl system call
                    310:         */
                    311: #if NETAT
                    312:        {
                    313:                extern int appletalk_inited;
                    314: 
                    315:                if (appletalk_inited && ((uap->com & 0x0000FFFF) == 0xff99)) {
                    316: #ifdef APPLETALK_DEBUG
                    317:                        kprintf("ioctl: special AppleTalk \n");
                    318: #endif
                    319:                        error = (*fp->f_ops->fo_ioctl)(fp, uap->com, uap->data, p);
                    320:                        return(error);
                    321:                }
                    322:        }
                    323: 
                    324: #endif /* NETAT */
                    325: 
                    326: 
                    327:        switch (com = uap->com) {
                    328:        case FIONCLEX:
                    329:                *fdflags(p, uap->fd) &= ~UF_EXCLOSE;
                    330:                return (0);
                    331:        case FIOCLEX:
                    332:                *fdflags(p, uap->fd) |= UF_EXCLOSE;
                    333:                return (0);
                    334:        }
                    335: 
                    336:        /*
                    337:         * Interpret high order word to find amount of data to be
                    338:         * copied to/from the user's address space.
                    339:         */
                    340:        size = IOCPARM_LEN(com);
                    341:        if (size > IOCPARM_MAX)
                    342:                return (ENOTTY);
                    343:        memp = NULL;
                    344:        if (size > sizeof (stkbuf)) {
                    345:                if ((memp = (caddr_t)kalloc(size)) == 0)
                    346:                        return(ENOMEM);
                    347:                data = memp;
                    348:        } else
                    349:                data = stkbuf;
                    350:        if (com&IOC_IN) {
                    351:                if (size) {
                    352:                        error = copyin(uap->data, data, (u_int)size);
                    353:                        if (error) {
                    354:                                if (memp)
                    355:                                        kfree(memp, size);
                    356:                                return (error);
                    357:                        }
                    358:                } else
                    359:                        *(caddr_t *)data = uap->data;
                    360:        } else if ((com&IOC_OUT) && size)
                    361:                /*
                    362:                 * Zero the buffer so the user always
                    363:                 * gets back something deterministic.
                    364:                 */
                    365:                bzero(data, size);
                    366:        else if (com&IOC_VOID)
                    367:                *(caddr_t *)data = uap->data;
                    368: 
                    369:        switch (com) {
                    370: 
                    371:        case FIONBIO:
                    372:                if (tmp = *(int *)data)
                    373:                        fp->f_flag |= FNONBLOCK;
                    374:                else
                    375:                        fp->f_flag &= ~FNONBLOCK;
                    376:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                    377:                break;
                    378: 
                    379:        case FIOASYNC:
                    380:                if (tmp = *(int *)data)
                    381:                        fp->f_flag |= FASYNC;
                    382:                else
                    383:                        fp->f_flag &= ~FASYNC;
                    384:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
                    385:                break;
                    386: 
                    387:        case FIOSETOWN:
                    388:                tmp = *(int *)data;
                    389:                if (fp->f_type == DTYPE_SOCKET) {
                    390:                        ((struct socket *)fp->f_data)->so_pgid = tmp;
                    391:                        error = 0;
                    392:                        break;
                    393:                }
                    394:                if (tmp <= 0) {
                    395:                        tmp = -tmp;
                    396:                } else {
                    397:                        struct proc *p1 = pfind(tmp);
                    398:                        if (p1 == 0) {
                    399:                                error = ESRCH;
                    400:                                break;
                    401:                        }
                    402:                        tmp = p1->p_pgrp->pg_id;
                    403:                }
                    404:                error = (*fp->f_ops->fo_ioctl)
                    405:                        (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
                    406:                break;
                    407: 
                    408:        case FIOGETOWN:
                    409:                if (fp->f_type == DTYPE_SOCKET) {
                    410:                        error = 0;
                    411:                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
                    412:                        break;
                    413:                }
                    414:                error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
                    415:                *(int *)data = -*(int *)data;
                    416:                break;
                    417: 
                    418:        default:
                    419:                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
                    420:                /*
                    421:                 * Copy any data to user, size was
                    422:                 * already set and checked above.
                    423:                 */
                    424:                if (error == 0 && (com&IOC_OUT) && size)
                    425:                        error = copyout(data, uap->data, (u_int)size);
                    426:                break;
                    427:        }
                    428:        if (memp)
                    429:                kfree(memp, size);
                    430:        return (error);
                    431: }
                    432: 
                    433: 
                    434: int    selwait, nselcoll;
                    435: 
                    436: /*
                    437:  * Select system call.
                    438:  */
                    439: struct select_args {
                    440:        u_int nd;
                    441:        fd_set *in;
                    442:        fd_set *ou;
                    443:        fd_set *ex;
                    444:        struct timeval *tv;
                    445: };
                    446: 
                    447: select(p, uap, retval)
                    448:        register struct proc *p;
                    449:        register struct select_args *uap;
                    450:        register_t *retval;
                    451: {
                    452:        fd_set ibits[3], obits[3];
                    453:        struct timeval atv;
                    454:        int s, ncoll, error = 0, timo;
                    455:        u_int ni;
                    456:        struct thread *th;
                    457:        struct uthread  *uth;
                    458: 
                    459:        th = current_thread();
                    460:        uth = th->_uthread;
                    461: 
                    462:        bzero((caddr_t)ibits, sizeof(ibits));
                    463:        bzero((caddr_t)obits, sizeof(obits));
                    464: 
                    465:        if (uap->nd > FD_SETSIZE)
                    466:                return (EINVAL);
                    467:        if (uap->nd > p->p_fd->fd_nfiles) {
                    468:                /* forgiving; slightly wrong */
                    469:                uap->nd = p->p_fd->fd_nfiles;
                    470:        }
                    471:        ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
                    472: 
                    473: #define        getbits(name, x) \
                    474:        if (uap->name && (error = copyin((caddr_t)uap->name, \
                    475:            (caddr_t)&ibits[x], ni))) \
                    476:                goto done;
                    477:        getbits(in, 0);
                    478:        getbits(ou, 1);
                    479:        getbits(ex, 2);
                    480: #undef getbits
                    481:        if (uap->tv) {
                    482:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    483:                        sizeof (atv));
                    484:                if (error)
                    485:                        goto done;
                    486:                if (itimerfix(&atv)) {
                    487:                        error = EINVAL;
                    488:                        goto done;
                    489:                }
                    490:                s = splhigh();
                    491:                timeradd(&atv, &time, &atv);
                    492:                timo = hzto(&atv);
                    493:                splx(s);
                    494:        } else
                    495:                timo = 0;
                    496: retry:
                    497:        ncoll = nselcoll;
                    498:        p->p_flag |= P_SELECT;
                    499:        error = selscan(p, ibits, obits, uap->nd, retval);
                    500:        if (error || *retval)
                    501:                goto done;
                    502:        s = splhigh();
                    503:        /* this should be timercmp(&time, &atv, >=) */
                    504:        if (uap->tv && (time.tv_sec > atv.tv_sec ||
                    505:            time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
                    506:                splx(s);
                    507:                goto done;
                    508:        }
                    509:        /*
                    510:         * To effect a poll, the timeout argument should be
                    511:         * non-nil, pointing to a zero-valued timeval structure.
                    512:         */
                    513:        if (uap->tv && (timo == 0)) {
                    514:                splx(s);
                    515:                goto done;
                    516:        }
                    517:        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
                    518:                splx(s);
                    519:                goto retry;
                    520:        }
                    521:        p->p_flag &= ~P_SELECT;
                    522:        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
                    523:        splx(s);
                    524:        if (error == 0)
                    525:                goto retry;
                    526: done:
                    527:        p->p_flag &= ~P_SELECT;
                    528:        /* select is not restarted after signals... */
                    529:        if (error == ERESTART)
                    530:                error = EINTR;
                    531:        if (error == EWOULDBLOCK)
                    532:                error = 0;
                    533: #define        putbits(name, x) \
                    534:        if (uap->name && (error2 = copyout((caddr_t)&obits[x], \
                    535:            (caddr_t)uap->name, ni))) \
                    536:                error = error2;
                    537:        if (error == 0) {
                    538:                int error2;
                    539: 
                    540:                putbits(in, 0);
                    541:                putbits(ou, 1);
                    542:                putbits(ex, 2);
                    543: #undef putbits
                    544:        }
                    545:        return (error);
                    546: }
                    547: 
                    548: selscan(p, ibits, obits, nfd, retval)
                    549:        struct proc *p;
                    550:        fd_set *ibits, *obits;
                    551:        int nfd;
                    552:        register_t *retval;
                    553: {
                    554:        register struct filedesc *fdp = p->p_fd;
                    555:        register int msk, i, j, fd;
                    556:        register fd_mask bits;
                    557:        struct file *fp;
                    558:        int n = 0;
                    559:        static int flag[3] = { FREAD, FWRITE, 0 };
                    560: 
                    561:        for (msk = 0; msk < 3; msk++) {
                    562:                for (i = 0; i < nfd; i += NFDBITS) {
                    563:                        bits = ibits[msk].fds_bits[i/NFDBITS];
                    564:                        while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
                    565:                                bits &= ~(1 << j);
                    566:                                fp = fdp->fd_ofiles[fd];
                    567:                                if (fp == NULL || (fdp->fd_ofileflags[fd] &
                    568:                                                                UF_RESERVED))
                    569:                                        return (EBADF);
                    570:                                if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
                    571:                                        FD_SET(fd, &obits[msk]);
                    572:                                        n++;
                    573:                                }
                    574:                        }
                    575:                }
                    576:        }
                    577:        *retval = n;
                    578:        return (0);
                    579: }
                    580: 
                    581: /*ARGSUSED*/
                    582: seltrue(dev, flag, p)
                    583:        dev_t dev;
                    584:        int flag;
                    585:        struct proc *p;
                    586: {
                    587: 
                    588:        return (1);
                    589: }
                    590: 
                    591: /*
                    592:  * Record a select request.
                    593:  */
                    594: void
                    595: selrecord(selector, sip)
                    596:        struct proc *selector;
                    597:        struct selinfo *sip;
                    598: {
                    599:        int             oldpri = splhigh();
                    600:        thread_t        my_thread = current_thread();
                    601:        thread_t        selthread;
                    602: 
                    603:        selthread = sip->si_thread;
                    604:        
                    605:        if (selthread == my_thread) {
                    606:                splx(oldpri);
                    607:                return;
                    608:        }
                    609:        
                    610:        if (selthread && selthread->active &&
                    611:            selthread->wait_event == (caddr_t)&selwait) {
                    612:                        sip->si_flags |= SI_COLL;
                    613:                        splx(oldpri);
                    614:        }
                    615:        else {
                    616:                        sip->si_thread = my_thread;
                    617:                        splx(oldpri);
                    618:                        thread_deallocate(selthread);
                    619:                        thread_reference(sip->si_thread);
                    620:        }
                    621: 
                    622:        return;
                    623: }
                    624: 
                    625: void
                    626: selwakeup(sip)
                    627:        register struct selinfo *sip;
                    628: {
                    629:        register thread_t       the_thread = (thread_t)sip->si_thread;
                    630:        int oldpri;
                    631:        
                    632:        if (the_thread == 0)
                    633:                return;
                    634: 
                    635:        if (sip->si_flags & SI_COLL) {
                    636:                nselcoll++;
                    637:                sip->si_flags &= ~SI_COLL;
                    638:                wakeup((caddr_t)&selwait);
                    639:        }
                    640:        
                    641:        oldpri = splhigh();
                    642: 
                    643:        if (the_thread->active) {
                    644:                /* protect p_flag minimally at splsched() */
                    645:                if (the_thread->wait_event == &selwait)
                    646:                        clear_wait(the_thread, THREAD_AWAKENED, TRUE);
                    647:                if (the_thread->task->proc)
                    648:                        the_thread->task->proc->p_flag &= ~P_SELECT;
                    649:        }
                    650:        
                    651:        thread_deallocate_interrupt(the_thread);
                    652:        
                    653:        sip->si_thread = 0;
                    654:        
                    655:        splx(oldpri);
                    656:        
                    657: }
                    658: 
                    659: void selthreadclear(sip)
                    660:        register struct selinfo *sip;
                    661: {
                    662: 
                    663:        if (sip->si_thread)
                    664:                        thread_deallocate_interrupt(sip->si_thread);
                    665: 
                    666: }
                    667: 
                    668: 
                    669: /*
                    670:  * called upon socket close. deque and free all events for
                    671:  * the socket
                    672:  */
                    673: evsofree(struct socket *sp)
                    674: {
                    675:   struct eventqelt *eqp, *next;
                    676: 
                    677:   if (sp == NULL) return;
                    678: 
                    679:   for (eqp = sp->so_evlist.tqh_first; eqp != NULL; eqp = next) {
                    680:     next = eqp->ee_slist.tqe_next;
                    681:     evprocdeque(eqp->ee_proc, eqp); // remove from proc q if there
                    682:     TAILQ_REMOVE(&sp->so_evlist, eqp, ee_slist); // remove from socket q
                    683:     FREE(eqp, M_TEMP);
                    684:   }
                    685: }
                    686: 
                    687: 
                    688: #define DBG_EVENT 0x10
                    689: 
                    690: #define DBG_POST 0x10
                    691: #define DBG_WATCH 0x11
                    692: #define DBG_WAIT 0x12
                    693: #define DBG_MOD 0x13
                    694: #define DBG_EWAKEUP 0x14
                    695: 
                    696: #define DBG_MISC_POST MISCDBG_CODE(DBG_EVENT,DBG_POST)
                    697: #define DBG_MISC_WATCH MISCDBG_CODE(DBG_EVENT,DBG_WATCH)
                    698: #define DBG_MISC_WAIT MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
                    699: #define DBG_MISC_MOD MISCDBG_CODE(DBG_EVENT,DBG_MOD)
                    700: #define DBG_MISC_EWAKEUP MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
                    701: 
                    702: 
                    703: 
                    704: /*
                    705:  * enque this event if it's not already queued. wakeup
                    706:    the proc if we do queue this event to it.
                    707:  */
                    708: evprocenque(struct eventqelt *eqp)
                    709: {
                    710:   struct proc *p;
                    711: 
                    712:   assert(eqp);
                    713:   if (eqp->ee_flags & EV_QUEUED) {
                    714:     return;
                    715:   }
                    716:   eqp->ee_flags |= EV_QUEUED;
                    717:   eqp->ee_eventmask = 0;  // disarm
                    718:   p = eqp->ee_proc;
                    719:   TAILQ_INSERT_TAIL(&p->p_evlist, eqp, ee_plist);
                    720:   KERNEL_DEBUG(DBG_MISC_EWAKEUP,0,0,0,eqp,0);
                    721:   wakeup(&p->p_evlist);
                    722: }
                    723: 
                    724: /*
                    725:  * given either a sockbuf or a socket run down the
                    726:  * event list and queue ready events found
                    727:  */
                    728: postevent(struct socket *sp, struct sockbuf *sb, int event)
                    729: {
                    730:   int mask;
                    731:   struct eventqelt *evq;
1.1.1.2 ! root      732:   register struct tcpcb *tp;
        !           733: 
1.1       root      734: 
                    735:   if (sb) sp = sb->sb_so;
                    736:   if (!sp || sp->so_evlist.tqh_first == NULL) return;
                    737: 
                    738:   KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_START, 0,0,0,0,0);
                    739: 
                    740:   for (evq = sp->so_evlist.tqh_first;
                    741:        evq != NULL; evq = evq->ee_slist.tqe_next) {
                    742: 
                    743:     mask = 0;
                    744: 
                    745:     /* ready for reading:
                    746:        - byte cnt >= receive low water mark
                    747:        - read-half of conn closed
                    748:        - conn pending for listening sock
                    749:        - socket error pending
                    750: 
                    751:        ready for writing
                    752:        - byte cnt avail >= send low water mark
                    753:        - write half of conn closed
                    754:        - socket error pending
                    755:        - non-blocking conn completed successfully
                    756: 
                    757:        exception pending
                    758:        - out of band data
                    759:        - sock at out of band mark
                    760: 
                    761:     */
                    762:     switch (event & EV_DMASK) {
                    763: 
                    764:     case EV_RWBYTES:
                    765:     case EV_OOB:
                    766:       if (event & EV_OOB) {
                    767:       if ((evq->ee_eventmask & EV_EX)) {
                    768:        if (sp->so_oobmark || ((sp->so_state & SS_RCVATMARK))) {
                    769:          mask |= EV_EX|EV_OOB;
                    770:        }
                    771:       }
                    772:       }
                    773:       if (event & EV_RWBYTES) {
                    774:       if ((evq->ee_eventmask & EV_RE) && soreadable(sp)) {
1.1.1.2 ! root      775:        if ((sp->so_type == SOCK_STREAM) && (sp->so_error == ECONNREFUSED) ||
        !           776:            (sp->so_error == ECONNRESET)) {
        !           777:           tp = sototcpcb(sp);
        !           778:          if (tp->t_state == TCPS_CLOSED) {
        !           779:            mask |= EV_RE|EV_RESET;
        !           780:            break;
        !           781:          }
        !           782:        }
        !           783:        if (sp->so_state & SS_CANTRCVMORE) {
        !           784:          mask |= EV_RE|EV_FIN;
        !           785:          break;
        !           786:        }
1.1       root      787:        mask |= EV_RE;
                    788:        evq->ee_req.er_rcnt = sp->so_rcv.sb_cc;
                    789:       }
                    790: 
                    791:       if ((evq->ee_eventmask & EV_WR) && sowriteable(sp)) {
1.1.1.2 ! root      792:        if ((sp->so_type == SOCK_STREAM) &&(sp->so_error == ECONNREFUSED) ||
        !           793:            (sp->so_error == ECONNRESET)) {
        !           794:           tp = sototcpcb(sp);
        !           795:          if (tp->t_state == TCPS_CLOSED) {
        !           796:          mask |= EV_WR|EV_RESET;
        !           797:          break;
        !           798:          }
        !           799:        }
1.1       root      800:        mask |= EV_WR;
                    801:        evq->ee_req.er_wcnt = sbspace(&sp->so_snd);
                    802:       }
                    803:       }
                    804:     break;
                    805: 
                    806:     case EV_RCONN:
                    807:       if ((evq->ee_eventmask & EV_RE)) {
                    808:        evq->ee_req.er_rcnt = sp->so_qlen + 1;  // incl this one
                    809:        mask |= EV_RE|EV_RCONN;
                    810:       }
                    811:       break;
                    812: 
                    813:     case EV_WCONN:
                    814:       if ((evq->ee_eventmask & EV_WR)) {
                    815:        mask |= EV_WR|EV_WCONN;
                    816:       }
                    817:       break;
                    818: 
                    819:     case EV_RCLOSED:
                    820:       if ((evq->ee_eventmask & EV_RE)) {
                    821:        mask |= EV_RE|EV_RCLOSED;
                    822:        break;
                    823:       }
                    824: 
                    825:     case EV_WCLOSED:
                    826:       if ((evq->ee_eventmask & EV_WR)) {
                    827:        mask |= EV_WR|EV_WCLOSED;
                    828:        break;
                    829:       }
                    830: 
                    831:     case EV_FIN:
1.1.1.2 ! root      832:       if (evq->ee_eventmask & EV_RE) {
        !           833:        mask |= EV_RE|EV_FIN;
1.1       root      834:        break;
                    835:       }
                    836: 
                    837:     case EV_RESET:
1.1.1.2 ! root      838:       if (evq->ee_eventmask & EV_RE) {
        !           839:        mask |= EV_RE|EV_RESET;
        !           840:       } 
        !           841:       if (evq->ee_eventmask & EV_WR) {
        !           842:        mask |= EV_WR|EV_RESET;
1.1       root      843:       }
1.1.1.2 ! root      844:       break;
1.1       root      845: 
                    846:     default:
                    847:       return;
                    848:     } /* switch */
                    849: 
                    850:     if (mask) {
                    851:       evq->ee_req.er_eventbits |= mask;
                    852:       evprocenque(evq);
                    853:     }
                    854:   }
                    855:   KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_END, 0,0,0,0,0);
                    856: }
                    857: 
                    858: /*
                    859:  * remove and return the first event (eqp=NULL) or a specific
                    860:  * event, or return NULL if no events found
                    861:  */
                    862: struct eventqelt *
                    863: evprocdeque(struct proc *p, struct eventqelt *eqp)
                    864: {
                    865: 
                    866:   
                    867:   if (eqp && ((eqp->ee_flags & EV_QUEUED) == NULL))
                    868:     return(NULL);
                    869:   if (p->p_evlist.tqh_first == NULL)
                    870:     return(NULL);
                    871:   if (eqp == NULL) {  // remove first
                    872:     eqp = p->p_evlist.tqh_first;
                    873:   }
                    874:   TAILQ_REMOVE(&p->p_evlist, eqp, ee_plist);
                    875:   eqp->ee_flags &= ~EV_QUEUED;
                    876:   return(eqp);
                    877: }
                    878: 
                    879: struct evwatch_args {
                    880:   struct eventreq  *u_req;
                    881:   int               u_eventmask;
                    882: };
                    883: 
                    884: 
                    885: /*
                    886:  * watchevent system call. user passes us an event to watch
                    887:  * for. we malloc an event object, initialize it, and queue
                    888:  * it to the open socket. when the event occurs, postevent()
                    889:  * will enque it back to our proc where we can retrieve it
                    890:  * via waitevent().
                    891:  *
                    892:  * should this prevent duplicate events on same socket?
                    893:  */
                    894: int
                    895: watchevent(p, uap, retval)
                    896:      struct proc *p;
                    897:      struct evwatch_args *uap;
                    898:      register_t *retval;
                    899: {
                    900:   struct eventqelt *eqp = (struct eventqelt *)0;
                    901:   struct eventqelt *np;
                    902:   struct eventreq *erp;
                    903:   struct file *fp;
                    904:   struct socket *sp;
                    905:   int error;
                    906: 
                    907:   // get a qelt and fill with users req
                    908:   MALLOC(eqp, struct eventqelt *, sizeof(struct eventqelt), M_TEMP, M_WAITOK);
                    909:   if (!eqp) panic("can't MALLOC eqp");
                    910:   erp = &eqp->ee_req;
                    911:   // get users request pkt
                    912:   if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
                    913:                     sizeof(struct eventreq))) {
                    914:     FREE(eqp, M_TEMP);
                    915:     KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    916:     return(error);
                    917:   }
                    918:   KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_START, 0,
                    919:               erp->er_handle,uap->u_eventmask,eqp,0);
                    920:   // validate, freeing qelt if errors
                    921:   error = 0;
                    922:   if (erp->er_type != EV_FD) {
                    923:     error = EINVAL;
                    924:   } else  if (erp->er_handle < 0) {
                    925:     error = EBADF;
                    926:   } else  if (erp->er_handle > p->p_fd->fd_nfiles) {
                    927:     error = EBADF;
                    928:   } else if ((fp = *fdfile(p, erp->er_handle)) == NULL) {
                    929:     error = EBADF;
                    930:   } else if (fp->f_type != DTYPE_SOCKET) {
                    931:     error = EINVAL;
                    932:   }
                    933:   if (error) {
                    934:     FREE(eqp,M_TEMP);
                    935:     KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    936:     return(error);
                    937:   }
                    938: 
                    939:   erp->er_rcnt = erp->er_wcnt = erp->er_eventbits = 0;
                    940:   eqp->ee_proc = p;
                    941:   eqp->ee_eventmask = uap->u_eventmask & EV_MASK;
                    942:   eqp->ee_flags = 0;
                    943: 
                    944:   sp = (struct socket *)fp->f_data;
                    945:   assert(sp != NULL);
1.1.1.2 ! root      946:   eqp->ee_sp = sp;
1.1       root      947: 
                    948:   // only allow one watch per file per proc
                    949:   for (np = sp->so_evlist.tqh_first; np != NULL; np = np->ee_slist.tqe_next) {
                    950:     if (np->ee_proc == p) {
                    951:       FREE(eqp,M_TEMP);
                    952:       KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    953:       return(EINVAL);
                    954:     }
                    955:   }
                    956: 
                    957:   TAILQ_INSERT_TAIL(&sp->so_evlist, eqp, ee_slist);
                    958:   postevent(sp, 0, EV_RWBYTES); // catch existing events
                    959:   KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    960:   return(0);
                    961: }
                    962: 
                    963: struct evwait_args {
                    964:   struct eventreq *u_req;
                    965:   struct timeval *tv;
                    966: };
                    967: 
                    968: /*
                    969:  * waitevent system call.
                    970:  * grabs the next waiting event for this proc and returns
                    971:  * it. if no events, user can request to sleep with timeout
                    972:  * or poll mode (tv=NULL);
                    973:  */
                    974: int
                    975: waitevent(p, uap, retval)
                    976:      struct proc *p;
                    977:      struct evwait_args *uap;
                    978:      register_t *retval;
                    979: {
                    980:   int error = 0;
                    981:   struct eventqelt *eqp;
                    982:   int timo;
                    983:   struct timeval atv;
                    984:   int s;
                    985: 
                    986:        if (uap->tv) {
                    987:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    988:                        sizeof (atv));
                    989:                if (error)
                    990:                        return(error);
                    991:                if (itimerfix(&atv)) {
                    992:                        error = EINVAL;
                    993:                        return(error);
                    994:                }
                    995:                s = splhigh();
                    996:                timeradd(&atv, &time, &atv);
                    997:                timo = hzto(&atv);
                    998:                splx(s);
                    999:        } else
                   1000:                timo = 0;
                   1001: 
                   1002:   KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_START, 0,0,0,0,0);
                   1003: 
                   1004: retry:
                   1005:   s = splhigh();
                   1006:   if ((eqp = evprocdeque(p,NULL)) != NULL) {
                   1007:     splx(s);
                   1008:     error = copyout((caddr_t)&eqp->ee_req, (caddr_t)uap->u_req,
                   1009:                    sizeof(struct eventreq));
                   1010:     KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,
                   1011:                 eqp->ee_req.er_handle,eqp->ee_req.er_eventbits,eqp,0);
                   1012:     return(error);
                   1013:   } else {
                   1014:     if (uap->tv && (timo == 0)) {
                   1015:         splx(s);
                   1016:         *retval = 1;  // poll failed
                   1017:        return(error);
                   1018:     }
                   1019: 
                   1020:     KERNEL_DEBUG(DBG_MISC_WAIT, 1,0,0,0,0);
                   1021:     error = tsleep(&p->p_evlist, PSOCK | PCATCH, "waitevent", timo);
                   1022:     KERNEL_DEBUG(DBG_MISC_WAIT, 0,0,2,p->p_evlist.tqh_first,0);
                   1023:     splx(s);
                   1024:     if (error == 0)
                   1025:       goto retry;
                   1026:     if (error == ERESTART)
                   1027:       error = EINTR;
                   1028:     if (error == EWOULDBLOCK) {
                   1029:       *retval = 1;
                   1030:       error = 0;
                   1031:     }
                   1032:   }
                   1033:   KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,0,0,0,0);
                   1034:   return(error);
                   1035: }
                   1036: 
                   1037: struct modwatch_args {
                   1038:   struct eventreq *u_req;
                   1039:   int               u_eventmask;
                   1040: };
                   1041: 
                   1042: /*
                   1043:  * modwatch system call. user passes in event to modify.
                   1044:  * if we find it we reset the event bits and que/deque event
                   1045:  * it needed.
                   1046:  */
                   1047: int
                   1048: modwatch(p, uap, retval)
                   1049:      struct proc *p;
                   1050:      struct modwatch_args *uap;
                   1051:      register_t *retval;
                   1052: {
                   1053:   struct eventreq er;
                   1054:   struct eventreq *erp = &er;
                   1055:   struct eventqelt *evq;
                   1056:   int error;
                   1057:   struct file *fp;
                   1058:   struct socket *sp;
                   1059:   int flag;
                   1060: 
                   1061: 
                   1062:   // get users request pkt
                   1063:   if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
                   1064:                     sizeof(struct eventreq))) return(error);
                   1065: 
                   1066:   if (erp->er_type != EV_FD) return(EINVAL);
                   1067:   if (erp->er_handle < 0) return(EBADF);
                   1068:   if (erp->er_handle > p->p_fd->fd_nfiles) return(EBADF);
                   1069:   if ((fp = *fdfile(p, erp->er_handle)) == NULL)
                   1070:     return(EBADF);
                   1071:   if (fp->f_type != DTYPE_SOCKET) return(EINVAL); // for now must be sock
                   1072:   sp = (struct socket *)fp->f_data;
                   1073:   assert(sp != NULL);
                   1074: 
                   1075:   // locate event if possible
                   1076:   for (evq = sp->so_evlist.tqh_first;
                   1077:        evq != NULL; evq = evq->ee_slist.tqe_next) {
                   1078:     if (evq->ee_proc == p) break;
                   1079:   }
                   1080:   if (evq == NULL) {
                   1081:     return(EINVAL);
                   1082:   }
                   1083: 
                   1084: 
                   1085:     if (uap->u_eventmask == EV_RM) {
                   1086:     evprocdeque(p, evq);
                   1087:     TAILQ_REMOVE(&sp->so_evlist, evq, ee_slist);
                   1088:     FREE(evq, M_TEMP);
                   1089:     return(0);
                   1090:     }
                   1091: 
                   1092:   switch (uap->u_eventmask & EV_MASK) {
                   1093:  
                   1094:   case 0:
                   1095:     flag = 0;
                   1096:     break;
                   1097: 
                   1098:   case EV_RE:
                   1099:   case EV_WR:
                   1100:   case EV_RE|EV_WR:
                   1101:     flag = EV_RWBYTES;
                   1102:     break;
                   1103: 
                   1104:   case EV_EX:
                   1105:     flag = EV_OOB;
                   1106:     break;
                   1107: 
                   1108:   case EV_EX|EV_RE:
                   1109:   case EV_EX|EV_WR:
                   1110:   case EV_EX|EV_RE|EV_WR:
                   1111:     flag = EV_OOB|EV_RWBYTES;
                   1112:     break;
                   1113: 
                   1114:   default:
                   1115:     return(EINVAL);
                   1116:   }
                   1117: 
                   1118:    evq->ee_eventmask = uap->u_eventmask & EV_MASK;
                   1119:    evprocdeque(p, evq);
                   1120:    evq->ee_req.er_eventbits = 0;
                   1121:    postevent(sp, 0, flag);
                   1122:    return(0);
                   1123: }
                   1124: 
                   1125: 
                   1126: 

unix.superglobalmegacorp.com

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