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

Defined functions

imp_addr_to_leader defined in line 754; used 2 times
imp_leader_to_addr defined in line 726; used 4 times
impdown defined in line 386; used 2 times
impinit defined in line 130; used 3 times
impintr defined in line 419; used 2 times
impioctl defined in line 647; used 2 times
impmsg defined in line 399; used 6 times
impnoops defined in line 622; used 4 times
impoutput defined in line 464; used 3 times
impsnd defined in line 546; used 2 times
printbyte defined in line 695; used 1 times
printleader defined in line 674; used 1 times

Defined variables

imp_softc defined in line 69; used 5 times
impdst defined in line 411; used 2 times
impintrq defined in line 71; used 4 times
impmessage defined in line 78; used 1 times
impprintfs defined in line 151; used 1 times
impproto defined in line 410; used 2 times
impqmaxlen defined in line 72; used 1 times
impsrc defined in line 412; used 4 times

Defined struct's

imp_softc defined in line 64; used 12 times

Defined macros

HOSTDEADTIMER defined in line 85; used 1 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2846
Valid CSS Valid XHTML 1.0 Strict