Annotation of 43BSD/sys/netimp/if_imp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  *
        !             6:  *     @(#)if_imp.c    7.1 (Berkeley) 6/4/86
        !             7:  */
        !             8: 
        !             9: #include "imp.h"
        !            10: #if NIMP > 0
        !            11: /*
        !            12:  * ARPANET IMP interface driver.
        !            13:  *
        !            14:  * The IMP-host protocol is handled here, leaving
        !            15:  * hardware specifics to the lower level interface driver.
        !            16:  */
        !            17: #include "../machine/pte.h"
        !            18: 
        !            19: #include "param.h"
        !            20: #include "systm.h"
        !            21: #include "mbuf.h"
        !            22: #include "buf.h"
        !            23: #include "protosw.h"
        !            24: #include "socket.h"
        !            25: #include "vmmac.h"
        !            26: #include "time.h"
        !            27: #include "kernel.h"
        !            28: #include "errno.h"
        !            29: #include "ioctl.h"
        !            30: 
        !            31: #include "../vax/cpu.h"
        !            32: #include "../vax/mtpr.h"
        !            33: #include "../vaxuba/ubareg.h"
        !            34: #include "../vaxuba/ubavar.h"
        !            35: 
        !            36: #include "../net/if.h"
        !            37: #include "../net/route.h"
        !            38: 
        !            39: #include "../net/netisr.h"
        !            40: #include "../netinet/in.h"
        !            41: #include "../netinet/in_systm.h"
        !            42: #include "../netinet/in_var.h"
        !            43: #include "../netinet/ip.h"
        !            44: #include "../netinet/ip_var.h"
        !            45: /* define IMPLEADERS here to get leader printing code */
        !            46: #include "if_imp.h"
        !            47: #include "if_imphost.h"
        !            48: 
        !            49: /*
        !            50:  * IMP software status per interface.
        !            51:  * (partially shared with the hardware specific module)
        !            52:  *
        !            53:  * Each interface is referenced by a network interface structure,
        !            54:  * imp_if, which the routing code uses to locate the interface.
        !            55:  * This structure contains the output queue for the interface, its
        !            56:  * address, ...  IMP specific structures used in connecting the
        !            57:  * IMP software modules to the hardware specific interface routines
        !            58:  * are stored here.  The common structures are made visible to the
        !            59:  * interface driver by passing a pointer to the hardware routine
        !            60:  * at "attach" time.
        !            61:  *
        !            62:  * NOTE: imp_if and imp_cb are assumed adjacent in hardware code.
        !            63:  */
        !            64: struct imp_softc {
        !            65:        struct  ifnet imp_if;           /* network visible interface */
        !            66:        struct  impcb imp_cb;           /* hooks to hardware module */
        !            67:        u_char  imp_state;              /* current state of IMP */
        !            68:        char    imp_dropcnt;            /* used during initialization */
        !            69: } imp_softc[NIMP];
        !            70: 
        !            71: struct ifqueue impintrq;
        !            72: int    impqmaxlen = IFQ_MAXLEN;
        !            73: 
        !            74: /*
        !            75:  * Messages from IMP regarding why
        !            76:  * it's going down.
        !            77:  */
        !            78: static char *impmessage[] = {
        !            79:        "in 30 seconds",
        !            80:        "for hardware PM",
        !            81:        "to reload software",
        !            82:        "for emergency reset"
        !            83: };
        !            84: 
        !            85: #define HOSTDEADTIMER  10              /* How long to wait when down */
        !            86: 
        !            87: int    impdown(), impinit(), impioctl(), impoutput();
        !            88: 
        !            89: /*
        !            90:  * IMP attach routine.  Called from hardware device attach routine
        !            91:  * at configuration time with a pointer to the UNIBUS device structure.
        !            92:  * Sets up local state and returns pointer to base of ifnet+impcb
        !            93:  * structures.  This is then used by the device's attach routine
        !            94:  * set up its back pointers. 
        !            95:  */
        !            96: impattach(ui, reset)
        !            97:        struct uba_device *ui;
        !            98:        int (*reset)();
        !            99: {
        !           100:        struct imp_softc *sc;
        !           101:        register struct ifnet *ifp;
        !           102: 
        !           103: #ifdef lint
        !           104:        impintr();
        !           105: #endif
        !           106:        if (ui->ui_unit >= NIMP) {
        !           107:                printf("imp%d: not configured\n", ui->ui_unit);
        !           108:                return (0);
        !           109:        }
        !           110:        sc = &imp_softc[ui->ui_unit];
        !           111:        ifp = &sc->imp_if;
        !           112:        /* UNIT COULD BE AMBIGUOUS */
        !           113:        ifp->if_unit = ui->ui_unit;
        !           114:        ifp->if_name = "imp";
        !           115:        ifp->if_mtu = IMPMTU - sizeof(struct imp_leader);
        !           116:        ifp->if_reset = reset;
        !           117:        ifp->if_init = impinit;
        !           118:        ifp->if_ioctl = impioctl;
        !           119:        ifp->if_output = impoutput;
        !           120:        /* reset is handled at the hardware level */
        !           121:        if_attach(ifp);
        !           122:        return ((int)ifp);
        !           123: }
        !           124: 
        !           125: /*
        !           126:  * IMP initialization routine: call hardware module to
        !           127:  * setup UNIBUS resources, init state and get ready for
        !           128:  * NOOPs the IMP should send us, and that we want to drop.
        !           129:  */
        !           130: impinit(unit)
        !           131:        int unit;
        !           132: {
        !           133:        int s = splimp();
        !           134:        register struct imp_softc *sc = &imp_softc[unit];
        !           135: 
        !           136:        if (sc->imp_if.if_addrlist == 0)
        !           137:                return;
        !           138:        if ((*sc->imp_cb.ic_init)(unit) == 0) {
        !           139:                sc->imp_state = IMPS_DOWN;
        !           140:                sc->imp_if.if_flags &= ~IFF_UP;
        !           141:                splx(s);
        !           142:                return;
        !           143:        }
        !           144:        sc->imp_state = IMPS_INIT;
        !           145:        impnoops(sc);
        !           146:        impintrq.ifq_maxlen = impqmaxlen;
        !           147:        splx(s);
        !           148: }
        !           149: 
        !           150: #ifdef IMPLEADERS
        !           151: int    impprintfs = 0;
        !           152: #endif
        !           153: 
        !           154: /*
        !           155:  * ARPAnet 1822 input routine.
        !           156:  * Called from hardware input interrupt routine to handle 1822
        !           157:  * IMP-host messages.  Type 0 messages (non-control) are
        !           158:  * passed to higher level protocol processors on the basis
        !           159:  * of link number.  Other type messages (control) are handled here.
        !           160:  */
        !           161: impinput(unit, m)
        !           162:        int unit;
        !           163:        register struct mbuf *m;
        !           164: {
        !           165:        register struct imp_leader *ip;
        !           166:        register struct imp_softc *sc = &imp_softc[unit];
        !           167:        struct ifnet *ifp;
        !           168:        register struct host *hp;
        !           169:        register struct ifqueue *inq;
        !           170:        struct control_leader *cp;
        !           171:        struct in_addr addr;
        !           172:        struct mbuf *next;
        !           173:        struct sockaddr_in *sin;
        !           174: 
        !           175:        /*
        !           176:         * Pull the interface pointer out of the mbuf
        !           177:         * and save for later; adjust mbuf to look at rest of data.
        !           178:         */
        !           179:        ifp = *(mtod(m, struct ifnet **));
        !           180:        IF_ADJ(m);
        !           181:        /* verify leader length. */
        !           182:        if (m->m_len < sizeof(struct control_leader) &&
        !           183:            (m = m_pullup(m, sizeof(struct control_leader))) == 0)
        !           184:                return;
        !           185:        cp = mtod(m, struct control_leader *);
        !           186:        if (cp->dl_mtype == IMPTYPE_DATA)
        !           187:                if (m->m_len < sizeof(struct imp_leader) &&
        !           188:                    (m = m_pullup(m, sizeof(struct imp_leader))) == 0)
        !           189:                        return;
        !           190:        ip = mtod(m, struct imp_leader *);
        !           191: #ifdef IMPLEADERS
        !           192:        if (impprintfs)
        !           193:                printleader("impinput", ip);
        !           194: #endif
        !           195:        inq = &impintrq;
        !           196: 
        !           197:        /* check leader type */
        !           198:        if (ip->il_format != IMP_NFF) {
        !           199:                sc->imp_if.if_collisions++;     /* XXX */
        !           200:                goto rawlinkin;
        !           201:        }
        !           202: 
        !           203:        if (ip->il_mtype != IMPTYPE_DATA) {
        !           204:                /* If not data packet, build IP addr from leader (BRL) */
        !           205:                imp_leader_to_addr(&addr, ip, &sc->imp_if);
        !           206:        }
        !           207: 
        !           208:        switch (ip->il_mtype) {
        !           209: 
        !           210:        case IMPTYPE_DATA:
        !           211:                /*
        !           212:                 * Data for a protocol.  Dispatch to the appropriate
        !           213:                 * protocol routine (running at software interrupt).
        !           214:                 * If this isn't a raw interface, advance pointer
        !           215:                 * into mbuf past leader.
        !           216:                 */
        !           217:                switch (ip->il_link) {
        !           218: 
        !           219:                case IMPLINK_IP:
        !           220:                        m->m_len -= sizeof(struct imp_leader);
        !           221:                        m->m_off += sizeof(struct imp_leader);
        !           222:                        schednetisr(NETISR_IP);
        !           223:                        inq = &ipintrq;
        !           224:                        break;
        !           225: 
        !           226:                default:
        !           227:                        break;
        !           228:                }
        !           229:                break;
        !           230: 
        !           231:        /*
        !           232:         * IMP leader error.  Reset the IMP and discard the packet.
        !           233:         */
        !           234:        case IMPTYPE_BADLEADER:
        !           235:                /*
        !           236:                 * According to 1822 document, this message
        !           237:                 * will be generated in response to the
        !           238:                 * first noop sent to the IMP after
        !           239:                 * the host resets the IMP interface.
        !           240:                 */
        !           241:                if (sc->imp_state != IMPS_INIT) {
        !           242:                        impmsg(sc, "leader error");
        !           243:                        hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net);
        !           244:                        impnoops(sc);
        !           245:                }
        !           246:                break;
        !           247: 
        !           248:        /*
        !           249:         * IMP going down.  Print message, and if not immediate,
        !           250:         * set off a timer to insure things will be reset at the
        !           251:         * appropriate time.
        !           252:         */
        !           253:        case IMPTYPE_DOWN:
        !           254:                if (sc->imp_state < IMPS_INIT)
        !           255:                        break;
        !           256:                if ((ip->il_link & IMP_DMASK) == 0) {
        !           257:                        sc->imp_state = IMPS_GOINGDOWN;
        !           258:                        timeout(impdown, (caddr_t)sc, 30 * hz);
        !           259:                }
        !           260:                impmsg(sc, "going down %s",
        !           261:                        (u_int)impmessage[ip->il_link&IMP_DMASK]);
        !           262:                break;
        !           263: 
        !           264:        /*
        !           265:         * A NOP usually seen during the initialization sequence.
        !           266:         * Compare the local address with that in the message.
        !           267:         * Reset the local address notion if it doesn't match.
        !           268:         */
        !           269:        case IMPTYPE_NOOP:
        !           270:                if (sc->imp_state == IMPS_DOWN) {
        !           271:                        sc->imp_state = IMPS_INIT;
        !           272:                        sc->imp_dropcnt = IMP_DROPCNT;
        !           273:                }
        !           274:                if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt > 0)
        !           275:                        break;
        !           276:                sin = (struct sockaddr_in *)&sc->imp_if.if_addrlist->ifa_addr;
        !           277:                if (ip->il_imp != 0) {
        !           278:                        struct in_addr leader_addr;
        !           279: 
        !           280:                        imp_leader_to_addr(&leader_addr, ip, &sc->imp_if);
        !           281:                        if (sin->sin_addr.s_addr != leader_addr.s_addr) {
        !           282:                                impmsg(sc, "address reset to x%x (%d/%d)",
        !           283:                                        ntohl(leader_addr.s_addr),
        !           284:                                        (u_int)ip->il_host,
        !           285:                                        ntohs(ip->il_imp));
        !           286:                                sin->sin_addr.s_addr = leader_addr.s_addr;
        !           287:                        }
        !           288:                }
        !           289:                sc->imp_state = IMPS_UP;
        !           290:                sc->imp_if.if_flags |= IFF_UP;
        !           291:                break;
        !           292: 
        !           293:        /*
        !           294:         * RFNM or INCOMPLETE message, send next
        !           295:         * message on the q.  We could pass incomplete's
        !           296:         * up to the next level, but this currently isn't
        !           297:         * needed.
        !           298:         */
        !           299:        case IMPTYPE_RFNM:
        !           300:        case IMPTYPE_INCOMPLETE:
        !           301:                if (hp = hostlookup(addr)) {
        !           302:                        hp->h_timer = HOSTTIMER;
        !           303:                        if (hp->h_rfnm == 0)
        !           304:                                hp->h_flags &= ~HF_INUSE;
        !           305:                        else if (next = hostdeque(hp))
        !           306:                                (void) impsnd(&sc->imp_if, next);
        !           307:                }
        !           308:                goto drop;
        !           309: 
        !           310:        /*
        !           311:         * Host or IMP can't be reached.  Flush any packets
        !           312:         * awaiting transmission and release the host structure.
        !           313:         * Enqueue for notifying protocols at software interrupt time.
        !           314:         */
        !           315:        case IMPTYPE_HOSTDEAD:
        !           316:        case IMPTYPE_HOSTUNREACH:
        !           317:                if (hp = hostlookup(addr)) {
        !           318:                        hp->h_flags |= (1 << (int)ip->il_mtype);
        !           319:                        hostfree(hp);
        !           320:                        hp->h_timer = HOSTDEADTIMER;
        !           321:                }
        !           322:                break;
        !           323: 
        !           324:        /*
        !           325:         * Error in data.  Clear RFNM status for this host and send
        !           326:         * noops to the IMP to clear the interface.
        !           327:         */
        !           328:        case IMPTYPE_BADDATA:
        !           329:                impmsg(sc, "data error");
        !           330:                if (hp = hostlookup(addr))
        !           331:                        hp->h_rfnm = 0;
        !           332:                impnoops(sc);
        !           333:                break;
        !           334: 
        !           335:        /*
        !           336:         * Interface reset.
        !           337:         */
        !           338:        case IMPTYPE_RESET:
        !           339:                impmsg(sc, "interface reset");
        !           340:                /* clear RFNM counts */
        !           341:                hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net);
        !           342:                impnoops(sc);
        !           343:                break;
        !           344: 
        !           345:        default:
        !           346:                sc->imp_if.if_collisions++;             /* XXX */
        !           347:                break;
        !           348:        }
        !           349: 
        !           350: rawlinkin:
        !           351:        if (inq == &impintrq)
        !           352:                schednetisr(NETISR_IMP);
        !           353:        /*
        !           354:         * Re-insert interface pointer in the mbuf chain
        !           355:         * for the next protocol up.
        !           356:         */
        !           357:        if (M_HASCL(m) && (mtod(m, int) & CLOFSET) < sizeof(struct ifnet *)) {
        !           358:                struct mbuf *n;
        !           359: 
        !           360:                MGET(n, M_DONTWAIT, MT_HEADER);
        !           361:                if (n == 0)
        !           362:                        goto drop;
        !           363:                n->m_next = m;
        !           364:                m = n;
        !           365:                m->m_len = 0;
        !           366:                m->m_off = MMINOFF + sizeof(struct ifnet  *);
        !           367:        }
        !           368:        m->m_off -= sizeof(struct ifnet *);
        !           369:        m->m_len += sizeof(struct ifnet *);
        !           370:        *(mtod(m, struct ifnet **)) = ifp;
        !           371: 
        !           372:        if (IF_QFULL(inq)) {
        !           373:                IF_DROP(inq);
        !           374:                goto drop;
        !           375:        }
        !           376:        IF_ENQUEUE(inq, m);
        !           377:        return;
        !           378: 
        !           379: drop:
        !           380:        m_freem(m);
        !           381: }
        !           382: 
        !           383: /*
        !           384:  * Bring the IMP down after notification.
        !           385:  */
        !           386: impdown(sc)
        !           387:        struct imp_softc *sc;
        !           388: {
        !           389:        int s = splimp();
        !           390: 
        !           391:        sc->imp_state = IMPS_DOWN;
        !           392:        impmsg(sc, "marked down");
        !           393:        hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net);
        !           394:        if_down(&sc->imp_if);
        !           395:        splx(s);
        !           396: }
        !           397: 
        !           398: /*VARARGS2*/
        !           399: impmsg(sc, fmt, a1, a2, a3)
        !           400:        struct imp_softc *sc;
        !           401:        char *fmt;
        !           402:        u_int a1;
        !           403: {
        !           404: 
        !           405:        printf("imp%d: ", sc->imp_if.if_unit);
        !           406:        printf(fmt, a1, a2, a3);
        !           407:        printf("\n");
        !           408: }
        !           409: 
        !           410: struct sockproto impproto = { PF_IMPLINK };
        !           411: struct sockaddr_in impdst = { AF_IMPLINK };
        !           412: struct sockaddr_in impsrc = { AF_IMPLINK };
        !           413: 
        !           414: /*
        !           415:  * Pick up the IMP "error" messages enqueued earlier,
        !           416:  * passing these up to the higher level protocol
        !           417:  * and the raw interface.
        !           418:  */
        !           419: impintr()
        !           420: {
        !           421:        register struct mbuf *m;
        !           422:        register struct control_leader *cp;
        !           423:        struct ifnet *ifp;
        !           424:        int s;
        !           425: 
        !           426:        for (;;) {
        !           427:                s = splimp();
        !           428:                IF_DEQUEUEIF(&impintrq, m, ifp);
        !           429:                splx(s);
        !           430:                if (m == 0)
        !           431:                        return;
        !           432: 
        !           433:                cp = mtod(m, struct control_leader *);
        !           434:                imp_leader_to_addr(&impsrc.sin_addr, (struct imp_leader *)cp,
        !           435:                    ifp);
        !           436:                impproto.sp_protocol = cp->dl_link;
        !           437:                impdst.sin_addr = IA_SIN(ifp->if_addrlist)->sin_addr;
        !           438: 
        !           439:                if (cp->dl_mtype == IMPTYPE_HOSTDEAD ||
        !           440:                    cp->dl_mtype == IMPTYPE_HOSTUNREACH)
        !           441:                        switch (cp->dl_link) {
        !           442: 
        !           443:                        case IMPLINK_IP:
        !           444:                                pfctlinput((int)cp->dl_mtype,
        !           445:                                    (struct sockaddr *)&impsrc);
        !           446:                                break;
        !           447:                        default:
        !           448:                                raw_ctlinput((int)cp->dl_mtype,
        !           449:                                    (struct sockaddr *)&impsrc);
        !           450:                                break;
        !           451:                        }
        !           452: 
        !           453:                raw_input(m, &impproto, (struct sockaddr *)&impsrc,
        !           454:                  (struct sockaddr *)&impdst);
        !           455:        }
        !           456: }
        !           457: 
        !           458: /*
        !           459:  * ARPAnet 1822 output routine.
        !           460:  * Called from higher level protocol routines to set up messages for
        !           461:  * transmission to the imp.  Sets up the header and calls impsnd to
        !           462:  * enqueue the message for this IMP's hardware driver.
        !           463:  */
        !           464: impoutput(ifp, m0, dst)
        !           465:        register struct ifnet *ifp;
        !           466:        struct mbuf *m0;
        !           467:        struct sockaddr *dst;
        !           468: {
        !           469:        register struct imp_leader *imp;
        !           470:        register struct mbuf *m = m0;
        !           471:        int dlink, len;
        !           472:        int error = 0;
        !           473: 
        !           474:        /*
        !           475:         * Don't even try if the IMP is unavailable.
        !           476:         */
        !           477:        if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) {
        !           478:                error = ENETDOWN;
        !           479:                goto drop;
        !           480:        }
        !           481: 
        !           482:        switch (dst->sa_family) {
        !           483: 
        !           484:        case AF_INET: {
        !           485:                struct ip *ip = mtod(m, struct ip *);
        !           486: 
        !           487:                dlink = IMPLINK_IP;
        !           488:                len = ntohs((u_short)ip->ip_len);
        !           489:                break;
        !           490:        }
        !           491: 
        !           492:        case AF_IMPLINK:
        !           493:                len = 0;
        !           494:                do
        !           495:                        len += m->m_len;
        !           496:                while (m = m->m_next);
        !           497:                m = m0;
        !           498:                goto leaderexists;
        !           499: 
        !           500:        default:
        !           501:                printf("imp%d: can't handle af%d\n", ifp->if_unit, 
        !           502:                        dst->sa_family);
        !           503:                error = EAFNOSUPPORT;
        !           504:                goto drop;
        !           505:        }
        !           506: 
        !           507:        /*
        !           508:         * Add IMP leader.  If there's not enough space in the
        !           509:         * first mbuf, allocate another.  If that should fail, we
        !           510:         * drop this sucker.
        !           511:         */
        !           512:        if (m->m_off > MMAXOFF ||
        !           513:            MMINOFF + sizeof(struct imp_leader) > m->m_off) {
        !           514:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           515:                if (m == 0) {
        !           516:                        error = ENOBUFS;
        !           517:                        goto drop;
        !           518:                }
        !           519:                m->m_next = m0;
        !           520:                m->m_len = sizeof(struct imp_leader);
        !           521:        } else {
        !           522:                m->m_off -= sizeof(struct imp_leader);
        !           523:                m->m_len += sizeof(struct imp_leader);
        !           524:        }
        !           525:        imp = mtod(m, struct imp_leader *);
        !           526:        imp->il_format = IMP_NFF;
        !           527:        imp->il_mtype = IMPTYPE_DATA;
        !           528:        imp_addr_to_leader(imp,
        !           529:                ((struct sockaddr_in *)dst)->sin_addr.s_addr); /* BRL */
        !           530:        imp->il_length = htons((u_short)len << 3);              /* BRL */
        !           531:        imp->il_link = dlink;
        !           532:        imp->il_flags = imp->il_htype = imp->il_subtype = 0;
        !           533: 
        !           534: leaderexists:
        !           535:        return (impsnd(ifp, m));
        !           536: drop:
        !           537:        m_freem(m0);
        !           538:        return (error);
        !           539: }
        !           540: 
        !           541: /* 
        !           542:  * Put a message on an interface's output queue. 
        !           543:  * Perform RFNM counting: no more than 8 message may be
        !           544:  * in flight to any one host.
        !           545:  */
        !           546: impsnd(ifp, m)             
        !           547:        struct ifnet *ifp;
        !           548:        struct mbuf *m;
        !           549: {
        !           550:        register struct imp_leader *ip;
        !           551:        register struct host *hp;
        !           552:        struct impcb *icp;
        !           553:        int s, error;
        !           554: 
        !           555:        ip = mtod(m, struct imp_leader *);
        !           556: 
        !           557:        /*
        !           558:         * Do RFNM counting for data messages
        !           559:         * (no more than 8 outstanding to any host)
        !           560:         */ 
        !           561:        s = splimp();
        !           562:        if (ip->il_mtype == IMPTYPE_DATA) {
        !           563:                struct in_addr addr;
        !           564: 
        !           565:                imp_leader_to_addr(&addr, ip, ifp);     /* BRL */
        !           566:                if ((hp = hostlookup(addr)) == 0)
        !           567:                        hp = hostenter(addr);
        !           568:                if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) {
        !           569:                        error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH;
        !           570:                        hp->h_flags &= ~HF_INUSE;
        !           571:                        goto bad;
        !           572:                }
        !           573: 
        !           574:                /*
        !           575:                 * If IMP would block, queue until RFNM
        !           576:                 */
        !           577:                if (hp) {
        !           578: #ifndef NORFNM
        !           579:                        if (hp->h_rfnm < 8)
        !           580: #endif
        !           581:                        {
        !           582:                                hp->h_timer = HOSTTIMER;
        !           583:                                hp->h_rfnm++;
        !           584:                                goto enque;
        !           585:                        }
        !           586:                        if (hp->h_qcnt < 8) {   /* high water mark */
        !           587:                                HOST_ENQUE(hp, m);
        !           588:                                goto start;
        !           589:                        }
        !           590:                }
        !           591:                error = ENOBUFS;
        !           592:                goto bad;
        !           593:        }
        !           594: enque:
        !           595:        if (IF_QFULL(&ifp->if_snd)) {
        !           596:                IF_DROP(&ifp->if_snd);
        !           597:                error = ENOBUFS;
        !           598:                if (ip->il_mtype == IMPTYPE_DATA)
        !           599:                        hp->h_rfnm--;
        !           600: bad:
        !           601:                m_freem(m);
        !           602:                splx(s);
        !           603:                return (error);
        !           604:        }
        !           605:        IF_ENQUEUE(&ifp->if_snd, m);
        !           606: start:
        !           607:        icp = &imp_softc[ifp->if_unit].imp_cb;
        !           608:        if (icp->ic_oactive == 0)
        !           609:                (*icp->ic_start)(ifp->if_unit);
        !           610:        splx(s);
        !           611:        return (0);
        !           612: }
        !           613: 
        !           614: /*
        !           615:  * Put three 1822 NOOPs at the head of the output queue. 
        !           616:  * Part of host-IMP initialization procedure.
        !           617:  * (Should return success/failure, but noone knows
        !           618:  * what to do with this, so why bother?)
        !           619:  * This routine is always called at splimp, so we don't
        !           620:  * protect the call to IF_PREPEND.
        !           621:  */
        !           622: impnoops(sc)             
        !           623:        register struct imp_softc *sc;
        !           624: {
        !           625:        register i;
        !           626:        register struct mbuf *m;
        !           627:        register struct control_leader *cp;
        !           628: 
        !           629:        sc->imp_dropcnt = IMP_DROPCNT;
        !           630:        for (i = 0; i < IMP_DROPCNT + 1; i++) { 
        !           631:                if ((m = m_getclr(M_DONTWAIT, MT_HEADER)) == 0) 
        !           632:                        return;
        !           633:                m->m_len = sizeof(struct control_leader);
        !           634:                cp = mtod(m, struct control_leader *);
        !           635:                cp->dl_format = IMP_NFF;
        !           636:                 cp->dl_link = i;
        !           637:                 cp->dl_mtype = IMPTYPE_NOOP;
        !           638:                IF_PREPEND(&sc->imp_if.if_snd, m);
        !           639:        }
        !           640:        if (sc->imp_cb.ic_oactive == 0)
        !           641:                (*sc->imp_cb.ic_start)(sc->imp_if.if_unit);
        !           642: }
        !           643: 
        !           644: /*
        !           645:  * Process an ioctl request.
        !           646:  */
        !           647: impioctl(ifp, cmd, data)
        !           648:        register struct ifnet *ifp;
        !           649:        int cmd;
        !           650:        caddr_t data;
        !           651: {
        !           652:        struct ifaddr *ifa = (struct ifaddr *) data;
        !           653:        int s = splimp(), error = 0;
        !           654: 
        !           655:        switch (cmd) {
        !           656: 
        !           657:        case SIOCSIFADDR:
        !           658:                if (ifa->ifa_addr.sa_family != AF_INET) {
        !           659:                        error = EINVAL;
        !           660:                        break;
        !           661:                }
        !           662:                if ((ifp->if_flags & IFF_RUNNING) == 0)
        !           663:                        impinit(ifp->if_unit);
        !           664:                break;
        !           665: 
        !           666:        default:
        !           667:                error = EINVAL;
        !           668:        }
        !           669:        splx(s);
        !           670:        return (error);
        !           671: }
        !           672: 
        !           673: #ifdef IMPLEADERS
        !           674: printleader(routine, ip)
        !           675:        char *routine;
        !           676:        register struct imp_leader *ip;
        !           677: {
        !           678:        printf("%s: ", routine);
        !           679:        printbyte((char *)ip, 12);
        !           680:        printf("<fmt=%x,net=%x,flags=%x,mtype=", ip->il_format, ip->il_network,
        !           681:                ip->il_flags);
        !           682:        if (ip->il_mtype <= IMPTYPE_READY)
        !           683:                printf("%s,", impleaders[ip->il_mtype]);
        !           684:        else
        !           685:                printf("%x,", ip->il_mtype);
        !           686:        printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host,
        !           687:                ntohs(ip->il_imp));
        !           688:        if (ip->il_link == IMPLINK_IP)
        !           689:                printf("ip,");
        !           690:        else
        !           691:                printf("%x,", ip->il_link);
        !           692:        printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3);
        !           693: }
        !           694: 
        !           695: printbyte(cp, n)
        !           696:        register char *cp;
        !           697:        int n;
        !           698: {
        !           699:        register i, j, c;
        !           700: 
        !           701:        for (i=0; i<n; i++) {
        !           702:                c = *cp++;
        !           703:                for (j=0; j<2; j++)
        !           704:                        putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf], 0);
        !           705:                putchar(' ', 0);
        !           706:        }
        !           707:        putchar('\n', 0);
        !           708: }
        !           709: #endif
        !           710: 
        !           711: /*
        !           712:  * Routine to convert from IMP Leader to InterNet Address.
        !           713:  *
        !           714:  * This procedure is necessary because IMPs may be assigned Class A, B, or C
        !           715:  * network numbers, but only have 8 bits in the leader to reflect the
        !           716:  * IMP "network number".  The strategy is to take the network number from
        !           717:  * the ifnet structure, and blend in the host-on-imp and imp-on-net numbers
        !           718:  * from the leader.
        !           719:  *
        !           720:  * There is no support for "Logical Hosts".
        !           721:  *
        !           722:  * Class A:    Net.Host.0.Imp
        !           723:  * Class B:    Net.net.Host.Imp
        !           724:  * Class C:    Net.net.net.(Host4|Imp4)
        !           725:  */
        !           726: imp_leader_to_addr(ap, ip, ifp)
        !           727:        struct in_addr *ap;
        !           728:        register struct imp_leader *ip;
        !           729:        struct ifnet *ifp;
        !           730: {
        !           731:        register u_long final;
        !           732:        register struct sockaddr_in *sin;
        !           733:        int imp = ntohs(ip->il_imp);
        !           734: 
        !           735:        sin = (struct sockaddr_in *)(&ifp->if_addrlist->ifa_addr);
        !           736:        final = ntohl(sin->sin_addr.s_addr);
        !           737: 
        !           738:        if (IN_CLASSA(final)) {
        !           739:                final &= IN_CLASSA_NET;
        !           740:                final |= (imp & 0xFF) | ((ip->il_host & 0xFF)<<16);
        !           741:        } else if (IN_CLASSB(final)) {
        !           742:                final &= IN_CLASSB_NET;
        !           743:                final |= (imp & 0xFF) | ((ip->il_host & 0xFF)<<8);
        !           744:        } else {
        !           745:                final &= IN_CLASSC_NET;
        !           746:                final |= (imp & 0x0F) | ((ip->il_host & 0x0F)<<4);
        !           747:        }
        !           748:        ap->s_addr = htonl(final);
        !           749: }
        !           750: 
        !           751: /*
        !           752:  * Function to take InterNet address and fill in IMP leader fields.
        !           753:  */
        !           754: imp_addr_to_leader(imp, a)
        !           755:        register struct imp_leader *imp;
        !           756:        u_long a;
        !           757: {
        !           758:        register u_long addr = ntohl(a);
        !           759: 
        !           760:        imp->il_network = 0;    /* !! */
        !           761: 
        !           762:        if (IN_CLASSA(addr)) {
        !           763:                imp->il_host = ((addr>>16) & 0xFF);
        !           764:                imp->il_imp = addr & 0xFF;
        !           765:        } else if (IN_CLASSB(addr)) {
        !           766:                imp->il_host = ((addr>>8) & 0xFF);
        !           767:                imp->il_imp = addr & 0xFF;
        !           768:        } else {
        !           769:                imp->il_host = ((addr>>4) & 0xF);
        !           770:                imp->il_imp = addr & 0xF;
        !           771:        }
        !           772:        imp->il_imp = htons(imp->il_imp);
        !           773: }
        !           774: #endif

unix.superglobalmegacorp.com

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