|
|
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: * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 ! 55: */ ! 56: ! 57: #if NOTFB31 ! 58: #include "opt_atalk.h" ! 59: #include "opt_inet.h" ! 60: #include "opt_ipx.h" ! 61: #include "opt_bdg.h" ! 62: #endif ! 63: ! 64: #include <sys/param.h> ! 65: #include <sys/systm.h> ! 66: #include <sys/kernel.h> ! 67: #include <sys/malloc.h> ! 68: #include <sys/mbuf.h> ! 69: #include <sys/socket.h> ! 70: #include <sys/sockio.h> ! 71: #include <sys/sysctl.h> ! 72: ! 73: #include <net/if.h> ! 74: #include <net/netisr.h> ! 75: #include <net/route.h> ! 76: #include <net/if_llc.h> ! 77: #include <net/if_dl.h> ! 78: #include <net/if_types.h> ! 79: #include <net/ndrv.h> ! 80: ! 81: #if INET ! 82: #include <netinet/in.h> ! 83: #include <netinet/in_var.h> ! 84: #include <netinet/if_ether.h> ! 85: #include <netinet/in_systm.h> ! 86: #include <netinet/ip.h> ! 87: #endif ! 88: ! 89: #if IPX ! 90: #include <netipx/ipx.h> ! 91: #include <netipx/ipx_if.h> ! 92: #endif ! 93: ! 94: #if NS ! 95: #include <netns/ns.h> ! 96: #include <netns/ns_if.h> ! 97: ushort ns_nettype; ! 98: int ether_outputdebug = 0; ! 99: int ether_inputdebug = 0; ! 100: #endif ! 101: ! 102: #if ISO ! 103: #include <netiso/argo_debug.h> ! 104: #include <netiso/iso.h> ! 105: #include <netiso/iso_var.h> ! 106: #include <netiso/iso_snpac.h> ! 107: #endif ! 108: ! 109: /*#if LLC ! 110: #include <netccitt/dll.h> ! 111: #include <netccitt/llc_var.h> ! 112: #endif*/ ! 113: ! 114: #include <sys/socketvar.h> ! 115: #include <net/if_blue.h> ! 116: ! 117: struct BlueFilter RhapFilter[BFCount]; ! 118: int BFIx; /* 0 for Atalk; 1..9 for IP */ ! 119: ! 120: ! 121: #if LLC && CCITT ! 122: extern struct ifqueue pkintrq; ! 123: #endif ! 124: ! 125: #if BRIDGE ! 126: #include <net/bridge.h> ! 127: #endif ! 128: ! 129: /* #include "vlan.h" */ ! 130: #if NVLAN > 0 ! 131: #include <net/if_vlan_var.h> ! 132: #endif /* NVLAN > 0 */ ! 133: ! 134: static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, ! 135: struct sockaddr *)); ! 136: extern u_char etherbroadcastaddr[]; ! 137: #define senderr(e) do { error = (e); goto bad;} while (0) ! 138: #define IFP2AC(IFP) ((struct arpcom *)IFP) ! 139: ! 140: /* ! 141: * Perform common duties while attaching to interface list ! 142: */ ! 143: ! 144: ! 145: void ! 146: ether_ifattach(ifp) ! 147: register struct ifnet *ifp; ! 148: { ! 149: register struct ifaddr *ifa; ! 150: register struct sockaddr_dl *sdl; ! 151: boolean_t funnel_state; ! 152: ! 153: funnel_state = thread_set_funneled(TRUE); ! 154: printf("ether_ifattach called for %s\n", ifp->if_name); ! 155: ether_family_init(); ! 156: ! 157: ifp->if_name = "en"; ! 158: ifp->if_family = APPLE_IF_FAM_ETHERNET; ! 159: ifp->if_type = IFT_ETHER; ! 160: ifp->if_addrlen = 6; ! 161: ifp->if_hdrlen = 14; ! 162: ifp->if_mtu = ETHERMTU; ! 163: ifp->if_resolvemulti = ether_resolvemulti; ! 164: if (ifp->if_baudrate == 0) ! 165: ifp->if_baudrate = 10000000; ! 166: ! 167: dlil_if_attach(ifp); ! 168: ifa = ifnet_addrs[ifp->if_index - 1]; ! 169: if (ifa == 0) { ! 170: printf("ether_ifattach: no lladdr!\n"); ! 171: (void) thread_set_funneled(funnel_state); ! 172: return; ! 173: } ! 174: sdl = (struct sockaddr_dl *)ifa->ifa_addr; ! 175: sdl->sdl_type = IFT_ETHER; ! 176: sdl->sdl_alen = ifp->if_addrlen; ! 177: bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); ! 178: (void) thread_set_funneled(funnel_state); ! 179: } ! 180: ! 181: SYSCTL_DECL(_net_link); ! 182: SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); ! 183: ! 184: int ! 185: ether_resolvemulti(ifp, llsa, sa) ! 186: struct ifnet *ifp; ! 187: struct sockaddr **llsa; ! 188: struct sockaddr *sa; ! 189: { ! 190: struct sockaddr_dl *sdl; ! 191: struct sockaddr_in *sin; ! 192: u_char *e_addr; ! 193: ! 194: switch(sa->sa_family) { ! 195: case AF_UNSPEC: ! 196: /* AppleTalk uses AF_UNSPEC for multicast registration. ! 197: * No mapping needed. Just check that it's a valid MC address. ! 198: */ ! 199: e_addr = &sa->sa_data[0]; ! 200: if ((e_addr[0] & 1) != 1) ! 201: return EADDRNOTAVAIL; ! 202: *llsa = 0; ! 203: return 0; ! 204: ! 205: case AF_LINK: ! 206: /* ! 207: * No mapping needed. Just check that it's a valid MC address. ! 208: */ ! 209: sdl = (struct sockaddr_dl *)sa; ! 210: e_addr = LLADDR(sdl); ! 211: if ((e_addr[0] & 1) != 1) ! 212: return EADDRNOTAVAIL; ! 213: *llsa = 0; ! 214: return 0; ! 215: ! 216: #if INET ! 217: case AF_INET: ! 218: sin = (struct sockaddr_in *)sa; ! 219: if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) ! 220: return EADDRNOTAVAIL; ! 221: MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, ! 222: M_WAITOK); ! 223: sdl->sdl_len = sizeof *sdl; ! 224: sdl->sdl_family = AF_LINK; ! 225: sdl->sdl_index = ifp->if_index; ! 226: sdl->sdl_type = IFT_ETHER; ! 227: sdl->sdl_nlen = 0; ! 228: sdl->sdl_alen = ETHER_ADDR_LEN; ! 229: sdl->sdl_slen = 0; ! 230: e_addr = LLADDR(sdl); ! 231: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); ! 232: *llsa = (struct sockaddr *)sdl; ! 233: return 0; ! 234: #endif ! 235: ! 236: default: ! 237: /* ! 238: * Well, the text isn't quite right, but it's the name ! 239: * that counts... ! 240: */ ! 241: return EAFNOSUPPORT; ! 242: } ! 243: } ! 244: ! 245: ! 246: ! 247: ! 248: ! 249: u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; ! 250: u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; ! 251: /* ! 252: * Add an Ethernet multicast address or range of addresses to the list for a ! 253: * given interface. ! 254: */ ! 255: int ! 256: ether_addmulti(ifr, ac) ! 257: struct ifreq *ifr; ! 258: register struct arpcom *ac; ! 259: { ! 260: register struct ether_multi *enm; ! 261: struct sockaddr_in *sin; ! 262: u_char addrlo[6]; ! 263: u_char addrhi[6]; ! 264: int s = splimp(); ! 265: ! 266: switch (ifr->ifr_addr.sa_family) { ! 267: ! 268: case AF_UNSPEC: ! 269: bcopy(ifr->ifr_addr.sa_data, addrlo, 6); ! 270: bcopy(addrlo, addrhi, 6); ! 271: break; ! 272: ! 273: #if INET ! 274: case AF_INET: ! 275: sin = (struct sockaddr_in *)&(ifr->ifr_addr); ! 276: if (sin->sin_addr.s_addr == INADDR_ANY) { ! 277: /* ! 278: * An IP address of INADDR_ANY means listen to all ! 279: * of the Ethernet multicast addresses used for IP. ! 280: * (This is for the sake of IP multicast routers.) ! 281: */ ! 282: bcopy(ether_ipmulticast_min, addrlo, 6); ! 283: bcopy(ether_ipmulticast_max, addrhi, 6); ! 284: } ! 285: else { ! 286: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); ! 287: bcopy(addrlo, addrhi, 6); ! 288: } ! 289: break; ! 290: #endif ! 291: ! 292: default: ! 293: splx(s); ! 294: return (EAFNOSUPPORT); ! 295: } ! 296: ! 297: /* ! 298: * Verify that we have valid Ethernet multicast addresses. ! 299: */ ! 300: if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { ! 301: splx(s); ! 302: return (EINVAL); ! 303: } ! 304: /* ! 305: * See if the address range is already in the list. ! 306: */ ! 307: ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); ! 308: if (enm != NULL) { ! 309: /* ! 310: * Found it; just increment the reference count. ! 311: */ ! 312: ++enm->enm_refcount; ! 313: splx(s); ! 314: return (0); ! 315: } ! 316: /* ! 317: * New address or range; malloc a new multicast record ! 318: * and link it into the interface's multicast list. ! 319: */ ! 320: enm = (struct ether_multi *)_MALLOC(sizeof(*enm), M_IFMADDR, M_WAITOK); ! 321: if (enm == NULL) { ! 322: splx(s); ! 323: return (ENOBUFS); ! 324: } ! 325: bcopy(addrlo, enm->enm_addrlo, 6); ! 326: bcopy(addrhi, enm->enm_addrhi, 6); ! 327: enm->enm_ac = ac; ! 328: enm->enm_refcount = 1; ! 329: enm->enm_next = ac->ac_multiaddrs; ! 330: ac->ac_multiaddrs = enm; ! 331: splx(s); ! 332: /* ! 333: * Return ENETRESET to inform the driver that the list has changed ! 334: * and its reception filter should be adjusted accordingly. ! 335: */ ! 336: return (ENETRESET); ! 337: } ! 338: ! 339: /* ! 340: * Delete a multicast address record. ! 341: */ ! 342: int ! 343: ether_delmulti(ifr, ac, ret_mca) ! 344: struct ifreq *ifr; ! 345: register struct arpcom *ac; ! 346: struct ether_addr * ret_mca; ! 347: { ! 348: register struct ether_multi *enm; ! 349: register struct ether_multi **p; ! 350: struct sockaddr_in *sin; ! 351: u_char addrlo[6]; ! 352: u_char addrhi[6]; ! 353: int s = splimp(); ! 354: ! 355: switch (ifr->ifr_addr.sa_family) { ! 356: ! 357: case AF_UNSPEC: ! 358: bcopy(ifr->ifr_addr.sa_data, addrlo, 6); ! 359: bcopy(addrlo, addrhi, 6); ! 360: break; ! 361: ! 362: #if INET ! 363: case AF_INET: ! 364: sin = (struct sockaddr_in *)&(ifr->ifr_addr); ! 365: if (sin->sin_addr.s_addr == INADDR_ANY) { ! 366: /* ! 367: * An IP address of INADDR_ANY means stop listening ! 368: * to the range of Ethernet multicast addresses used ! 369: * for IP. ! 370: */ ! 371: bcopy(ether_ipmulticast_min, addrlo, 6); ! 372: bcopy(ether_ipmulticast_max, addrhi, 6); ! 373: } ! 374: else { ! 375: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); ! 376: bcopy(addrlo, addrhi, 6); ! 377: } ! 378: break; ! 379: #endif ! 380: ! 381: default: ! 382: splx(s); ! 383: return (EAFNOSUPPORT); ! 384: } ! 385: ! 386: /* ! 387: * Look up the address in our list. ! 388: */ ! 389: ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); ! 390: if (enm == NULL) { ! 391: splx(s); ! 392: return (ENXIO); ! 393: } ! 394: if (--enm->enm_refcount != 0) { ! 395: /* ! 396: * Still some claims to this record. ! 397: */ ! 398: splx(s); ! 399: return (0); ! 400: } ! 401: ! 402: /* save the low and high address of the range before deletion */ ! 403: if (ret_mca) { ! 404: *ret_mca = *((struct ether_addr *)addrlo); ! 405: *(ret_mca + 1) = *((struct ether_addr *)addrhi); ! 406: } ! 407: ! 408: /* ! 409: * No remaining claims to this record; unlink and free it. ! 410: */ ! 411: for (p = &enm->enm_ac->ac_multiaddrs; ! 412: *p != enm; ! 413: p = &(*p)->enm_next) ! 414: continue; ! 415: *p = (*p)->enm_next; ! 416: FREE(enm, M_IFMADDR); ! 417: splx(s); ! 418: /* ! 419: * Return ENETRESET to inform the driver that the list has changed ! 420: * and its reception filter should be adjusted accordingly. ! 421: */ ! 422: return (ENETRESET); ! 423: } ! 424: ! 425: ! 426: /* ! 427: * NB: need to register Atalk addresses from MacOSX ! 428: */ ! 429: int ! 430: if_register(register struct BlueFilter *f ! 431: #if BF_if ! 432: , ! 433: register struct ifnet *ifp ! 434: #endif ! 435: ) ! 436: { register int ix; ! 437: register struct BlueFilter *nf; ! 438: ! 439: if (f->BF_flags & BF_VALID) ! 440: return(EINVAL); ! 441: if (f->BF_flags & BF_IP) ! 442: { if (BFIx == 0) ! 443: ix = BFIx = 1; /* Starting at 1 for IP */ ! 444: else if (BFIx >= BFCount) ! 445: return(0); /* We'll just deal with it */ ! 446: else ! 447: ix = ++BFIx; ! 448: } else if (!(f->BF_flags & BF_ATALK)) ! 449: return(EINVAL); ! 450: else /* AppleTalk */ ! 451: ix = 0; ! 452: ! 453: nf = &RhapFilter[ix]; ! 454: *nf = *f; ! 455: nf->BF_flags |= BF_VALID; ! 456: #if BF_if ! 457: nf->BF_if = ifp; ! 458: #endif ! 459: return(0); ! 460: } ! 461: ! 462: /* ! 463: * Convert Ethernet address to printable (loggable) representation. ! 464: */ ! 465: static u_char digits[] = "0123456789abcdef"; ! 466: char * ! 467: ether_sprintf(p, ap) ! 468: register u_char *p; ! 469: register u_char *ap; ! 470: { register char *cp; ! 471: register i; ! 472: ! 473: for (cp = p, i = 0; i < 6; i++) { ! 474: *cp++ = digits[*ap >> 4]; ! 475: *cp++ = digits[*ap++ & 0xf]; ! 476: *cp++ = ':'; ! 477: } ! 478: *--cp = 0; ! 479: return (p); ! 480: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.