Annotation of XNU/bsd/netat/sys_glue.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  *     Copyright (c) 1995 Apple Computer, Inc. 
                     24:  *
                     25:  *  Change Log:
                     26:  *    Created, March 17, 1997 by Tuyen Nguyen for MacOSX.
                     27:  */
                     28: 
                     29: #include <sys/errno.h>
                     30: #include <sys/types.h>
                     31: #include <sys/param.h>
                     32: #include <machine/spl.h>
                     33: #include <sys/systm.h>
                     34: #include <sys/kernel.h>
                     35: #include <sys/proc.h>
                     36: #include <sys/filedesc.h>
                     37: #include <sys/fcntl.h>
                     38: #include <sys/mbuf.h>
                     39: #include <sys/ioctl.h>
                     40: #include <sys/malloc.h>
                     41: #include <sys/socket.h>
                     42: #include <sys/socketvar.h>
                     43: #include <sys/ioccom.h>
                     44: 
                     45: #include <sys/sysctl.h>
                     46: 
                     47: #include <net/if.h>
                     48: 
                     49: #include <netat/sysglue.h>
                     50: #include <netat/appletalk.h>
                     51: #include <netat/ddp.h>
                     52: #include <netat/at_pcb.h>
                     53: #include <netat/at_var.h>
                     54: #include <netat/routing_tables.h>
                     55: #include <netat/debug.h>
                     56: 
                     57: extern struct atpcb ddp_head;
                     58: 
                     59: extern void 
                     60:   ddp_putmsg(gref_t *gref, gbuf_t *m),
                     61:   elap_wput(gref_t *gref, gbuf_t *m),
                     62:   atp_wput(gref_t *gref, gbuf_t *m),
                     63:   asp_wput(gref_t *gref, gbuf_t *m),
                     64: #ifdef AURP_SUPPORT
                     65:   aurp_wput(gref_t *gref, gbuf_t *m),
                     66: #endif
                     67:   adsp_wput(gref_t *gref, gbuf_t *m);
                     68: 
                     69: void atalk_putnext(gref_t *gref, gbuf_t *m);
                     70: static int gref_close(gref_t *gref);
                     71: 
                     72: SYSCTL_DECL(_net_appletalk);
                     73: dbgBits_t dbgBits;
                     74: SYSCTL_STRUCT(_net_appletalk, OID_AUTO, debug, CTLFLAG_WR, 
                     75:              &dbgBits, dbgBits, "Appletalk Debug Flags");
                     76: volatile int RouterMix = RT_MIX_DEFAULT; /* default for nbr of ppsec */
                     77: SYSCTL_INT(_net_appletalk, OID_AUTO, routermix, CTLFLAG_WR, 
                     78:           &RouterMix, 0, "Appletalk RouterMix");
                     79: 
                     80: atlock_t refall_lock;
                     81: 
                     82: static void gref_wput(gref, m)
                     83:        gref_t *gref;
                     84:        gbuf_t *m;
                     85: {
                     86:        switch (gref->proto) {
                     87:        case ATPROTO_DDP:
                     88:                ddp_putmsg(gref, m); break;
                     89:        case ATPROTO_LAP:
                     90:                elap_wput(gref, m); break;
                     91:        case ATPROTO_ATP:
                     92:                atp_wput(gref, m); break;
                     93:        case ATPROTO_ASP:
                     94:                asp_wput(gref, m); break;
                     95: #ifdef AURP_SUPPORT
                     96:        case ATPROTO_AURP:
                     97:                aurp_wput(gref, m); break;
                     98: #endif
                     99:        case ATPROTO_ADSP:
                    100:                adsp_wput(gref, m); break;
                    101:        case ATPROTO_NONE:
                    102:                if (gbuf_type(m) == MSG_IOCTL) {
                    103:                        gbuf_freem(gbuf_cont(m));
                    104:                        gbuf_cont(m) = 0;
                    105:                        ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
                    106:                        ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO;
                    107:                        gbuf_set_type(m, MSG_IOCNAK);
                    108:                        atalk_putnext(gref, m);
                    109:                } else
                    110:                        gbuf_freem(m);
                    111:                break;
                    112:        default:
                    113:                gbuf_freem(m);
                    114:                break;
                    115:        }
                    116: }
                    117: 
                    118: int _ATsocket(proto, err, proc)
                    119:        int proto;
                    120:        int *err;
                    121:        void *proc;
                    122: {
                    123:        int fd;
                    124:        gref_t *gref;
                    125: 
                    126:        /* make sure the specified protocol id is valid */
                    127:        switch (proto) {
                    128: 
                    129:        /* ATPROTO_DDP and ATPROTO_LAP have been replaced with 
                    130:           BSD-style socket interface. */
                    131: 
                    132:        case ATPROTO_ATP:
                    133:        case ATPROTO_ASP:
                    134:        case ATPROTO_AURP:
                    135:        case ATPROTO_ADSP:
                    136:                break;
                    137:        default:
                    138:                *err = EPROTOTYPE;
                    139: #ifdef APPLETALK_DEBUG
                    140:                kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err);
                    141: #endif
                    142:                return -1;
                    143:        }
                    144: 
                    145:        /* allocate a protocol channel */
                    146:        if ((*err = gref_alloc(&gref)) != 0) {
                    147: #ifdef APPLETALK_DEBUG
                    148:                kprintf("_ATsocket: error gref_open =%d\n", *err);
                    149: #endif
                    150:                return -1;
                    151:        }
                    152:        gref->proto = proto;
                    153:        gref->pid = ((struct proc *)proc)->p_pid;
                    154: 
                    155:        /* open the specified protocol */
                    156:        switch (gref->proto) {
                    157: 
                    158:        /* ATPROTO_DDP and ATPROTO_LAP have been replaced with 
                    159:           BSD-style socket interface. */
                    160: 
                    161:        case ATPROTO_ATP:
                    162:                *err = atp_open(gref, 1); break;
                    163:        case ATPROTO_ASP:
                    164:                *err = asp_open(gref); break;
                    165: #ifdef AURP_SUPPORT
                    166:        case ATPROTO_AURP:
                    167:                *err = aurp_open(gref); break;
                    168: #endif
                    169:        case ATPROTO_ADSP:
                    170:                *err = adsp_open(gref); break;
                    171:        }
                    172: 
                    173:        /* create the descriptor for the channel */
                    174:        if (*err) {
                    175: #ifdef APPLETALK_DEBUG
                    176:                kprintf("_ATsocket: open failed for %d proto; err = %d\n", 
                    177:                        gref->proto, *err);
                    178: #endif
                    179:                gref->proto = ATPROTO_NONE;
                    180:        }
                    181:        if (*err || (*err = atalk_openref(gref, &fd, proc))) {
                    182: #ifdef APPLETALK_DEBUG
                    183:                kprintf("_ATsocket: error atalk_openref =%d\n", *err);
                    184: #endif
                    185:                (void)gref_close(gref);
                    186:                return -1;
                    187:        }
                    188: /*
                    189:        kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd);
                    190: */
                    191:        return fd;
                    192: } /* _ATsocket */
                    193: 
                    194: int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc)
                    195:        int fd;
                    196:        strbuf_t *ctlptr;
                    197:        strbuf_t *datptr;
                    198:        int *flags;
                    199:        int *err;
                    200:        void *proc;
                    201: {
                    202:        int rc = -1;
                    203:        gref_t *gref;
                    204: 
                    205:        if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
                    206:                switch (gref->proto) {
                    207:                case ATPROTO_ASP:
                    208:                        rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); break;
                    209:                case ATPROTO_AURP:
                    210: #ifdef AURP_SUPPORT
                    211:                        rc = AURPgetmsg(err); break;
                    212: #endif
                    213:                default:
                    214:                        *err = EPROTONOSUPPORT; break;
                    215:                }
                    216:        }
                    217: 
                    218: 
                    219: /*     kprintf("_ATgetmsg: return=%d\n", *err);*/
                    220:        return rc;
                    221: }
                    222: 
                    223: int _ATputmsg(fd, ctlptr, datptr, flags, err, proc)
                    224:        int fd;
                    225:        strbuf_t *ctlptr;
                    226:        strbuf_t *datptr;
                    227:        int flags;
                    228:        int *err;
                    229:        void *proc;
                    230: {
                    231:        int rc = -1;
                    232:        gref_t *gref;
                    233: 
                    234:        if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
                    235:                switch (gref->proto) {
                    236:                case ATPROTO_ASP:
                    237:                        rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break;
                    238:                default:
                    239:                        *err = EPROTONOSUPPORT; break;
                    240:                }
                    241:        }
                    242: 
                    243: /*     kprintf("_ATputmsg: return=%d\n", *err); */
                    244:        return rc;
                    245: }
                    246: 
                    247: int _ATclose(fp, proc)
                    248:        void *fp;
                    249:        void *proc;
                    250: {
                    251:        int err;
                    252:        gref_t *gref;
                    253: 
                    254:        if ((err = atalk_closeref(fp, &gref)) != 0)
                    255:                return err;
                    256: 
                    257:        (void)gref_close(gref);
                    258:        return 0;
                    259: }
                    260: 
                    261: int _ATrw(fp, rw, uio, ext)
                    262:      void *fp;
                    263:      enum uio_rw rw;
                    264:      struct uio *uio;
                    265:      int ext;
                    266: {
                    267:     int s, err, len, clen = 0, res;
                    268:     gref_t *gref;
                    269:     gbuf_t *m, *mhead, *mprev;
                    270: 
                    271:     if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
                    272:        return err;
                    273: 
                    274:     if ((len = uio->uio_resid) == 0)
                    275:        return 0;
                    276: 
                    277:     ATDISABLE(s, gref->lock);
                    278:     if (gref->errno) {
                    279:        ATENABLE(s, gref->lock);
                    280:        return (int)gref->errno;
                    281:     }
                    282: 
                    283:     if (rw == UIO_READ) {
                    284:        KERNEL_DEBUG(DBG_ADSP_ATRW, 0, gref, len, gref->rdhead, 0);
                    285:        while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) {
                    286:                gref->sevents |= POLLMSG;
                    287:                err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0);
                    288:                gref->sevents &= ~POLLMSG;
                    289:                if (err != 0) {
                    290:                        ATENABLE(s, gref->lock);
                    291:                        return err;
                    292:                }
                    293:                KERNEL_DEBUG(DBG_ADSP_ATRW, 1, gref, gref->rdhead, mhead, gbuf_next(mhead));
                    294:        }
                    295: 
                    296:        if (gref->errno) {
                    297:                ATENABLE(s, gref->lock);
                    298:                return EPIPE;
                    299:        }
                    300:        if ((gref->rdhead = gbuf_next(mhead)) == 0)
                    301:                gref->rdtail = 0;
                    302: 
                    303:        KERNEL_DEBUG(DBG_ADSP_ATRW, 2, gref, gref->rdhead, mhead, gbuf_next(mhead));
                    304: 
                    305:        ATENABLE(s, gref->lock);
                    306: 
                    307: //##### LD TEST 08/05
                    308: //     simple_lock(&gref->lock);
                    309: 
                    310:        gbuf_next(mhead) = 0;
                    311: 
                    312:        for (mprev=0, m=mhead; m && len; len-=clen) {
                    313:                if ((clen = gbuf_len(m)) > 0) {
                    314:                        if (clen > len)
                    315:                                clen = len;
                    316:                        uio->uio_rw = UIO_READ;
                    317:                        if ((res = uiomove((caddr_t)gbuf_rptr(m), 
                    318:                                           clen, uio))) {
                    319:                                KERNEL_DEBUG(DBG_ADSP_ATRW, 3, m, clen, 
                    320:                                             len, gbuf_cont(m));
                    321:                                break;
                    322:                        }
                    323:                        if (gbuf_len(m) > len) {
                    324:                                gbuf_rinc(m,clen);
                    325:                                break;
                    326:                        }
                    327:                }
                    328:                mprev = m;
                    329:                m = gbuf_cont(m);
                    330:        }
                    331:        if (m) {
                    332:                KERNEL_DEBUG(DBG_ADSP_ATRW, 4, m, gbuf_len(m), mprev, gref->rdhead);
                    333:                if (mprev)
                    334:                        gbuf_cont(mprev) = 0;
                    335:                else
                    336:                        mhead = 0;
                    337:                ATDISABLE(s, gref->lock);
                    338:                if (gref->rdhead == 0)
                    339:                        gref->rdtail = m;
                    340:                gbuf_next(m) = gref->rdhead;
                    341:                gref->rdhead = m;
                    342:                ATENABLE(s, gref->lock);
                    343:        }
                    344:        if (mhead)
                    345:                gbuf_freem(mhead);
                    346: //### LD TEST
                    347: //     simple_unlock(&gref->lock);
                    348:     } else {
                    349:        if (gref->writeable) {
                    350:                while (!(*gref->writeable)(gref)) {
                    351:                        /* flow control on, wait to be enabled to write */ 
                    352:                        gref->sevents |= POLLSYNC;
                    353:                        err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0);
                    354:                        gref->sevents &= ~POLLSYNC;
                    355:                        if (err != 0) {
                    356:                                ATENABLE(s, gref->lock);
                    357:                                return err;
                    358:                        }
                    359:                }
                    360:        }
                    361: 
                    362:        ATENABLE(s, gref->lock);
                    363: 
                    364:        /* allocate a buffer to copy in the write data */
                    365:        if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0)
                    366:                return ENOBUFS;
                    367:        gbuf_rinc(m,AT_WR_OFFSET);
                    368:        gbuf_wset(m,len);
                    369: 
                    370:        /* copy in the write data */
                    371:        uio->uio_rw = UIO_WRITE;
                    372:        if ((res = uiomove((caddr_t)gbuf_rptr(m), len, uio))) {
                    373: #ifdef APPLETALK_DEBUG
                    374:                kprintf("_ATrw: UIO_WRITE: res=%d\n", res);
                    375: #endif
                    376:                gbuf_freeb(m);
                    377:                return EIO;
                    378:        }
                    379: 
                    380:        /* forward the write data to the appropriate protocol module */
                    381:        gref_wput(gref, m);
                    382:   }
                    383: 
                    384:   return 0;
                    385: } /* _ATrw */
                    386: 
                    387: int _ATread(fp, uio, cred)
                    388:        void *fp;
                    389:        struct uio *uio;
                    390:        void *cred;
                    391: {
                    392:        return _ATrw(fp, UIO_READ, uio, 0);
                    393: }
                    394: 
                    395: int _ATwrite(fp, uio, cred)
                    396:        void *fp;
                    397:        struct uio *uio;
                    398:        void *cred;
                    399: {
                    400:        return _ATrw(fp, UIO_WRITE, uio, 0);
                    401: }
                    402: 
                    403: /* Most of the processing from _ATioctl, so that it can be called
                    404:    from the new select code */
                    405: int at_ioctl(gref, cmd, arg)
                    406:      gref_t *gref;
                    407:      register caddr_t arg;
                    408: {
                    409:        int s, err = 0, len;
                    410:        gbuf_t *m, *mdata;
                    411:        ioc_t *ioc;
                    412:        ioccmd_t ioccmd;
                    413: 
                    414:        /* error if not for us */
                    415:        if ((cmd  & 0xffff) != 0xff99)
                    416:                return EOPNOTSUPP;
                    417: 
                    418:        /* copy in ioc command info */
                    419: /*
                    420:        kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n",
                    421:                ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, 
                    422:                gref->lock, gref->event);
                    423: */
                    424:        if ((err = copyin((caddr_t)arg,
                    425:                        (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) { 
                    426: #ifdef APPLETALK_DEBUG
                    427:          kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err, 
                    428:                  (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t));
                    429: #endif
                    430:                return err;
                    431:        } 
                    432: 
                    433:        /* allocate a buffer to create an ioc command */
                    434:        if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
                    435:                return ENOBUFS;
                    436:        gbuf_wset(m,sizeof(ioc_t));
                    437:        gbuf_set_type(m, MSG_IOCTL);
                    438: 
                    439:        /* create the ioc command */
                    440:        if (ioccmd.ic_len) {
                    441:                if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) {
                    442:                        gbuf_freem(m);
                    443: #ifdef APPLETALK_DEBUG
                    444:                        kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS);
                    445: #endif
                    446:                        return ENOBUFS;
                    447:                }
                    448:                gbuf_wset(gbuf_cont(m),ioccmd.ic_len);
                    449:                if ((err = copyin((caddr_t)ioccmd.ic_dp,
                    450:                                (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) { 
                    451:                        gbuf_freem(m);
                    452:                        return err;
                    453:                }
                    454:        }
                    455:        ioc = (ioc_t *)gbuf_rptr(m);
                    456:        ioc->ioc_cmd = ioccmd.ic_cmd;
                    457:        ioc->ioc_count = ioccmd.ic_len;
                    458:        ioc->ioc_error = 0;
                    459:        ioc->ioc_rval = 0;
                    460: 
                    461:        /* send the ioc command to the appropriate recipient */
                    462:        gref_wput(gref, m);
                    463: 
                    464:        /* wait for the ioc ack */
                    465:        ATDISABLE(s, gref->lock);
                    466:        while ((m = gref->ichead) == 0) {
                    467:                gref->sevents |= POLLPRI;
                    468: #ifdef APPLETALK_DEBUG
                    469:                kprintf("sleep gref = 0x%x\n", (unsigned)gref);
                    470: #endif
                    471:                err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0);
                    472:                gref->sevents &= ~POLLPRI;
                    473:                if (err != 0) {
                    474:                        ATENABLE(s, gref->lock);
                    475: #ifdef APPLETALK_DEBUG
                    476:                        kprintf("at_ioctl: EINTR\n");
                    477: #endif
                    478:                        return err;
                    479:                }
                    480:        }
                    481: 
                    482:        /* PR-2224797 */
                    483:        if (gbuf_next(m) == m)          /* error case */
                    484:                gbuf_next(m) = 0; 
                    485: 
                    486:        gref->ichead = gbuf_next(m);
                    487: 
                    488:        ATENABLE(s, gref->lock);
                    489: 
                    490: #ifdef APPLETALK_DEBUG
                    491:        kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n", 
                    492:                (unsigned)gref);
                    493: #endif
                    494:        /* process the ioc response */
                    495:        ioc = (ioc_t *)gbuf_rptr(m);
                    496:        if ((err = ioc->ioc_error) == 0) {
                    497:                ioccmd.ic_timout = ioc->ioc_rval;
                    498:                ioccmd.ic_len = 0;
                    499:                mdata = gbuf_cont(m);
                    500:                if (mdata && ioccmd.ic_dp) {
                    501:                        ioccmd.ic_len = gbuf_msgsize(mdata);
                    502:                  for (len=0; mdata; mdata=gbuf_cont(mdata)) {
                    503:                        if ((err = copyout((caddr_t)gbuf_rptr(mdata),
                    504:                                        (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) {
                    505: #ifdef APPLETALK_DEBUG
                    506:                                kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
                    507:                                         len, err, (caddr_t)gbuf_rptr(mdata), 
                    508:                                         (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata));
                    509: #endif
                    510:                                goto l_done;
                    511:                        }
                    512:                        len += gbuf_len(mdata);
                    513:                  }
                    514:                }
                    515:                if ((err = copyout((caddr_t)&ioccmd,
                    516:                                (caddr_t)arg, sizeof(ioccmd_t))) != 0) {
                    517: #ifdef APPLETALK_DEBUG
                    518:                                kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n",
                    519:                                         err, &ioccmd, arg, sizeof(ioccmd_t));
                    520: #endif
                    521:                        goto l_done;
                    522:                }
                    523:        }
                    524: 
                    525: l_done:
                    526:        gbuf_freem(m);
                    527:        /*kprintf("at_ioctl: I_done=%d\n", err);*/
                    528:        return err;
                    529: } /* at_ioctl */
                    530: 
                    531: int _ATioctl(fp, cmd, arg, proc)
                    532:        void *fp;
                    533:        u_long cmd;
                    534:        register caddr_t arg;
                    535:        void *proc;
                    536: {
                    537:        int err;
                    538:        gref_t *gref;
                    539: 
                    540:        if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) {
                    541: #ifdef APPLETALK_DEBUG
                    542:                kprintf("_ATioctl: atalk_getref err = %d\n", err);
                    543: #endif
                    544:                return err;
                    545:        }
                    546: 
                    547:        return((err = at_ioctl(gref, cmd, arg)));
                    548: }
                    549: 
                    550: int _ATselect(fp, which, proc)
                    551:        void *fp;
                    552:        int which;
                    553:        void *proc;
                    554: {
                    555:        int s, err, rc = 0;
                    556:        gref_t *gref;
                    557: 
                    558:        if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
                    559:                return err;
                    560: 
                    561:        ATDISABLE(s, gref->lock);
                    562:        if (which == FREAD) {
                    563:                if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
                    564:                        rc = 1;
                    565:                else {
                    566:                        gref->sevents |= POLLIN;
                    567:                        selrecord(proc, &gref->si);
                    568:                }
                    569:        }
                    570: 
                    571:        else if (which == POLLOUT) {
                    572:                if (gref->writeable) {
                    573:                        if ((*gref->writeable)(gref))
                    574:                                rc = 1;
                    575:                        else {
                    576:                                gref->sevents |= POLLOUT;
                    577:                                selrecord(proc, &gref->si);
                    578:                        }
                    579:                } else
                    580:                        rc = 1;
                    581:        }
                    582:        ATENABLE(s, gref->lock);
                    583: 
                    584:        return rc;
                    585: }
                    586: 
                    587: void atalk_putnext(gref, m)
                    588:        gref_t *gref;
                    589:        gbuf_t *m;
                    590: {
                    591:        int s;
                    592: 
                    593:        ATDISABLE(s, gref->lock);
                    594: 
                    595:        /* *** potential leak? *** */
                    596:        gbuf_next(m) = 0;
                    597: 
                    598:        switch (gbuf_type(m)) {
                    599:        case MSG_IOCACK:
                    600:        case MSG_IOCNAK:
                    601:                if (gref->ichead)
                    602:                        gbuf_next(gref->ichead) = m;
                    603:                else {
                    604:                        gref->ichead = m;
                    605:                        if (gref->sevents & POLLPRI) {
                    606: #ifdef APPLETALK_DEBUG
                    607:                                kprintf("wakeup gref = 0x%x\n", (unsigned)gref);
                    608: #endif
                    609:                                thread_wakeup(&gref->iocevent);
                    610:                        }
                    611:                }
                    612:                break;
                    613:        case MSG_ERROR:
                    614:                /* *** this processing was moved to atalk_notify *** */
                    615:                panic("atalk_putnext receved MSG_ERROR");
                    616:                break;
                    617:        default:
                    618:                if (gref->errno)
                    619:                   gbuf_freem(m);
                    620:                else 
                    621:                   if (gref->rdhead) {
                    622:                        gbuf_next(gref->rdtail) = m;
                    623:                        gref->rdtail = m;
                    624:                    } else {
                    625:                        gref->rdhead = m;
                    626:                        if (gref->sevents & POLLMSG) {
                    627:                                gref->sevents &= ~POLLMSG;
                    628:                                thread_wakeup(&gref->event);
                    629:                        }
                    630:                        if (gref->sevents & POLLIN) {
                    631:                                gref->sevents &= ~POLLIN;
                    632:                                selwakeup(&gref->si);
                    633:                        }
                    634:                        gref->rdtail = m;
                    635:                    }
                    636:        } /* switch gbuf_type(m) */
                    637: 
                    638:        ATENABLE(s, gref->lock);
                    639: } /* atalk_putnext */
                    640: 
                    641: void atalk_enablew(gref)
                    642:        gref_t *gref;
                    643: {
                    644:        if (gref->sevents & POLLSYNC)
                    645:                thread_wakeup(&gref->event);
                    646: }
                    647: 
                    648: void atalk_flush(gref)
                    649:        gref_t *gref;
                    650: {
                    651:        int s;
                    652: 
                    653:        ATDISABLE(s, gref->lock);
                    654:        if (gref->rdhead) {
                    655:                gbuf_freel(gref->rdhead);
                    656:                gref->rdhead = 0;
                    657:        }
                    658:        if (gref->ichead) {
                    659:                gbuf_freel(gref->ichead);
                    660:                gref->ichead = 0;
                    661:        }
                    662:        ATENABLE(s, gref->lock);
                    663: }
                    664: 
                    665: /*
                    666:  * Notify an appletalk user of an asynchronous error;
                    667:  * just wake up so that he can collect error status.
                    668:  */
                    669: /* *** separate out the error wakeup stuff to eliminate use
                    670:        of MSG_ERROR and atalk_putnext(), moving towards 
                    671:        standard socket code
                    672:    *** */
                    673: void atalk_notify(gref, errno)
                    674:        register gref_t *gref;
                    675:        int errno;
                    676: {
                    677:   /* *** code from udp_notify() in netinet/udp_usrreq.c 
                    678:        inp->inp_socket->so_error = errno;
                    679:        sorwakeup(inp->inp_socket);
                    680:        sowwakeup(inp->inp_socket);
                    681:      *** */
                    682: 
                    683:        int s;
                    684:        ATDISABLE(s, gref->lock);
                    685: 
                    686:        if (gref->errno == 0) {
                    687:                gref->errno = errno;
                    688:                if (gref->rdhead) {
                    689:                        gbuf_freel(gref->rdhead);
                    690:                        gref->rdhead = 0;
                    691:                }
                    692:                if (gref->sevents & POLLMSG) {
                    693:                        gref->sevents &= ~POLLMSG;
                    694:                        thread_wakeup(&gref->event);
                    695:                }
                    696:                if (gref->sevents & POLLIN) {
                    697:                        gref->sevents &= ~POLLIN;
                    698:                        selwakeup(&gref->si);
                    699:                }
                    700:        }
                    701:        ATENABLE(s, gref->lock);
                    702: } /* atalk_notify */
                    703: 
                    704: void atalk_notify_sel(gref)
                    705:        gref_t *gref;
                    706: {
                    707:        int s;
                    708: 
                    709:        ATDISABLE(s, gref->lock);
                    710:        if (gref->sevents & POLLIN) {
                    711:                gref->sevents &= ~POLLIN;
                    712:                selwakeup(&gref->si);
                    713:        }
                    714:        ATENABLE(s, gref->lock);
                    715: }
                    716: 
                    717: int atalk_peek(gref, event)
                    718:        gref_t *gref;
                    719:        unsigned char *event;
                    720: {
                    721:        int s, rc;
                    722: 
                    723:        ATDISABLE(s, gref->lock);
                    724:        if (gref->rdhead) {
                    725:                *event = *gbuf_rptr(gref->rdhead);
                    726:                rc = 0;
                    727:        } else
                    728:                rc = -1;
                    729:        ATENABLE(s, gref->lock);
                    730: 
                    731:        return rc;
                    732: }
                    733: 
                    734: static gbuf_t *trace_msg;
                    735: 
                    736: void atalk_settrace(str, p1, p2, p3, p4, p5)
                    737:        char *str;
                    738: {
                    739:        int len;
                    740:        gbuf_t *m, *nextm;
                    741:        char trace_buf[256];
                    742: 
                    743:        sprintf(trace_buf, str, p1, p2, p3, p4, p5);
                    744:        len = strlen(trace_buf);
                    745: #ifdef APPLETALK_DEBUG
                    746:        kprintf("atalk_settrace: gbufalloc size=%d\n", len+1);
                    747: #endif
                    748:        if ((m = gbuf_alloc(len+1, PRI_MED)) == 0)
                    749:                return;
                    750:        gbuf_wset(m,len);
                    751:        strcpy(gbuf_rptr(m), trace_buf);
                    752:        if (trace_msg) {
                    753:                for (nextm=trace_msg; gbuf_cont(nextm); nextm=gbuf_cont(nextm)) ;
                    754:                gbuf_cont(nextm) = m;
                    755:        } else
                    756:                trace_msg = m;
                    757: }
                    758: 
                    759: void atalk_gettrace(m)
                    760:        gbuf_t *m;
                    761: {
                    762:        if (trace_msg) {
                    763:                gbuf_cont(m) = trace_msg;
                    764:                trace_msg = 0;
                    765:        }
                    766: }
                    767: 
                    768: #define GREF_PER_BLK 32
                    769: static gref_t *gref_free_list = 0;
                    770: 
                    771: int gref_alloc(grefp)
                    772:        gref_t **grefp;
                    773: {
                    774:        extern gbuf_t *atp_resource_m;
                    775:        int i, s;
                    776:        gbuf_t *m;
                    777:        gref_t *gref, *gref_array;
                    778: 
                    779:        *grefp = (gref_t *)NULL;
                    780: 
                    781:        ATDISABLE(s, refall_lock);
                    782:        if (gref_free_list == 0) {
                    783:                ATENABLE(s, refall_lock);
                    784: #ifdef APPLETALK_DEBUG
                    785:                kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t));
                    786: #endif
                    787:                if ((m = gbuf_alloc(GREF_PER_BLK*sizeof(gref_t),PRI_HI)) == 0)
                    788:                        return ENOBUFS;
                    789:                bzero(gbuf_rptr(m), GREF_PER_BLK*sizeof(gref_t));
                    790:                gref_array = (gref_t *)gbuf_rptr(m);
                    791:                for (i=0; i < GREF_PER_BLK-1; i++)
                    792:                        gref_array[i].atpcb_next = (gref_t *)&gref_array[i+1];
                    793:                ATDISABLE(s, refall_lock);
                    794:                gbuf_cont(m) = atp_resource_m;
                    795:                atp_resource_m = m;
                    796:                gref_array[i].atpcb_next = gref_free_list;
                    797:                gref_free_list = (gref_t *)&gref_array[0];
                    798:        }
                    799: 
                    800:        gref = gref_free_list;
                    801:        gref_free_list = gref->atpcb_next;
                    802:        ATENABLE(s, refall_lock);
                    803:        ATLOCKINIT(gref->lock);
                    804: //### LD Test 08/05/98
                    805: //     simple_lock_init(&gref->lock);
                    806:        ATEVENTINIT(gref->event);
                    807:        ATEVENTINIT(gref->iocevent);
                    808: 
                    809:        /* *** just for now *** */
                    810:        gref->atpcb_socket = (struct socket *)NULL;
                    811: 
                    812:        *grefp = gref;
                    813:        return 0;
                    814: } /* gref_alloc */
                    815: 
                    816: static int gref_close(gref)
                    817:        gref_t *gref;
                    818: {
                    819:        int s, rc;
                    820: 
                    821:        switch (gref->proto) {
                    822: 
                    823:        /* ATPROTO_DDP and ATPROTO_LAP have been replaced with 
                    824:           BSD-style socket interface. */
                    825: 
                    826:        case ATPROTO_ATP:
                    827:                rc = atp_close(gref, 1); break;
                    828:        case ATPROTO_ASP:
                    829:                rc = asp_close(gref); break;
                    830: #ifdef AURP_SUPPORT
                    831:        case ATPROTO_AURP:
                    832:                rc = aurp_close(gref); break;
                    833:                break;
                    834: #endif
                    835:        case ATPROTO_ADSP:
                    836:                rc = adsp_close(gref); break;
                    837:        default:
                    838:                rc = 0;
                    839:                break;
                    840:        }
                    841: 
                    842:        if (rc == 0) {
                    843:                atalk_flush(gref);
                    844:                selthreadclear(&gref->si);
                    845: 
                    846:                /* from original gref_free() */
                    847:                ATDISABLE(s, refall_lock);
                    848:                bzero((char *)gref, sizeof(gref_t));
                    849:                gref->atpcb_next = gref_free_list;
                    850:                gref_free_list = gref;
                    851:                ATENABLE(s, refall_lock);
                    852:        }
                    853: 
                    854:        return rc;
                    855: }
                    856: 
                    857: /* 
                    858:    Buffer Routines
                    859: 
                    860:    *** Some to be replaced with mbuf routines, some to be re-written
                    861:        as mbuf routines (and moved to kern/uicp_mbuf.c or sys/mbuf.h?).
                    862:    ***
                    863: 
                    864: */
                    865: 
                    866: /*
                    867:  * LD 5/12/97 Added for MacOSX, defines a m_clattach function that:
                    868:  * "Allocates an mbuf structure and attaches an external cluster."
                    869:  */
                    870: 
                    871: struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
                    872:        caddr_t extbuf; 
                    873:        int (*extfree)();
                    874:        int extsize;
                    875:        int extarg;
                    876:        int wait;
                    877: {
                    878:         struct mbuf *m;
                    879: 
                    880:         if ((m = m_gethdr(wait, MSG_DATA)) == NULL)
                    881:                 return (NULL);
                    882: 
                    883:         m->m_ext.ext_buf = extbuf;
                    884:         m->m_ext.ext_free = extfree;
                    885:         m->m_ext.ext_size = extsize;
                    886:         m->m_ext.ext_arg = extarg;
                    887:         m->m_ext.ext_refs.forward = 
                    888:          m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
                    889:         m->m_data = extbuf;
                    890:         m->m_flags |= M_EXT;
                    891: 
                    892:         return (m);
                    893: }
                    894: 
                    895: /* 
                    896:    Used as the "free" routine for over-size clusters allocated using
                    897:    m_lgbuf_alloc(). 
                    898: */
                    899: 
                    900: void m_lgbuf_free(buf, size, arg)
                    901:      void *buf;
                    902:      int size, arg; /* not needed, but they're in m_free() */
                    903: {
                    904:        FREE(buf, M_MCLUST);
                    905: }
                    906: 
                    907: /*
                    908:   Used to allocate an mbuf when there is the possibility that it may
                    909:   need to be larger than the size of a standard cluster.
                    910: */
                    911: 
                    912: struct mbuf *m_lgbuf_alloc(size, wait)
                    913:        int size, wait;
                    914: {
                    915:        struct mbuf *m;
                    916: 
                    917:        /* If size is too large, allocate a cluster, otherwise, use the
                    918:           standard mbuf allocation routines.*/
                    919:        if (size > MCLBYTES) {
                    920:                void *buf;
                    921:                if (NULL == 
                    922:                    (buf = (void *)_MALLOC(size, M_MCLUST, 
                    923:                                           (wait)? M_WAITOK: M_NOWAIT))) {
                    924:                        return(NULL);
                    925:                }
                    926:                if (NULL == 
                    927:                    (m = m_clattach(buf, m_lgbuf_free, size, 0, 
                    928:                                    (wait)? M_WAIT: M_DONTWAIT))) {
                    929:                        m_lgbuf_free(buf);
                    930:                        return(NULL);
                    931:                }
                    932:        } else {
                    933:                m = m_gethdr(((wait)? M_WAIT: M_DONTWAIT), MSG_DATA);
                    934:                if (m && (size > MHLEN)) {
                    935:                        MCLGET(m, ((wait)? M_WAIT: M_DONTWAIT));
                    936:                        if (!(m->m_flags & M_EXT)) {
                    937:                                (void)m_free(m);
                    938:                                return(NULL);
                    939:                        }
                    940:                }
                    941:        }
                    942: 
                    943:        return(m);
                    944: } /* m_lgbuf_alloc */
                    945: 
                    946: /*
                    947:    gbuf_alloc() is a wrapper for m_lgbuf_alloc(), which is used to 
                    948:    allocate an mbuf when there is the possibility that it may need 
                    949:    to be larger than the size of a standard cluster.
                    950: 
                    951:    gbuf_alloc() sets the mbuf lengths, unlike the standard mbuf routines.
                    952: */     
                    953: 
                    954: gbuf_t *gbuf_alloc_wait(size, wait)
                    955:      int size, wait;
                    956: {
                    957:        gbuf_t *m = (gbuf_t *)m_lgbuf_alloc(size, wait);
                    958: 
                    959:        /* Standard mbuf allocation routines assume that the caller
                    960:           will set the size. */
                    961:        if (m) {
                    962:                (struct mbuf *)m->m_pkthdr.len = size;
                    963:                (struct mbuf *)m->m_len = size;
                    964:        }
                    965: 
                    966:        return(m);
                    967: }
                    968: 
                    969: int gbuf_msgsize(m)
                    970:        gbuf_t *m;
                    971: {
                    972:        int size;
                    973: 
                    974:        for (size=0; m; m=gbuf_cont(m))
                    975:                size += gbuf_len(m);
                    976:        return size;
                    977: }
                    978: 
                    979: int append_copy(m1, m2, wait)
                    980:      struct mbuf *m1, *m2;
                    981:      int wait;
                    982: {
                    983:        if ((!(m1->m_flags & M_EXT)) && (!(m2->m_flags & M_EXT)) && 
                    984:            (m_trailingspace(m1) >= m2->m_len)) {
                    985:                /* splat the data from one into the other */
                    986:                bcopy(mtod(m2, caddr_t), mtod(m1, caddr_t) + m1->m_len,
                    987:                      (u_int)m2->m_len);
                    988:                m1->m_len += m2->m_len;
                    989:                if (m1->m_flags & M_PKTHDR)
                    990:                    m1->m_pkthdr.len += m2->m_len;
                    991:                return 1;
                    992:        }
                    993:        if ((m1->m_next = m_copym(m2, 0, m2->m_len, 
                    994:                                  (wait)? M_WAIT: M_DONTWAIT)) == NULL)
                    995:                return 0;
                    996:        return 1;
                    997: } /* append_copy */
                    998: 
                    999: /* 
                   1000:    Copy an mbuf chain, referencing existing external storage, if any.
                   1001:    Leave space for a header in the new chain, if the space has been 
                   1002:    left in the origin chain.
                   1003: */ 
                   1004: struct mbuf *copy_pkt(mlist, pad) 
                   1005:      struct mbuf *mlist; /* the mbuf chain to be copied */ 
                   1006:      int pad;           /* hint as to how long the header might be
                   1007:                            If pad is < 0, leave the same amount of space
                   1008:                            as there was in the original. */ 
                   1009: { 
                   1010:        struct mbuf *new_m; 
                   1011:        int len;
                   1012: 
                   1013:        if (pad < 0)
                   1014:                len = m_leadingspace(mlist);
                   1015:        else
                   1016:                len = min(pad, m_leadingspace(mlist));
                   1017: 
                   1018:        /* preserve space for the header at the beginning of the mbuf */
                   1019:        if (len) {
                   1020:                mlist->m_data -= (len);
                   1021:                mlist->m_len += (len);
                   1022:                if (mlist->m_flags & M_PKTHDR)
                   1023:                    mlist->m_pkthdr.len += (len);
                   1024:                new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT);
                   1025:                m_adj(mlist, len);
                   1026:                m_adj(new_m, len);
                   1027:        } else 
                   1028:                new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT);
                   1029: 
                   1030:        return(new_m);
                   1031: }
                   1032: 
                   1033: void gbuf_linkb(m1, m2)
                   1034:        gbuf_t *m1;
                   1035:        gbuf_t *m2;
                   1036: {
                   1037:        while (gbuf_cont(m1) != 0)
                   1038:                m1 = gbuf_cont(m1);
                   1039:        gbuf_cont(m1) = m2;
                   1040: }
                   1041: 
                   1042: void gbuf_linkpkt(m1, m2)
                   1043:        gbuf_t *m1;
                   1044:        gbuf_t *m2;
                   1045: {
                   1046:        while (gbuf_next(m1) != 0)
                   1047:                m1 = gbuf_next(m1);
                   1048:        gbuf_next(m1) = m2;
                   1049: }
                   1050: 
                   1051: int gbuf_freel(m)
                   1052:        gbuf_t *m;
                   1053: {
                   1054:        gbuf_t *tmp_m;
                   1055: 
                   1056:        while ((tmp_m = m) != 0) {
                   1057:                m = gbuf_next(m);
                   1058:                gbuf_next(tmp_m) = 0;
                   1059:                gbuf_freem(tmp_m);
                   1060:        }
                   1061:        return (0);
                   1062: }
                   1063: 
                   1064: /* free empty mbufs at the front of the chain */
                   1065: gbuf_t *gbuf_strip(m)
                   1066:      gbuf_t *m;
                   1067: {
                   1068:        gbuf_t *tmp_m;
                   1069: 
                   1070:        while (m && gbuf_len(m) == 0) {
                   1071:                tmp_m = m;
                   1072:                m = gbuf_cont(m);
                   1073:                gbuf_freeb(tmp_m);
                   1074:        }
                   1075:        return(m);
                   1076: }
                   1077: 
                   1078: /**************************************/
                   1079: 
                   1080: int ddp_adjmsg(m, len)
                   1081:        gbuf_t          *m;
                   1082:        int     len;
                   1083: {
                   1084:        int buf_len;
                   1085:        gbuf_t *curr_m, *prev_m;
                   1086: 
                   1087:        if (m == (gbuf_t *)0)
                   1088:                return 0;
                   1089: 
                   1090:        if (len > 0) {
                   1091:                for (curr_m=m; curr_m;) {
                   1092:                        buf_len = gbuf_len(curr_m);
                   1093:                        if (len < buf_len) {
                   1094:                                gbuf_rinc(curr_m,len);
                   1095:                                return 1;
                   1096:                        }
                   1097:                        len -= buf_len;
                   1098:                        gbuf_rinc(curr_m,buf_len);
                   1099:                        if ((curr_m = gbuf_cont(curr_m)) == 0) {
                   1100:                                gbuf_freem(m);
                   1101:                                return 0;
                   1102:                        }
                   1103:                }
                   1104: 
                   1105:        } else if (len < 0) {
                   1106:                len = -len;
                   1107: l_cont:        prev_m = 0;
                   1108:                for (curr_m=m; gbuf_cont(curr_m);
                   1109:                        prev_m=curr_m, curr_m=gbuf_cont(curr_m)) ;
                   1110:                buf_len = gbuf_len(curr_m);
                   1111:                if (len < buf_len) {
                   1112:                        gbuf_wdec(curr_m,len);
                   1113:                        return 1;
                   1114:                }
                   1115:                if (prev_m == 0)
                   1116:                        return 0;
                   1117:                gbuf_cont(prev_m) = 0;
                   1118:                gbuf_freeb(curr_m);
                   1119:                len -= buf_len;
                   1120:                goto l_cont;
                   1121: 
                   1122:        } else
                   1123:                return 1;
                   1124: }
                   1125: 
                   1126: /*
                   1127:  * The message chain, m is grown in size by len contiguous bytes.
                   1128:  * If len is non-negative, len bytes are added to the
                   1129:  * end of the gbuf_t chain.  If len is negative, the
                   1130:  * bytes are added to the front. ddp_growmsg only adds bytes to 
                   1131:  * message blocks of the same type.
                   1132:  * It returns a pointer to the new gbuf_t on sucess, 0 on failure.
                   1133:  */
                   1134: 
                   1135: gbuf_t *ddp_growmsg(mp, len)
                   1136:        gbuf_t  *mp;
                   1137:        int     len;
                   1138: {
                   1139:        gbuf_t  *m, *d;
                   1140: 
                   1141:        if ((m = mp) == (gbuf_t *) 0)
                   1142:                return ((gbuf_t *) 0);
                   1143: 
                   1144:        if (len <= 0) {
                   1145:                len = -len;
                   1146:                if ((d = gbuf_alloc(len, PRI_MED)) == 0)
                   1147:                        return ((gbuf_t *) 0);
                   1148:                gbuf_set_type(d, gbuf_type(m));
                   1149:                gbuf_wset(d,len);
                   1150:                /* link in new gbuf_t */
                   1151:                gbuf_cont(d) = m;
                   1152:                return (d);
                   1153: 
                   1154:        } else {
                   1155:                register int    count;
                   1156:                /*
                   1157:                 * Add to tail.
                   1158:                 */
                   1159:                if ((count = gbuf_msgsize(m)) < 0)
                   1160:                        return ((gbuf_t *) 0);
                   1161:                /* find end of chain */
                   1162:                for ( ; m; m = gbuf_cont(m)) {
                   1163:                        if (gbuf_len(m) >= count) 
                   1164:                                break;
                   1165:                        count -= gbuf_len(m);
                   1166:                }
                   1167:                /* m now points to gbuf_t to add to */
                   1168:                if ((d = gbuf_alloc(len, PRI_MED)) == 0)
                   1169:                        return ((gbuf_t *) 0);
                   1170:                gbuf_set_type(d, gbuf_type(m));
                   1171:                /* link in new gbuf_t */
                   1172:                gbuf_cont(d) = gbuf_cont(m);
                   1173:                gbuf_cont(m) = d;
                   1174:                gbuf_wset(d,len);
                   1175:                return (d);
                   1176:        }
                   1177: }
                   1178: 
                   1179: /*
                   1180:  *     return the MSG_IOCACK/MSG_IOCNAK. Note that the same message
                   1181:  *     block is used as the vehicle, and that if there is an error return,
                   1182:  *     then linked blocks are lopped off. BEWARE of multiple references.
                   1183:  *     Used by other appletalk modules, so it is not static!
                   1184:  */
                   1185: 
                   1186: void ioc_ack(errno, m, gref)
                   1187:      int               errno;
                   1188:      register gbuf_t   *m;
                   1189:      register gref_t   *gref;
                   1190: {
                   1191:        ioc_t *iocbp = (ioc_t *)gbuf_rptr(m);
                   1192:        
                   1193:        /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/
                   1194:        if ((iocbp->ioc_error = errno) != 0)
                   1195:        {       /* errno != 0, then there is an error, get rid of linked blocks! */
                   1196: 
                   1197:                if (gbuf_cont(m)) {
                   1198:                        gbuf_freem(gbuf_cont(m));
                   1199:                        gbuf_cont(m) = 0;
                   1200:                }
                   1201:                gbuf_set_type(m, MSG_IOCNAK);
                   1202:                iocbp->ioc_count = 0;   /* only make zero length if error */
                   1203:                iocbp->ioc_rval = -1;
                   1204:        } else
                   1205:                gbuf_set_type(m, MSG_IOCACK);
                   1206: 
                   1207:        atalk_putnext(gref, m);
                   1208: }
                   1209: 

unix.superglobalmegacorp.com

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