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
imp_leader_to_addr defined in line 721; used 4 times
impattach defined in line 91; never used
impdown defined in line 381; used 2 times
impinit defined in line 125; used 3 times
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
impmsg defined in line 394; used 6 times
impnoops defined in line 617; used 4 times
impoutput defined in line 459; used 2 times
impsnd defined in line 541; used 2 times
printbyte defined in line 690; used 1 times
printleader defined in line 669; used 1 times

Defined variables

imp_softc defined in line 63; used 5 times
impdst defined in line 406; used 2 times
impintrq defined in line 66; used 4 times
impmessage defined in line 73; used 1 times
impprintfs defined in line 146; used 1 times
impproto defined in line 405; used 2 times
impqmaxlen defined in line 67; used 1 times
impsrc defined in line 407; used 4 times

Defined struct's

imp_softc defined in line 58; used 12 times

Defined macros

HOSTDEADTIMER defined in line 80; used 1 times
putchar defined in line 40; used 3 times
Last modified: 1994-01-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5766
Valid CSS Valid XHTML 1.0 Strict