|
|
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) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1989, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * The NEXTSTEP Software License Agreement specifies the terms ! 31: * and conditions for redistribution. ! 32: * ! 33: */ ! 34: ! 35: #include <sys/param.h> ! 36: #include <sys/systm.h> ! 37: #include <sys/kernel.h> ! 38: #include <sys/malloc.h> ! 39: #include <sys/mbuf.h> ! 40: #include <sys/protosw.h> ! 41: #include <sys/socket.h> ! 42: #include <sys/ioctl.h> ! 43: #include <sys/errno.h> ! 44: #include <sys/syslog.h> ! 45: ! 46: #include <machine/cpu.h> ! 47: ! 48: #include <net/if.h> ! 49: #include <net/netisr.h> ! 50: #include <net/route.h> ! 51: #include <net/if_llc.h> ! 52: #include <net/if_dl.h> ! 53: #include <net/if_types.h> ! 54: ! 55: #if INET ! 56: #include <netinet/in.h> ! 57: #include <netinet/in_var.h> ! 58: #endif ! 59: #include <netinet/if_ether.h> ! 60: #include <netinet/if_fddi.h> ! 61: ! 62: #if NS ! 63: #include <netns/ns.h> ! 64: #include <netns/ns_if.h> ! 65: #endif ! 66: ! 67: #if DECNET ! 68: #include <netdnet/dn.h> ! 69: #endif ! 70: ! 71: #if defined(ISO) && notyet ! 72: #include <netiso/argo_debug.h> ! 73: #include <netiso/iso.h> ! 74: #include <netiso/iso_var.h> ! 75: #include <netiso/iso_snpac.h> ! 76: #endif /* defined(ISO) && notyet */ ! 77: ! 78: #include "bpfilter.h" ! 79: ! 80: #if LLC ! 81: #include <netccitt/dll.h> ! 82: #include <netccitt/llc_var.h> ! 83: #endif ! 84: ! 85: #if defined(LLC) && defined(CCITT) ! 86: extern struct ifqueue pkintrq; ! 87: #endif ! 88: ! 89: #define senderr(e) { error = (e); goto bad;} ! 90: ! 91: /* ! 92: * This really should be defined in if_llc.h but in case it isn't. ! 93: */ ! 94: #ifndef llc_snap ! 95: #define llc_snap llc_un.type_snap ! 96: #endif ! 97: ! 98: /* ! 99: * FDDI output routine. ! 100: * Encapsulate a packet of type family for the local net. ! 101: * Use trailer local net encapsulation if enough data in first ! 102: * packet leaves a multiple of 512 bytes of data in remainder. ! 103: * Assumes that ifp is actually pointer to arpcom structure. ! 104: */ ! 105: int ! 106: fddi_output(ifp, m0, dst, rt0) ! 107: register struct ifnet *ifp; ! 108: struct mbuf *m0; ! 109: struct sockaddr *dst; ! 110: struct rtentry *rt0; ! 111: { ! 112: short type; ! 113: int s, error = 0; ! 114: u_char edst[6]; ! 115: register struct mbuf *m = m0; ! 116: register struct rtentry *rt; ! 117: struct mbuf *mcopy = (struct mbuf *)0; ! 118: register struct fddi_header *fh; ! 119: struct arpcom *ac = (struct arpcom *)ifp; ! 120: ! 121: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 122: senderr(ENETDOWN); ! 123: ifp->if_lastchange = time; ! 124: if (rt = rt0) { ! 125: if ((rt->rt_flags & RTF_UP) == 0) { ! 126: if (rt0 = rt = rtalloc1(dst, 1)) ! 127: rt->rt_refcnt--; ! 128: else ! 129: senderr(EHOSTUNREACH); ! 130: } ! 131: if (rt->rt_flags & RTF_GATEWAY) { ! 132: if (rt->rt_gwroute == 0) ! 133: goto lookup; ! 134: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { ! 135: rtfree(rt); rt = rt0; ! 136: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); ! 137: if ((rt = rt->rt_gwroute) == 0) ! 138: senderr(EHOSTUNREACH); ! 139: } ! 140: } ! 141: if (rt->rt_flags & RTF_REJECT) ! 142: if (rt->rt_rmx.rmx_expire == 0 || ! 143: time.tv_sec < rt->rt_rmx.rmx_expire) ! 144: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); ! 145: } ! 146: switch (dst->sa_family) { ! 147: ! 148: #if INET ! 149: case AF_INET: ! 150: if (!arpresolve(ac, rt, m, dst, edst)) ! 151: return (0); /* if not yet resolved */ ! 152: /* If broadcasting on a simplex interface, loopback a copy */ ! 153: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) ! 154: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 155: type = ETHERTYPE_IP; ! 156: break; ! 157: #endif ! 158: #if NS ! 159: case AF_NS: ! 160: type = ETHERTYPE_NS; ! 161: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 162: (caddr_t)edst, sizeof (edst)); ! 163: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) ! 164: return (looutput(ifp, m, dst, rt)); ! 165: /* If broadcasting on a simplex interface, loopback a copy */ ! 166: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) ! 167: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 168: break; ! 169: #endif ! 170: #if defined(ISO) && notyet ! 171: case AF_ISO: { ! 172: int snpalen; ! 173: struct llc *l; ! 174: register struct sockaddr_dl *sdl; ! 175: ! 176: if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && ! 177: sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { ! 178: bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); ! 179: } else if (error = ! 180: iso_snparesolve(ifp, (struct sockaddr_iso *)dst, ! 181: (char *)edst, &snpalen)) ! 182: goto bad; /* Not Resolved */ ! 183: /* If broadcasting on a simplex interface, loopback a copy */ ! 184: if (*edst & 1) ! 185: m->m_flags |= (M_BCAST|M_MCAST); ! 186: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && ! 187: (mcopy = m_copy(m, 0, (int)M_COPYALL))) { ! 188: M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT); ! 189: if (mcopy) { ! 190: fh = mtod(mcopy, struct fddi_header *); ! 191: bcopy((caddr_t)edst, ! 192: (caddr_t)fh->fddi_dhost, sizeof (edst)); ! 193: bcopy((caddr_t)ac->ac_enaddr, ! 194: (caddr_t)fh->fddi_shost, sizeof (edst)); ! 195: } ! 196: } ! 197: M_PREPEND(m, 3, M_DONTWAIT); ! 198: if (m == NULL) ! 199: return (0); ! 200: type = 0; ! 201: l = mtod(m, struct llc *); ! 202: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; ! 203: l->llc_control = LLC_UI; ! 204: IFDEBUG(D_ETHER) ! 205: int i; ! 206: printf("unoutput: sending pkt to: "); ! 207: for (i=0; i<6; i++) ! 208: printf("%x ", edst[i] & 0xff); ! 209: printf("\n"); ! 210: ENDDEBUG ! 211: } break; ! 212: #endif /* defined(ISO) && notyet */ ! 213: #if LLC ! 214: /* case AF_NSAP: */ ! 215: case AF_CCITT: { ! 216: register struct sockaddr_dl *sdl = ! 217: (struct sockaddr_dl *) rt -> rt_gateway; ! 218: ! 219: if (sdl && sdl->sdl_family == AF_LINK ! 220: && sdl->sdl_alen > 0) { ! 221: bcopy(LLADDR(sdl), (char *)edst, ! 222: sizeof(edst)); ! 223: } else goto bad; /* Not a link interface ? Funny ... */ ! 224: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && ! 225: (mcopy = m_copy(m, 0, (int)M_COPYALL))) { ! 226: M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT); ! 227: if (mcopy) { ! 228: fh = mtod(mcopy, struct fddi_header *); ! 229: bcopy((caddr_t)edst, ! 230: (caddr_t)fh->fddi_dhost, sizeof (edst)); ! 231: bcopy((caddr_t)ac->ac_enaddr, ! 232: (caddr_t)fh->fddi_shost, sizeof (edst)); ! 233: fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; ! 234: } ! 235: } ! 236: type = 0; ! 237: #if LLC_DEBUG ! 238: { ! 239: int i; ! 240: register struct llc *l = mtod(m, struct llc *); ! 241: ! 242: printf("fddi_output: sending LLC2 pkt to: "); ! 243: for (i=0; i<6; i++) ! 244: printf("%x ", edst[i] & 0xff); ! 245: printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", ! 246: type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, ! 247: l->llc_control & 0xff); ! 248: ! 249: } ! 250: #endif /* LLC_DEBUG */ ! 251: } break; ! 252: #endif /* LLC */ ! 253: ! 254: case AF_UNSPEC: ! 255: { ! 256: struct ether_header *eh; ! 257: eh = (struct ether_header *)dst->sa_data; ! 258: (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); ! 259: if (*edst & 1) ! 260: m->m_flags |= (M_BCAST|M_MCAST); ! 261: type = eh->ether_type; ! 262: break; ! 263: } ! 264: ! 265: #if NBPFILTER > 0 ! 266: case AF_IMPLINK: ! 267: { ! 268: fh = mtod(m, struct fddi_header *); ! 269: error = EPROTONOSUPPORT; ! 270: switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { ! 271: case FDDIFC_LLC_ASYNC: { ! 272: /* legal priorities are 0 through 7 */ ! 273: if ((fh->fddi_fc & FDDIFC_Z) > 7) ! 274: goto bad; ! 275: break; ! 276: } ! 277: case FDDIFC_LLC_SYNC: { ! 278: /* FDDIFC_Z bits reserved, must be zero */ ! 279: if (fh->fddi_fc & FDDIFC_Z) ! 280: goto bad; ! 281: break; ! 282: } ! 283: case FDDIFC_SMT: { ! 284: /* FDDIFC_Z bits must be non zero */ ! 285: if ((fh->fddi_fc & FDDIFC_Z) == 0) ! 286: goto bad; ! 287: break; ! 288: } ! 289: default: { ! 290: /* anything else is too dangerous */ ! 291: goto bad; ! 292: } ! 293: } ! 294: error = 0; ! 295: if (fh->fddi_dhost[0] & 1) ! 296: m->m_flags |= (M_BCAST|M_MCAST); ! 297: goto queue_it; ! 298: } ! 299: #endif ! 300: default: ! 301: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, ! 302: dst->sa_family); ! 303: senderr(EAFNOSUPPORT); ! 304: } ! 305: ! 306: ! 307: if (mcopy) ! 308: (void) looutput(ifp, mcopy, dst, rt); ! 309: if (type != 0) { ! 310: register struct llc *l; ! 311: M_PREPEND(m, sizeof (struct llc), M_DONTWAIT); ! 312: if (m == 0) ! 313: senderr(ENOBUFS); ! 314: l = mtod(m, struct llc *); ! 315: l->llc_control = LLC_UI; ! 316: l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; ! 317: l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0; ! 318: type = ntohs(type); ! 319: (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type, ! 320: sizeof(u_short)); ! 321: } ! 322: /* ! 323: * Add local net header. If no space in first mbuf, ! 324: * allocate another. ! 325: */ ! 326: M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT); ! 327: if (m == 0) ! 328: senderr(ENOBUFS); ! 329: fh = mtod(m, struct fddi_header *); ! 330: fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; ! 331: (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); ! 332: queue_it: ! 333: (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, ! 334: sizeof(fh->fddi_shost)); ! 335: s = splimp(); ! 336: /* ! 337: * Queue message on interface, and start output if interface ! 338: * not yet active. ! 339: */ ! 340: if (IF_QFULL(&ifp->if_snd)) { ! 341: IF_DROP(&ifp->if_snd); ! 342: splx(s); ! 343: senderr(ENOBUFS); ! 344: } ! 345: ifp->if_obytes += m->m_pkthdr.len; ! 346: IF_ENQUEUE(&ifp->if_snd, m); ! 347: if ((ifp->if_flags & IFF_OACTIVE) == 0) ! 348: (*ifp->if_start)(ifp); ! 349: splx(s); ! 350: if (m->m_flags & M_MCAST) ! 351: ifp->if_omcasts++; ! 352: return (error); ! 353: ! 354: bad: ! 355: if (m) ! 356: m_freem(m); ! 357: return (error); ! 358: } ! 359: ! 360: /* ! 361: * Process a received FDDI packet; ! 362: * the packet is in the mbuf chain m without ! 363: * the fddi header, which is provided separately. ! 364: */ ! 365: void ! 366: fddi_input(ifp, fh, m) ! 367: struct ifnet *ifp; ! 368: register struct fddi_header *fh; ! 369: struct mbuf *m; ! 370: { ! 371: register struct ifqueue *inq; ! 372: register struct llc *l; ! 373: int s; ! 374: ! 375: if ((ifp->if_flags & IFF_UP) == 0) { ! 376: m_freem(m); ! 377: return; ! 378: } ! 379: ifp->if_lastchange = time; ! 380: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh); ! 381: if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost, ! 382: sizeof(fddibroadcastaddr)) == 0) ! 383: m->m_flags |= M_BCAST; ! 384: else if (fh->fddi_dhost[0] & 1) ! 385: m->m_flags |= M_MCAST; ! 386: if (m->m_flags & (M_BCAST|M_MCAST)) ! 387: ifp->if_imcasts++; ! 388: ! 389: l = mtod(m, struct llc *); ! 390: switch (l->llc_dsap) { ! 391: #if defined(INET) || defined(NS) || defined(DECNET) ! 392: case LLC_SNAP_LSAP: ! 393: { ! 394: unsigned fddi_type; ! 395: if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP) ! 396: goto dropanyway; ! 397: if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0) ! 398: goto dropanyway; ! 399: fddi_type = ntohs(l->llc_snap.ether_type); ! 400: m_adj(m, 8); ! 401: switch (fddi_type) { ! 402: #if INET ! 403: case ETHERTYPE_IP: ! 404: schednetisr(NETISR_IP); ! 405: inq = &ipintrq; ! 406: break; ! 407: ! 408: case ETHERTYPE_ARP: ! 409: schednetisr(NETISR_ARP); ! 410: inq = &arpintrq; ! 411: break; ! 412: #endif ! 413: #if NS ! 414: case ETHERTYPE_NS: ! 415: schednetisr(NETISR_NS); ! 416: inq = &nsintrq; ! 417: break; ! 418: #endif ! 419: #if DECNET ! 420: case ETHERTYPE_DECENT: ! 421: schednetisr(NETISR_DECNET); ! 422: inq = &decnetintrq; ! 423: break; ! 424: #endif ! 425: default: ! 426: printf("fddi_input: unknown protocol 0x%x\n", fddi_type); ! 427: ifp->if_noproto++; ! 428: goto dropanyway; ! 429: } ! 430: break; ! 431: } ! 432: #endif /* INET || NS */ ! 433: #if defined(ISO) && notyet ! 434: case LLC_ISO_LSAP: ! 435: switch (l->llc_control) { ! 436: case LLC_UI: ! 437: /* LLC_UI_P forbidden in class 1 service */ ! 438: if ((l->llc_dsap == LLC_ISO_LSAP) && ! 439: (l->llc_ssap == LLC_ISO_LSAP)) { ! 440: /* LSAP for ISO */ ! 441: m->m_data += 3; /* XXX */ ! 442: m->m_len -= 3; /* XXX */ ! 443: m->m_pkthdr.len -= 3; /* XXX */ ! 444: M_PREPEND(m, sizeof *fh, M_DONTWAIT); ! 445: if (m == 0) ! 446: return; ! 447: *mtod(m, struct fddi_header *) = *fh; ! 448: IFDEBUG(D_ETHER) ! 449: printf("clnp packet"); ! 450: ENDDEBUG ! 451: schednetisr(NETISR_ISO); ! 452: inq = &clnlintrq; ! 453: break; ! 454: } ! 455: goto dropanyway; ! 456: ! 457: case LLC_XID: ! 458: case LLC_XID_P: ! 459: if(m->m_len < 6) ! 460: goto dropanyway; ! 461: l->llc_window = 0; ! 462: l->llc_fid = 9; ! 463: l->llc_class = 1; ! 464: l->llc_dsap = l->llc_ssap = 0; ! 465: /* Fall through to */ ! 466: case LLC_TEST: ! 467: case LLC_TEST_P: ! 468: { ! 469: struct sockaddr sa; ! 470: register struct ether_header *eh2; ! 471: int i; ! 472: u_char c = l->llc_dsap; ! 473: ! 474: l->llc_dsap = l->llc_ssap; ! 475: l->llc_ssap = c; ! 476: if (m->m_flags & (M_BCAST | M_MCAST)) ! 477: bcopy((caddr_t)ac->ac_enaddr, ! 478: (caddr_t)eh->ether_dhost, 6); ! 479: sa.sa_family = AF_UNSPEC; ! 480: sa.sa_len = sizeof(sa); ! 481: eh2 = (struct ether_header *)sa.sa_data; ! 482: for (i = 0; i < 6; i++) { ! 483: eh2->ether_shost[i] = c = eh->fddi_dhost[i]; ! 484: eh2->ether_dhost[i] = ! 485: eh->ether_dhost[i] = eh->fddi_shost[i]; ! 486: eh2->ether_shost[i] = c; ! 487: } ! 488: eh2->ether_type = 0; ! 489: ifp->if_output(ifp, m, &sa, NULL); ! 490: return; ! 491: } ! 492: default: ! 493: m_freem(m); ! 494: return; ! 495: } ! 496: break; ! 497: #endif /* defined(ISO) && notyet */ ! 498: #if LLC ! 499: case LLC_X25_LSAP: ! 500: { ! 501: M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); ! 502: if (m == 0) ! 503: return; ! 504: if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP, ! 505: fh->fddi_dhost, LLC_X25_LSAP, 6, ! 506: mtod(m, struct sdl_hdr *))) ! 507: panic("ETHER cons addr failure"); ! 508: mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr); ! 509: #if LLC_DEBUG ! 510: printf("llc packet\n"); ! 511: #endif /* LLC_DEBUG */ ! 512: schednetisr(NETISR_CCITT); ! 513: inq = &llcintrq; ! 514: break; ! 515: } ! 516: #endif /* LLC */ ! 517: ! 518: default: ! 519: printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); ! 520: ifp->if_noproto++; ! 521: dropanyway: ! 522: m_freem(m); ! 523: return; ! 524: } ! 525: ! 526: s = splimp(); ! 527: if (IF_QFULL(inq)) { ! 528: IF_DROP(inq); ! 529: m_freem(m); ! 530: } else ! 531: IF_ENQUEUE(inq, m); ! 532: splx(s); ! 533: } ! 534: /* ! 535: * Perform common duties while attaching to interface list ! 536: */ ! 537: void ! 538: fddi_ifattach(ifp) ! 539: register struct ifnet *ifp; ! 540: { ! 541: register struct ifaddr *ifa; ! 542: register struct sockaddr_dl *sdl; ! 543: ! 544: ifp->if_type = IFT_FDDI; ! 545: ifp->if_addrlen = 6; ! 546: ifp->if_hdrlen = 21; ! 547: ifp->if_mtu = FDDIMTU; ! 548: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 549: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && ! 550: sdl->sdl_family == AF_LINK) { ! 551: sdl->sdl_type = IFT_FDDI; ! 552: sdl->sdl_alen = ifp->if_addrlen; ! 553: bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, ! 554: LLADDR(sdl), ifp->if_addrlen); ! 555: break; ! 556: } ! 557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.