1 /* $OpenBSD: if_ethersubr.c,v 1.259 2019/02/20 00:03:15 dlg 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 #include "bpe.h" 112 #if NBPE > 0 113 #include <net/if_bpe.h> 114 #endif 115 116 #ifdef INET6 117 #include <netinet6/in6_var.h> 118 #include <netinet6/nd6.h> 119 #endif 120 121 #ifdef PIPEX 122 #include <net/pipex.h> 123 #endif 124 125 #ifdef MPLS 126 #include <netmpls/mpls.h> 127 #endif /* MPLS */ 128 129 u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] = 130 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 131 u_int8_t etheranyaddr[ETHER_ADDR_LEN] = 132 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 133 #define senderr(e) { error = (e); goto bad;} 134 135 int 136 ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data) 137 { 138 struct ifreq *ifr = (struct ifreq *)data; 139 int error = 0; 140 141 switch (cmd) { 142 case SIOCSIFADDR: 143 break; 144 145 case SIOCSIFMTU: 146 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 147 error = EINVAL; 148 else 149 ifp->if_mtu = ifr->ifr_mtu; 150 break; 151 152 case SIOCADDMULTI: 153 case SIOCDELMULTI: 154 if (ifp->if_flags & IFF_MULTICAST) { 155 error = (cmd == SIOCADDMULTI) ? 156 ether_addmulti(ifr, arp) : 157 ether_delmulti(ifr, arp); 158 } else 159 error = ENOTTY; 160 break; 161 162 default: 163 error = ENOTTY; 164 } 165 166 return (error); 167 } 168 169 170 void 171 ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) 172 { 173 switch (rt_key(rt)->sa_family) { 174 case AF_INET: 175 arp_rtrequest(ifp, req, rt); 176 break; 177 #ifdef INET6 178 case AF_INET6: 179 nd6_rtrequest(ifp, req, rt); 180 break; 181 #endif 182 default: 183 break; 184 } 185 } 186 187 int 188 ether_resolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 189 struct rtentry *rt, struct ether_header *eh) 190 { 191 struct arpcom *ac = (struct arpcom *)ifp; 192 sa_family_t af = dst->sa_family; 193 int error = 0; 194 195 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 196 senderr(ENETDOWN); 197 198 KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) || 199 af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT); 200 201 #ifdef DIAGNOSTIC 202 if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) { 203 printf("%s: trying to send packet on wrong domain. " 204 "if %d vs. mbuf %d\n", ifp->if_xname, 205 ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid)); 206 } 207 #endif 208 209 switch (af) { 210 case AF_INET: 211 error = arpresolve(ifp, rt, m, dst, eh->ether_dhost); 212 if (error) 213 return (error); 214 eh->ether_type = htons(ETHERTYPE_IP); 215 216 /* If broadcasting on a simplex interface, loopback a copy */ 217 if (ISSET(m->m_flags, M_BCAST) && 218 ISSET(ifp->if_flags, IFF_SIMPLEX) && 219 !m->m_pkthdr.pf.routed) { 220 struct mbuf *mcopy; 221 222 /* XXX Should we input an unencrypted IPsec packet? */ 223 mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT); 224 if (mcopy != NULL) 225 if_input_local(ifp, mcopy, af); 226 } 227 break; 228 #ifdef INET6 229 case AF_INET6: 230 error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost); 231 if (error) 232 return (error); 233 eh->ether_type = htons(ETHERTYPE_IPV6); 234 break; 235 #endif 236 #ifdef MPLS 237 case AF_MPLS: 238 if (rt == NULL) 239 senderr(EHOSTUNREACH); 240 241 if (!ISSET(ifp->if_xflags, IFXF_MPLS)) 242 senderr(ENETUNREACH); 243 244 dst = ISSET(rt->rt_flags, RTF_GATEWAY) ? 245 rt->rt_gateway : rt_key(rt); 246 247 switch (dst->sa_family) { 248 case AF_LINK: 249 if (satosdl(dst)->sdl_alen < sizeof(eh->ether_dhost)) 250 senderr(EHOSTUNREACH); 251 memcpy(eh->ether_dhost, LLADDR(satosdl(dst)), 252 sizeof(eh->ether_dhost)); 253 break; 254 #ifdef INET6 255 case AF_INET6: 256 error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost); 257 if (error) 258 return (error); 259 break; 260 #endif 261 case AF_INET: 262 error = arpresolve(ifp, rt, m, dst, eh->ether_dhost); 263 if (error) 264 return (error); 265 break; 266 default: 267 senderr(EHOSTUNREACH); 268 } 269 /* XXX handling for simplex devices in case of M/BCAST ?? */ 270 if (m->m_flags & (M_BCAST | M_MCAST)) 271 eh->ether_type = htons(ETHERTYPE_MPLS_MCAST); 272 else 273 eh->ether_type = htons(ETHERTYPE_MPLS); 274 break; 275 #endif /* MPLS */ 276 case pseudo_AF_HDRCMPLT: 277 /* take the whole header from the sa */ 278 memcpy(eh, dst->sa_data, sizeof(*eh)); 279 return (0); 280 281 case AF_UNSPEC: 282 /* take the dst and type from the sa, but get src below */ 283 memcpy(eh, dst->sa_data, sizeof(*eh)); 284 break; 285 286 default: 287 printf("%s: can't handle af%d\n", ifp->if_xname, af); 288 senderr(EAFNOSUPPORT); 289 } 290 291 memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(eh->ether_shost)); 292 293 return (0); 294 295 bad: 296 m_freem(m); 297 return (error); 298 } 299 300 struct mbuf* 301 ether_encap(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 302 struct rtentry *rt, int *errorp) 303 { 304 struct ether_header eh; 305 int error; 306 307 error = ether_resolve(ifp, m, dst, rt, &eh); 308 switch (error) { 309 case 0: 310 break; 311 case EAGAIN: 312 error = 0; 313 default: 314 *errorp = error; 315 return (NULL); 316 } 317 318 m = m_prepend(m, ETHER_ALIGN + sizeof(eh), M_DONTWAIT); 319 if (m == NULL) { 320 *errorp = ENOBUFS; 321 return (NULL); 322 } 323 324 m_adj(m, ETHER_ALIGN); 325 memcpy(mtod(m, struct ether_header *), &eh, sizeof(eh)); 326 327 return (m); 328 } 329 330 int 331 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 332 struct rtentry *rt) 333 { 334 int error; 335 336 m = ether_encap(ifp, m, dst, rt, &error); 337 if (m == NULL) 338 return (error); 339 340 return (if_enqueue(ifp, m)); 341 } 342 343 /* 344 * Process a received Ethernet packet; 345 * the packet is in the mbuf chain m without 346 * the ether header, which is provided separately. 347 */ 348 int 349 ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie) 350 { 351 struct ether_header *eh; 352 void (*input)(struct ifnet *, struct mbuf *); 353 u_int16_t etype; 354 struct arpcom *ac; 355 356 /* Drop short frames */ 357 if (m->m_len < ETHER_HDR_LEN) 358 goto dropanyway; 359 360 ac = (struct arpcom *)ifp; 361 eh = mtod(m, struct ether_header *); 362 363 /* Is the packet for us? */ 364 if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0) { 365 366 /* If not, it must be multicast or broadcast to go further */ 367 if (!ETHER_IS_MULTICAST(eh->ether_dhost)) 368 goto dropanyway; 369 370 /* 371 * If this is not a simplex interface, drop the packet 372 * if it came from us. 373 */ 374 if ((ifp->if_flags & IFF_SIMPLEX) == 0) { 375 if (memcmp(ac->ac_enaddr, eh->ether_shost, 376 ETHER_ADDR_LEN) == 0) 377 goto dropanyway; 378 } 379 380 if (memcmp(etherbroadcastaddr, eh->ether_dhost, 381 ETHER_ADDR_LEN) == 0) 382 m->m_flags |= M_BCAST; 383 else 384 m->m_flags |= M_MCAST; 385 ifp->if_imcasts++; 386 } 387 388 /* 389 * HW vlan tagged packets that were not collected by vlan(4) must 390 * be dropped now. 391 */ 392 if (m->m_flags & M_VLANTAG) 393 goto dropanyway; 394 395 etype = ntohs(eh->ether_type); 396 397 switch (etype) { 398 case ETHERTYPE_IP: 399 input = ipv4_input; 400 break; 401 402 case ETHERTYPE_ARP: 403 if (ifp->if_flags & IFF_NOARP) 404 goto dropanyway; 405 input = arpinput; 406 break; 407 408 case ETHERTYPE_REVARP: 409 if (ifp->if_flags & IFF_NOARP) 410 goto dropanyway; 411 input = revarpinput; 412 break; 413 414 #ifdef INET6 415 /* 416 * Schedule IPv6 software interrupt for incoming IPv6 packet. 417 */ 418 case ETHERTYPE_IPV6: 419 input = ipv6_input; 420 break; 421 #endif /* INET6 */ 422 #if NPPPOE > 0 || defined(PIPEX) 423 case ETHERTYPE_PPPOEDISC: 424 case ETHERTYPE_PPPOE: 425 if (m->m_flags & (M_MCAST | M_BCAST)) 426 goto dropanyway; 427 #ifdef PIPEX 428 if (pipex_enable) { 429 struct pipex_session *session; 430 431 if ((session = pipex_pppoe_lookup_session(m)) != NULL) { 432 pipex_pppoe_input(m, session); 433 return (1); 434 } 435 } 436 #endif 437 if (etype == ETHERTYPE_PPPOEDISC) 438 niq_enqueue(&pppoediscinq, m); 439 else 440 niq_enqueue(&pppoeinq, m); 441 return (1); 442 #endif 443 #ifdef MPLS 444 case ETHERTYPE_MPLS: 445 case ETHERTYPE_MPLS_MCAST: 446 input = mpls_input; 447 break; 448 #endif 449 #if NBPE > 0 450 case ETHERTYPE_PBB: 451 bpe_input(ifp, m); 452 return (1); 453 #endif 454 default: 455 goto dropanyway; 456 } 457 458 m_adj(m, sizeof(*eh)); 459 (*input)(ifp, m); 460 return (1); 461 dropanyway: 462 m_freem(m); 463 return (1); 464 } 465 466 /* 467 * Convert Ethernet address to printable (loggable) representation. 468 */ 469 static char digits[] = "0123456789abcdef"; 470 char * 471 ether_sprintf(u_char *ap) 472 { 473 int i; 474 static char etherbuf[ETHER_ADDR_LEN * 3]; 475 char *cp = etherbuf; 476 477 for (i = 0; i < ETHER_ADDR_LEN; i++) { 478 *cp++ = digits[*ap >> 4]; 479 *cp++ = digits[*ap++ & 0xf]; 480 *cp++ = ':'; 481 } 482 *--cp = 0; 483 return (etherbuf); 484 } 485 486 /* 487 * Generate a (hopefully) acceptable MAC address, if asked. 488 */ 489 void 490 ether_fakeaddr(struct ifnet *ifp) 491 { 492 static int unit; 493 int rng = arc4random(); 494 495 /* Non-multicast; locally administered address */ 496 ((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe; 497 ((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1; 498 ((struct arpcom *)ifp)->ac_enaddr[2] = 0xba; 499 ((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf); 500 ((struct arpcom *)ifp)->ac_enaddr[4] = rng; 501 ((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8; 502 } 503 504 /* 505 * Perform common duties while attaching to interface list 506 */ 507 void 508 ether_ifattach(struct ifnet *ifp) 509 { 510 struct arpcom *ac = (struct arpcom *)ifp; 511 512 /* 513 * Any interface which provides a MAC address which is obviously 514 * invalid gets whacked, so that users will notice. 515 */ 516 if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr)) 517 ether_fakeaddr(ifp); 518 519 ifp->if_type = IFT_ETHER; 520 ifp->if_addrlen = ETHER_ADDR_LEN; 521 ifp->if_hdrlen = ETHER_HDR_LEN; 522 ifp->if_mtu = ETHERMTU; 523 if (ifp->if_output == NULL) 524 ifp->if_output = ether_output; 525 ifp->if_rtrequest = ether_rtrequest; 526 527 if_ih_insert(ifp, ether_input, NULL); 528 529 if (ifp->if_hardmtu == 0) 530 ifp->if_hardmtu = ETHERMTU; 531 532 if_alloc_sadl(ifp); 533 memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen); 534 LIST_INIT(&ac->ac_multiaddrs); 535 #if NBPFILTER > 0 536 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); 537 #endif 538 } 539 540 void 541 ether_ifdetach(struct ifnet *ifp) 542 { 543 struct arpcom *ac = (struct arpcom *)ifp; 544 struct ether_multi *enm; 545 546 /* Undo pseudo-driver changes. */ 547 if_deactivate(ifp); 548 549 if_ih_remove(ifp, ether_input, NULL); 550 551 KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs)); 552 553 for (enm = LIST_FIRST(&ac->ac_multiaddrs); 554 enm != NULL; 555 enm = LIST_FIRST(&ac->ac_multiaddrs)) { 556 LIST_REMOVE(enm, enm_list); 557 free(enm, M_IFMADDR, sizeof *enm); 558 } 559 } 560 561 #if 0 562 /* 563 * This is for reference. We have table-driven versions of the 564 * crc32 generators, which are faster than the double-loop. 565 */ 566 u_int32_t __pure 567 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len) 568 { 569 u_int32_t c, carry; 570 size_t i, j; 571 572 for (i = 0; i < len; i++) { 573 c = buf[i]; 574 for (j = 0; j < 8; j++) { 575 carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); 576 crc >>= 1; 577 c >>= 1; 578 if (carry) 579 crc = (crc ^ ETHER_CRC_POLY_LE); 580 } 581 } 582 583 return (crc); 584 } 585 586 u_int32_t __pure 587 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len) 588 { 589 u_int32_t c, carry; 590 size_t i, j; 591 592 for (i = 0; i < len; i++) { 593 c = buf[i]; 594 for (j = 0; j < 8; j++) { 595 carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); 596 crc <<= 1; 597 c >>= 1; 598 if (carry) 599 crc = (crc ^ ETHER_CRC_POLY_BE) | carry; 600 } 601 } 602 603 return (crc); 604 } 605 #else 606 u_int32_t __pure 607 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len) 608 { 609 static const u_int32_t crctab[] = { 610 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 611 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 612 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 613 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 614 }; 615 size_t i; 616 617 for (i = 0; i < len; i++) { 618 crc ^= buf[i]; 619 crc = (crc >> 4) ^ crctab[crc & 0xf]; 620 crc = (crc >> 4) ^ crctab[crc & 0xf]; 621 } 622 623 return (crc); 624 } 625 626 u_int32_t __pure 627 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len) 628 { 629 static const u_int8_t rev[] = { 630 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 631 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf 632 }; 633 static const u_int32_t crctab[] = { 634 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 635 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 636 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 637 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd 638 }; 639 size_t i; 640 u_int8_t data; 641 642 for (i = 0; i < len; i++) { 643 data = buf[i]; 644 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]]; 645 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]]; 646 } 647 648 return (crc); 649 } 650 #endif 651 652 u_int32_t 653 ether_crc32_le(const u_int8_t *buf, size_t len) 654 { 655 return ether_crc32_le_update(0xffffffff, buf, len); 656 } 657 658 u_int32_t 659 ether_crc32_be(const u_int8_t *buf, size_t len) 660 { 661 return ether_crc32_be_update(0xffffffff, buf, len); 662 } 663 664 u_char ether_ipmulticast_min[ETHER_ADDR_LEN] = 665 { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 666 u_char ether_ipmulticast_max[ETHER_ADDR_LEN] = 667 { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 668 669 #ifdef INET6 670 u_char ether_ip6multicast_min[ETHER_ADDR_LEN] = 671 { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; 672 u_char ether_ip6multicast_max[ETHER_ADDR_LEN] = 673 { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; 674 #endif 675 676 /* 677 * Convert a sockaddr into an Ethernet address or range of Ethernet 678 * addresses. 679 */ 680 int 681 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN], 682 u_int8_t addrhi[ETHER_ADDR_LEN]) 683 { 684 struct sockaddr_in *sin; 685 #ifdef INET6 686 struct sockaddr_in6 *sin6; 687 #endif /* INET6 */ 688 689 switch (sa->sa_family) { 690 691 case AF_UNSPEC: 692 memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); 693 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 694 break; 695 696 case AF_INET: 697 sin = satosin(sa); 698 if (sin->sin_addr.s_addr == INADDR_ANY) { 699 /* 700 * An IP address of INADDR_ANY means listen to 701 * or stop listening to all of the Ethernet 702 * multicast addresses used for IP. 703 * (This is for the sake of IP multicast routers.) 704 */ 705 memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); 706 memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); 707 } else { 708 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 709 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 710 } 711 break; 712 #ifdef INET6 713 case AF_INET6: 714 sin6 = satosin6(sa); 715 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 716 /* 717 * An IP6 address of 0 means listen to or stop 718 * listening to all of the Ethernet multicast 719 * address used for IP6. 720 * 721 * (This might not be healthy, given IPv6's reliance on 722 * multicast for things like neighbor discovery. 723 * Perhaps initializing all-nodes, solicited nodes, and 724 * possibly all-routers for this interface afterwards 725 * is not a bad idea.) 726 */ 727 728 memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); 729 memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); 730 } else { 731 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); 732 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 733 } 734 break; 735 #endif 736 737 default: 738 return (EAFNOSUPPORT); 739 } 740 return (0); 741 } 742 743 /* 744 * Add an Ethernet multicast address or range of addresses to the list for a 745 * given interface. 746 */ 747 int 748 ether_addmulti(struct ifreq *ifr, struct arpcom *ac) 749 { 750 struct ether_multi *enm; 751 u_char addrlo[ETHER_ADDR_LEN]; 752 u_char addrhi[ETHER_ADDR_LEN]; 753 int s = splnet(), error; 754 755 error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 756 if (error != 0) { 757 splx(s); 758 return (error); 759 } 760 761 /* 762 * Verify that we have valid Ethernet multicast addresses. 763 */ 764 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 765 splx(s); 766 return (EINVAL); 767 } 768 /* 769 * See if the address range is already in the list. 770 */ 771 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 772 if (enm != NULL) { 773 /* 774 * Found it; just increment the reference count. 775 */ 776 ++enm->enm_refcount; 777 splx(s); 778 return (0); 779 } 780 /* 781 * New address or range; malloc a new multicast record 782 * and link it into the interface's multicast list. 783 */ 784 enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 785 if (enm == NULL) { 786 splx(s); 787 return (ENOBUFS); 788 } 789 memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); 790 memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); 791 enm->enm_refcount = 1; 792 LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list); 793 ac->ac_multicnt++; 794 if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) 795 ac->ac_multirangecnt++; 796 splx(s); 797 /* 798 * Return ENETRESET to inform the driver that the list has changed 799 * and its reception filter should be adjusted accordingly. 800 */ 801 return (ENETRESET); 802 } 803 804 /* 805 * Delete a multicast address record. 806 */ 807 int 808 ether_delmulti(struct ifreq *ifr, struct arpcom *ac) 809 { 810 struct ether_multi *enm; 811 u_char addrlo[ETHER_ADDR_LEN]; 812 u_char addrhi[ETHER_ADDR_LEN]; 813 int s = splnet(), error; 814 815 error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 816 if (error != 0) { 817 splx(s); 818 return (error); 819 } 820 821 /* 822 * Look up the address in our list. 823 */ 824 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 825 if (enm == NULL) { 826 splx(s); 827 return (ENXIO); 828 } 829 if (--enm->enm_refcount != 0) { 830 /* 831 * Still some claims to this record. 832 */ 833 splx(s); 834 return (0); 835 } 836 /* 837 * No remaining claims to this record; unlink and free it. 838 */ 839 LIST_REMOVE(enm, enm_list); 840 free(enm, M_IFMADDR, sizeof *enm); 841 ac->ac_multicnt--; 842 if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) 843 ac->ac_multirangecnt--; 844 splx(s); 845 /* 846 * Return ENETRESET to inform the driver that the list has changed 847 * and its reception filter should be adjusted accordingly. 848 */ 849 return (ENETRESET); 850 } 851