1 /* $OpenBSD: if_ethersubr.c,v 1.246 2017/05/31 05:59:09 mpi Exp $ */ 2 /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1982, 1989, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 62 */ 63 64 /* 65 %%% portions-copyright-nrl-95 66 Portions of this software are Copyright 1995-1998 by Randall Atkinson, 67 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights 68 Reserved. All rights under this copyright have been assigned to the US 69 Naval Research Laboratory (NRL). The NRL Copyright Notice and License 70 Agreement Version 1.1 (January 17, 1995) applies to these portions of the 71 software. 72 You should have received a copy of the license with this software. If you 73 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. 74 */ 75 76 #include "bpfilter.h" 77 78 #include <sys/param.h> 79 #include <sys/systm.h> 80 #include <sys/kernel.h> 81 #include <sys/malloc.h> 82 #include <sys/mbuf.h> 83 #include <sys/protosw.h> 84 #include <sys/socket.h> 85 #include <sys/ioctl.h> 86 #include <sys/errno.h> 87 #include <sys/syslog.h> 88 #include <sys/timeout.h> 89 90 #include <net/if.h> 91 #include <net/netisr.h> 92 #include <net/route.h> 93 #include <net/if_llc.h> 94 #include <net/if_dl.h> 95 #include <net/if_media.h> 96 #include <net/if_types.h> 97 98 #include <netinet/in.h> 99 #include <netinet/if_ether.h> 100 #include <netinet/ip_ipsp.h> 101 102 #if NBPFILTER > 0 103 #include <net/bpf.h> 104 #endif 105 106 #include "pppoe.h" 107 #if NPPPOE > 0 108 #include <net/if_pppoe.h> 109 #endif 110 111 #ifdef INET6 112 #include <netinet6/in6_var.h> 113 #include <netinet6/nd6.h> 114 #endif 115 116 #ifdef PIPEX 117 #include <net/pipex.h> 118 #endif 119 120 #ifdef MPLS 121 #include <netmpls/mpls.h> 122 #endif /* MPLS */ 123 124 u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] = 125 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 126 u_int8_t etheranyaddr[ETHER_ADDR_LEN] = 127 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 128 #define senderr(e) { error = (e); goto bad;} 129 130 int 131 ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data) 132 { 133 struct ifreq *ifr = (struct ifreq *)data; 134 int error = 0; 135 136 switch (cmd) { 137 case SIOCSIFADDR: 138 break; 139 140 case SIOCSIFMTU: 141 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 142 error = EINVAL; 143 else 144 ifp->if_mtu = ifr->ifr_mtu; 145 break; 146 147 case SIOCADDMULTI: 148 case SIOCDELMULTI: 149 if (ifp->if_flags & IFF_MULTICAST) { 150 error = (cmd == SIOCADDMULTI) ? 151 ether_addmulti(ifr, arp) : 152 ether_delmulti(ifr, arp); 153 } else 154 error = ENOTTY; 155 break; 156 157 default: 158 error = ENOTTY; 159 } 160 161 return (error); 162 } 163 164 165 void 166 ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) 167 { 168 switch (rt_key(rt)->sa_family) { 169 case AF_INET: 170 arp_rtrequest(ifp, req, rt); 171 break; 172 #ifdef INET6 173 case AF_INET6: 174 nd6_rtrequest(ifp, req, rt); 175 break; 176 #endif 177 default: 178 break; 179 } 180 } 181 /* 182 * Ethernet output routine. 183 * Encapsulate a packet of type family for the local net. 184 * Assumes that ifp is actually pointer to arpcom structure. 185 */ 186 int 187 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 188 struct rtentry *rt) 189 { 190 u_int16_t etype; 191 u_char edst[ETHER_ADDR_LEN]; 192 u_char *esrc; 193 struct mbuf *mcopy = NULL; 194 struct ether_header *eh; 195 struct arpcom *ac = (struct arpcom *)ifp; 196 sa_family_t af = dst->sa_family; 197 int error = 0; 198 199 KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) || 200 af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT); 201 202 #ifdef DIAGNOSTIC 203 if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) { 204 printf("%s: trying to send packet on wrong domain. " 205 "if %d vs. mbuf %d\n", ifp->if_xname, 206 ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid)); 207 } 208 #endif 209 210 esrc = ac->ac_enaddr; 211 212 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 213 senderr(ENETDOWN); 214 215 switch (af) { 216 case AF_INET: 217 error = arpresolve(ifp, rt, m, dst, edst); 218 if (error) 219 return (error == EAGAIN ? 0 : error); 220 /* If broadcasting on a simplex interface, loopback a copy */ 221 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && 222 !m->m_pkthdr.pf.routed) 223 mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT); 224 etype = htons(ETHERTYPE_IP); 225 break; 226 #ifdef INET6 227 case AF_INET6: 228 error = nd6_resolve(ifp, rt, m, dst, edst); 229 if (error) 230 return (error == EAGAIN ? 0 : error); 231 etype = htons(ETHERTYPE_IPV6); 232 break; 233 #endif 234 #ifdef MPLS 235 case AF_MPLS: 236 if (rt) 237 dst = rt_key(rt); 238 else 239 senderr(EHOSTUNREACH); 240 241 if (!ISSET(ifp->if_xflags, IFXF_MPLS)) 242 senderr(ENETUNREACH); 243 244 switch (dst->sa_family) { 245 case AF_LINK: 246 if (satosdl(dst)->sdl_alen < sizeof(edst)) 247 senderr(EHOSTUNREACH); 248 memcpy(edst, LLADDR(satosdl(dst)), 249 sizeof(edst)); 250 break; 251 case AF_INET: 252 case AF_MPLS: 253 error = arpresolve(ifp, rt, m, dst, edst); 254 if (error) 255 return (error == EAGAIN ? 0 : error); 256 break; 257 default: 258 senderr(EHOSTUNREACH); 259 } 260 /* XXX handling for simplex devices in case of M/BCAST ?? */ 261 if (m->m_flags & (M_BCAST | M_MCAST)) 262 etype = htons(ETHERTYPE_MPLS_MCAST); 263 else 264 etype = htons(ETHERTYPE_MPLS); 265 break; 266 #endif /* MPLS */ 267 case pseudo_AF_HDRCMPLT: 268 eh = (struct ether_header *)dst->sa_data; 269 esrc = eh->ether_shost; 270 /* FALLTHROUGH */ 271 272 case AF_UNSPEC: 273 eh = (struct ether_header *)dst->sa_data; 274 memcpy(edst, eh->ether_dhost, sizeof(edst)); 275 /* AF_UNSPEC doesn't swap the byte order of the ether_type. */ 276 etype = eh->ether_type; 277 break; 278 279 default: 280 printf("%s: can't handle af%d\n", ifp->if_xname, 281 dst->sa_family); 282 senderr(EAFNOSUPPORT); 283 } 284 285 /* XXX Should we feed-back an unencrypted IPsec packet ? */ 286 if (mcopy) 287 if_input_local(ifp, mcopy, dst->sa_family); 288 289 M_PREPEND(m, sizeof(struct ether_header) + ETHER_ALIGN, M_DONTWAIT); 290 if (m == NULL) 291 return (ENOBUFS); 292 m_adj(m, ETHER_ALIGN); 293 eh = mtod(m, struct ether_header *); 294 eh->ether_type = etype; 295 memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost)); 296 memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost)); 297 298 return (if_enqueue(ifp, m)); 299 bad: 300 m_freem(m); 301 return (error); 302 } 303 304 /* 305 * Process a received Ethernet packet; 306 * the packet is in the mbuf chain m without 307 * the ether header, which is provided separately. 308 */ 309 int 310 ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie) 311 { 312 struct ether_header *eh; 313 struct niqueue *inq; 314 u_int16_t etype; 315 int llcfound = 0; 316 struct llc *l; 317 struct arpcom *ac; 318 #if NPPPOE > 0 319 struct ether_header *eh_tmp; 320 #endif 321 322 /* Drop short frames */ 323 if (m->m_len < ETHER_HDR_LEN) 324 goto dropanyway; 325 326 ac = (struct arpcom *)ifp; 327 eh = mtod(m, struct ether_header *); 328 m_adj(m, ETHER_HDR_LEN); 329 330 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 331 /* 332 * If this is not a simplex interface, drop the packet 333 * if it came from us. 334 */ 335 if ((ifp->if_flags & IFF_SIMPLEX) == 0) { 336 if (memcmp(ac->ac_enaddr, eh->ether_shost, 337 ETHER_ADDR_LEN) == 0) { 338 m_freem(m); 339 return (1); 340 } 341 } 342 343 if (memcmp(etherbroadcastaddr, eh->ether_dhost, 344 sizeof(etherbroadcastaddr)) == 0) 345 m->m_flags |= M_BCAST; 346 else 347 m->m_flags |= M_MCAST; 348 ifp->if_imcasts++; 349 } 350 351 /* 352 * HW vlan tagged packets that were not collected by vlan(4) must 353 * be dropped now. 354 */ 355 if (m->m_flags & M_VLANTAG) { 356 m_freem(m); 357 return (1); 358 } 359 360 /* 361 * If packet is unicast, make sure it is for us. Drop otherwise. 362 * This check is required in promiscous mode, and for some hypervisors 363 * where the MAC filter is 'best effort' only. 364 */ 365 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) { 366 if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) { 367 m_freem(m); 368 return (1); 369 } 370 } 371 372 etype = ntohs(eh->ether_type); 373 374 decapsulate: 375 switch (etype) { 376 case ETHERTYPE_IP: 377 ipv4_input(ifp, m); 378 return (1); 379 380 case ETHERTYPE_ARP: 381 if (ifp->if_flags & IFF_NOARP) 382 goto dropanyway; 383 arpinput(ifp, m); 384 return (1); 385 386 case ETHERTYPE_REVARP: 387 if (ifp->if_flags & IFF_NOARP) 388 goto dropanyway; 389 revarpinput(ifp, m); 390 return (1); 391 392 #ifdef INET6 393 /* 394 * Schedule IPv6 software interrupt for incoming IPv6 packet. 395 */ 396 case ETHERTYPE_IPV6: 397 ipv6_input(ifp, m); 398 return (1); 399 #endif /* INET6 */ 400 #if NPPPOE > 0 || defined(PIPEX) 401 case ETHERTYPE_PPPOEDISC: 402 case ETHERTYPE_PPPOE: 403 if (m->m_flags & (M_MCAST | M_BCAST)) 404 goto dropanyway; 405 M_PREPEND(m, sizeof(*eh), M_DONTWAIT); 406 if (m == NULL) 407 return (1); 408 409 eh_tmp = mtod(m, struct ether_header *); 410 /* 411 * danger! 412 * eh_tmp and eh may overlap because eh 413 * is stolen from the mbuf above. 414 */ 415 memmove(eh_tmp, eh, sizeof(struct ether_header)); 416 #ifdef PIPEX 417 if (pipex_enable) { 418 struct pipex_session *session; 419 420 if ((session = pipex_pppoe_lookup_session(m)) != NULL) { 421 pipex_pppoe_input(m, session); 422 return (1); 423 } 424 } 425 #endif 426 if (etype == ETHERTYPE_PPPOEDISC) 427 inq = &pppoediscinq; 428 else 429 inq = &pppoeinq; 430 break; 431 #endif 432 #ifdef MPLS 433 case ETHERTYPE_MPLS: 434 case ETHERTYPE_MPLS_MCAST: 435 mpls_input(m); 436 return (1); 437 #endif 438 default: 439 if (llcfound || etype > ETHERMTU || 440 m->m_len < sizeof(struct llc)) 441 goto dropanyway; 442 llcfound = 1; 443 l = mtod(m, struct llc *); 444 switch (l->llc_dsap) { 445 case LLC_SNAP_LSAP: 446 if (l->llc_control == LLC_UI && 447 l->llc_dsap == LLC_SNAP_LSAP && 448 l->llc_ssap == LLC_SNAP_LSAP) { 449 /* SNAP */ 450 if (m->m_pkthdr.len > etype) 451 m_adj(m, etype - m->m_pkthdr.len); 452 m_adj(m, 6); 453 M_PREPEND(m, sizeof(*eh), M_DONTWAIT); 454 if (m == NULL) 455 return (1); 456 *mtod(m, struct ether_header *) = *eh; 457 goto decapsulate; 458 } 459 default: 460 goto dropanyway; 461 } 462 } 463 464 niq_enqueue(inq, m); 465 return (1); 466 dropanyway: 467 m_freem(m); 468 return (1); 469 } 470 471 /* 472 * Convert Ethernet address to printable (loggable) representation. 473 */ 474 static char digits[] = "0123456789abcdef"; 475 char * 476 ether_sprintf(u_char *ap) 477 { 478 int i; 479 static char etherbuf[ETHER_ADDR_LEN * 3]; 480 char *cp = etherbuf; 481 482 for (i = 0; i < ETHER_ADDR_LEN; i++) { 483 *cp++ = digits[*ap >> 4]; 484 *cp++ = digits[*ap++ & 0xf]; 485 *cp++ = ':'; 486 } 487 *--cp = 0; 488 return (etherbuf); 489 } 490 491 /* 492 * Generate a (hopefully) acceptable MAC address, if asked. 493 */ 494 void 495 ether_fakeaddr(struct ifnet *ifp) 496 { 497 static int unit; 498 int rng = arc4random(); 499 500 /* Non-multicast; locally administered address */ 501 ((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe; 502 ((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1; 503 ((struct arpcom *)ifp)->ac_enaddr[2] = 0xba; 504 ((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf); 505 ((struct arpcom *)ifp)->ac_enaddr[4] = rng; 506 ((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8; 507 } 508 509 /* 510 * Perform common duties while attaching to interface list 511 */ 512 void 513 ether_ifattach(struct ifnet *ifp) 514 { 515 struct arpcom *ac = (struct arpcom *)ifp; 516 517 /* 518 * Any interface which provides a MAC address which is obviously 519 * invalid gets whacked, so that users will notice. 520 */ 521 if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr)) 522 ether_fakeaddr(ifp); 523 524 ifp->if_type = IFT_ETHER; 525 ifp->if_addrlen = ETHER_ADDR_LEN; 526 ifp->if_hdrlen = ETHER_HDR_LEN; 527 ifp->if_mtu = ETHERMTU; 528 ifp->if_output = ether_output; 529 ifp->if_rtrequest = ether_rtrequest; 530 531 if_ih_insert(ifp, ether_input, NULL); 532 533 if (ifp->if_hardmtu == 0) 534 ifp->if_hardmtu = ETHERMTU; 535 536 if_alloc_sadl(ifp); 537 memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen); 538 LIST_INIT(&ac->ac_multiaddrs); 539 #if NBPFILTER > 0 540 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); 541 #endif 542 } 543 544 void 545 ether_ifdetach(struct ifnet *ifp) 546 { 547 struct arpcom *ac = (struct arpcom *)ifp; 548 struct ether_multi *enm; 549 550 /* Undo pseudo-driver changes. */ 551 if_deactivate(ifp); 552 553 if_ih_remove(ifp, ether_input, NULL); 554 555 KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs)); 556 557 for (enm = LIST_FIRST(&ac->ac_multiaddrs); 558 enm != NULL; 559 enm = LIST_FIRST(&ac->ac_multiaddrs)) { 560 LIST_REMOVE(enm, enm_list); 561 free(enm, M_IFMADDR, sizeof *enm); 562 } 563 } 564 565 #if 0 566 /* 567 * This is for reference. We have table-driven versions of the 568 * crc32 generators, which are faster than the double-loop. 569 */ 570 u_int32_t __pure 571 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len) 572 { 573 u_int32_t c, carry; 574 size_t i, j; 575 576 for (i = 0; i < len; i++) { 577 c = buf[i]; 578 for (j = 0; j < 8; j++) { 579 carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); 580 crc >>= 1; 581 c >>= 1; 582 if (carry) 583 crc = (crc ^ ETHER_CRC_POLY_LE); 584 } 585 } 586 587 return (crc); 588 } 589 590 u_int32_t __pure 591 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len) 592 { 593 u_int32_t c, carry; 594 size_t i, j; 595 596 for (i = 0; i < len; i++) { 597 c = buf[i]; 598 for (j = 0; j < 8; j++) { 599 carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); 600 crc <<= 1; 601 c >>= 1; 602 if (carry) 603 crc = (crc ^ ETHER_CRC_POLY_BE) | carry; 604 } 605 } 606 607 return (crc); 608 } 609 #else 610 u_int32_t __pure 611 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len) 612 { 613 static const u_int32_t crctab[] = { 614 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 615 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 616 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 617 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 618 }; 619 size_t i; 620 621 for (i = 0; i < len; i++) { 622 crc ^= buf[i]; 623 crc = (crc >> 4) ^ crctab[crc & 0xf]; 624 crc = (crc >> 4) ^ crctab[crc & 0xf]; 625 } 626 627 return (crc); 628 } 629 630 u_int32_t __pure 631 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len) 632 { 633 static const u_int8_t rev[] = { 634 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 635 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf 636 }; 637 static const u_int32_t crctab[] = { 638 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 639 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 640 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 641 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd 642 }; 643 size_t i; 644 u_int8_t data; 645 646 for (i = 0; i < len; i++) { 647 data = buf[i]; 648 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]]; 649 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]]; 650 } 651 652 return (crc); 653 } 654 #endif 655 656 u_int32_t 657 ether_crc32_le(const u_int8_t *buf, size_t len) 658 { 659 return ether_crc32_le_update(0xffffffff, buf, len); 660 } 661 662 u_int32_t 663 ether_crc32_be(const u_int8_t *buf, size_t len) 664 { 665 return ether_crc32_be_update(0xffffffff, buf, len); 666 } 667 668 u_char ether_ipmulticast_min[ETHER_ADDR_LEN] = 669 { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 670 u_char ether_ipmulticast_max[ETHER_ADDR_LEN] = 671 { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 672 673 #ifdef INET6 674 u_char ether_ip6multicast_min[ETHER_ADDR_LEN] = 675 { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; 676 u_char ether_ip6multicast_max[ETHER_ADDR_LEN] = 677 { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; 678 #endif 679 680 /* 681 * Convert a sockaddr into an Ethernet address or range of Ethernet 682 * addresses. 683 */ 684 int 685 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN], 686 u_int8_t addrhi[ETHER_ADDR_LEN]) 687 { 688 struct sockaddr_in *sin; 689 #ifdef INET6 690 struct sockaddr_in6 *sin6; 691 #endif /* INET6 */ 692 693 switch (sa->sa_family) { 694 695 case AF_UNSPEC: 696 memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); 697 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 698 break; 699 700 case AF_INET: 701 sin = satosin(sa); 702 if (sin->sin_addr.s_addr == INADDR_ANY) { 703 /* 704 * An IP address of INADDR_ANY means listen to 705 * or stop listening to all of the Ethernet 706 * multicast addresses used for IP. 707 * (This is for the sake of IP multicast routers.) 708 */ 709 memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); 710 memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); 711 } else { 712 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 713 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 714 } 715 break; 716 #ifdef INET6 717 case AF_INET6: 718 sin6 = satosin6(sa); 719 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 720 /* 721 * An IP6 address of 0 means listen to or stop 722 * listening to all of the Ethernet multicast 723 * address used for IP6. 724 * 725 * (This might not be healthy, given IPv6's reliance on 726 * multicast for things like neighbor discovery. 727 * Perhaps initializing all-nodes, solicited nodes, and 728 * possibly all-routers for this interface afterwards 729 * is not a bad idea.) 730 */ 731 732 memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); 733 memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); 734 } else { 735 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); 736 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 737 } 738 break; 739 #endif 740 741 default: 742 return (EAFNOSUPPORT); 743 } 744 return (0); 745 } 746 747 /* 748 * Add an Ethernet multicast address or range of addresses to the list for a 749 * given interface. 750 */ 751 int 752 ether_addmulti(struct ifreq *ifr, struct arpcom *ac) 753 { 754 struct ether_multi *enm; 755 u_char addrlo[ETHER_ADDR_LEN]; 756 u_char addrhi[ETHER_ADDR_LEN]; 757 int s = splnet(), error; 758 759 error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 760 if (error != 0) { 761 splx(s); 762 return (error); 763 } 764 765 /* 766 * Verify that we have valid Ethernet multicast addresses. 767 */ 768 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 769 splx(s); 770 return (EINVAL); 771 } 772 /* 773 * See if the address range is already in the list. 774 */ 775 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 776 if (enm != NULL) { 777 /* 778 * Found it; just increment the reference count. 779 */ 780 ++enm->enm_refcount; 781 splx(s); 782 return (0); 783 } 784 /* 785 * New address or range; malloc a new multicast record 786 * and link it into the interface's multicast list. 787 */ 788 enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 789 if (enm == NULL) { 790 splx(s); 791 return (ENOBUFS); 792 } 793 memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); 794 memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); 795 enm->enm_refcount = 1; 796 LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list); 797 ac->ac_multicnt++; 798 if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) 799 ac->ac_multirangecnt++; 800 splx(s); 801 /* 802 * Return ENETRESET to inform the driver that the list has changed 803 * and its reception filter should be adjusted accordingly. 804 */ 805 return (ENETRESET); 806 } 807 808 /* 809 * Delete a multicast address record. 810 */ 811 int 812 ether_delmulti(struct ifreq *ifr, struct arpcom *ac) 813 { 814 struct ether_multi *enm; 815 u_char addrlo[ETHER_ADDR_LEN]; 816 u_char addrhi[ETHER_ADDR_LEN]; 817 int s = splnet(), error; 818 819 error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 820 if (error != 0) { 821 splx(s); 822 return (error); 823 } 824 825 /* 826 * Look up the address in our list. 827 */ 828 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 829 if (enm == NULL) { 830 splx(s); 831 return (ENXIO); 832 } 833 if (--enm->enm_refcount != 0) { 834 /* 835 * Still some claims to this record. 836 */ 837 splx(s); 838 return (0); 839 } 840 /* 841 * No remaining claims to this record; unlink and free it. 842 */ 843 LIST_REMOVE(enm, enm_list); 844 free(enm, M_IFMADDR, sizeof *enm); 845 ac->ac_multicnt--; 846 if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) 847 ac->ac_multirangecnt--; 848 splx(s); 849 /* 850 * Return ENETRESET to inform the driver that the list has changed 851 * and its reception filter should be adjusted accordingly. 852 */ 853 return (ENETRESET); 854 } 855