# 2.11BSD#431 - /usr/src/sys/netimp/if_imp.c

##### Functions

    imp_addr_to_leaderX
    imp_leader_to_addrX
    impattach         X
    impdown           X
    impinit           X
    impinput          X
    impintr           X
    impioctl          X
    impmsg            X
    impnoops          X
    impoutput         X
    impsnd            X
    printbyte         X
    printleader       X

##### Variables

    imp_softc         X
    impdst            X
    impintrq          X
    impprintfs        X
    impproto          X
    impqmaxlen        X
    impsrc            X

##### Macros

    HOSTDEADTIMER     X
    putchar           X

##### struct's

    imp_softc         X

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

#### Defined functions

imp_addr_to_leader defined in line 749; used 1 times

- in line 523

imp_leader_to_addr defined in line 721; used 4 times

- in line 200, 275, 429, 560

impattach defined in line 91; never used
impdown defined in line 381; used 2 times

- in line 82, 253

impinit defined in line 125; used 3 times

- in line 82, 112, 658

impinput defined in line 156; never used
impintr defined in line 414; used 1 times

- in line 99

impioctl defined in line 642; used 2 times

- in line 82, 113

impmsg defined in line 394; used 6 times

- in line 237, 255, 277, 324, 334, 387

impnoops defined in line 617; used 4 times

- in line 140, 239, 327, 337

impoutput defined in line 459; used 2 times

- in line 82, 114

impsnd defined in line 541; used 2 times

- in line 301, 530

printbyte defined in line 690; used 1 times

- in line 674

printleader defined in line 669; used 1 times

- in line 188

#### Defined variables

imp_softc defined in line 63; used 5 times

- in line 105, 129, 161, 472, 602

impdst defined in line 406; used 2 times

- in line 432, 449

impintrq defined in line 66; used 4 times

- in line 141, 190, 346, 423

impmessage defined in line 73; used 1 times

- in line 256

impprintfs defined in line 146; used 1 times

- in line 187

impproto defined in line 405; used 2 times

- in line 431, 448

impqmaxlen defined in line 67; used 1 times

- in line 141

impsrc defined in line 407; used 4 times

- in line 429, 440-448(3)

#### Defined struct's

imp_softc defined in line 58; used 12 times

- in line 95(2), 129(2), 161(2), 382(2), 395(2), 618(2)

#### Defined macros

HOSTDEADTIMER defined in line 80; used 1 times

- in line 315

putchar defined in line 40; used 3 times

- in line 699-702(3)

Last modified: 1994-01-01 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2448 |