|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)if_ethersubr.c 7.10 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "systm.h" ! 25: #include "malloc.h" ! 26: #include "mbuf.h" ! 27: #include "protosw.h" ! 28: #include "socket.h" ! 29: #include "ioctl.h" ! 30: #include "errno.h" ! 31: #include "syslog.h" ! 32: ! 33: #include "if.h" ! 34: #include "netisr.h" ! 35: #include "route.h" ! 36: #include "if_llc.h" ! 37: #include "if_dl.h" ! 38: ! 39: #include "machine/mtpr.h" ! 40: ! 41: #ifdef INET ! 42: #include "../netinet/in.h" ! 43: #include "../netinet/in_var.h" ! 44: #include "../netinet/if_ether.h" ! 45: #endif ! 46: ! 47: #ifdef NS ! 48: #include "../netns/ns.h" ! 49: #include "../netns/ns_if.h" ! 50: #endif ! 51: ! 52: #ifdef ISO ! 53: #include "../netiso/argo_debug.h" ! 54: #include "../netiso/iso.h" ! 55: #include "../netiso/iso_var.h" ! 56: #include "../netiso/iso_snpac.h" ! 57: #endif ! 58: ! 59: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ! 60: extern struct ifnet loif; ! 61: ! 62: /* ! 63: * Ethernet output routine. ! 64: * Encapsulate a packet of type family for the local net. ! 65: * Use trailer local net encapsulation if enough data in first ! 66: * packet leaves a multiple of 512 bytes of data in remainder. ! 67: * Assumes that ifp is actually pointer to arpcom structure. ! 68: */ ! 69: ether_output(ifp, m0, dst, rt) ! 70: register struct ifnet *ifp; ! 71: struct mbuf *m0; ! 72: struct sockaddr *dst; ! 73: struct rtentry *rt; ! 74: { ! 75: short type; ! 76: int s, error = 0; ! 77: u_char edst[6]; ! 78: struct in_addr idst; ! 79: register struct mbuf *m = m0; ! 80: struct mbuf *mcopy = (struct mbuf *)0; ! 81: register struct ether_header *eh; ! 82: int usetrailers, off, len = m->m_pkthdr.len; ! 83: extern struct timeval time; ! 84: #define ac ((struct arpcom *)ifp) ! 85: ! 86: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 87: error = ENETDOWN; ! 88: goto bad; ! 89: } ! 90: ifp->if_lastchange = time; ! 91: switch (dst->sa_family) { ! 92: ! 93: #ifdef INET ! 94: case AF_INET: ! 95: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 96: if (!arpresolve(ac, m, &idst, edst, &usetrailers)) ! 97: return (0); /* if not yet resolved */ ! 98: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1)) ! 99: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 100: off = m->m_pkthdr.len - m->m_len; ! 101: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && ! 102: (m->m_flags & M_EXT) == 0 && ! 103: m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) { ! 104: type = ETHERTYPE_TRAIL + (off>>9); ! 105: m->m_data -= 2 * sizeof (u_short); ! 106: m->m_len += 2 * sizeof (u_short); ! 107: len += 2 * sizeof (u_short); ! 108: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); ! 109: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); ! 110: goto gottrailertype; ! 111: } ! 112: type = ETHERTYPE_IP; ! 113: goto gottype; ! 114: #endif ! 115: #ifdef NS ! 116: case AF_NS: ! 117: type = ETHERTYPE_NS; ! 118: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 119: (caddr_t)edst, sizeof (edst)); ! 120: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) ! 121: return (looutput(&loif, m, dst)); ! 122: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1)) ! 123: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 124: goto gottype; ! 125: #endif ! 126: #ifdef ISO ! 127: case AF_ISO: { ! 128: int snpalen; ! 129: struct llc *l; ! 130: ! 131: iso_again: ! 132: iso_etherout(); ! 133: if (rt && rt->rt_gateway && (rt->rt_flags & RTF_UP)) { ! 134: if (rt->rt_flags & RTF_GATEWAY) { ! 135: if (rt->rt_llinfo) { ! 136: rt = (struct rtentry *)rt->rt_llinfo; ! 137: goto iso_again; ! 138: } ! 139: } else { ! 140: register struct sockaddr_dl *sdl = ! 141: (struct sockaddr_dl *)rt->rt_gateway; ! 142: if (sdl && sdl->sdl_family == AF_LINK ! 143: && sdl->sdl_alen > 0) { ! 144: bcopy(LLADDR(sdl), (char *)edst, ! 145: sizeof(edst)); ! 146: goto iso_resolved; ! 147: } ! 148: } ! 149: } ! 150: if ((error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst, ! 151: (char *)edst, &snpalen)) > 0) ! 152: goto bad; /* Not Resolved */ ! 153: iso_resolved: ! 154: M_PREPEND(m, 3, M_DONTWAIT); ! 155: if (m == NULL) ! 156: return (0); ! 157: type = m->m_pkthdr.len; ! 158: l = mtod(m, struct llc *); ! 159: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; ! 160: l->llc_control = LLC_UI; ! 161: len += 3; ! 162: IFDEBUG(D_ETHER) ! 163: int i; ! 164: printf("unoutput: sending pkt to: "); ! 165: for (i=0; i<6; i++) ! 166: printf("%x ", edst[i] & 0xff); ! 167: printf("\n"); ! 168: ENDDEBUG ! 169: } goto gottype; ! 170: #endif ISO ! 171: #ifdef RMP ! 172: case AF_RMP: ! 173: /* ! 174: * This is IEEE 802.3 -- the Ethernet `type' field is ! 175: * really a `length' field. ! 176: */ ! 177: type = m->m_len; ! 178: bcopy((caddr_t)dst->sa_data, (caddr_t)edst, sizeof(edst)); ! 179: break; ! 180: #endif ! 181: ! 182: case AF_UNSPEC: ! 183: eh = (struct ether_header *)dst->sa_data; ! 184: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 185: type = eh->ether_type; ! 186: goto gottype; ! 187: ! 188: default: ! 189: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, ! 190: dst->sa_family); ! 191: error = EAFNOSUPPORT; ! 192: goto bad; ! 193: } ! 194: ! 195: gottrailertype: ! 196: /* ! 197: * Packet to be sent as trailer: move first packet ! 198: * (control information) to end of chain. ! 199: */ ! 200: while (m->m_next) ! 201: m = m->m_next; ! 202: m->m_next = m0; ! 203: m = m0->m_next; ! 204: m0->m_next = 0; ! 205: ! 206: gottype: ! 207: /* ! 208: * Add local net header. If no space in first mbuf, ! 209: * allocate another. ! 210: */ ! 211: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); ! 212: if (m == 0) { ! 213: error = ENOBUFS; ! 214: goto bad; ! 215: } ! 216: eh = mtod(m, struct ether_header *); ! 217: type = htons((u_short)type); ! 218: bcopy((caddr_t)&type,(caddr_t)&eh->ether_type, ! 219: sizeof(eh->ether_type)); ! 220: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); ! 221: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, ! 222: sizeof(eh->ether_shost)); ! 223: /* ! 224: * Queue message on interface, and start output if interface ! 225: * not yet active. ! 226: */ ! 227: s = splimp(); ! 228: if (IF_QFULL(&ifp->if_snd)) { ! 229: IF_DROP(&ifp->if_snd); ! 230: splx(s); ! 231: error = ENOBUFS; ! 232: goto bad; ! 233: } ! 234: IF_ENQUEUE(&ifp->if_snd, m); ! 235: if ((ifp->if_flags & IFF_OACTIVE) == 0) ! 236: (*ifp->if_start)(ifp); ! 237: splx(s); ! 238: if (mcopy) ! 239: (void) looutput(&loif, mcopy, dst); ! 240: ifp->if_obytes += len + sizeof (struct ether_header); ! 241: if (edst[0] & 1) ! 242: ifp->if_omcasts++; ! 243: return (error); ! 244: ! 245: bad: ! 246: if (mcopy) ! 247: m_freem(mcopy); ! 248: if (m) ! 249: m_freem(m); ! 250: return (error); ! 251: } ! 252: ! 253: /* ! 254: * Process a received Ethernet packet; ! 255: * the packet is in the mbuf chain m without ! 256: * the ether header, which is provided separately. ! 257: */ ! 258: ether_input(ifp, eh, m) ! 259: struct ifnet *ifp; ! 260: register struct ether_header *eh; ! 261: struct mbuf *m; ! 262: { ! 263: register struct ifqueue *inq; ! 264: register struct llc *l; ! 265: int s; ! 266: ! 267: ifp->if_lastchange = time; ! 268: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); ! 269: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, ! 270: sizeof(etherbroadcastaddr)) == 0) ! 271: m->m_flags |= M_BCAST; ! 272: else if (eh->ether_dhost[0] & 1) ! 273: m->m_flags |= M_MCAST; ! 274: if (m->m_flags & (M_BCAST|M_MCAST)) ! 275: ifp->if_imcasts++; ! 276: ! 277: switch (eh->ether_type) { ! 278: #ifdef INET ! 279: case ETHERTYPE_IP: ! 280: schednetisr(NETISR_IP); ! 281: inq = &ipintrq; ! 282: break; ! 283: ! 284: case ETHERTYPE_ARP: ! 285: arpinput((struct arpcom *)ifp, m); ! 286: return; ! 287: #endif ! 288: #ifdef NS ! 289: case ETHERTYPE_NS: ! 290: schednetisr(NETISR_NS); ! 291: inq = &nsintrq; ! 292: break; ! 293: ! 294: #endif ! 295: default: ! 296: #ifdef ISO ! 297: if (eh->ether_type > ETHERMTU) ! 298: goto dropanyway; ! 299: l = mtod(m, struct llc *); ! 300: switch (l->llc_control) { ! 301: case LLC_UI: ! 302: /* LLC_UI_P forbidden in class 1 service */ ! 303: if ((l->llc_dsap == LLC_ISO_LSAP) && ! 304: (l->llc_ssap == LLC_ISO_LSAP)) { ! 305: /* LSAP for ISO */ ! 306: m->m_data += 3; /* XXX */ ! 307: m->m_len -= 3; /* XXX */ ! 308: m->m_pkthdr.len -= 3; /* XXX */ ! 309: M_PREPEND(m, sizeof *eh, M_DONTWAIT); ! 310: if (m == 0) ! 311: return; ! 312: *mtod(m, struct ether_header *) = *eh; ! 313: IFDEBUG(D_ETHER) ! 314: printf("clnp packet"); ! 315: ENDDEBUG ! 316: schednetisr(NETISR_ISO); ! 317: inq = &clnlintrq; ! 318: break; ! 319: } ! 320: goto dropanyway; ! 321: ! 322: case LLC_XID: ! 323: case LLC_XID_P: ! 324: if(m->m_len < 6) ! 325: goto dropanyway; ! 326: l->llc_window = 0; ! 327: l->llc_fid = 9; ! 328: l->llc_class = 1; ! 329: l->llc_dsap = l->llc_ssap = 0; ! 330: /* Fall through to */ ! 331: case LLC_TEST: ! 332: case LLC_TEST_P: ! 333: { ! 334: struct sockaddr sa; ! 335: register struct ether_header *eh2; ! 336: int i; ! 337: u_char c = l->llc_dsap; ! 338: l->llc_dsap = l->llc_ssap; ! 339: l->llc_ssap = c; ! 340: if (m->m_flags & (M_BCAST | M_MCAST)) ! 341: bcopy((caddr_t)ac->ac_enaddr, ! 342: (caddr_t)eh->ether_dhost, 6); ! 343: sa.sa_family = AF_UNSPEC; ! 344: sa.sa_len = sizeof(sa); ! 345: eh2 = (struct ether_header *)sa.sa_data; ! 346: for (i = 0; i < 6; i++) { ! 347: eh2->ether_shost[i] = c = eh->ether_dhost[i]; ! 348: eh2->ether_dhost[i] = ! 349: eh->ether_dhost[i] = eh->ether_shost[i]; ! 350: eh->ether_shost[i] = c; ! 351: } ! 352: ifp->if_output(ifp, m, &sa); ! 353: return; ! 354: } ! 355: dropanyway: ! 356: default: ! 357: m_freem(m); ! 358: return; ! 359: } ! 360: #else ! 361: m_freem(m); ! 362: return; ! 363: #endif ISO ! 364: } ! 365: ! 366: s = splimp(); ! 367: if (IF_QFULL(inq)) { ! 368: IF_DROP(inq); ! 369: m_freem(m); ! 370: } else ! 371: IF_ENQUEUE(inq, m); ! 372: splx(s); ! 373: } ! 374: ! 375: /* ! 376: * Convert Ethernet address to printable (loggable) representation. ! 377: */ ! 378: static char digits[] = "0123456789abcdef"; ! 379: char * ! 380: ether_sprintf(ap) ! 381: register u_char *ap; ! 382: { ! 383: register i; ! 384: static char etherbuf[18]; ! 385: register char *cp = etherbuf; ! 386: ! 387: for (i = 0; i < 6; i++) { ! 388: *cp++ = digits[*ap >> 4]; ! 389: *cp++ = digits[*ap++ & 0xf]; ! 390: *cp++ = ':'; ! 391: } ! 392: *--cp = 0; ! 393: return (etherbuf); ! 394: } ! 395: iso_etherout() {}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.