|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.