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

unix.superglobalmegacorp.com

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