|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1997, 1998 Apple Computer, Inc. All Rights Reserved */ ! 26: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 27: /* ! 28: * Copyright (c) 1982, 1989, 1993 ! 29: * The Regents of the University of California. All rights reserved. ! 30: * ! 31: * Redistribution and use in source and binary forms, with or without ! 32: * modification, are permitted provided that the following conditions ! 33: * are met: ! 34: * 1. Redistributions of source code must retain the above copyright ! 35: * notice, this list of conditions and the following disclaimer. ! 36: * 2. Redistributions in binary form must reproduce the above copyright ! 37: * notice, this list of conditions and the following disclaimer in the ! 38: * documentation and/or other materials provided with the distribution. ! 39: * 3. All advertising materials mentioning features or use of this software ! 40: * must display the following acknowledgement: ! 41: * This product includes software developed by the University of ! 42: * California, Berkeley and its contributors. ! 43: * 4. Neither the name of the University nor the names of its contributors ! 44: * may be used to endorse or promote products derived from this software ! 45: * without specific prior written permission. ! 46: * ! 47: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 48: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 49: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 50: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 51: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 52: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 53: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 54: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 55: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 56: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 57: * SUCH DAMAGE. ! 58: * ! 59: * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 ! 60: */ ! 61: ! 62: #include <sys/param.h> ! 63: #include <sys/systm.h> ! 64: #include <sys/kernel.h> ! 65: #include <sys/malloc.h> ! 66: #include <sys/mbuf.h> ! 67: #include <sys/protosw.h> ! 68: #include <sys/socket.h> ! 69: #include <sys/ioctl.h> ! 70: #include <sys/errno.h> ! 71: #include <sys/syslog.h> ! 72: ! 73: #include <machine/cpu.h> ! 74: ! 75: #include <net/if.h> ! 76: #include <net/netisr.h> ! 77: #include <net/route.h> ! 78: #include <net/if_llc.h> ! 79: #include <net/if_dl.h> ! 80: #include <net/if_types.h> ! 81: ! 82: #if INET ! 83: #include <netinet/in.h> ! 84: #include <netinet/in_var.h> ! 85: ! 86: #include <netinet/in_systm.h> ! 87: #include <netinet/ip.h> ! 88: ! 89: #endif ! 90: #include <netinet/if_ether.h> ! 91: ! 92: #if NS ! 93: #include <netns/ns.h> ! 94: #include <netns/ns_if.h> ! 95: #endif ! 96: ! 97: #if ISO ! 98: #include <netiso/argo_debug.h> ! 99: #include <netiso/iso.h> ! 100: #include <netiso/iso_var.h> ! 101: #include <netiso/iso_snpac.h> ! 102: #endif ! 103: ! 104: #if LLC ! 105: #include <netccitt/dll.h> ! 106: #include <netccitt/llc_var.h> ! 107: #endif ! 108: ! 109: #if defined(ppc) ! 110: #include <sys/socketvar.h> ! 111: #include <net/if_blue.h> ! 112: ! 113: struct BlueFilter RhapFilter[BFCount]; ! 114: int BFIx; /* 0 for Atalk; 1..9 for IP */ ! 115: #endif /* ppc */ ! 116: ! 117: #include <net/ndrv.h> ! 118: ! 119: #if defined(LLC) && defined(CCITT) ! 120: extern struct ifqueue pkintrq; ! 121: #endif ! 122: ! 123: #include <h/at_pat.h> ! 124: #if NETAT ! 125: extern struct ifqueue atalkintrq; ! 126: #endif ! 127: ! 128: #include <machine/spl.h> ! 129: ! 130: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ! 131: extern struct ifnet loif; ! 132: #define senderr(e) { error = (e); goto bad;} ! 133: ! 134: /* ! 135: * Ethernet output routine. ! 136: * Encapsulate a packet of type family for the local net. ! 137: * Use trailer local net encapsulation if enough data in first ! 138: * packet leaves a multiple of 512 bytes of data in remainder. ! 139: * Assumes that ifp is actually pointer to arpcom structure. ! 140: */ ! 141: int ! 142: ether_output(ifp, m0, dst, rt0) ! 143: register struct ifnet *ifp; ! 144: struct mbuf *m0; ! 145: struct sockaddr *dst; ! 146: struct rtentry *rt0; ! 147: { ! 148: u_int16_t etype; ! 149: int s, error = 0; ! 150: u_char edst[6]; ! 151: register struct mbuf *m = m0; ! 152: register struct rtentry *rt; ! 153: struct mbuf *mcopy = (struct mbuf *)0; ! 154: register struct ether_header *eh; ! 155: int off, len = m->m_pkthdr.len; ! 156: struct arpcom *ac = (struct arpcom *)ifp; ! 157: int ismulticast = 0; ! 158: extern void kprintf( const char *, ...); ! 159: extern struct mbuf *splitter_input(struct mbuf *, struct ifnet *); ! 160: ! 161: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 162: senderr(ENETDOWN); ! 163: ifp->if_lastchange = time; ! 164: if ((rt = rt0)) { ! 165: if ((rt->rt_flags & RTF_UP) == 0) { ! 166: if ((rt0 = rt = rtalloc1(dst, 1))) ! 167: rt->rt_refcnt--; ! 168: else ! 169: senderr(EHOSTUNREACH); ! 170: } ! 171: if (rt->rt_flags & RTF_GATEWAY) { ! 172: if (rt->rt_gwroute == 0) ! 173: goto lookup; ! 174: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { ! 175: rtfree(rt); rt = rt0; ! 176: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); ! 177: if ((rt = rt->rt_gwroute) == 0) ! 178: senderr(EHOSTUNREACH); ! 179: } ! 180: } ! 181: if (rt->rt_flags & RTF_REJECT) ! 182: if (rt->rt_rmx.rmx_expire == 0 || ! 183: time.tv_sec < rt->rt_rmx.rmx_expire) ! 184: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); ! 185: } ! 186: switch (dst->sa_family) { ! 187: ! 188: #if INET ! 189: case AF_INET: ! 190: if (!arpresolve(ac, rt, m, dst, edst)) ! 191: return (0); /* if not yet resolved */ ! 192: /* If broadcasting on a simplex interface, loopback a copy */ ! 193: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) ! 194: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 195: off = m->m_pkthdr.len - m->m_len; ! 196: etype = ETHERTYPE_IP; ! 197: break; ! 198: #endif ! 199: #if NS ! 200: case AF_NS: ! 201: etype = ETHERTYPE_NS; ! 202: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 203: (caddr_t)edst, sizeof (edst)); ! 204: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) ! 205: return (looutput(ifp, m, dst, rt)); ! 206: /* If broadcasting on a simplex interface, loopback a copy */ ! 207: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) ! 208: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 209: break; ! 210: #endif ! 211: #if ISO ! 212: case AF_ISO: { ! 213: int snpalen; ! 214: struct llc *l; ! 215: register struct sockaddr_dl *sdl; ! 216: ! 217: if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && ! 218: sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { ! 219: bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); ! 220: } else if (error = ! 221: iso_snparesolve(ifp, (struct sockaddr_iso *)dst, ! 222: (char *)edst, &snpalen)) ! 223: goto bad; /* Not Resolved */ ! 224: /* If broadcasting on a simplex interface, loopback a copy */ ! 225: if (*edst & 1) ! 226: m->m_flags |= (M_BCAST|M_MCAST); ! 227: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && ! 228: (mcopy = m_copy(m, 0, (int)M_COPYALL))) { ! 229: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); ! 230: if (mcopy) { ! 231: eh = mtod(mcopy, struct ether_header *); ! 232: bcopy((caddr_t)edst, ! 233: (caddr_t)eh->ether_dhost, sizeof (edst)); ! 234: bcopy((caddr_t)ac->ac_enaddr, ! 235: (caddr_t)eh->ether_shost, sizeof (edst)); ! 236: } ! 237: } ! 238: M_PREPEND(m, 3, M_DONTWAIT); ! 239: if (m == NULL) ! 240: return (0); ! 241: etype = m->m_pkthdr.len; ! 242: l = mtod(m, struct llc *); ! 243: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; ! 244: l->llc_control = LLC_UI; ! 245: len += 3; ! 246: IFDEBUG(D_ETHER) ! 247: int i; ! 248: printf("unoutput: sending pkt to: "); ! 249: for (i=0; i<6; i++) ! 250: printf("%x ", edst[i] & 0xff); ! 251: printf("\n"); ! 252: ENDDEBUG ! 253: } break; ! 254: #endif /* ISO */ ! 255: #if LLC ! 256: /* case AF_NSAP: */ ! 257: case AF_CCITT: { ! 258: register struct sockaddr_dl *sdl = ! 259: (struct sockaddr_dl *) rt -> rt_gateway; ! 260: ! 261: if (sdl && sdl->sdl_family == AF_LINK ! 262: && sdl->sdl_alen > 0) { ! 263: bcopy(LLADDR(sdl), (char *)edst, ! 264: sizeof(edst)); ! 265: } else goto bad; /* Not a link interface ? Funny ... */ ! 266: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && ! 267: (mcopy = m_copy(m, 0, (int)M_COPYALL))) { ! 268: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); ! 269: if (mcopy) { ! 270: eh = mtod(mcopy, struct ether_header *); ! 271: bcopy((caddr_t)edst, ! 272: (caddr_t)eh->ether_dhost, sizeof (edst)); ! 273: bcopy((caddr_t)ac->ac_enaddr, ! 274: (caddr_t)eh->ether_shost, sizeof (edst)); ! 275: } ! 276: } ! 277: etype = m->m_pkthdr.len; ! 278: #if LLC_DEBUG ! 279: { ! 280: int i; ! 281: register struct llc *l = mtod(m, struct llc *); ! 282: ! 283: printf("ether_output: sending LLC2 pkt to: "); ! 284: for (i=0; i<6; i++) ! 285: printf("%x ", edst[i] & 0xff); ! 286: printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", ! 287: etype & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, ! 288: l->llc_control & 0xff); ! 289: ! 290: } ! 291: #endif /* LLC_DEBUG */ ! 292: } break; ! 293: #endif /* LLC */ ! 294: ! 295: case AF_UNSPEC: ! 296: eh = (struct ether_header *)dst->sa_data; ! 297: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 298: /* AF_UNSPEC doesn't swap the byte order of the ether_type. */ ! 299: etype = ntohs(eh->ether_type); ! 300: break; ! 301: ! 302: #if NETAT ! 303: ! 304: case AF_APPLETALK: ! 305: ! 306: { ! 307: #ifdef APPLETALK_DEBUG ! 308: int i; ! 309: register struct llc *l = mtod(m, struct llc *); ! 310: #endif ! 311: ! 312: eh = (struct ether_header *)dst->sa_data; ! 313: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 314: ! 315: etype = m->m_pkthdr.len; ! 316: #ifdef APPLETALK_DEBUG ! 317: kprintf("ether_output: sending AppleTalk pkt to: "); ! 318: for (i=0; i<6; i++) ! 319: kprintf("%x ", edst[i] & 0xff); ! 320: kprintf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", ! 321: etype & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, ! 322: l->llc_control & 0xff); ! 323: #endif /* APPLETALK_DEBUG */ ! 324: } ! 325: break; ! 326: ! 327: #endif /* NETAT */ ! 328: ! 329: default: ! 330: #if 0 ! 331: kprintf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, ! 332: dst->sa_family); ! 333: #endif ! 334: senderr(EAFNOSUPPORT); ! 335: } ! 336: ! 337: ! 338: if (mcopy) ! 339: (void) looutput(ifp, mcopy, dst, rt); ! 340: /* ! 341: * Add local net header. If no space in first mbuf, ! 342: * allocate another. ! 343: */ ! 344: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); ! 345: if (m == 0) ! 346: senderr(ENOBUFS); ! 347: eh = mtod(m, struct ether_header *); ! 348: etype = htons(etype); ! 349: bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type, ! 350: sizeof(eh->ether_type)); ! 351: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); ! 352: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, ! 353: sizeof(eh->ether_shost)); ! 354: ismulticast = (m->m_flags & M_MCAST); ! 355: ! 356: #if defined(ppc) ! 357: /* ! 358: * We're already to send. Let's check for the blue box... ! 359: */ ! 360: if (ifp->if_flags&IFF_SPLITTER) ! 361: { m->m_flags |= 0x10; ! 362: if ((m = splitter_input(m, ifp)) == NULL) ! 363: return(0); ! 364: } ! 365: #endif /* ppc */ ! 366: s = splimp(); ! 367: /* ! 368: * Queue message on interface, and start output if interface ! 369: * not yet active. ! 370: */ ! 371: if (IF_QFULL(&ifp->if_snd)) { ! 372: IF_DROP(&ifp->if_snd); ! 373: splx(s); ! 374: senderr(ENOBUFS); ! 375: } ! 376: IF_ENQUEUE(&ifp->if_snd, m); ! 377: /* if ((ifp->if_flags & IFF_OACTIVE) == 0) */ ! 378: (*ifp->if_start)(ifp); ! 379: splx(s); ! 380: ifp->if_obytes += len + sizeof (struct ether_header); ! 381: if (ismulticast) ! 382: ifp->if_omcasts++; ! 383: return (error); ! 384: bad: ! 385: if (m) ! 386: m_freem(m); ! 387: return (error); ! 388: } ! 389: ! 390: /* ! 391: * Process a received Ethernet packet; ! 392: * the packet is in the mbuf chain m without ! 393: * the ether header, which is provided separately. ! 394: */ ! 395: void ! 396: ether_input(ifp, eh, m) ! 397: struct ifnet *ifp; ! 398: register struct ether_header *eh; ! 399: struct mbuf *m; ! 400: { ! 401: register struct ifqueue *inq; ! 402: register struct llc *l; ! 403: u_int16_t etype; ! 404: int s; ! 405: extern void revarpinput(struct mbuf *); ! 406: ! 407: u_int16_t ptype; ! 408: ! 409: ! 410: #if defined(ppc) ! 411: extern struct ifnet_blue *blue_if; ! 412: extern struct mbuf *splitter_input(struct mbuf *, struct ifnet *); ! 413: ! 414: /* ! 415: * Y-adapter input processing: ! 416: * - Don't split if coming from a dummy if ! 417: * - If coming from a real if, if splitting enabled, ! 418: * then filter the incoming packet ! 419: */ ! 420: if (ifp != (struct ifnet *)blue_if) ! 421: { /* Is splitter turned on? */ ! 422: if (ifp->if_flags&IFF_SPLITTER) ! 423: { m->m_data -= sizeof(struct ether_header); ! 424: m->m_len += sizeof (struct ether_header); ! 425: m->m_pkthdr.len += sizeof(struct ether_header); ! 426: /* ! 427: * Check to see if destined for BlueBox or Rhapsody ! 428: * If NULL return, mbuf's been consumed by the BlueBox. ! 429: * Otherwise, send on to Rhapsody ! 430: */ ! 431: if ((m = splitter_input(m, ifp)) == NULL) ! 432: return; ! 433: m->m_data += sizeof(struct ether_header); ! 434: m->m_len -= sizeof (struct ether_header); ! 435: m->m_pkthdr.len -= sizeof(struct ether_header); ! 436: } ! 437: } else ! 438: { /* Get the "real" IF */ ! 439: ifp = ((struct ndrv_cb *)(blue_if->ifb_so->so_pcb))->nd_if; ! 440: m->m_pkthdr.rcvif = ifp; ! 441: blue_if->pkts_looped_b2r++; ! 442: } ! 443: #endif /* ppc */ ! 444: ! 445: if ((ifp->if_flags & IFF_UP) == 0) { ! 446: m_freem(m); ! 447: return; ! 448: } ! 449: #if defined(ppc) ! 450: /* ! 451: * Here, we're working on the "real" i/f ! 452: */ ! 453: #endif ! 454: ! 455: ifp->if_lastchange = time; ! 456: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); ! 457: if (eh->ether_dhost[0] & 1) { ! 458: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, ! 459: sizeof(etherbroadcastaddr)) == 0) ! 460: m->m_flags |= M_BCAST; ! 461: else ! 462: m->m_flags |= M_MCAST; ! 463: } ! 464: if (m->m_flags & (M_BCAST|M_MCAST)) ! 465: ifp->if_imcasts++; ! 466: ! 467: etype = ntohs(eh->ether_type); ! 468: ptype = -1; ! 469: ! 470: switch (etype) { ! 471: #if INET ! 472: case ETHERTYPE_IP: ! 473: ! 474: #if defined(ppc) ! 475: ptype = mtod(m, struct ip *)->ip_p; ! 476: if (((ifp->if_eflags & IFEF_DVR_REENTRY_OK) == 0) || ! 477: (ptype != IPPROTO_TCP && ptype != IPPROTO_UDP)) ! 478: #endif ! 479: schednetisr(NETISR_IP); ! 480: inq = &ipintrq; ! 481: break; ! 482: ! 483: case ETHERTYPE_ARP: ! 484: schednetisr(NETISR_ARP); ! 485: inq = &arpintrq; ! 486: break; ! 487: ! 488: case ETHERTYPE_REVARP: ! 489: revarpinput(m); /* XXX queue? */ ! 490: return; ! 491: #endif /* INET */ ! 492: #if NS ! 493: case ETHERTYPE_NS: ! 494: schednetisr(NETISR_NS); ! 495: inq = &nsintrq; ! 496: break; ! 497: ! 498: #endif /* NS */ ! 499: default: ! 500: #if defined (ISO) || defined (LLC) || NETAT ! 501: if (etype > ETHERMTU) ! 502: goto dropanyway; ! 503: l = mtod(m, struct llc *); ! 504: ! 505: /* Temporary hack: check for AppleTalk and AARP packets */ ! 506: /* WARNING we're checking only on the "ether_type" (the 2 bytes ! 507: * of the SNAP header. This shouldn't be a big deal, ! 508: * AppleTalk pat_input is making sure we have the right packets ! 509: * because it needs to discrimante AARP from EtherTalk packets. ! 510: */ ! 511: ! 512: if (l->llc_dsap == LLC_SNAP_LSAP && ! 513: l->llc_ssap == LLC_SNAP_LSAP && ! 514: l->llc_un.type_snap.control == 0x03) { ! 515: #if NETAT ! 516: #ifdef APPLETALK_DEBUG ! 517: printf("ether_input: SNAP Cntrol type=0x%x Src=%s\n", ! 518: l->llc_un.type_snap.ether_type, ! 519: ether_sprintf(&eh->ether_shost)); ! 520: printf(" Dst=%s\n", ! 521: ether_sprintf(&eh->ether_dhost)); ! 522: #endif /* APPLETALK_DEBUG */ ! 523: #endif /* NETAT */ ! 524: if ((l->llc_un.type_snap.ether_type == 0x809B) || ! 525: (l->llc_un.type_snap.ether_type == 0x80F3)) { ! 526: ! 527: #if NETAT ! 528: /* ! 529: * note: for AppleTalk we need to pass the enet header of the ! 530: * packet up stack. To do so, we made sure in that the FULL packet ! 531: * is copied in the mbuf by the mace driver, and only the m_data and ! 532: * length have been shifted to make IP and the other guys happy. ! 533: */ ! 534: ! 535: m->m_data -= sizeof(*eh); ! 536: m->m_len += sizeof(*eh); ! 537: m->m_pkthdr.len += sizeof(*eh); ! 538: #ifdef APPLETALK_DEBUG ! 539: l == (struct llc *)(eh+1); ! 540: if (l->llc_un.type_snap.ether_type == 0x80F3) { ! 541: kprintf("ether_input: RCV AppleTalk type=0x%x Src=%s\n", ! 542: l->llc_un.type_snap.ether_type, ! 543: ether_sprintf(&eh->ether_shost)); ! 544: kprintf(" Dst=%s\n", ! 545: ether_sprintf(&eh->ether_dhost)); ! 546: } ! 547: #endif /* APPLETALK_DEBUG */ ! 548: schednetisr(NETISR_APPLETALK); ! 549: inq = &atalkintrq ; ! 550: #else /* no APPLETALK */ ! 551: goto dropanyway; ! 552: #endif /* NETAT */ ! 553: break; ! 554: } ! 555: } ! 556: ! 557: ! 558: switch (l->llc_dsap) { ! 559: ! 560: #if ISO ! 561: case LLC_ISO_LSAP: ! 562: switch (l->llc_control) { ! 563: case LLC_UI: ! 564: /* LLC_UI_P forbidden in class 1 service */ ! 565: if ((l->llc_dsap == LLC_ISO_LSAP) && ! 566: (l->llc_ssap == LLC_ISO_LSAP)) { ! 567: /* LSAP for ISO */ ! 568: if (m->m_pkthdr.len > etype) ! 569: m_adj(m, etype - m->m_pkthdr.len); ! 570: m->m_data += 3; /* XXX */ ! 571: m->m_len -= 3; /* XXX */ ! 572: m->m_pkthdr.len -= 3; /* XXX */ ! 573: M_PREPEND(m, sizeof *eh, M_DONTWAIT); ! 574: if (m == 0) ! 575: return; ! 576: *mtod(m, struct ether_header *) = *eh; ! 577: IFDEBUG(D_ETHER) ! 578: printf("clnp packet"); ! 579: ENDDEBUG ! 580: schednetisr(NETISR_ISO); ! 581: inq = &clnlintrq; ! 582: break; ! 583: } ! 584: goto dropanyway; ! 585: ! 586: case LLC_XID: ! 587: case LLC_XID_P: ! 588: if(m->m_len < 6) ! 589: goto dropanyway; ! 590: l->llc_window = 0; ! 591: l->llc_fid = 9; ! 592: l->llc_class = 1; ! 593: l->llc_dsap = l->llc_ssap = 0; ! 594: /* Fall through to */ ! 595: case LLC_TEST: ! 596: case LLC_TEST_P: ! 597: { ! 598: struct sockaddr sa; ! 599: register struct ether_header *eh2; ! 600: int i; ! 601: u_char c = l->llc_dsap; ! 602: ! 603: l->llc_dsap = l->llc_ssap; ! 604: l->llc_ssap = c; ! 605: if (m->m_flags & (M_BCAST | M_MCAST)) ! 606: bcopy((caddr_t)ac->ac_enaddr, ! 607: (caddr_t)eh->ether_dhost, 6); ! 608: sa.sa_family = AF_UNSPEC; ! 609: sa.sa_len = sizeof(sa); ! 610: eh2 = (struct ether_header *)sa.sa_data; ! 611: for (i = 0; i < 6; i++) { ! 612: eh2->ether_shost[i] = c = eh->ether_dhost[i]; ! 613: eh2->ether_dhost[i] = ! 614: eh->ether_dhost[i] = eh->ether_shost[i]; ! 615: eh->ether_shost[i] = c; ! 616: } ! 617: ifp->if_output(ifp, m, &sa, NULL); ! 618: return; ! 619: } ! 620: default: ! 621: m_freem(m); ! 622: return; ! 623: } ! 624: break; ! 625: #endif /* ISO */ ! 626: #if LLC ! 627: case LLC_X25_LSAP: ! 628: { ! 629: if (m->m_pkthdr.len > etype) ! 630: m_adj(m, etype - m->m_pkthdr.len); ! 631: M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); ! 632: if (m == 0) ! 633: return; ! 634: if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, ! 635: eh->ether_dhost, LLC_X25_LSAP, 6, ! 636: mtod(m, struct sdl_hdr *))) ! 637: panic("ETHER cons addr failure"); ! 638: mtod(m, struct sdl_hdr *)->sdlhdr_len = etype; ! 639: #if LLC_DEBUG ! 640: printf("llc packet\n"); ! 641: #endif /* LLC_DEBUG */ ! 642: schednetisr(NETISR_CCITT); ! 643: inq = &llcintrq; ! 644: break; ! 645: } ! 646: #endif /* LLC */ ! 647: dropanyway: ! 648: default: ! 649: m_freem(m); ! 650: return; ! 651: } ! 652: #else /* ISO || LLC */ ! 653: m_freem(m); ! 654: return; ! 655: #endif /* ISO || LLC */ ! 656: } ! 657: ! 658: s = splimp(); ! 659: if (IF_QFULL(inq)) { ! 660: IF_DROP(inq); ! 661: m_freem(m); ! 662: } else ! 663: IF_ENQUEUE(inq, m); ! 664: splx(s); ! 665: ! 666: if ((ifp->if_eflags & IFEF_DVR_REENTRY_OK) && (ptype == IPPROTO_TCP || ptype == IPPROTO_UDP)) { ! 667: extern void ipintr(void); ! 668: ! 669: s = splnet(); ! 670: ipintr(); ! 671: splx(s); ! 672: } ! 673: ! 674: } ! 675: ! 676: /* ! 677: * Convert Ethernet address to printable (loggable) representation. ! 678: */ ! 679: static char digits[] = "0123456789abcdef"; ! 680: char * ! 681: ether_sprintf(ap) ! 682: register u_char *ap; ! 683: { ! 684: register i; ! 685: static char etherbuf[18]; ! 686: register char *cp = etherbuf; ! 687: ! 688: for (i = 0; i < 6; i++) { ! 689: *cp++ = digits[*ap >> 4]; ! 690: *cp++ = digits[*ap++ & 0xf]; ! 691: *cp++ = ':'; ! 692: } ! 693: *--cp = 0; ! 694: return (etherbuf); ! 695: } ! 696: ! 697: /* ! 698: * Perform common duties while attaching to interface list ! 699: */ ! 700: void ! 701: ether_ifattach(ifp) ! 702: register struct ifnet *ifp; ! 703: { ! 704: register struct ifaddr *ifa; ! 705: register struct sockaddr_dl *sdl; ! 706: extern appletalk_hack_start(struct ifnet *); ! 707: ! 708: ifp->if_type = IFT_ETHER; ! 709: ifp->if_addrlen = 6; ! 710: ifp->if_hdrlen = 14; ! 711: ifp->if_mtu = ETHERMTU; ! 712: ifp->if_output = ether_output; ! 713: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 714: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && ! 715: sdl->sdl_family == AF_LINK) { ! 716: sdl->sdl_type = IFT_ETHER; ! 717: sdl->sdl_alen = ifp->if_addrlen; ! 718: bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, ! 719: LLADDR(sdl), ifp->if_addrlen); ! 720: break; ! 721: } ! 722: } ! 723: ! 724: #if NETAT ! 725: ! 726: /* ! 727: * BIG HACK ALERT ### LD 06/02/97 ! 728: * This is a way to get the appletalk stack inited. JUST A TEMPO Hack ! 729: */ ! 730: ! 731: appletalk_hack_start(ifp); ! 732: ! 733: ! 734: #endif /* NETAT */ ! 735: } ! 736: ! 737: u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; ! 738: u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; ! 739: /* ! 740: * Add an Ethernet multicast address or range of addresses to the list for a ! 741: * given interface. ! 742: */ ! 743: int ! 744: ether_addmulti(ifr, ac) ! 745: struct ifreq *ifr; ! 746: register struct arpcom *ac; ! 747: { ! 748: register struct ether_multi *enm; ! 749: struct sockaddr_in *sin; ! 750: u_char addrlo[6]; ! 751: u_char addrhi[6]; ! 752: int s = splimp(); ! 753: ! 754: switch (ifr->ifr_addr.sa_family) { ! 755: ! 756: case AF_UNSPEC: ! 757: bcopy(ifr->ifr_addr.sa_data, addrlo, 6); ! 758: bcopy(addrlo, addrhi, 6); ! 759: break; ! 760: ! 761: #if INET ! 762: case AF_INET: ! 763: sin = (struct sockaddr_in *)&(ifr->ifr_addr); ! 764: if (sin->sin_addr.s_addr == INADDR_ANY) { ! 765: /* ! 766: * An IP address of INADDR_ANY means listen to all ! 767: * of the Ethernet multicast addresses used for IP. ! 768: * (This is for the sake of IP multicast routers.) ! 769: */ ! 770: bcopy(ether_ipmulticast_min, addrlo, 6); ! 771: bcopy(ether_ipmulticast_max, addrhi, 6); ! 772: } ! 773: else { ! 774: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); ! 775: bcopy(addrlo, addrhi, 6); ! 776: } ! 777: break; ! 778: #endif ! 779: ! 780: default: ! 781: splx(s); ! 782: return (EAFNOSUPPORT); ! 783: } ! 784: ! 785: /* ! 786: * Verify that we have valid Ethernet multicast addresses. ! 787: */ ! 788: if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { ! 789: splx(s); ! 790: return (EINVAL); ! 791: } ! 792: /* ! 793: * See if the address range is already in the list. ! 794: */ ! 795: ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); ! 796: if (enm != NULL) { ! 797: /* ! 798: * Found it; just increment the reference count. ! 799: */ ! 800: ++enm->enm_refcount; ! 801: splx(s); ! 802: return (0); ! 803: } ! 804: /* ! 805: * New address or range; malloc a new multicast record ! 806: * and link it into the interface's multicast list. ! 807: */ ! 808: enm = (struct ether_multi *)_MALLOC(sizeof(*enm), M_IFMADDR, M_WAITOK); ! 809: if (enm == NULL) { ! 810: splx(s); ! 811: return (ENOBUFS); ! 812: } ! 813: bcopy(addrlo, enm->enm_addrlo, 6); ! 814: bcopy(addrhi, enm->enm_addrhi, 6); ! 815: enm->enm_ac = ac; ! 816: enm->enm_refcount = 1; ! 817: enm->enm_next = ac->ac_multiaddrs; ! 818: ac->ac_multiaddrs = enm; ! 819: ac->ac_multicnt++; ! 820: splx(s); ! 821: /* ! 822: * Return ENETRESET to inform the driver that the list has changed ! 823: * and its reception filter should be adjusted accordingly. ! 824: */ ! 825: return (ENETRESET); ! 826: } ! 827: ! 828: /* ! 829: * Delete a multicast address record. ! 830: */ ! 831: int ! 832: ether_delmulti(ifr, ac, ret_mca) ! 833: struct ifreq *ifr; ! 834: register struct arpcom *ac; ! 835: struct ether_addr * ret_mca; ! 836: { ! 837: register struct ether_multi *enm; ! 838: register struct ether_multi **p; ! 839: struct sockaddr_in *sin; ! 840: u_char addrlo[6]; ! 841: u_char addrhi[6]; ! 842: int s = splimp(); ! 843: ! 844: switch (ifr->ifr_addr.sa_family) { ! 845: ! 846: case AF_UNSPEC: ! 847: bcopy(ifr->ifr_addr.sa_data, addrlo, 6); ! 848: bcopy(addrlo, addrhi, 6); ! 849: break; ! 850: ! 851: #if INET ! 852: case AF_INET: ! 853: sin = (struct sockaddr_in *)&(ifr->ifr_addr); ! 854: if (sin->sin_addr.s_addr == INADDR_ANY) { ! 855: /* ! 856: * An IP address of INADDR_ANY means stop listening ! 857: * to the range of Ethernet multicast addresses used ! 858: * for IP. ! 859: */ ! 860: bcopy(ether_ipmulticast_min, addrlo, 6); ! 861: bcopy(ether_ipmulticast_max, addrhi, 6); ! 862: } ! 863: else { ! 864: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); ! 865: bcopy(addrlo, addrhi, 6); ! 866: } ! 867: break; ! 868: #endif ! 869: ! 870: default: ! 871: splx(s); ! 872: return (EAFNOSUPPORT); ! 873: } ! 874: ! 875: /* ! 876: * Look up the address in our list. ! 877: */ ! 878: ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); ! 879: if (enm == NULL) { ! 880: splx(s); ! 881: return (ENXIO); ! 882: } ! 883: if (--enm->enm_refcount != 0) { ! 884: /* ! 885: * Still some claims to this record. ! 886: */ ! 887: splx(s); ! 888: return (0); ! 889: } ! 890: ! 891: /* save the low and high address of the range before deletion */ ! 892: if (ret_mca) { ! 893: *ret_mca = *((struct ether_addr *)addrlo); ! 894: *(ret_mca + 1) = *((struct ether_addr *)addrhi); ! 895: } ! 896: ! 897: /* ! 898: * No remaining claims to this record; unlink and free it. ! 899: */ ! 900: for (p = &enm->enm_ac->ac_multiaddrs; ! 901: *p != enm; ! 902: p = &(*p)->enm_next) ! 903: continue; ! 904: *p = (*p)->enm_next; ! 905: _FREE(enm, M_IFMADDR); ! 906: ac->ac_multicnt--; ! 907: splx(s); ! 908: /* ! 909: * Return ENETRESET to inform the driver that the list has changed ! 910: * and its reception filter should be adjusted accordingly. ! 911: */ ! 912: return (ENETRESET); ! 913: } ! 914: ! 915: #ifdef sparc ! 916: localetheraddr(hint, result) ! 917: struct ether_addr *hint, *result; ! 918: { ! 919: static int found = 0; ! 920: static struct ether_addr addr; ! 921: ! 922: if (!found) { ! 923: found = 1; ! 924: if (hint == NULL) ! 925: return (0); ! 926: addr = *hint; ! 927: printf("Ethernet address = %s\n", ether_sprintf(&addr) ); ! 928: } ! 929: if (result != NULL) ! 930: *result = addr; ! 931: return (1); ! 932: } ! 933: #endif ! 934: ! 935: #if defined(ppc) ! 936: /* ! 937: * NB: need to register Atalk addresses from Rhapsody ! 938: */ ! 939: int ! 940: if_register(register struct BlueFilter *f ! 941: #ifdef BF_if ! 942: , ! 943: register struct ifnet *ifp ! 944: #endif ! 945: ) ! 946: { register int ix; ! 947: register struct BlueFilter *nf; ! 948: ! 949: if (f->BF_flags & BF_VALID) ! 950: return(EINVAL); ! 951: if (f->BF_flags & BF_IP) ! 952: { if (BFIx == 0) ! 953: ix = BFIx = 1; /* Starting at 1 for IP */ ! 954: else if (BFIx >= BFCount) ! 955: return(0); /* We'll just deal with it */ ! 956: else ! 957: ix = ++BFIx; ! 958: } else if (!(f->BF_flags & BF_ATALK)) ! 959: return(EINVAL); ! 960: else /* AppleTalk */ ! 961: ix = 0; ! 962: ! 963: nf = &RhapFilter[ix]; ! 964: *nf = *f; ! 965: nf->BF_flags |= BF_VALID; ! 966: #ifdef BF_if ! 967: nf->BF_if = ifp; ! 968: #endif ! 969: return(0); ! 970: } ! 971: ! 972: /* ! 973: * Y-adapter filter check ! 974: * The rules here: ! 975: * For Rhap: return 1 ! 976: * For Both: return 0 ! 977: * Not for Rhap: return -1 ! 978: * Multicast/Broadcast => For Both ! 979: * Atalk address registered ! 980: * filter matches => For Rhap else Not For Rhap ! 981: * IP address registered ! 982: * filter matches => For Rhap else Not For Rhap ! 983: * For Rhap ! 984: * Note this is *not* a general filter mechanism in that we know ! 985: * what we *could* be looking for. ! 986: * WARNING: this is a big-endian routine. ! 987: * Note: ARP and AARP packets are implicitly accepted for "both" ! 988: */ ! 989: int ! 990: Filter_check(struct mbuf **m0) ! 991: { register struct BlueFilter *bf; ! 992: register unsigned char *p; ! 993: register unsigned short *s; ! 994: register unsigned long *l; ! 995: int total, flags; ! 996: struct mbuf *m; ! 997: extern struct mbuf *m_pullup(struct mbuf *, int); ! 998: extern void kprintf( const char *, ...); ! 999: #define FILTER_LEN 32 ! 1000: ! 1001: m = *m0; ! 1002: flags = m->m_flags; ! 1003: if (FILTER_LEN > m->m_pkthdr.len) ! 1004: return(1); ! 1005: while ((FILTER_LEN > m->m_len) && m->m_next) { ! 1006: total = m->m_len + (m->m_next)->m_len; ! 1007: if ((m = m_pullup(m, min(FILTER_LEN, total))) == 0) ! 1008: return(-1); ! 1009: } ! 1010: *m0 = m; ! 1011: ! 1012: p = mtod(m, unsigned char *); /* Point to destination media addr */ ! 1013: if (p[0] & 0x01) /* Multicast/broadcast */ ! 1014: return(0); ! 1015: s = (unsigned short *)p; ! 1016: bf = &RhapFilter[BFS_ATALK]; ! 1017: #if 0 ! 1018: kprintf("!PKT: %x, %x, %x\n", s[6], s[7], s[8]); ! 1019: #endif ! 1020: ! 1021: if (bf->BF_flags) /* Filtering Appletalk */ ! 1022: { ! 1023: l = (unsigned long *)&s[8]; ! 1024: #if 0 ! 1025: kprintf("!AT: %x, %x, %x, %x, %x, %x\n", s[6], s[7], ! 1026: *l, s[10], s[13], p[30]); ! 1027: #endif ! 1028: if (s[6] <= ETHERMTU) ! 1029: { if (s[7] == 0xaaaa) /* Could be Atalk */ ! 1030: { /* Verify SNAP header */ ! 1031: if (*l == 0x03080007 && s[10] == 0x809b) ! 1032: { if (s[13] == bf->BF_address && ! 1033: p[30] == bf->BF_node) ! 1034: return(1); ! 1035: } else if (*l == 0x03000000 && s[10] == 0x80f3) ! 1036: /* AARP pkts aren't net-addressed */ ! 1037: return(0); ! 1038: return(0); ! 1039: } else /* Not for us? */ ! 1040: return(0); ! 1041: } /* Fall through */ ! 1042: } /* Fall through */ ! 1043: bf++; /* Look for IP next */ ! 1044: if (bf->BF_flags) /* Filtering IP */ ! 1045: { ! 1046: l = (unsigned long *)&s[15]; ! 1047: #if 0 ! 1048: kprintf("!IP: %x, %x\n", s[6], *l); ! 1049: #endif ! 1050: if (s[6] > ETHERMTU) ! 1051: { if (s[6] == 0x800) /* Is IP */ ! 1052: { /* Verify IP address */ ! 1053: if (*l == bf->BF_address) ! 1054: return(1); ! 1055: else /* Not for us */ ! 1056: return(0); ! 1057: } else if (s[6] == 0x806) ! 1058: /* ARP pkts aren't net-addressed */ ! 1059: return(0); ! 1060: } ! 1061: } ! 1062: return(0); /* No filters => Accept */ ! 1063: } ! 1064: #endif /* ppc */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.