Annotation of 43BSD/sys/netimp/if_imp.c, revision 1.1.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.