1 /* 2 * Copyright (c) 1982, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_ethersubr.c 7.23 (Berkeley) 02/25/93 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/kernel.h> 13 #include <sys/malloc.h> 14 #include <sys/mbuf.h> 15 #include <sys/protosw.h> 16 #include <sys/socket.h> 17 #include <sys/ioctl.h> 18 #include <sys/errno.h> 19 #include <sys/syslog.h> 20 21 #include <machine/cpu.h> 22 23 #include <net/if.h> 24 #include <net/netisr.h> 25 #include <net/route.h> 26 #include <net/if_llc.h> 27 #include <net/if_dl.h> 28 #include <net/if_types.h> 29 30 #ifdef INET 31 #include <netinet/in.h> 32 #include <netinet/in_var.h> 33 #endif 34 #include <netinet/if_ether.h> 35 36 #ifdef NS 37 #include <netns/ns.h> 38 #include <netns/ns_if.h> 39 #endif 40 41 #ifdef ISO 42 #include <netiso/argo_debug.h> 43 #include <netiso/iso.h> 44 #include <netiso/iso_var.h> 45 #include <netiso/iso_snpac.h> 46 #endif 47 48 #ifdef LLC 49 #include <netccitt/dll.h> 50 #include <netccitt/llc_var.h> 51 #endif 52 53 #if defined(LLC) && defined(CCITT) 54 extern struct ifqueue pkintrq; 55 #endif 56 57 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 58 extern struct ifnet loif; 59 #define senderr(e) { error = (e); goto bad;} 60 61 /* 62 * Ethernet output routine. 63 * Encapsulate a packet of type family for the local net. 64 * Use trailer local net encapsulation if enough data in first 65 * packet leaves a multiple of 512 bytes of data in remainder. 66 * Assumes that ifp is actually pointer to arpcom structure. 67 */ 68 ether_output(ifp, m0, dst, rt0) 69 register struct ifnet *ifp; 70 struct mbuf *m0; 71 struct sockaddr *dst; 72 struct rtentry *rt0; 73 { 74 short type; 75 int s, error = 0; 76 u_char edst[6]; 77 register struct mbuf *m = m0; 78 register struct rtentry *rt; 79 struct mbuf *mcopy = (struct mbuf *)0; 80 register struct ether_header *eh; 81 int off, len = m->m_pkthdr.len; 82 struct arpcom *ac = (struct arpcom *)ifp; 83 84 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 85 senderr(ENETDOWN); 86 ifp->if_lastchange = time; 87 if (rt = rt0) { 88 if ((rt->rt_flags & RTF_UP) == 0) { 89 if (rt0 = rt = rtalloc1(dst, 1)) 90 rt->rt_refcnt--; 91 else 92 senderr(EHOSTUNREACH); 93 } 94 if (rt->rt_flags & RTF_GATEWAY) { 95 if (rt->rt_gwroute == 0) 96 goto lookup; 97 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 98 rtfree(rt); rt = rt0; 99 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); 100 if ((rt = rt->rt_gwroute) == 0) 101 senderr(EHOSTUNREACH); 102 } 103 } 104 if (rt->rt_flags & RTF_REJECT) 105 if (rt->rt_rmx.rmx_expire == 0 || 106 time.tv_sec < rt->rt_rmx.rmx_expire) 107 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 108 } 109 switch (dst->sa_family) { 110 111 #ifdef INET 112 case AF_INET: 113 if (!arpresolve(ac, rt, m, (struct sockaddr_in *)dst, 114 edst)) 115 return (0); /* if not yet resolved */ 116 /* If broadcasting on a simplex interface, loopback a copy */ 117 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 118 mcopy = m_copy(m, 0, (int)M_COPYALL); 119 off = m->m_pkthdr.len - m->m_len; 120 type = ETHERTYPE_IP; 121 break; 122 #endif 123 #ifdef NS 124 case AF_NS: 125 type = ETHERTYPE_NS; 126 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 127 (caddr_t)edst, sizeof (edst)); 128 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) 129 return (looutput(ifp, m, dst, rt)); 130 /* If broadcasting on a simplex interface, loopback a copy */ 131 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 132 mcopy = m_copy(m, 0, (int)M_COPYALL); 133 break; 134 #endif 135 #ifdef ISO 136 case AF_ISO: { 137 int snpalen; 138 struct llc *l; 139 register struct sockaddr_dl *sdl; 140 141 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 142 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 143 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 144 } else if (error = 145 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 146 (char *)edst, &snpalen)) 147 goto bad; /* Not Resolved */ 148 /* If broadcasting on a simplex interface, loopback a copy */ 149 if (*edst & 1) 150 m->m_flags |= (M_BCAST|M_MCAST); 151 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && 152 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 153 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 154 if (mcopy) { 155 eh = mtod(mcopy, struct ether_header *); 156 bcopy((caddr_t)edst, 157 (caddr_t)eh->ether_dhost, sizeof (edst)); 158 bcopy((caddr_t)ac->ac_enaddr, 159 (caddr_t)eh->ether_shost, sizeof (edst)); 160 } 161 } 162 M_PREPEND(m, 3, M_DONTWAIT); 163 if (m == NULL) 164 return (0); 165 type = m->m_pkthdr.len; 166 l = mtod(m, struct llc *); 167 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 168 l->llc_control = LLC_UI; 169 len += 3; 170 IFDEBUG(D_ETHER) 171 int i; 172 printf("unoutput: sending pkt to: "); 173 for (i=0; i<6; i++) 174 printf("%x ", edst[i] & 0xff); 175 printf("\n"); 176 ENDDEBUG 177 } break; 178 #endif ISO 179 #ifdef LLC 180 /* case AF_NSAP: */ 181 case AF_CCITT: { 182 register struct sockaddr_dl *sdl = 183 (struct sockaddr_dl *) rt -> rt_gateway; 184 185 if (sdl && sdl->sdl_family == AF_LINK 186 && sdl->sdl_alen > 0) { 187 bcopy(LLADDR(sdl), (char *)edst, 188 sizeof(edst)); 189 } else goto bad; /* Not a link interface ? Funny ... */ 190 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && 191 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 192 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 193 if (mcopy) { 194 eh = mtod(mcopy, struct ether_header *); 195 bcopy((caddr_t)edst, 196 (caddr_t)eh->ether_dhost, sizeof (edst)); 197 bcopy((caddr_t)ac->ac_enaddr, 198 (caddr_t)eh->ether_shost, sizeof (edst)); 199 } 200 } 201 type = m->m_pkthdr.len; 202 #ifdef LLC_DEBUG 203 { 204 int i; 205 register struct llc *l = mtod(m, struct llc *); 206 207 printf("ether_output: sending LLC2 pkt to: "); 208 for (i=0; i<6; i++) 209 printf("%x ", edst[i] & 0xff); 210 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 211 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 212 l->llc_control & 0xff); 213 214 } 215 #endif LLC_DEBUG 216 } break; 217 #endif/* LLC */ 218 #ifdef RMP 219 case AF_RMP: 220 /* 221 * This is IEEE 802.3 -- the Ethernet `type' field is 222 * really a `length' field. 223 */ 224 type = m->m_len; 225 bcopy((caddr_t)dst->sa_data, (caddr_t)edst, sizeof(edst)); 226 break; 227 #endif 228 229 case AF_UNSPEC: 230 eh = (struct ether_header *)dst->sa_data; 231 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 232 type = eh->ether_type; 233 break; 234 235 default: 236 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 237 dst->sa_family); 238 senderr(EAFNOSUPPORT); 239 } 240 241 242 if (mcopy) 243 (void) looutput(ifp, mcopy, dst, rt); 244 /* 245 * Add local net header. If no space in first mbuf, 246 * allocate another. 247 */ 248 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 249 if (m == 0) 250 senderr(ENOBUFS); 251 eh = mtod(m, struct ether_header *); 252 type = htons((u_short)type); 253 bcopy((caddr_t)&type,(caddr_t)&eh->ether_type, 254 sizeof(eh->ether_type)); 255 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 256 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, 257 sizeof(eh->ether_shost)); 258 s = splimp(); 259 /* 260 * Queue message on interface, and start output if interface 261 * not yet active. 262 */ 263 if (IF_QFULL(&ifp->if_snd)) { 264 IF_DROP(&ifp->if_snd); 265 splx(s); 266 senderr(ENOBUFS); 267 } 268 IF_ENQUEUE(&ifp->if_snd, m); 269 if ((ifp->if_flags & IFF_OACTIVE) == 0) 270 (*ifp->if_start)(ifp); 271 splx(s); 272 ifp->if_obytes += len + sizeof (struct ether_header); 273 if (m->m_flags & M_MCAST) 274 ifp->if_omcasts++; 275 return (error); 276 277 bad: 278 if (m) 279 m_freem(m); 280 return (error); 281 } 282 283 /* 284 * Process a received Ethernet packet; 285 * the packet is in the mbuf chain m without 286 * the ether header, which is provided separately. 287 */ 288 ether_input(ifp, eh, m) 289 struct ifnet *ifp; 290 register struct ether_header *eh; 291 struct mbuf *m; 292 { 293 register struct ifqueue *inq; 294 register struct llc *l; 295 struct arpcom *ac = (struct arpcom *)ifp; 296 int s; 297 298 if ((ifp->if_flags & IFF_UP) == 0) { 299 m_freem(m); 300 return; 301 } 302 ifp->if_lastchange = time; 303 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 304 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 305 sizeof(etherbroadcastaddr)) == 0) 306 m->m_flags |= M_BCAST; 307 else if (eh->ether_dhost[0] & 1) 308 m->m_flags |= M_MCAST; 309 if (m->m_flags & (M_BCAST|M_MCAST)) 310 ifp->if_imcasts++; 311 312 switch (eh->ether_type) { 313 #ifdef INET 314 case ETHERTYPE_IP: 315 schednetisr(NETISR_IP); 316 inq = &ipintrq; 317 break; 318 319 case ETHERTYPE_ARP: 320 schednetisr(NETISR_ARP); 321 inq = &arpintrq; 322 break; 323 #endif 324 #ifdef NS 325 case ETHERTYPE_NS: 326 schednetisr(NETISR_NS); 327 inq = &nsintrq; 328 break; 329 330 #endif 331 default: 332 #if defined (ISO) || defined (LLC) 333 if (eh->ether_type > ETHERMTU) 334 goto dropanyway; 335 l = mtod(m, struct llc *); 336 switch (l->llc_dsap) { 337 #ifdef ISO 338 case LLC_ISO_LSAP: 339 switch (l->llc_control) { 340 case LLC_UI: 341 /* LLC_UI_P forbidden in class 1 service */ 342 if ((l->llc_dsap == LLC_ISO_LSAP) && 343 (l->llc_ssap == LLC_ISO_LSAP)) { 344 /* LSAP for ISO */ 345 if (m->m_pkthdr.len > eh->ether_type) 346 m_adj(m, eh->ether_type - m->m_pkthdr.len); 347 m->m_data += 3; /* XXX */ 348 m->m_len -= 3; /* XXX */ 349 m->m_pkthdr.len -= 3; /* XXX */ 350 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 351 if (m == 0) 352 return; 353 *mtod(m, struct ether_header *) = *eh; 354 IFDEBUG(D_ETHER) 355 printf("clnp packet"); 356 ENDDEBUG 357 schednetisr(NETISR_ISO); 358 inq = &clnlintrq; 359 break; 360 } 361 goto dropanyway; 362 363 case LLC_XID: 364 case LLC_XID_P: 365 if(m->m_len < 6) 366 goto dropanyway; 367 l->llc_window = 0; 368 l->llc_fid = 9; 369 l->llc_class = 1; 370 l->llc_dsap = l->llc_ssap = 0; 371 /* Fall through to */ 372 case LLC_TEST: 373 case LLC_TEST_P: 374 { 375 struct sockaddr sa; 376 register struct ether_header *eh2; 377 int i; 378 u_char c = l->llc_dsap; 379 380 l->llc_dsap = l->llc_ssap; 381 l->llc_ssap = c; 382 if (m->m_flags & (M_BCAST | M_MCAST)) 383 bcopy((caddr_t)ac->ac_enaddr, 384 (caddr_t)eh->ether_dhost, 6); 385 sa.sa_family = AF_UNSPEC; 386 sa.sa_len = sizeof(sa); 387 eh2 = (struct ether_header *)sa.sa_data; 388 for (i = 0; i < 6; i++) { 389 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 390 eh2->ether_dhost[i] = 391 eh->ether_dhost[i] = eh->ether_shost[i]; 392 eh->ether_shost[i] = c; 393 } 394 ifp->if_output(ifp, m, &sa, NULL); 395 return; 396 } 397 default: 398 m_freem(m); 399 return; 400 } 401 break; 402 #endif /* ISO */ 403 #ifdef LLC 404 case LLC_X25_LSAP: 405 { 406 if (m->m_pkthdr.len > eh->ether_type) 407 m_adj(m, eh->ether_type - m->m_pkthdr.len); 408 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 409 if (m == 0) 410 return; 411 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 412 eh->ether_dhost, LLC_X25_LSAP, 6, 413 mtod(m, struct sdl_hdr *))) 414 panic("ETHER cons addr failure"); 415 mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type; 416 #ifdef LLC_DEBUG 417 printf("llc packet\n"); 418 #endif LLC_DEBUG 419 schednetisr(NETISR_CCITT); 420 inq = &llcintrq; 421 break; 422 } 423 #endif /* LLC */ 424 dropanyway: 425 default: 426 m_freem(m); 427 return; 428 } 429 #else /* ISO || LLC */ 430 m_freem(m); 431 return; 432 #endif /* ISO || LLC */ 433 } 434 435 s = splimp(); 436 if (IF_QFULL(inq)) { 437 IF_DROP(inq); 438 m_freem(m); 439 } else 440 IF_ENQUEUE(inq, m); 441 splx(s); 442 } 443 444 /* 445 * Convert Ethernet address to printable (loggable) representation. 446 */ 447 static char digits[] = "0123456789abcdef"; 448 char * 449 ether_sprintf(ap) 450 register u_char *ap; 451 { 452 register i; 453 static char etherbuf[18]; 454 register char *cp = etherbuf; 455 456 for (i = 0; i < 6; i++) { 457 *cp++ = digits[*ap >> 4]; 458 *cp++ = digits[*ap++ & 0xf]; 459 *cp++ = ':'; 460 } 461 *--cp = 0; 462 return (etherbuf); 463 } 464 465 /* 466 * Perform common duties while attaching to interface list 467 */ 468 ether_ifattach(ifp) 469 register struct ifnet *ifp; 470 { 471 register struct ifaddr *ifa; 472 register struct sockaddr_dl *sdl; 473 474 ifp->if_type = IFT_ETHER; 475 ifp->if_addrlen = 6; 476 ifp->if_hdrlen = 14; 477 ifp->if_mtu = ETHERMTU; 478 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 479 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 480 sdl->sdl_family == AF_LINK) { 481 sdl->sdl_type = IFT_ETHER; 482 sdl->sdl_alen = ifp->if_addrlen; 483 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 484 LLADDR(sdl), ifp->if_addrlen); 485 break; 486 } 487 } 488 489 u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 490 u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 491 /* 492 * Add an Ethernet multicast address or range of addresses to the list for a 493 * given interface. 494 */ 495 int 496 ether_addmulti(ifr, ac) 497 struct ifreq *ifr; 498 register struct arpcom *ac; 499 { 500 register struct ether_multi *enm; 501 struct sockaddr_in *sin; 502 u_char addrlo[6]; 503 u_char addrhi[6]; 504 int s = splimp(); 505 506 switch (ifr->ifr_addr.sa_family) { 507 508 case AF_UNSPEC: 509 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 510 bcopy(addrlo, addrhi, 6); 511 break; 512 513 #ifdef INET 514 case AF_INET: 515 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 516 if (sin->sin_addr.s_addr == INADDR_ANY) { 517 /* 518 * An IP address of INADDR_ANY means listen to all 519 * of the Ethernet multicast addresses used for IP. 520 * (This is for the sake of IP multicast routers.) 521 */ 522 bcopy(ether_ipmulticast_min, addrlo, 6); 523 bcopy(ether_ipmulticast_max, addrhi, 6); 524 } 525 else { 526 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 527 bcopy(addrlo, addrhi, 6); 528 } 529 break; 530 #endif 531 532 default: 533 splx(s); 534 return (EAFNOSUPPORT); 535 } 536 537 /* 538 * Verify that we have valid Ethernet multicast addresses. 539 */ 540 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 541 splx(s); 542 return (EINVAL); 543 } 544 /* 545 * See if the address range is already in the list. 546 */ 547 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 548 if (enm != NULL) { 549 /* 550 * Found it; just increment the reference count. 551 */ 552 ++enm->enm_refcount; 553 splx(s); 554 return (0); 555 } 556 /* 557 * New address or range; malloc a new multicast record 558 * and link it into the interface's multicast list. 559 */ 560 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 561 if (enm == NULL) { 562 splx(s); 563 return (ENOBUFS); 564 } 565 bcopy(addrlo, enm->enm_addrlo, 6); 566 bcopy(addrhi, enm->enm_addrhi, 6); 567 enm->enm_ac = ac; 568 enm->enm_refcount = 1; 569 enm->enm_next = ac->ac_multiaddrs; 570 ac->ac_multiaddrs = enm; 571 ac->ac_multicnt++; 572 splx(s); 573 /* 574 * Return ENETRESET to inform the driver that the list has changed 575 * and its reception filter should be adjusted accordingly. 576 */ 577 return (ENETRESET); 578 } 579 580 /* 581 * Delete a multicast address record. 582 */ 583 int 584 ether_delmulti(ifr, ac) 585 struct ifreq *ifr; 586 register struct arpcom *ac; 587 { 588 register struct ether_multi *enm; 589 register struct ether_multi **p; 590 struct sockaddr_in *sin; 591 u_char addrlo[6]; 592 u_char addrhi[6]; 593 int s = splimp(); 594 595 switch (ifr->ifr_addr.sa_family) { 596 597 case AF_UNSPEC: 598 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 599 bcopy(addrlo, addrhi, 6); 600 break; 601 602 #ifdef INET 603 case AF_INET: 604 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 605 if (sin->sin_addr.s_addr == INADDR_ANY) { 606 /* 607 * An IP address of INADDR_ANY means stop listening 608 * to the range of Ethernet multicast addresses used 609 * for IP. 610 */ 611 bcopy(ether_ipmulticast_min, addrlo, 6); 612 bcopy(ether_ipmulticast_max, addrhi, 6); 613 } 614 else { 615 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 616 bcopy(addrlo, addrhi, 6); 617 } 618 break; 619 #endif 620 621 default: 622 splx(s); 623 return (EAFNOSUPPORT); 624 } 625 626 /* 627 * Look up the address in our list. 628 */ 629 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 630 if (enm == NULL) { 631 splx(s); 632 return (ENXIO); 633 } 634 if (--enm->enm_refcount != 0) { 635 /* 636 * Still some claims to this record. 637 */ 638 splx(s); 639 return (0); 640 } 641 /* 642 * No remaining claims to this record; unlink and free it. 643 */ 644 for (p = &enm->enm_ac->ac_multiaddrs; 645 *p != enm; 646 p = &(*p)->enm_next) 647 continue; 648 *p = (*p)->enm_next; 649 free(enm, M_IFMADDR); 650 ac->ac_multicnt--; 651 splx(s); 652 /* 653 * Return ENETRESET to inform the driver that the list has changed 654 * and its reception filter should be adjusted accordingly. 655 */ 656 return (ENETRESET); 657 } 658