|
|
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_en.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: ! 9: #include "en.h" ! 10: #include "enetfilter.h" ! 11: #if NEN > 0 ! 12: ! 13: /* ! 14: * Xerox prototype (3 Mb) Ethernet interface driver. ! 15: */ ! 16: #include "../machine/pte.h" ! 17: ! 18: #include "param.h" ! 19: #include "systm.h" ! 20: #include "mbuf.h" ! 21: #include "buf.h" ! 22: #include "protosw.h" ! 23: #include "socket.h" ! 24: #include "vmmac.h" ! 25: #include "errno.h" ! 26: #include "ioctl.h" ! 27: ! 28: #include "../net/if.h" ! 29: #include "../net/netisr.h" ! 30: #include "../net/route.h" ! 31: ! 32: #ifdef INET ! 33: #include "../netinet/in.h" ! 34: #include "../netinet/in_systm.h" ! 35: #include "../netinet/in_var.h" ! 36: #include "../netinet/ip.h" ! 37: #endif ! 38: ! 39: #ifdef PUP ! 40: #include "../netpup/pup.h" ! 41: #include "../netpup/ether.h" ! 42: #endif ! 43: ! 44: #ifdef NS ! 45: #include "../netns/ns.h" ! 46: #include "../netns/ns_if.h" ! 47: #endif ! 48: ! 49: #include "../vax/cpu.h" ! 50: #include "../vax/mtpr.h" ! 51: #include "if_en.h" ! 52: #include "if_enreg.h" ! 53: #include "if_uba.h" ! 54: #if NENETFILTER > 0 ! 55: #include "../net/enet.h" ! 56: #endif NENETFILTER > 0 ! 57: #include "../vaxuba/ubareg.h" ! 58: #include "../vaxuba/ubavar.h" ! 59: ! 60: #define ENMTU (1024+512) ! 61: #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */ ! 62: ! 63: int enprobe(), enattach(), enrint(), enxint(), encollide(); ! 64: struct uba_device *eninfo[NEN]; ! 65: u_short enstd[] = { 0 }; ! 66: struct uba_driver endriver = ! 67: { enprobe, 0, enattach, 0, enstd, "en", eninfo }; ! 68: #define ENUNIT(x) minor(x) ! 69: ! 70: int eninit(),enoutput(),enreset(),enioctl(); ! 71: ! 72: #ifdef notdef ! 73: /* ! 74: * If you need to byte swap IP's in the system, define ! 75: * this and do a SIOCSIFFLAGS at boot time. ! 76: */ ! 77: #define ENF_SWABIPS 0x1000 ! 78: #endif ! 79: ! 80: /* ! 81: * Ethernet software status per interface. ! 82: * ! 83: * Each interface is referenced by a network interface structure, ! 84: * es_if, which the routing code uses to locate the interface. ! 85: * This structure contains the output queue for the interface, its address, ... ! 86: * We also have, for each interface, a UBA interface structure, which ! 87: * contains information about the UNIBUS resources held by the interface: ! 88: * map registers, buffered data paths, etc. Information is cached in this ! 89: * structure for use by the if_uba.c routines in running the interface ! 90: * efficiently. ! 91: */ ! 92: struct en_softc { ! 93: struct ifnet es_if; /* network-visible interface */ ! 94: struct ifuba es_ifuba; /* UNIBUS resources */ ! 95: short es_host; /* hardware host number */ ! 96: short es_delay; /* current output delay */ ! 97: short es_mask; /* mask for current output delay */ ! 98: short es_lastx; /* host last transmitted to */ ! 99: short es_oactive; /* is output active? */ ! 100: short es_olen; /* length of last output */ ! 101: short es_nsactive; /* is interface enabled for ns? */ ! 102: #if NENETFILTER > 0 ! 103: short es_enetunit; /* unit number for enet filtering */ ! 104: #endif NENETFILTER > 0 ! 105: } en_softc[NEN]; ! 106: ! 107: /* ! 108: * Do output DMA to determine interface presence and ! 109: * interrupt vector. DMA is too short to disturb other hosts. ! 110: */ ! 111: enprobe(reg) ! 112: caddr_t reg; ! 113: { ! 114: register int br, cvec; /* r11, r10 value-result */ ! 115: register struct endevice *addr = (struct endevice *)reg; ! 116: ! 117: #ifdef lint ! 118: br = 0; cvec = br; br = cvec; ! 119: enrint(0); enxint(0); encollide(0); ! 120: #endif ! 121: addr->en_istat = 0; ! 122: addr->en_owc = -1; ! 123: addr->en_oba = 0; ! 124: addr->en_ostat = EN_IEN|EN_GO; ! 125: DELAY(100000); ! 126: addr->en_ostat = 0; ! 127: return (1); ! 128: } ! 129: ! 130: /* ! 131: * Interface exists: make available by filling in network interface ! 132: * record. System will initialize the interface when it is ready ! 133: * to accept packets. ! 134: */ ! 135: enattach(ui) ! 136: struct uba_device *ui; ! 137: { ! 138: register struct en_softc *es = &en_softc[ui->ui_unit]; ! 139: ! 140: es->es_if.if_unit = ui->ui_unit; ! 141: es->es_if.if_name = "en"; ! 142: es->es_if.if_mtu = ENMTU; ! 143: es->es_if.if_flags = IFF_BROADCAST; ! 144: es->es_if.if_init = eninit; ! 145: es->es_if.if_output = enoutput; ! 146: es->es_if.if_ioctl = enioctl; ! 147: es->es_if.if_reset = enreset; ! 148: es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT; ! 149: #if defined(VAX750) ! 150: /* don't chew up 750 bdp's */ ! 151: if (cpu == VAX_750 && ui->ui_unit > 0) ! 152: es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP; ! 153: #endif ! 154: #if NENETFILTER > 0 ! 155: { ! 156: struct endevp enp; ! 157: struct en_header dummy; ! 158: struct endevice *enaddr = (struct endevice *)ui->ui_addr; ! 159: ! 160: #ifdef SWABALL ! 161: enp.end_dev_type = ENDT_3MB; ! 162: #else ! 163: enp.end_dev_type = ENDT_BS3MB; /* packets appear byte-swapped */ ! 164: #endif ! 165: ! 166: enp.end_addr_len = sizeof(dummy.en_shost); ! 167: enp.end_hdr_len = sizeof(struct en_header); ! 168: enp.end_MTU = ENMTU; ! 169: enp.end_addr[0] = (~enaddr->en_addr) & 0xFF; ! 170: enp.end_broadaddr[0] = 0; ! 171: ! 172: es->es_enetunit = enetattach(&es->es_if, &enp); ! 173: } ! 174: #endif NENETFILTER > 0 ! 175: if_attach(&es->es_if); ! 176: } ! 177: ! 178: /* ! 179: * Reset of interface after UNIBUS reset. ! 180: * If interface is on specified uba, reset its state. ! 181: */ ! 182: enreset(unit, uban) ! 183: int unit, uban; ! 184: { ! 185: register struct uba_device *ui; ! 186: ! 187: if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || ! 188: ui->ui_ubanum != uban) ! 189: return; ! 190: printf(" en%d", unit); ! 191: eninit(unit); ! 192: } ! 193: ! 194: /* ! 195: * Initialization of interface; clear recorded pending ! 196: * operations, and reinitialize UNIBUS usage. ! 197: */ ! 198: eninit(unit) ! 199: int unit; ! 200: { ! 201: register struct en_softc *es = &en_softc[unit]; ! 202: register struct uba_device *ui = eninfo[unit]; ! 203: register struct endevice *addr; ! 204: int s; ! 205: ! 206: if (es->es_if.if_addrlist == (struct ifaddr *)0) ! 207: return; ! 208: if (if_ubainit(&es->es_ifuba, ui->ui_ubanum, ! 209: sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { ! 210: printf("en%d: can't initialize\n", unit); ! 211: es->es_if.if_flags &= ~IFF_UP; ! 212: return; ! 213: } ! 214: addr = (struct endevice *)ui->ui_addr; ! 215: addr->en_istat = addr->en_ostat = 0; ! 216: ! 217: /* ! 218: * Hang a receive and start any ! 219: * pending writes by faking a transmit complete. ! 220: */ ! 221: s = splimp(); ! 222: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; ! 223: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; ! 224: addr->en_istat = EN_IEN|EN_GO; ! 225: es->es_oactive = 1; ! 226: es->es_if.if_flags |= IFF_RUNNING; ! 227: enxint(unit); ! 228: splx(s); ! 229: } ! 230: ! 231: int enalldelay = 0; ! 232: int enlastdel = 50; ! 233: int enlastmask = (~0) << 5; ! 234: ! 235: /* ! 236: * Start or restart output on interface. ! 237: * If interface is already active, then this is a retransmit ! 238: * after a collision, and just restuff registers and delay. ! 239: * If interface is not already active, get another datagram ! 240: * to send off of the interface queue, and map it to the interface ! 241: * before starting the output. ! 242: */ ! 243: enstart(dev) ! 244: dev_t dev; ! 245: { ! 246: int unit = ENUNIT(dev); ! 247: struct uba_device *ui = eninfo[unit]; ! 248: register struct en_softc *es = &en_softc[unit]; ! 249: register struct endevice *addr; ! 250: register struct en_header *en; ! 251: struct mbuf *m; ! 252: int dest; ! 253: ! 254: if (es->es_oactive) ! 255: goto restart; ! 256: ! 257: /* ! 258: * Not already active: dequeue another request ! 259: * and map it to the UNIBUS. If no more requests, ! 260: * just return. ! 261: */ ! 262: IF_DEQUEUE(&es->es_if.if_snd, m); ! 263: if (m == 0) { ! 264: es->es_oactive = 0; ! 265: return; ! 266: } ! 267: en = mtod(m, struct en_header *); ! 268: dest = en->en_dhost; ! 269: en->en_shost = es->es_host; ! 270: es->es_olen = if_wubaput(&es->es_ifuba, m); ! 271: #ifdef ENF_SWABIPS ! 272: /* ! 273: * The Xerox interface does word at a time DMA, so ! 274: * someone must do byte swapping of user data if high ! 275: * and low ender machines are to communicate. ! 276: */ ! 277: if (es->es_if.if_flags & ENF_SWABIPS) { ! 278: en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr; ! 279: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), ! 280: es->es_olen - sizeof (struct en_header) + 1); ! 281: } ! 282: #endif ! 283: ! 284: /* ! 285: * Ethernet cannot take back-to-back packets (no ! 286: * buffering in interface. To help avoid overrunning ! 287: * receivers, enforce a small delay (about 1ms) in interface: ! 288: * * between all packets when enalldelay ! 289: * * whenever last packet was broadcast ! 290: * * whenever this packet is to same host as last packet ! 291: */ ! 292: if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) { ! 293: es->es_delay = enlastdel; ! 294: es->es_mask = enlastmask; ! 295: } ! 296: es->es_lastx = dest; ! 297: ! 298: restart: ! 299: /* ! 300: * Have request mapped to UNIBUS for transmission. ! 301: * Purge any stale data from this BDP, and start the otput. ! 302: */ ! 303: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) ! 304: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp); ! 305: addr = (struct endevice *)ui->ui_addr; ! 306: addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info; ! 307: addr->en_odelay = es->es_delay; ! 308: addr->en_owc = -((es->es_olen + 1) >> 1); ! 309: addr->en_ostat = EN_IEN|EN_GO; ! 310: es->es_oactive = 1; ! 311: } ! 312: ! 313: /* ! 314: * Ethernet interface transmitter interrupt. ! 315: * Start another output if more data to send. ! 316: */ ! 317: enxint(unit) ! 318: int unit; ! 319: { ! 320: register struct uba_device *ui = eninfo[unit]; ! 321: register struct en_softc *es = &en_softc[unit]; ! 322: register struct endevice *addr = (struct endevice *)ui->ui_addr; ! 323: ! 324: if (es->es_oactive == 0) ! 325: return; ! 326: if (es->es_mask && (addr->en_ostat&EN_OERROR)) { ! 327: es->es_if.if_oerrors++; ! 328: endocoll(unit); ! 329: return; ! 330: } ! 331: es->es_if.if_opackets++; ! 332: es->es_oactive = 0; ! 333: es->es_delay = 0; ! 334: es->es_mask = ~0; ! 335: if (es->es_ifuba.ifu_xtofree) { ! 336: m_freem(es->es_ifuba.ifu_xtofree); ! 337: es->es_ifuba.ifu_xtofree = 0; ! 338: } ! 339: if (es->es_if.if_snd.ifq_head == 0) { ! 340: es->es_lastx = 256; /* putatively illegal */ ! 341: return; ! 342: } ! 343: enstart(unit); ! 344: } ! 345: ! 346: /* ! 347: * Collision on ethernet interface. Do exponential ! 348: * backoff, and retransmit. If have backed off all ! 349: * the way print warning diagnostic, and drop packet. ! 350: */ ! 351: encollide(unit) ! 352: int unit; ! 353: { ! 354: struct en_softc *es = &en_softc[unit]; ! 355: ! 356: es->es_if.if_collisions++; ! 357: if (es->es_oactive == 0) ! 358: return; ! 359: endocoll(unit); ! 360: } ! 361: ! 362: endocoll(unit) ! 363: int unit; ! 364: { ! 365: register struct en_softc *es = &en_softc[unit]; ! 366: ! 367: /* ! 368: * Es_mask is a 16 bit number with n low zero bits, with ! 369: * n the number of backoffs. When es_mask is 0 we have ! 370: * backed off 16 times, and give up. ! 371: */ ! 372: if (es->es_mask == 0) { ! 373: printf("en%d: send error\n", unit); ! 374: enxint(unit); ! 375: return; ! 376: } ! 377: /* ! 378: * Another backoff. Restart with delay based on n low bits ! 379: * of the interval timer. ! 380: */ ! 381: es->es_mask <<= 1; ! 382: es->es_delay = mfpr(ICR) &~ es->es_mask; ! 383: enstart(unit); ! 384: } ! 385: ! 386: #ifdef notdef ! 387: struct sockproto enproto = { AF_ETHERLINK }; ! 388: struct sockaddr_en endst = { AF_ETHERLINK }; ! 389: struct sockaddr_en ensrc = { AF_ETHERLINK }; ! 390: #endif ! 391: /* ! 392: * Ethernet interface receiver interrupt. ! 393: * If input error just drop packet. ! 394: * Otherwise purge input buffered data path and examine ! 395: * packet to determine type. If can't determine length ! 396: * from type, then have to drop packet. Othewise decapsulate ! 397: * packet based on type and pass to type specific higher-level ! 398: * input routine. ! 399: */ ! 400: enrint(unit) ! 401: int unit; ! 402: { ! 403: register struct en_softc *es = &en_softc[unit]; ! 404: struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr; ! 405: register struct en_header *en; ! 406: struct mbuf *m; ! 407: int len; short resid; ! 408: register struct ifqueue *inq; ! 409: int off, s; ! 410: ! 411: es->es_if.if_ipackets++; ! 412: ! 413: /* ! 414: * Purge BDP; drop if input error indicated. ! 415: */ ! 416: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) ! 417: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp); ! 418: if (addr->en_istat&EN_IERROR) { ! 419: es->es_if.if_ierrors++; ! 420: goto setup; ! 421: } ! 422: ! 423: /* ! 424: * Calculate input data length. ! 425: * Get pointer to ethernet header (in input buffer). ! 426: * Deal with trailer protocol: if type is PUP trailer ! 427: * get true type from first 16-bit word past data. ! 428: * Remember that type was trailer by setting off. ! 429: */ ! 430: resid = addr->en_iwc; ! 431: if (resid) ! 432: resid |= 0176000; ! 433: len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1; ! 434: len -= sizeof (struct en_header); ! 435: if (len > ENMRU || len <= 0) ! 436: goto setup; /* sanity */ ! 437: en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr); ! 438: #ifdef SWABALL ! 439: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len); ! 440: #else ! 441: en->en_type = ntohs(en->en_type); ! 442: #endif SWABALL ! 443: #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) ! 444: if (en->en_type >= ENTYPE_TRAIL && ! 445: en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) { ! 446: off = (en->en_type - ENTYPE_TRAIL) * 512; ! 447: if (off > ENMTU) ! 448: goto setup; /* sanity */ ! 449: #ifndef SWABALL ! 450: en->en_type = *endataaddr(en, off, u_short *); ! 451: resid = *(endataaddr(en, off+2, u_short *)); ! 452: #else SWABALL ! 453: en->en_type = ntohs(*endataaddr(en, off, u_short *)); ! 454: resid = ntohs(*(endataaddr(en, off+2, u_short *))); ! 455: #endif SWABALL ! 456: if (off + resid > len) ! 457: goto setup; /* sanity */ ! 458: len = off + resid; ! 459: } else ! 460: off = 0; ! 461: if (len == 0) ! 462: goto setup; ! 463: #ifdef ENF_SWABIPS ! 464: if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP) ! 465: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len); ! 466: #endif ! 467: /* ! 468: * Pull packet off interface. Off is nonzero if packet ! 469: * has trailing header; if_rubaget will then force this header ! 470: * information to be at the front, but we still have to drop ! 471: * the type and length which are at the front of any trailer data. ! 472: */ ! 473: m = if_rubaget(&es->es_ifuba, len, off, &es->es_if); ! 474: if (m == 0) ! 475: goto setup; ! 476: if (off) { ! 477: struct ifnet *ifp; ! 478: ! 479: ifp = *(mtod(m, struct ifnet **)); ! 480: m->m_off += 2 * sizeof (u_short); ! 481: m->m_len -= 2 * sizeof (u_short); ! 482: *(mtod(m, struct ifnet **)) = ifp; ! 483: } ! 484: switch (en->en_type) { ! 485: ! 486: #ifdef INET ! 487: case ENTYPE_IP: ! 488: schednetisr(NETISR_IP); ! 489: inq = &ipintrq; ! 490: break; ! 491: #endif ! 492: #ifdef PUP ! 493: case ENTYPE_PUP: ! 494: rpup_input(m); ! 495: goto setup; ! 496: #endif ! 497: #ifdef NS ! 498: case ETHERTYPE_NS: ! 499: if (es->es_nsactive) { ! 500: schednetisr(NETISR_NS); ! 501: inq = &nsintrq; ! 502: } else { ! 503: m_freem(m); ! 504: goto setup; ! 505: } ! 506: break; ! 507: #endif ! 508: ! 509: #if NENETFILTER > 0 ! 510: default: ! 511: { ! 512: register struct mbuf *mtop; ! 513: /* ! 514: * We need the local net header after all. Oh well, ! 515: * this could be improved. ! 516: */ ! 517: MGET(mtop, M_DONTWAIT, MT_DATA); ! 518: if (mtop == 0) { /* no more mbufs? */ ! 519: m_freem(m); /* wasted effort */ ! 520: goto setup; ! 521: } ! 522: #ifdef SWABALL ! 523: /* ! 524: * the interface has put en_type in host order and we ! 525: * want it in net order. ! 526: */ ! 527: en->en_type = htons(en->en_type); ! 528: #endif SWABALL ! 529: bcopy(en, mtod(mtop, struct en_header *), ! 530: sizeof(struct en_header)); ! 531: mtop->m_len = sizeof(struct en_header); ! 532: IF_ADJ(m); ! 533: mtop->m_next = m; ! 534: enetFilter(es->es_enetunit, mtop, ! 535: (len + sizeof(struct en_header)) ); ! 536: goto setup; ! 537: } ! 538: #else ! 539: default: ! 540: #ifdef notdef ! 541: enproto.sp_protocol = en->en_type; ! 542: endst.sen_host = en->en_dhost; ! 543: endst.sen_net = ensrc.sen_net = es->es_if.if_net; ! 544: ensrc.sen_host = en->en_shost; ! 545: raw_input(m, &enproto, ! 546: (struct sockaddr *)&ensrc, (struct sockaddr *)&endst); ! 547: #else ! 548: m_freem(m); ! 549: #endif ! 550: goto setup; ! 551: #endif NENETFILTER > 0 ! 552: } ! 553: ! 554: s = splimp(); ! 555: if (IF_QFULL(inq)) { ! 556: IF_DROP(inq); ! 557: m_freem(m); ! 558: } else ! 559: IF_ENQUEUE(inq, m); ! 560: splx(s); ! 561: ! 562: setup: ! 563: /* ! 564: * Reset for next packet. ! 565: */ ! 566: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; ! 567: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; ! 568: addr->en_istat = EN_IEN|EN_GO; ! 569: } ! 570: ! 571: /* ! 572: * Ethernet output routine. ! 573: * Encapsulate a packet of type family for the local net. ! 574: * Use trailer local net encapsulation if enough data in first ! 575: * packet leaves a multiple of 512 bytes of data in remainder. ! 576: */ ! 577: enoutput(ifp, m0, dst) ! 578: struct ifnet *ifp; ! 579: struct mbuf *m0; ! 580: struct sockaddr *dst; ! 581: { ! 582: int type, dest, s, error; ! 583: register struct mbuf *m = m0; ! 584: register struct en_header *en; ! 585: register int off; ! 586: ! 587: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 588: error = ENETDOWN; ! 589: goto bad; ! 590: } ! 591: switch (dst->sa_family) { ! 592: ! 593: #ifdef INET ! 594: case AF_INET: ! 595: { ! 596: struct in_addr in; ! 597: ! 598: in = ((struct sockaddr_in *)dst)->sin_addr; ! 599: if (in_broadcast(in)) ! 600: dest = EN_BROADCAST; ! 601: else ! 602: dest = in_lnaof(in); ! 603: } ! 604: if (dest >= 0x100) { ! 605: error = EPERM; /* ??? */ ! 606: goto bad; ! 607: } ! 608: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 609: /* need per host negotiation */ ! 610: if ((ifp->if_flags & IFF_NOTRAILERS) == 0) ! 611: if (off > 0 && (off & 0x1ff) == 0 && ! 612: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { ! 613: type = ENTYPE_TRAIL + (off>>9); ! 614: m->m_off -= 2 * sizeof (u_short); ! 615: m->m_len += 2 * sizeof (u_short); ! 616: *mtod(m, u_short *) = htons((u_short)ENTYPE_IP); ! 617: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); ! 618: goto gottrailertype; ! 619: } ! 620: type = ENTYPE_IP; ! 621: off = 0; ! 622: goto gottype; ! 623: #endif ! 624: #ifdef NS ! 625: case AF_NS: ! 626: { ! 627: u_char *up; ! 628: ! 629: type = ETHERTYPE_NS; ! 630: up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host; ! 631: if (*up & 1) ! 632: dest = EN_BROADCAST; ! 633: else ! 634: dest = up[5]; ! 635: ! 636: off = 0; ! 637: goto gottype; ! 638: } ! 639: #endif ! 640: #ifdef PUP ! 641: case AF_PUP: ! 642: dest = ((struct sockaddr_pup *)dst)->spup_host; ! 643: type = ENTYPE_PUP; ! 644: off = 0; ! 645: goto gottype; ! 646: #endif ! 647: ! 648: #if NENETFILTER > 0 ! 649: case AF_IMPLINK: ! 650: en = mtod(m, struct en_header *); ! 651: #ifdef SWABALL ! 652: /* ! 653: * enstart doesn't swab header fields; en_type is in ! 654: * net order and interface expects host order. ! 655: */ ! 656: en->en_type = ntohs(en->en_type); ! 657: #endif SWABALL ! 658: goto gotheader; ! 659: #endif ! 660: ! 661: default: ! 662: printf("en%d: can't handle af%d\n", ifp->if_unit, ! 663: dst->sa_family); ! 664: error = EAFNOSUPPORT; ! 665: goto bad; ! 666: } ! 667: ! 668: gottrailertype: ! 669: /* ! 670: * Packet to be sent as trailer: move first packet ! 671: * (control information) to end of chain. ! 672: */ ! 673: while (m->m_next) ! 674: m = m->m_next; ! 675: m->m_next = m0; ! 676: m = m0->m_next; ! 677: m0->m_next = 0; ! 678: m0 = m; ! 679: ! 680: gottype: ! 681: /* ! 682: * Add local net header. If no space in first mbuf, ! 683: * allocate another. ! 684: */ ! 685: if (m->m_off > MMAXOFF || ! 686: MMINOFF + sizeof (struct en_header) > m->m_off) { ! 687: MGET(m, M_DONTWAIT, MT_HEADER); ! 688: if (m == 0) { ! 689: error = ENOBUFS; ! 690: goto bad; ! 691: } ! 692: m->m_next = m0; ! 693: m->m_off = MMINOFF; ! 694: m->m_len = sizeof (struct en_header); ! 695: } else { ! 696: m->m_off -= sizeof (struct en_header); ! 697: m->m_len += sizeof (struct en_header); ! 698: } ! 699: en = mtod(m, struct en_header *); ! 700: /* add en_shost later */ ! 701: en->en_dhost = dest; ! 702: #ifdef SWABALL ! 703: en->en_type = type; ! 704: #else ! 705: en->en_type = htons((u_short)type); ! 706: #endif ! 707: #if NENETFILTER > 0 ! 708: gotheader: /* will add en_shost later, in enstart() */ ! 709: #endif ! 710: /* ! 711: * Queue message on interface, and start output if interface ! 712: * not yet active. ! 713: */ ! 714: s = splimp(); ! 715: if (IF_QFULL(&ifp->if_snd)) { ! 716: IF_DROP(&ifp->if_snd); ! 717: error = ENOBUFS; ! 718: goto qfull; ! 719: } ! 720: IF_ENQUEUE(&ifp->if_snd, m); ! 721: if (en_softc[ifp->if_unit].es_oactive == 0) ! 722: enstart(ifp->if_unit); ! 723: splx(s); ! 724: return (0); ! 725: qfull: ! 726: m0 = m; ! 727: splx(s); ! 728: bad: ! 729: m_freem(m0); ! 730: return (error); ! 731: } ! 732: ! 733: /* ! 734: * Process an ioctl request. ! 735: */ ! 736: enioctl(ifp, cmd, data) ! 737: register struct ifnet *ifp; ! 738: int cmd; ! 739: caddr_t data; ! 740: { ! 741: register struct en_softc *es = ((struct en_softc *)ifp); ! 742: struct ifaddr *ifa = (struct ifaddr *) data; ! 743: int s = splimp(), error = 0; ! 744: struct endevice *enaddr; ! 745: ! 746: switch (cmd) { ! 747: ! 748: case SIOCSIFADDR: ! 749: enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr; ! 750: es->es_host = (~enaddr->en_addr) & 0xff; ! 751: /* ! 752: * Attempt to check agreement of protocol address ! 753: * and board address. ! 754: */ ! 755: switch (ifa->ifa_addr.sa_family) { ! 756: case AF_INET: ! 757: if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host) ! 758: return (EADDRNOTAVAIL); ! 759: break; ! 760: #ifdef NS ! 761: case AF_NS: ! 762: if (IA_SNS(ifa)->sns_addr.x_host.c_host[5] ! 763: != es->es_host) ! 764: return (EADDRNOTAVAIL); ! 765: es->es_nsactive = 1; ! 766: break; ! 767: #endif ! 768: } ! 769: ifp->if_flags |= IFF_UP; ! 770: if ((ifp->if_flags & IFF_RUNNING) == 0) ! 771: eninit(ifp->if_unit); ! 772: break; ! 773: ! 774: default: ! 775: error = EINVAL; ! 776: break; ! 777: } ! 778: splx(s); ! 779: return (error); ! 780: } ! 781: ! 782: #if defined(SWABALL) || defined(ENF_SWABIPS) ! 783: /* ! 784: * Swab bytes ! 785: * Jeffrey Mogul, Stanford ! 786: */ ! 787: enswab(from, to, n) ! 788: register unsigned char *from, *to; ! 789: register int n; ! 790: { ! 791: register unsigned long temp; ! 792: ! 793: if ((n <= 0) || (n > 0xFFFF)) { ! 794: printf("enswab: bad len %d\n", n); ! 795: return; ! 796: } ! 797: ! 798: n >>= 1; n++; ! 799: #define STEP {temp = *from++;*to++ = *from++;*to++ = temp;} ! 800: /* round to multiple of 8 */ ! 801: while ((--n) & 07) ! 802: STEP; ! 803: n >>= 3; ! 804: while (--n >= 0) { ! 805: STEP; STEP; STEP; STEP; ! 806: STEP; STEP; STEP; STEP; ! 807: } ! 808: } ! 809: #endif ! 810: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.