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.26 (Berkeley) 06/04/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 int 69 ether_output(ifp, m0, dst, rt0) 70 register struct ifnet *ifp; 71 struct mbuf *m0; 72 struct sockaddr *dst; 73 struct rtentry *rt0; 74 { 75 short type; 76 int s, error = 0; 77 u_char edst[6]; 78 register struct mbuf *m = m0; 79 register struct rtentry *rt; 80 struct mbuf *mcopy = (struct mbuf *)0; 81 register struct ether_header *eh; 82 int off, len = m->m_pkthdr.len; 83 struct arpcom *ac = (struct arpcom *)ifp; 84 85 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 86 senderr(ENETDOWN); 87 ifp->if_lastchange = time; 88 if (rt = rt0) { 89 if ((rt->rt_flags & RTF_UP) == 0) { 90 if (rt0 = rt = rtalloc1(dst, 1)) 91 rt->rt_refcnt--; 92 else 93 senderr(EHOSTUNREACH); 94 } 95 if (rt->rt_flags & RTF_GATEWAY) { 96 if (rt->rt_gwroute == 0) 97 goto lookup; 98 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 99 rtfree(rt); rt = rt0; 100 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); 101 if ((rt = rt->rt_gwroute) == 0) 102 senderr(EHOSTUNREACH); 103 } 104 } 105 if (rt->rt_flags & RTF_REJECT) 106 if (rt->rt_rmx.rmx_expire == 0 || 107 time.tv_sec < rt->rt_rmx.rmx_expire) 108 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 109 } 110 switch (dst->sa_family) { 111 112 #ifdef INET 113 case AF_INET: 114 if (!arpresolve(ac, rt, m, dst, 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 219 case AF_UNSPEC: 220 eh = (struct ether_header *)dst->sa_data; 221 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 222 type = eh->ether_type; 223 break; 224 225 default: 226 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 227 dst->sa_family); 228 senderr(EAFNOSUPPORT); 229 } 230 231 232 if (mcopy) 233 (void) looutput(ifp, mcopy, dst, rt); 234 /* 235 * Add local net header. If no space in first mbuf, 236 * allocate another. 237 */ 238 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 239 if (m == 0) 240 senderr(ENOBUFS); 241 eh = mtod(m, struct ether_header *); 242 type = htons((u_short)type); 243 bcopy((caddr_t)&type,(caddr_t)&eh->ether_type, 244 sizeof(eh->ether_type)); 245 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 246 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, 247 sizeof(eh->ether_shost)); 248 s = splimp(); 249 /* 250 * Queue message on interface, and start output if interface 251 * not yet active. 252 */ 253 if (IF_QFULL(&ifp->if_snd)) { 254 IF_DROP(&ifp->if_snd); 255 splx(s); 256 senderr(ENOBUFS); 257 } 258 IF_ENQUEUE(&ifp->if_snd, m); 259 if ((ifp->if_flags & IFF_OACTIVE) == 0) 260 (*ifp->if_start)(ifp); 261 splx(s); 262 ifp->if_obytes += len + sizeof (struct ether_header); 263 if (m->m_flags & M_MCAST) 264 ifp->if_omcasts++; 265 return (error); 266 267 bad: 268 if (m) 269 m_freem(m); 270 return (error); 271 } 272 273 /* 274 * Process a received Ethernet packet; 275 * the packet is in the mbuf chain m without 276 * the ether header, which is provided separately. 277 */ 278 void 279 ether_input(ifp, eh, m) 280 struct ifnet *ifp; 281 register struct ether_header *eh; 282 struct mbuf *m; 283 { 284 register struct ifqueue *inq; 285 register struct llc *l; 286 struct arpcom *ac = (struct arpcom *)ifp; 287 int s; 288 289 if ((ifp->if_flags & IFF_UP) == 0) { 290 m_freem(m); 291 return; 292 } 293 ifp->if_lastchange = time; 294 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 295 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 296 sizeof(etherbroadcastaddr)) == 0) 297 m->m_flags |= M_BCAST; 298 else if (eh->ether_dhost[0] & 1) 299 m->m_flags |= M_MCAST; 300 if (m->m_flags & (M_BCAST|M_MCAST)) 301 ifp->if_imcasts++; 302 303 switch (eh->ether_type) { 304 #ifdef INET 305 case ETHERTYPE_IP: 306 schednetisr(NETISR_IP); 307 inq = &ipintrq; 308 break; 309 310 case ETHERTYPE_ARP: 311 schednetisr(NETISR_ARP); 312 inq = &arpintrq; 313 break; 314 #endif 315 #ifdef NS 316 case ETHERTYPE_NS: 317 schednetisr(NETISR_NS); 318 inq = &nsintrq; 319 break; 320 321 #endif 322 default: 323 #if defined (ISO) || defined (LLC) 324 if (eh->ether_type > ETHERMTU) 325 goto dropanyway; 326 l = mtod(m, struct llc *); 327 switch (l->llc_dsap) { 328 #ifdef ISO 329 case LLC_ISO_LSAP: 330 switch (l->llc_control) { 331 case LLC_UI: 332 /* LLC_UI_P forbidden in class 1 service */ 333 if ((l->llc_dsap == LLC_ISO_LSAP) && 334 (l->llc_ssap == LLC_ISO_LSAP)) { 335 /* LSAP for ISO */ 336 if (m->m_pkthdr.len > eh->ether_type) 337 m_adj(m, eh->ether_type - m->m_pkthdr.len); 338 m->m_data += 3; /* XXX */ 339 m->m_len -= 3; /* XXX */ 340 m->m_pkthdr.len -= 3; /* XXX */ 341 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 342 if (m == 0) 343 return; 344 *mtod(m, struct ether_header *) = *eh; 345 IFDEBUG(D_ETHER) 346 printf("clnp packet"); 347 ENDDEBUG 348 schednetisr(NETISR_ISO); 349 inq = &clnlintrq; 350 break; 351 } 352 goto dropanyway; 353 354 case LLC_XID: 355 case LLC_XID_P: 356 if(m->m_len < 6) 357 goto dropanyway; 358 l->llc_window = 0; 359 l->llc_fid = 9; 360 l->llc_class = 1; 361 l->llc_dsap = l->llc_ssap = 0; 362 /* Fall through to */ 363 case LLC_TEST: 364 case LLC_TEST_P: 365 { 366 struct sockaddr sa; 367 register struct ether_header *eh2; 368 int i; 369 u_char c = l->llc_dsap; 370 371 l->llc_dsap = l->llc_ssap; 372 l->llc_ssap = c; 373 if (m->m_flags & (M_BCAST | M_MCAST)) 374 bcopy((caddr_t)ac->ac_enaddr, 375 (caddr_t)eh->ether_dhost, 6); 376 sa.sa_family = AF_UNSPEC; 377 sa.sa_len = sizeof(sa); 378 eh2 = (struct ether_header *)sa.sa_data; 379 for (i = 0; i < 6; i++) { 380 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 381 eh2->ether_dhost[i] = 382 eh->ether_dhost[i] = eh->ether_shost[i]; 383 eh->ether_shost[i] = c; 384 } 385 ifp->if_output(ifp, m, &sa, NULL); 386 return; 387 } 388 default: 389 m_freem(m); 390 return; 391 } 392 break; 393 #endif /* ISO */ 394 #ifdef LLC 395 case LLC_X25_LSAP: 396 { 397 if (m->m_pkthdr.len > eh->ether_type) 398 m_adj(m, eh->ether_type - m->m_pkthdr.len); 399 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 400 if (m == 0) 401 return; 402 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 403 eh->ether_dhost, LLC_X25_LSAP, 6, 404 mtod(m, struct sdl_hdr *))) 405 panic("ETHER cons addr failure"); 406 mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type; 407 #ifdef LLC_DEBUG 408 printf("llc packet\n"); 409 #endif /* LLC_DEBUG */ 410 schednetisr(NETISR_CCITT); 411 inq = &llcintrq; 412 break; 413 } 414 #endif /* LLC */ 415 dropanyway: 416 default: 417 m_freem(m); 418 return; 419 } 420 #else /* ISO || LLC */ 421 m_freem(m); 422 return; 423 #endif /* ISO || LLC */ 424 } 425 426 s = splimp(); 427 if (IF_QFULL(inq)) { 428 IF_DROP(inq); 429 m_freem(m); 430 } else 431 IF_ENQUEUE(inq, m); 432 splx(s); 433 } 434 435 /* 436 * Convert Ethernet address to printable (loggable) representation. 437 */ 438 static char digits[] = "0123456789abcdef"; 439 char * 440 ether_sprintf(ap) 441 register u_char *ap; 442 { 443 register i; 444 static char etherbuf[18]; 445 register char *cp = etherbuf; 446 447 for (i = 0; i < 6; i++) { 448 *cp++ = digits[*ap >> 4]; 449 *cp++ = digits[*ap++ & 0xf]; 450 *cp++ = ':'; 451 } 452 *--cp = 0; 453 return (etherbuf); 454 } 455 456 /* 457 * Perform common duties while attaching to interface list 458 */ 459 void 460 ether_ifattach(ifp) 461 register struct ifnet *ifp; 462 { 463 register struct ifaddr *ifa; 464 register struct sockaddr_dl *sdl; 465 466 ifp->if_type = IFT_ETHER; 467 ifp->if_addrlen = 6; 468 ifp->if_hdrlen = 14; 469 ifp->if_mtu = ETHERMTU; 470 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 471 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 472 sdl->sdl_family == AF_LINK) { 473 sdl->sdl_type = IFT_ETHER; 474 sdl->sdl_alen = ifp->if_addrlen; 475 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 476 LLADDR(sdl), ifp->if_addrlen); 477 break; 478 } 479 } 480 481 u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 482 u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 483 /* 484 * Add an Ethernet multicast address or range of addresses to the list for a 485 * given interface. 486 */ 487 int 488 ether_addmulti(ifr, ac) 489 struct ifreq *ifr; 490 register struct arpcom *ac; 491 { 492 register struct ether_multi *enm; 493 struct sockaddr_in *sin; 494 u_char addrlo[6]; 495 u_char addrhi[6]; 496 int s = splimp(); 497 498 switch (ifr->ifr_addr.sa_family) { 499 500 case AF_UNSPEC: 501 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 502 bcopy(addrlo, addrhi, 6); 503 break; 504 505 #ifdef INET 506 case AF_INET: 507 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 508 if (sin->sin_addr.s_addr == INADDR_ANY) { 509 /* 510 * An IP address of INADDR_ANY means listen to all 511 * of the Ethernet multicast addresses used for IP. 512 * (This is for the sake of IP multicast routers.) 513 */ 514 bcopy(ether_ipmulticast_min, addrlo, 6); 515 bcopy(ether_ipmulticast_max, addrhi, 6); 516 } 517 else { 518 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 519 bcopy(addrlo, addrhi, 6); 520 } 521 break; 522 #endif 523 524 default: 525 splx(s); 526 return (EAFNOSUPPORT); 527 } 528 529 /* 530 * Verify that we have valid Ethernet multicast addresses. 531 */ 532 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 533 splx(s); 534 return (EINVAL); 535 } 536 /* 537 * See if the address range is already in the list. 538 */ 539 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 540 if (enm != NULL) { 541 /* 542 * Found it; just increment the reference count. 543 */ 544 ++enm->enm_refcount; 545 splx(s); 546 return (0); 547 } 548 /* 549 * New address or range; malloc a new multicast record 550 * and link it into the interface's multicast list. 551 */ 552 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 553 if (enm == NULL) { 554 splx(s); 555 return (ENOBUFS); 556 } 557 bcopy(addrlo, enm->enm_addrlo, 6); 558 bcopy(addrhi, enm->enm_addrhi, 6); 559 enm->enm_ac = ac; 560 enm->enm_refcount = 1; 561 enm->enm_next = ac->ac_multiaddrs; 562 ac->ac_multiaddrs = enm; 563 ac->ac_multicnt++; 564 splx(s); 565 /* 566 * Return ENETRESET to inform the driver that the list has changed 567 * and its reception filter should be adjusted accordingly. 568 */ 569 return (ENETRESET); 570 } 571 572 /* 573 * Delete a multicast address record. 574 */ 575 int 576 ether_delmulti(ifr, ac) 577 struct ifreq *ifr; 578 register struct arpcom *ac; 579 { 580 register struct ether_multi *enm; 581 register struct ether_multi **p; 582 struct sockaddr_in *sin; 583 u_char addrlo[6]; 584 u_char addrhi[6]; 585 int s = splimp(); 586 587 switch (ifr->ifr_addr.sa_family) { 588 589 case AF_UNSPEC: 590 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 591 bcopy(addrlo, addrhi, 6); 592 break; 593 594 #ifdef INET 595 case AF_INET: 596 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 597 if (sin->sin_addr.s_addr == INADDR_ANY) { 598 /* 599 * An IP address of INADDR_ANY means stop listening 600 * to the range of Ethernet multicast addresses used 601 * for IP. 602 */ 603 bcopy(ether_ipmulticast_min, addrlo, 6); 604 bcopy(ether_ipmulticast_max, addrhi, 6); 605 } 606 else { 607 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 608 bcopy(addrlo, addrhi, 6); 609 } 610 break; 611 #endif 612 613 default: 614 splx(s); 615 return (EAFNOSUPPORT); 616 } 617 618 /* 619 * Look up the address in our list. 620 */ 621 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 622 if (enm == NULL) { 623 splx(s); 624 return (ENXIO); 625 } 626 if (--enm->enm_refcount != 0) { 627 /* 628 * Still some claims to this record. 629 */ 630 splx(s); 631 return (0); 632 } 633 /* 634 * No remaining claims to this record; unlink and free it. 635 */ 636 for (p = &enm->enm_ac->ac_multiaddrs; 637 *p != enm; 638 p = &(*p)->enm_next) 639 continue; 640 *p = (*p)->enm_next; 641 free(enm, M_IFMADDR); 642 ac->ac_multicnt--; 643 splx(s); 644 /* 645 * Return ENETRESET to inform the driver that the list has changed 646 * and its reception filter should be adjusted accordingly. 647 */ 648 return (ENETRESET); 649 } 650