|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1982, 1989, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: */ ! 55: ! 56: ! 57: ! 58: #include <sys/param.h> ! 59: #include <sys/systm.h> ! 60: #include <sys/kernel.h> ! 61: #include <sys/malloc.h> ! 62: #include <sys/mbuf.h> ! 63: #include <sys/socket.h> ! 64: #include <sys/sockio.h> ! 65: #include <sys/sysctl.h> ! 66: ! 67: #include <net/if.h> ! 68: #include <net/netisr.h> ! 69: #include <net/route.h> ! 70: #include <net/if_llc.h> ! 71: #include <net/if_dl.h> ! 72: #include <net/if_types.h> ! 73: #include <net/ndrv.h> ! 74: ! 75: #if INET ! 76: #include <netinet/in.h> ! 77: #include <netinet/in_var.h> ! 78: #include <netinet/if_ether.h> ! 79: #include <netinet/in_systm.h> ! 80: #include <netinet/ip.h> ! 81: #endif ! 82: ! 83: ! 84: #include <sys/socketvar.h> ! 85: #include <net/if_blue.h> ! 86: ! 87: #include <net/dlil.h> ! 88: ! 89: ! 90: #if LLC && CCITT ! 91: extern struct ifqueue pkintrq; ! 92: #endif ! 93: ! 94: /* General stuff from if_ethersubr.c - may not need some of it */ ! 95: ! 96: #include <netat/at_pat.h> ! 97: #if NETAT ! 98: extern struct ifqueue atalkintrq; ! 99: #endif ! 100: ! 101: ! 102: #if BRIDGE ! 103: #include <net/bridge.h> ! 104: #endif ! 105: ! 106: /* #include "vlan.h" */ ! 107: #if NVLAN > 0 ! 108: #include <net/if_vlan_var.h> ! 109: #endif /* NVLAN > 0 */ ! 110: ! 111: ! 112: extern struct ifnet_blue *blue_if; ! 113: extern struct mbuf *splitter_input(struct mbuf *, struct ifnet *); ! 114: ! 115: static u_long lo_dlt = 0; ! 116: static ivedonethis = 0; ! 117: static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, ! 118: struct sockaddr *)); ! 119: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ! 120: ! 121: #define IFP2AC(IFP) ((struct arpcom *)IFP) ! 122: ! 123: /* This stuff is new */ ! 124: ! 125: #define DB_HEADER_SIZE 20 ! 126: struct en_desc { ! 127: short total_len; ! 128: u_short ethertype; ! 129: u_long dl_tag; ! 130: struct ifnet *ifp; ! 131: struct if_proto *proto; ! 132: u_long proto_id_length; ! 133: u_long proto_id_data[8]; /* probably less - proto-id and bitmasks */ ! 134: }; ! 135: ! 136: #define LITMUS_SIZE 16 ! 137: #define ETHER_DESC_BLK_SIZE 50 ! 138: #define MAX_INTERFACES 50 ! 139: ! 140: /* ! 141: * Statics for demux module ! 142: */ ! 143: ! 144: struct ether_desc_blk_str { ! 145: u_long n_blocks; ! 146: u_long *block_ptr; ! 147: }; ! 148: ! 149: static struct ether_desc_blk_str ether_desc_blk[MAX_INTERFACES]; ! 150: static u_long litmus_mask[LITMUS_SIZE]; ! 151: static u_long litmus_length = 0; ! 152: ! 153: ! 154: /* ! 155: * Temp static for protocol registration XXX ! 156: */ ! 157: ! 158: #define MAX_EN_COUNT 30 ! 159: ! 160: static struct if_proto *en_array[MAX_EN_COUNT]; ! 161: ! 162: /* ! 163: * This could be done below in-line with heavy casting, but the pointer arithmetic is ! 164: * prone to error. ! 165: */ ! 166: ! 167: static ! 168: int desc_in_bounds(block, current_ptr, offset_length) ! 169: u_int block; ! 170: char *current_ptr; ! 171: u_long offset_length; ! 172: { ! 173: u_long end_of_block; ! 174: u_long current_ptr_tmp; ! 175: ! 176: current_ptr_tmp = (u_long) current_ptr; ! 177: end_of_block = (u_long) ether_desc_blk[block].block_ptr; ! 178: end_of_block += (ETHER_DESC_BLK_SIZE * ether_desc_blk[block].n_blocks); ! 179: if ((current_ptr_tmp + offset_length) < end_of_block) ! 180: return 1; ! 181: else ! 182: return 0; ! 183: } ! 184: ! 185: ! 186: /* ! 187: * Release all descriptor entries owned by this dl_tag (there may be several). ! 188: * Setting the dl_tag to 0 releases the entry. Eventually we should compact-out ! 189: * the unused entries. ! 190: */ ! 191: static ! 192: int ether_del_proto(struct if_proto *proto, u_long dl_tag) ! 193: { ! 194: char *current_ptr = (char *) ether_desc_blk[proto->ifp->family_cookie].block_ptr; ! 195: struct en_desc *ed; ! 196: int i; ! 197: int found = 0; ! 198: ! 199: ed = (struct en_desc *) current_ptr; ! 200: ! 201: while(ed->total_len) { ! 202: if (ed->dl_tag == dl_tag) { ! 203: found = 1; ! 204: ed->dl_tag = 0; ! 205: } ! 206: ! 207: current_ptr += ed->total_len; ! 208: ed = (struct en_desc *) current_ptr; ! 209: } ! 210: ! 211: if (found) { ! 212: for (i=0; i < MAX_EN_COUNT; i++) ! 213: if (en_array[i] == proto) { ! 214: en_array[i] = 0; ! 215: break; ! 216: } ! 217: ! 218: return 0; ! 219: } ! 220: else ! 221: return ENOENT; ! 222: } ! 223: ! 224: ! 225: ! 226: static ! 227: int ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag) ! 228: { ! 229: char *current_ptr; ! 230: struct dlil_demux_desc *desc; ! 231: u_long id_length; /* IN LONGWORDS!!! */ ! 232: struct en_desc *ed; ! 233: u_long *bitmask; ! 234: u_long *proto_id; ! 235: int i; ! 236: short total_length; ! 237: u_long block_count; ! 238: u_long *tmp; ! 239: ! 240: for (i=0; i < MAX_EN_COUNT; i++) ! 241: if (en_array[i] == 0) { ! 242: en_array[i] = proto; ! 243: break; ! 244: } ! 245: ! 246: if (i == MAX_EN_COUNT) { ! 247: printf("WARNING: ether_add_proto -- Too many attachments\n"); ! 248: return ENOMEM; ! 249: } ! 250: ! 251: TAILQ_FOREACH(desc, desc_head, next) { ! 252: switch (desc->type) ! 253: { ! 254: case DLIL_DESC_RAW: ! 255: id_length = desc->variants.bitmask.proto_id_length; ! 256: break; ! 257: ! 258: case DLIL_DESC_802_2: ! 259: id_length = 1; ! 260: break; ! 261: ! 262: case DLIL_DESC_802_2_SNAP: ! 263: id_length = 2; ! 264: break; ! 265: ! 266: default: ! 267: return EINVAL; ! 268: } ! 269: ! 270: restart: ! 271: block_count = ether_desc_blk[proto->ifp->family_cookie].n_blocks; ! 272: current_ptr = (char *) ether_desc_blk[proto->ifp->family_cookie].block_ptr; ! 273: ed = (struct en_desc *) current_ptr; ! 274: total_length = ((id_length << 2) * 2) + DB_HEADER_SIZE; ! 275: ! 276: while ((ed->total_len) && (desc_in_bounds(proto->ifp->family_cookie, ! 277: current_ptr, total_length))) { ! 278: if ((ed->dl_tag == 0) && (total_length <= ed->total_len)) ! 279: break; ! 280: else ! 281: current_ptr += *(short *)current_ptr; ! 282: ! 283: ed = (struct en_desc *) current_ptr; ! 284: } ! 285: ! 286: if (!desc_in_bounds(proto->ifp->family_cookie, current_ptr, total_length)) { ! 287: ! 288: tmp = _MALLOC((ETHER_DESC_BLK_SIZE * (block_count + 1)), ! 289: M_IFADDR, M_NOWAIT); ! 290: if (tmp == 0) { ! 291: /* ! 292: * Remove any previous descriptors set in the call. ! 293: */ ! 294: ether_del_proto(proto, dl_tag); ! 295: return ENOMEM; ! 296: } ! 297: ! 298: bzero(tmp, ETHER_DESC_BLK_SIZE * (block_count + 1)); ! 299: bcopy(ether_desc_blk[proto->ifp->family_cookie].block_ptr, ! 300: tmp, (ETHER_DESC_BLK_SIZE * block_count)); ! 301: FREE(ether_desc_blk[proto->ifp->family_cookie].block_ptr, M_IFADDR); ! 302: ether_desc_blk[proto->ifp->family_cookie].n_blocks = block_count + 1; ! 303: ether_desc_blk[proto->ifp->family_cookie].block_ptr = tmp; ! 304: goto restart; ! 305: } ! 306: ! 307: if (ed->total_len == 0) ! 308: ed->total_len = total_length; ! 309: ed->ethertype = *((u_short *) desc->native_type); ! 310: ! 311: ed->dl_tag = dl_tag; ! 312: ed->proto = proto; ! 313: ed->proto_id_length = id_length; ! 314: ed->ifp = proto->ifp; ! 315: ! 316: switch (desc->type) ! 317: { ! 318: case DLIL_DESC_RAW: ! 319: bcopy(desc->variants.bitmask.proto_id, &ed->proto_id_data[0], (id_length << 2) ); ! 320: bcopy(desc->variants.bitmask.proto_id_mask, &ed->proto_id_data[id_length], ! 321: (id_length << 2)); ! 322: break; ! 323: ! 324: case DLIL_DESC_802_2: ! 325: ed->proto_id_data[0] = 0; ! 326: bcopy(&desc->variants.desc_802_2, &ed->proto_id_data[0], 3); ! 327: ed->proto_id_data[1] = 0xffffff00; ! 328: break; ! 329: ! 330: case DLIL_DESC_802_2_SNAP: ! 331: /* XXX Add verification of fixed values here */ ! 332: ! 333: ed->proto_id_data[0] = 0; ! 334: ed->proto_id_data[1] = 0; ! 335: bcopy(&desc->variants.desc_802_2_SNAP, &ed->proto_id_data[0], 8); ! 336: ed->proto_id_data[2] = 0xffffffff; ! 337: ed->proto_id_data[3] = 0xffffffff;; ! 338: break; ! 339: } ! 340: ! 341: if (id_length) { ! 342: proto_id = (u_long *) &ed->proto_id_data[0]; ! 343: bitmask = (u_long *) &ed->proto_id_data[id_length]; ! 344: for (i=0; i < (id_length); i++) { ! 345: litmus_mask[i] &= bitmask[i]; ! 346: litmus_mask[i] &= proto_id[i]; ! 347: } ! 348: if (id_length > litmus_length) ! 349: litmus_length = id_length; ! 350: } ! 351: } ! 352: ! 353: return 0; ! 354: } ! 355: ! 356: ! 357: static ! 358: int ether_shutdown() ! 359: { ! 360: return 0; ! 361: } ! 362: ! 363: ! 364: ! 365: ! 366: /* ! 367: * Process a received Ethernet packet; ! 368: * the packet is in the mbuf chain m without ! 369: * the ether header, which is provided separately. ! 370: */ ! 371: int ! 372: new_ether_input(m, frame_header, ifp, dl_tag, sync_ok) ! 373: struct mbuf *m; ! 374: char *frame_header; ! 375: struct ifnet *ifp; ! 376: u_long dl_tag; ! 377: int sync_ok; ! 378: ! 379: { ! 380: register struct ether_header *eh = (struct ether_header *) frame_header; ! 381: register struct ifqueue *inq=0; ! 382: u_short ether_type; ! 383: int s; ! 384: u_int16_t ptype = -1; ! 385: unsigned char buf[18]; ! 386: ! 387: #if ISO || LLC || NETAT ! 388: register struct llc *l; ! 389: #endif ! 390: ! 391: ! 392: #if DLIL_BLUEBOX ! 393: ! 394: /* ! 395: * Y-adapter input processing: ! 396: * - Don't split if coming from a dummy if ! 397: * - If coming from a real if, if splitting enabled, ! 398: * then filter the incoming packet ! 399: */ ! 400: if (ifp != (struct ifnet *)blue_if) ! 401: { /* Is splitter turned on? */ ! 402: if (ifp->if_flags&IFF_SPLITTER) ! 403: { m->m_data -= sizeof(struct ether_header); ! 404: m->m_len += sizeof (struct ether_header); ! 405: m->m_pkthdr.len += sizeof(struct ether_header); ! 406: /* ! 407: * Check to see if destined for BlueBox or Rhapsody ! 408: * If NULL return, mbuf's been consumed by the BlueBox. ! 409: * Otherwise, send on to Rhapsody ! 410: */ ! 411: if ((m = splitter_input(m, ifp)) == NULL) ! 412: return EJUSTRETURN; ! 413: m->m_data += sizeof(struct ether_header); ! 414: m->m_len -= sizeof (struct ether_header); ! 415: m->m_pkthdr.len -= sizeof(struct ether_header); ! 416: } ! 417: } else ! 418: { /* Get the "real" IF */ ! 419: ifp = ((struct ndrv_cb *)(blue_if->ifb_so->so_pcb))->nd_if; ! 420: m->m_pkthdr.rcvif = ifp; ! 421: blue_if->pkts_looped_b2r++; ! 422: } ! 423: ! 424: #endif ! 425: if ((ifp->if_flags & IFF_UP) == 0) { ! 426: m_freem(m); ! 427: return EJUSTRETURN; ! 428: } ! 429: ! 430: ifp->if_lastchange = time; ! 431: ! 432: if (eh->ether_dhost[0] & 1) { ! 433: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, ! 434: sizeof(etherbroadcastaddr)) == 0) ! 435: m->m_flags |= M_BCAST; ! 436: else ! 437: m->m_flags |= M_MCAST; ! 438: } ! 439: if (m->m_flags & (M_BCAST|M_MCAST)) ! 440: ifp->if_imcasts++; ! 441: ! 442: ether_type = ntohs(eh->ether_type); ! 443: ! 444: #if NVLAN > 0 ! 445: if (ether_type == vlan_proto) { ! 446: if (vlan_input(eh, m) < 0) ! 447: ifp->if_data.ifi_noproto++; ! 448: return EJUSTRETURN; ! 449: } ! 450: #endif /* NVLAN > 0 */ ! 451: ! 452: switch (ether_type) { ! 453: #if INET ! 454: case ETHERTYPE_IP: ! 455: if (ipflow_fastforward(m)) ! 456: return EJUSTRETURN; ! 457: ptype = mtod(m, struct ip *)->ip_p; ! 458: if ((sync_ok == 0) || ! 459: (ptype != IPPROTO_TCP && ptype != IPPROTO_UDP)) { ! 460: schednetisr(NETISR_IP); ! 461: } ! 462: ! 463: inq = &ipintrq; ! 464: break; ! 465: ! 466: case ETHERTYPE_ARP: ! 467: schednetisr(NETISR_ARP); ! 468: inq = &arpintrq; ! 469: break; ! 470: #endif ! 471: ! 472: default: { ! 473: #if NETAT ! 474: if (ether_type > ETHERMTU) ! 475: return ENOENT; ! 476: l = mtod(m, struct llc *); ! 477: switch (l->llc_dsap) { ! 478: case LLC_SNAP_LSAP: ! 479: ! 480: /* Temporary hack: check for AppleTalk and AARP packets */ ! 481: /* WARNING we're checking only on the "ether_type" (the 2 bytes ! 482: * of the SNAP header. This shouldn't be a big deal, ! 483: * AppleTalk pat_input is making sure we have the right packets ! 484: * because it needs to discrimante AARP from EtherTalk packets. ! 485: */ ! 486: ! 487: if (l->llc_ssap == LLC_SNAP_LSAP && ! 488: l->llc_un.type_snap.control == 0x03) { ! 489: ! 490: #ifdef APPLETALK_DEBUG ! 491: printf("new_ether_input: SNAP Cntrol type=0x%x Src=%s\n", ! 492: l->llc_un.type_snap.ether_type, ! 493: ether_sprintf(buf, &eh->ether_shost)); ! 494: printf(" Dst=%s\n", ! 495: ether_sprintf(buf, &eh->ether_dhost)); ! 496: #endif /* APPLETALK_DEBUG */ ! 497: ! 498: if ((l->llc_un.type_snap.ether_type == 0x809B) || ! 499: (l->llc_un.type_snap.ether_type == 0x80F3)) { ! 500: ! 501: ! 502: /* ! 503: * note: for AppleTalk we need to pass the enet header of the ! 504: * packet up stack. To do so, we made sure in that the FULL packet ! 505: * is copied in the mbuf by the mace driver, and only the m_data and ! 506: * length have been shifted to make IP and the other guys happy. ! 507: */ ! 508: ! 509: m->m_data -= sizeof(*eh); ! 510: m->m_len += sizeof(*eh); ! 511: m->m_pkthdr.len += sizeof(*eh); ! 512: #ifdef APPLETALK_DEBUG ! 513: l == (struct llc *)(eh+1); ! 514: if (l->llc_un.type_snap.ether_type == 0x80F3) { ! 515: kprintf("new_ether_input: RCV AppleTalk type=0x%x Src=%s\n", ! 516: l->llc_un.type_snap.ether_type, ! 517: ether_sprintf(buf, &eh->ether_shost)); ! 518: kprintf(" Dst=%s\n", ! 519: ether_sprintf(buf, &eh->ether_dhost)); ! 520: } ! 521: #endif /* APPLETALK_DEBUG */ ! 522: schednetisr(NETISR_APPLETALK); ! 523: inq = &atalkintrq ; ! 524: ! 525: break; ! 526: } ! 527: } ! 528: ! 529: break; ! 530: ! 531: ! 532: default: ! 533: return ENOENT; ! 534: } ! 535: ! 536: #else /*NETAT*/ ! 537: return ENOENT; ! 538: #endif /* NETAT */ ! 539: ! 540: } ! 541: } ! 542: ! 543: if (inq == 0) ! 544: return ENOENT; ! 545: ! 546: s = splimp(); ! 547: if (IF_QFULL(inq)) { ! 548: IF_DROP(inq); ! 549: m_freem(m); ! 550: splx(s); ! 551: return EJUSTRETURN; ! 552: } else ! 553: IF_ENQUEUE(inq, m); ! 554: splx(s); ! 555: ! 556: if ((sync_ok) && ! 557: (ptype == IPPROTO_TCP || ptype == IPPROTO_UDP)) { ! 558: extern void ipintr(void); ! 559: ! 560: s = splnet(); ! 561: ipintr(); ! 562: splx(s); ! 563: } ! 564: ! 565: return 0; ! 566: } ! 567: ! 568: ! 569: ! 570: ! 571: int ether_demux(ifp, m, frame_header, proto) ! 572: struct ifnet *ifp; ! 573: struct mbuf *m; ! 574: char *frame_header; ! 575: struct if_proto **proto; ! 576: ! 577: { ! 578: register struct ether_header *eh = (struct ether_header *)frame_header; ! 579: u_short ether_type; ! 580: char *current_ptr = (char *) ether_desc_blk[ifp->family_cookie].block_ptr; ! 581: struct dlil_demux_desc *desc; ! 582: register u_long temp; ! 583: u_long *data; ! 584: register struct if_proto *ifproto; ! 585: u_long i; ! 586: struct en_desc *ed; ! 587: ! 588: ! 589: if (eh->ether_dhost[0] & 1) { ! 590: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, ! 591: sizeof(etherbroadcastaddr)) == 0) ! 592: m->m_flags |= M_BCAST; ! 593: else ! 594: m->m_flags |= M_MCAST; ! 595: } ! 596: ! 597: ether_type = ntohs(eh->ether_type); ! 598: ! 599: /* ! 600: * Search through the connected protocols for a match. ! 601: */ ! 602: ! 603: ! 604: data = mtod(m, u_long *); ! 605: ed = (struct en_desc *) current_ptr; ! 606: while (desc_in_bounds(ifp->family_cookie, current_ptr, DB_HEADER_SIZE)) { ! 607: if (ed->total_len == 0) ! 608: break; ! 609: ! 610: if ((ed->dl_tag != 0) && (ed->ifp == ifp) && ! 611: ((ed->ethertype == ntohs(eh->ether_type)) || (ed->ethertype == 0))) { ! 612: if (ed->proto_id_length) { ! 613: for (i=0; i < (ed->proto_id_length); i++) { ! 614: temp = ntohs(data[i]) & ed->proto_id_data[ed->proto_id_length + i]; ! 615: if ((temp ^ ed->proto_id_data[i])) ! 616: break; ! 617: } ! 618: ! 619: if (i >= (ed->proto_id_length)) { ! 620: *proto = ed->proto; ! 621: return 0; ! 622: } ! 623: } ! 624: else { ! 625: *proto = ed->proto; ! 626: return 0; ! 627: } ! 628: } ! 629: current_ptr += ed->total_len; ! 630: ed = (struct en_desc *) current_ptr; ! 631: } ! 632: ! 633: /* ! 634: kprintf("ether_demux - No match for <%x><%x><%x><%x><%x><%x><%x<%x>\n", ! 635: eh->ether_type,data[0], data[1], data[2], data[3], data[4],data[5],data[6]); ! 636: */ ! 637: ! 638: return ENOENT; ! 639: } ! 640: ! 641: ! 642: ! 643: /* ! 644: * Ethernet output routine. ! 645: * Encapsulate a packet of type family for the local net. ! 646: * Use trailer local net encapsulation if enough data in first ! 647: * packet leaves a multiple of 512 bytes of data in remainder. ! 648: * Assumes that ifp is actually pointer to arpcom structure. ! 649: */ ! 650: int ! 651: ether_frameout(ifp, m, ndest, edst, ether_type) ! 652: register struct ifnet *ifp; ! 653: struct mbuf **m; ! 654: struct sockaddr *ndest; ! 655: char *edst; ! 656: char *ether_type; ! 657: { ! 658: register struct ether_header *eh; ! 659: int hlen; /* link layer header lenght */ ! 660: struct arpcom *ac = IFP2AC(ifp); ! 661: ! 662: ! 663: hlen = ETHER_HDR_LEN; ! 664: ! 665: /* ! 666: * If a simplex interface, and the packet is being sent to our ! 667: * Ethernet address or a broadcast address, loopback a copy. ! 668: * XXX To make a simplex device behave exactly like a duplex ! 669: * device, we should copy in the case of sending to our own ! 670: * ethernet address (thus letting the original actually appear ! 671: * on the wire). However, we don't do that here for security ! 672: * reasons and compatibility with the original behavior. ! 673: */ ! 674: if ((ifp->if_flags & IFF_SIMPLEX) && ! 675: ((*m)->m_flags & M_LOOP)) { ! 676: if (lo_dlt == 0) ! 677: dlil_find_dltag(APPLE_IF_FAM_LOOPBACK, 0, PF_INET, &lo_dlt); ! 678: ! 679: if (lo_dlt) { ! 680: if ((*m)->m_flags & M_BCAST) { ! 681: struct mbuf *n = m_copy(*m, 0, (int)M_COPYALL); ! 682: dlil_output(lo_dlt, n, 0, ndest, 0); ! 683: } ! 684: else ! 685: { ! 686: if (bcmp(edst, ac->ac_enaddr, ETHER_ADDR_LEN) == 0) { ! 687: dlil_output(lo_dlt, *m, 0, ndest, 0); ! 688: return EJUSTRETURN; ! 689: } ! 690: } ! 691: } ! 692: } ! 693: ! 694: ! 695: /* ! 696: * Add local net header. If no space in first mbuf, ! 697: * allocate another. ! 698: */ ! 699: M_PREPEND(*m, sizeof (struct ether_header), M_DONTWAIT); ! 700: if (*m == 0) { ! 701: return (EJUSTRETURN); ! 702: } ! 703: ! 704: ! 705: eh = mtod(*m, struct ether_header *); ! 706: (void)memcpy(&eh->ether_type, ether_type, ! 707: sizeof(eh->ether_type)); ! 708: (void)memcpy(eh->ether_dhost, edst, 6); ! 709: (void)memcpy(eh->ether_shost, ac->ac_enaddr, ! 710: sizeof(eh->ether_shost)); ! 711: ! 712: #if DLIL_BLUEBOX ! 713: /* ! 714: * We're already to send. Let's check for the blue box... ! 715: */ ! 716: if (ifp->if_flags&IFF_SPLITTER) ! 717: { ! 718: (*m)->m_flags |= 0x10; ! 719: if ((*m = splitter_input(*m, ifp)) == NULL) ! 720: return EJUSTRETURN; ! 721: else ! 722: return (0); ! 723: } ! 724: else ! 725: #endif ! 726: return 0; ! 727: } ! 728: ! 729: ! 730: static ! 731: int ether_add_if(struct ifnet *ifp) ! 732: { ! 733: u_long i; ! 734: ! 735: ifp->if_framer = ether_frameout; ! 736: ifp->if_demux = ether_demux; ! 737: ! 738: for (i=0; i < MAX_INTERFACES; i++) ! 739: if (ether_desc_blk[i].n_blocks == 0) ! 740: break; ! 741: ! 742: if (i == MAX_INTERFACES) ! 743: return EOVERFLOW; ! 744: ! 745: ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_NOWAIT); ! 746: if (ether_desc_blk[i].block_ptr == 0) ! 747: return ENOMEM; ! 748: ! 749: ether_desc_blk[i].n_blocks = 1; ! 750: bzero(ether_desc_blk[i].block_ptr, ETHER_DESC_BLK_SIZE); ! 751: ! 752: ifp->family_cookie = i; ! 753: ! 754: return 0; ! 755: } ! 756: ! 757: static ! 758: int ether_del_if(struct ifnet *ifp) ! 759: { ! 760: if ((ifp->family_cookie < MAX_INTERFACES) && ! 761: (ether_desc_blk[ifp->family_cookie].n_blocks)) { ! 762: FREE(ether_desc_blk[ifp->family_cookie].block_ptr, M_IFADDR); ! 763: ether_desc_blk[ifp->family_cookie].n_blocks = 0; ! 764: return 0; ! 765: } ! 766: else ! 767: return ENOENT; ! 768: } ! 769: ! 770: ! 771: ! 772: ! 773: int ! 774: ether_pre_output(ifp, m0, dst_netaddr, route, type, edst, dl_tag ) ! 775: struct ifnet *ifp; ! 776: struct mbuf **m0; ! 777: struct sockaddr *dst_netaddr; ! 778: caddr_t route; ! 779: char *type; ! 780: char *edst; ! 781: u_long dl_tag; ! 782: { ! 783: struct rtentry *rt0 = (struct rtentry *) route; ! 784: int s; ! 785: register struct mbuf *m = *m0; ! 786: register struct rtentry *rt; ! 787: register struct ether_header *eh; ! 788: int off, len = m->m_pkthdr.len; ! 789: int hlen; /* link layer header lenght */ ! 790: struct arpcom *ac = IFP2AC(ifp); ! 791: ! 792: ! 793: ! 794: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 795: return ENETDOWN; ! 796: ! 797: rt = rt0; ! 798: if (rt) { ! 799: if ((rt->rt_flags & RTF_UP) == 0) { ! 800: rt0 = rt = rtalloc1(dst_netaddr, 1, 0UL); ! 801: if (rt0) ! 802: rt->rt_refcnt--; ! 803: else ! 804: return EHOSTUNREACH; ! 805: } ! 806: ! 807: if (rt->rt_flags & RTF_GATEWAY) { ! 808: if (rt->rt_gwroute == 0) ! 809: goto lookup; ! 810: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { ! 811: rtfree(rt); rt = rt0; ! 812: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, ! 813: 0UL); ! 814: if ((rt = rt->rt_gwroute) == 0) ! 815: return (EHOSTUNREACH); ! 816: } ! 817: } ! 818: ! 819: ! 820: if (rt->rt_flags & RTF_REJECT) ! 821: if (rt->rt_rmx.rmx_expire == 0 || ! 822: time_second < rt->rt_rmx.rmx_expire) ! 823: return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); ! 824: } ! 825: ! 826: hlen = ETHER_HDR_LEN; ! 827: ! 828: /* ! 829: * Tell ether_frameout it's ok to loop packet unless negated below. ! 830: */ ! 831: m->m_flags |= M_LOOP; ! 832: ! 833: switch (dst_netaddr->sa_family) { ! 834: ! 835: #if INET ! 836: case AF_INET: ! 837: if (!arpresolve(ac, rt, m, dst_netaddr, edst, rt0)) ! 838: return (EJUSTRETURN); /* if not yet resolved */ ! 839: off = m->m_pkthdr.len - m->m_len; ! 840: *(u_short *)type = htons(ETHERTYPE_IP); ! 841: break; ! 842: #endif ! 843: ! 844: case AF_UNSPEC: ! 845: m->m_flags &= ~M_LOOP; ! 846: eh = (struct ether_header *)dst_netaddr->sa_data; ! 847: (void)memcpy(edst, eh->ether_dhost, 6); ! 848: *(u_short *)type = eh->ether_type; ! 849: break; ! 850: ! 851: #if NETAT ! 852: case AF_APPLETALK: ! 853: { ! 854: eh = (struct ether_header *)dst_netaddr->sa_data; ! 855: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, 6); ! 856: ! 857: *(u_short *)type = m->m_pkthdr.len; ! 858: } ! 859: break; ! 860: ! 861: #endif /* NETAT */ ! 862: ! 863: default: ! 864: kprintf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, ! 865: dst_netaddr->sa_family); ! 866: ! 867: return EAFNOSUPPORT; ! 868: } ! 869: ! 870: return (0); ! 871: } ! 872: ! 873: ! 874: ! 875: ! 876: ! 877: int ! 878: ether_ioctl(dl_tag, ifp, command, data) ! 879: u_long dl_tag; ! 880: struct ifnet *ifp; ! 881: int command; ! 882: caddr_t data; ! 883: { ! 884: struct ifaddr *ifa = (struct ifaddr *) data; ! 885: struct ifreq *ifr = (struct ifreq *) data; ! 886: int error = 0; ! 887: boolean_t funnel_state; ! 888: ! 889: funnel_state = thread_set_funneled(TRUE); ! 890: ! 891: switch (command) { ! 892: case SIOCSIFADDR: ! 893: ifp->if_flags |= IFF_UP; ! 894: ! 895: switch (ifa->ifa_addr->sa_family) { ! 896: ! 897: case AF_INET: ! 898: ! 899: if (ifp->if_init) ! 900: ifp->if_init(ifp->if_softc); /* before arpwhohas */ ! 901: ! 902: ! 903: arp_ifinit(IFP2AC(ifp), ifa); ! 904: ! 905: break; ! 906: ! 907: default: ! 908: break; ! 909: } ! 910: ! 911: break; ! 912: ! 913: case SIOCGIFADDR: ! 914: { ! 915: struct sockaddr *sa; ! 916: ! 917: sa = (struct sockaddr *) & ifr->ifr_data; ! 918: bcopy(IFP2AC(ifp)->ac_enaddr, ! 919: (caddr_t) sa->sa_data, ETHER_ADDR_LEN); ! 920: } ! 921: break; ! 922: ! 923: case SIOCSIFMTU: ! 924: /* ! 925: * Set the interface MTU. ! 926: */ ! 927: if (ifr->ifr_mtu > ETHERMTU) { ! 928: error = EINVAL; ! 929: } else { ! 930: ifp->if_mtu = ifr->ifr_mtu; ! 931: } ! 932: break; ! 933: } ! 934: ! 935: (void) thread_set_funneled(funnel_state); ! 936: ! 937: return (error); ! 938: } ! 939: ! 940: ! 941: ! 942: ! 943: /* ! 944: * Y-adapter filter check ! 945: * The rules here: ! 946: * For Rhap: return 1 ! 947: * For Both: return 0 ! 948: * Not for Rhap: return -1 ! 949: * Multicast/Broadcast => For Both ! 950: * Atalk address registered ! 951: * filter matches => For Rhap else Not For Rhap ! 952: * IP address registered ! 953: * filter matches => For Rhap else Not For Rhap ! 954: * For Rhap ! 955: * Note this is *not* a general filter mechanism in that we know ! 956: * what we *could* be looking for. ! 957: * WARNING: this is a big-endian routine. ! 958: * Note: ARP and AARP packets are implicitly accepted for "both" ! 959: */ ! 960: int ! 961: Filter_check(struct mbuf **m0) ! 962: { register struct BlueFilter *bf; ! 963: register unsigned char *p; ! 964: register unsigned short *s; ! 965: register unsigned long *l; ! 966: int total, flags; ! 967: struct mbuf *m; ! 968: extern struct mbuf *m_pullup(struct mbuf *, int); ! 969: extern void kprintf( const char *, ...); ! 970: #define FILTER_LEN 32 ! 971: ! 972: m = *m0; ! 973: flags = m->m_flags; ! 974: if (FILTER_LEN > m->m_pkthdr.len) ! 975: return(1); ! 976: while ((FILTER_LEN > m->m_len) && m->m_next) { ! 977: total = m->m_len + (m->m_next)->m_len; ! 978: if ((m = m_pullup(m, min(FILTER_LEN, total))) == 0) ! 979: return(-1); ! 980: } ! 981: *m0 = m; ! 982: ! 983: p = mtod(m, unsigned char *); /* Point to destination media addr */ ! 984: if (p[0] & 0x01) /* Multicast/broadcast */ ! 985: return(0); ! 986: s = (unsigned short *)p; ! 987: bf = &RhapFilter[BFS_ATALK]; ! 988: #if 0 ! 989: kprintf("!PKT: %x, %x, %x\n", s[6], s[7], s[8]); ! 990: #endif ! 991: ! 992: if (bf->BF_flags) /* Filtering Appletalk */ ! 993: { ! 994: l = (unsigned long *)&s[8]; ! 995: #if 0 ! 996: kprintf("!AT: %x, %x, %x, %x, %x, %x\n", s[6], s[7], ! 997: *l, s[10], s[13], p[30]); ! 998: #endif ! 999: if (s[6] <= ETHERMTU) ! 1000: { if (s[7] == 0xaaaa) /* Could be Atalk */ ! 1001: { /* Verify SNAP header */ ! 1002: if (*l == 0x03080007 && s[10] == 0x809b) ! 1003: { if (s[13] == bf->BF_address && ! 1004: p[30] == bf->BF_node) ! 1005: return(1); ! 1006: } else if (*l == 0x03000000 && s[10] == 0x80f3) ! 1007: /* AARP pkts aren't net-addressed */ ! 1008: return(0); ! 1009: return(0); ! 1010: } else /* Not for us? */ ! 1011: return(0); ! 1012: } /* Fall through */ ! 1013: } /* Fall through */ ! 1014: bf++; /* Look for IP next */ ! 1015: if (bf->BF_flags) /* Filtering IP */ ! 1016: { ! 1017: l = (unsigned long *)&s[15]; ! 1018: #if 0 ! 1019: kprintf("!IP: %x, %x\n", s[6], *l); ! 1020: #endif ! 1021: if (s[6] > ETHERMTU) ! 1022: { if (s[6] == 0x800) /* Is IP */ ! 1023: { /* Verify IP address */ ! 1024: if (*l == bf->BF_address) ! 1025: return(1); ! 1026: else /* Not for us */ ! 1027: return(0); ! 1028: } else if (s[6] == 0x806) ! 1029: /* ARP pkts aren't net-addressed */ ! 1030: return(0); ! 1031: } ! 1032: } ! 1033: return(0); /* No filters => Accept */ ! 1034: } ! 1035: ! 1036: ! 1037: ! 1038: int ether_family_init() ! 1039: { ! 1040: ! 1041: int i; ! 1042: ! 1043: if (ivedonethis) ! 1044: return 0; ! 1045: ! 1046: ivedonethis = 1; ! 1047: ! 1048: ! 1049: if (dlil_reg_if_modules(APPLE_IF_FAM_ETHERNET, ether_add_if, ether_del_if, ! 1050: ether_add_proto, ether_del_proto, ! 1051: ether_shutdown)) { ! 1052: printf("WARNING: ether_family_init -- Can't register if family modules\n"); ! 1053: return EIO; ! 1054: } ! 1055: ! 1056: for (i=0; i < (LITMUS_SIZE/4); i++) ! 1057: litmus_mask[i] = 0xffffffff; ! 1058: ! 1059: for (i=0; i < MAX_EN_COUNT; i++) ! 1060: en_array[i] = (struct if_proto *) 0; ! 1061: ! 1062: for (i=0; i < MAX_INTERFACES; i++) ! 1063: ether_desc_blk[i].n_blocks = 0; ! 1064: ! 1065: return 0; ! 1066: } ! 1067: ! 1068: ! 1069: ! 1070: u_long ether_attach_inet(struct ifnet *ifp) ! 1071: { ! 1072: struct dlil_proto_reg_str reg; ! 1073: struct dlil_demux_desc desc; ! 1074: struct dlil_demux_desc desc2; ! 1075: u_long ip_dl_tag=0; ! 1076: u_short en_native=ETHERTYPE_IP; ! 1077: u_short arp_native=ETHERTYPE_ARP; ! 1078: int stat; ! 1079: int i; ! 1080: ! 1081: ! 1082: for (i=0; i < MAX_EN_COUNT; i++) ! 1083: if ((en_array[i]) && (en_array[i]->ifp == ifp) && ! 1084: (en_array[i]->protocol_family == PF_INET)) { ! 1085: return en_array[i]->dl_tag; ! 1086: } ! 1087: ! 1088: TAILQ_INIT(®.demux_desc_head); ! 1089: desc.type = DLIL_DESC_RAW; ! 1090: desc.variants.bitmask.proto_id_length = 0; ! 1091: desc.variants.bitmask.proto_id = 0; ! 1092: desc.variants.bitmask.proto_id_mask = 0; ! 1093: desc.native_type = (char *) &en_native; ! 1094: TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next); ! 1095: reg.interface_family = ifp->if_family; ! 1096: reg.unit_number = ifp->if_unit; ! 1097: reg.input = new_ether_input; ! 1098: reg.pre_output = ether_pre_output; ! 1099: reg.event = 0; ! 1100: reg.offer = 0; ! 1101: reg.ioctl = ether_ioctl; ! 1102: reg.default_proto = 1; ! 1103: reg.protocol_family = PF_INET; ! 1104: ! 1105: desc2 = desc; ! 1106: desc2.native_type = (char *) &arp_native; ! 1107: TAILQ_INSERT_TAIL(®.demux_desc_head, &desc2, next); ! 1108: ! 1109: stat = dlil_attach_protocol(®, &ip_dl_tag); ! 1110: if (stat) { ! 1111: printf("WARNING: ether_attach_inet can't attach ip to interface\n"); ! 1112: return stat; ! 1113: } ! 1114: ! 1115: return ip_dl_tag; ! 1116: } ! 1117: ! 1118: void ether_attach_at(struct ifnet *ifp, u_long *at_dl_tag, u_long *aarp_dl_tag) ! 1119: { ! 1120: struct dlil_proto_reg_str reg; ! 1121: struct dlil_demux_desc desc; ! 1122: struct dlil_demux_desc desc2; ! 1123: u_short native = 0; /* 802.2 frames use a length here */ ! 1124: int stat; ! 1125: ! 1126: TAILQ_INIT(®.demux_desc_head); ! 1127: desc.type = DLIL_DESC_802_2_SNAP; ! 1128: desc.variants.desc_802_2_SNAP.dsap = LLC_SNAP_LSAP; ! 1129: desc.variants.desc_802_2_SNAP.ssap = LLC_SNAP_LSAP; ! 1130: desc.variants.desc_802_2_SNAP.control_code = 0x03; ! 1131: desc.variants.desc_802_2_SNAP.org[0] = 0x08; ! 1132: desc.variants.desc_802_2_SNAP.org[1] = 0x00; ! 1133: desc.variants.desc_802_2_SNAP.org[2] = 0x07; ! 1134: desc.variants.desc_802_2_SNAP.protocol_type = 0x809B; ! 1135: desc.native_type = (char *) &native; ! 1136: TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next); ! 1137: reg.interface_family = ifp->if_family; ! 1138: reg.unit_number = ifp->if_unit; ! 1139: reg.input = new_ether_input; ! 1140: reg.pre_output = ether_pre_output; ! 1141: reg.event = 0; ! 1142: reg.offer = 0; ! 1143: reg.ioctl = ether_ioctl; ! 1144: reg.default_proto = 0; ! 1145: reg.protocol_family = PF_APPLETALK; ! 1146: ! 1147: desc2 = desc; ! 1148: desc2.variants.desc_802_2_SNAP.protocol_type = 0x80F3; ! 1149: desc2.variants.desc_802_2_SNAP.org[0] = 0; ! 1150: desc2.variants.desc_802_2_SNAP.org[1] = 0; ! 1151: desc2.variants.desc_802_2_SNAP.org[2] = 0; ! 1152: ! 1153: TAILQ_INSERT_TAIL(®.demux_desc_head, &desc2, next); ! 1154: ! 1155: stat = dlil_attach_protocol(®, at_dl_tag); ! 1156: if (stat) { ! 1157: printf("WARNING: ether_attach_at can't attach at to interface\n"); ! 1158: return; ! 1159: } ! 1160: ! 1161: *aarp_dl_tag = *at_dl_tag; ! 1162: ! 1163: } /* ether_attach_at */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.