1 /* $OpenBSD: if_ethersubr.c,v 1.260 2019/07/17 16:46:17 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 #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 (ETHER_IS_BROADCAST(eh->ether_dhost)) 381 m->m_flags |= M_BCAST; 382 else 383 m->m_flags |= M_MCAST; 384 ifp->if_imcasts++; 385 } 386 387 /* 388 * HW vlan tagged packets that were not collected by vlan(4) must 389 * be dropped now. 390 */ 391 if (m->m_flags & M_VLANTAG) 392 goto dropanyway; 393 394 etype = ntohs(eh->ether_type); 395 396 switch (etype) { 397 case ETHERTYPE_IP: 398 input = ipv4_input; 399 break; 400 401 case ETHERTYPE_ARP: 402 if (ifp->if_flags & IFF_NOARP) 403 goto dropanyway; 404 input = arpinput; 405 break; 406 407 case ETHERTYPE_REVARP: 408 if (ifp->if_flags & IFF_NOARP) 409 goto dropanyway; 410 input = revarpinput; 411 break; 412 413 #ifdef INET6 414 /* 415 * Schedule IPv6 software interrupt for incoming IPv6 packet. 416 */ 417 case ETHERTYPE_IPV6: 418 input = ipv6_input; 419 break; 420 #endif /* INET6 */ 421 #if NPPPOE > 0 || defined(PIPEX) 422 case ETHERTYPE_PPPOEDISC: 423 case ETHERTYPE_PPPOE: 424 if (m->m_flags & (M_MCAST | M_BCAST)) 425 goto dropanyway; 426 #ifdef PIPEX 427 if (pipex_enable) { 428 struct pipex_session *session; 429 430 if ((session = pipex_pppoe_lookup_session(m)) != NULL) { 431 pipex_pppoe_input(m, session); 432 return (1); 433 } 434 } 435 #endif 436 if (etype == ETHERTYPE_PPPOEDISC) 437 niq_enqueue(&pppoediscinq, m); 438 else 439 niq_enqueue(&pppoeinq, m); 440 return (1); 441 #endif 442 #ifdef MPLS 443 case ETHERTYPE_MPLS: 444 case ETHERTYPE_MPLS_MCAST: 445 input = mpls_input; 446 break; 447 #endif 448 #if NBPE > 0 449 case ETHERTYPE_PBB: 450 bpe_input(ifp, m); 451 return (1); 452 #endif 453 default: 454 goto dropanyway; 455 } 456 457 m_adj(m, sizeof(*eh)); 458 (*input)(ifp, m); 459 return (1); 460 dropanyway: 461 m_freem(m); 462 return (1); 463 } 464 465 /* 466 * Convert Ethernet address to printable (loggable) representation. 467 */ 468 static char digits[] = "0123456789abcdef"; 469 char * 470 ether_sprintf(u_char *ap) 471 { 472 int i; 473 static char etherbuf[ETHER_ADDR_LEN * 3]; 474 char *cp = etherbuf; 475 476 for (i = 0; i < ETHER_ADDR_LEN; i++) { 477 *cp++ = digits[*ap >> 4]; 478 *cp++ = digits[*ap++ & 0xf]; 479 *cp++ = ':'; 480 } 481 *--cp = 0; 482 return (etherbuf); 483 } 484 485 /* 486 * Generate a (hopefully) acceptable MAC address, if asked. 487 */ 488 void 489 ether_fakeaddr(struct ifnet *ifp) 490 { 491 static int unit; 492 int rng = arc4random(); 493 494 /* Non-multicast; locally administered address */ 495 ((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe; 496 ((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1; 497 ((struct arpcom *)ifp)->ac_enaddr[2] = 0xba; 498 ((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf); 499 ((struct arpcom *)ifp)->ac_enaddr[4] = rng; 500 ((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8; 501 } 502 503 /* 504 * Perform common duties while attaching to interface list 505 */ 506 void 507 ether_ifattach(struct ifnet *ifp) 508 { 509 struct arpcom *ac = (struct arpcom *)ifp; 510 511 /* 512 * Any interface which provides a MAC address which is obviously 513 * invalid gets whacked, so that users will notice. 514 */ 515 if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr)) 516 ether_fakeaddr(ifp); 517 518 ifp->if_type = IFT_ETHER; 519 ifp->if_addrlen = ETHER_ADDR_LEN; 520 ifp->if_hdrlen = ETHER_HDR_LEN; 521 ifp->if_mtu = ETHERMTU; 522 if (ifp->if_output == NULL) 523 ifp->if_output = ether_output; 524 ifp->if_rtrequest = ether_rtrequest; 525 526 if_ih_insert(ifp, ether_input, NULL); 527 528 if (ifp->if_hardmtu == 0) 529 ifp->if_hardmtu = ETHERMTU; 530 531 if_alloc_sadl(ifp); 532 memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen); 533 LIST_INIT(&ac->ac_multiaddrs); 534 #if NBPFILTER > 0 535 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); 536 #endif 537 } 538 539 void 540 ether_ifdetach(struct ifnet *ifp) 541 { 542 struct arpcom *ac = (struct arpcom *)ifp; 543 struct ether_multi *enm; 544 545 /* Undo pseudo-driver changes. */ 546 if_deactivate(ifp); 547 548 if_ih_remove(ifp, ether_input, NULL); 549 550 KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs)); 551 552 for (enm = LIST_FIRST(&ac->ac_multiaddrs); 553 enm != NULL; 554 enm = LIST_FIRST(&ac->ac_multiaddrs)) { 555 LIST_REMOVE(enm, enm_list); 556 free(enm, M_IFMADDR, sizeof *enm); 557 } 558 } 559 560 #if 0 561 /* 562 * This is for reference. We have table-driven versions of the 563 * crc32 generators, which are faster than the double-loop. 564 */ 565 u_int32_t __pure 566 ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len) 567 { 568 u_int32_t c, carry; 569 size_t i, j; 570 571 for (i = 0; i < len; i++) { 572 c = buf[i]; 573 for (j = 0; j < 8; j++) { 574 carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); 575 crc >>= 1; 576 c >>= 1; 577 if (carry) 578 crc = (crc ^ ETHER_CRC_POLY_LE); 579 } 580 } 581 582 return (crc); 583 } 584 585 u_int32_t __pure 586 ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len) 587 { 588 u_int32_t c, carry; 589 size_t i, j; 590 591 for (i = 0; i < len; i++) { 592 c = buf[i]; 593 for (j = 0; j < 8; j++) { 594 carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); 595 crc <<= 1; 596 c >>= 1; 597 if (carry) 598 crc = (crc ^ ETHER_CRC_POLY_BE) | carry; 599 } 600 } 601 602 return (crc); 603 } 604 #else 605 u_int32_t __pure 606 ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len) 607 { 608 static const u_int32_t crctab[] = { 609 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 610 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 611 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 612 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 613 }; 614 size_t i; 615 616 for (i = 0; i < len; i++) { 617 crc ^= buf[i]; 618 crc = (crc >> 4) ^ crctab[crc & 0xf]; 619 crc = (crc >> 4) ^ crctab[crc & 0xf]; 620 } 621 622 return (crc); 623 } 624 625 u_int32_t __pure 626 ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len) 627 { 628 static const u_int8_t rev[] = { 629 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 630 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf 631 }; 632 static const u_int32_t crctab[] = { 633 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 634 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 635 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 636 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd 637 }; 638 size_t i; 639 u_int8_t data; 640 641 for (i = 0; i < len; i++) { 642 data = buf[i]; 643 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]]; 644 crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]]; 645 } 646 647 return (crc); 648 } 649 #endif 650 651 u_int32_t 652 ether_crc32_le(const u_int8_t *buf, size_t len) 653 { 654 return ether_crc32_le_update(0xffffffff, buf, len); 655 } 656 657 u_int32_t 658 ether_crc32_be(const u_int8_t *buf, size_t len) 659 { 660 return ether_crc32_be_update(0xffffffff, buf, len); 661 } 662 663 u_char ether_ipmulticast_min[ETHER_ADDR_LEN] = 664 { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 665 u_char ether_ipmulticast_max[ETHER_ADDR_LEN] = 666 { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 667 668 #ifdef INET6 669 u_char ether_ip6multicast_min[ETHER_ADDR_LEN] = 670 { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; 671 u_char ether_ip6multicast_max[ETHER_ADDR_LEN] = 672 { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; 673 #endif 674 675 /* 676 * Convert a sockaddr into an Ethernet address or range of Ethernet 677 * addresses. 678 */ 679 int 680 ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN], 681 u_int8_t addrhi[ETHER_ADDR_LEN]) 682 { 683 struct sockaddr_in *sin; 684 #ifdef INET6 685 struct sockaddr_in6 *sin6; 686 #endif /* INET6 */ 687 688 switch (sa->sa_family) { 689 690 case AF_UNSPEC: 691 memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); 692 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 693 break; 694 695 case AF_INET: 696 sin = satosin(sa); 697 if (sin->sin_addr.s_addr == INADDR_ANY) { 698 /* 699 * An IP address of INADDR_ANY means listen to 700 * or stop listening to all of the Ethernet 701 * multicast addresses used for IP. 702 * (This is for the sake of IP multicast routers.) 703 */ 704 memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); 705 memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); 706 } else { 707 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 708 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 709 } 710 break; 711 #ifdef INET6 712 case AF_INET6: 713 sin6 = satosin6(sa); 714 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 715 /* 716 * An IP6 address of 0 means listen to or stop 717 * listening to all of the Ethernet multicast 718 * address used for IP6. 719 * 720 * (This might not be healthy, given IPv6's reliance on 721 * multicast for things like neighbor discovery. 722 * Perhaps initializing all-nodes, solicited nodes, and 723 * possibly all-routers for this interface afterwards 724 * is not a bad idea.) 725 */ 726 727 memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); 728 memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); 729 } else { 730 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); 731 memcpy(addrhi, addrlo, ETHER_ADDR_LEN); 732 } 733 break; 734 #endif 735 736 default: 737 return (EAFNOSUPPORT); 738 } 739 return (0); 740 } 741 742 /* 743 * Add an Ethernet multicast address or range of addresses to the list for a 744 * given interface. 745 */ 746 int 747 ether_addmulti(struct ifreq *ifr, struct arpcom *ac) 748 { 749 struct ether_multi *enm; 750 u_char addrlo[ETHER_ADDR_LEN]; 751 u_char addrhi[ETHER_ADDR_LEN]; 752 int s = splnet(), error; 753 754 error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 755 if (error != 0) { 756 splx(s); 757 return (error); 758 } 759 760 /* 761 * Verify that we have valid Ethernet multicast addresses. 762 */ 763 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 764 splx(s); 765 return (EINVAL); 766 } 767 /* 768 * See if the address range is already in the list. 769 */ 770 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 771 if (enm != NULL) { 772 /* 773 * Found it; just increment the reference count. 774 */ 775 ++enm->enm_refcount; 776 splx(s); 777 return (0); 778 } 779 /* 780 * New address or range; malloc a new multicast record 781 * and link it into the interface's multicast list. 782 */ 783 enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 784 if (enm == NULL) { 785 splx(s); 786 return (ENOBUFS); 787 } 788 memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); 789 memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); 790 enm->enm_refcount = 1; 791 LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list); 792 ac->ac_multicnt++; 793 if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) 794 ac->ac_multirangecnt++; 795 splx(s); 796 /* 797 * Return ENETRESET to inform the driver that the list has changed 798 * and its reception filter should be adjusted accordingly. 799 */ 800 return (ENETRESET); 801 } 802 803 /* 804 * Delete a multicast address record. 805 */ 806 int 807 ether_delmulti(struct ifreq *ifr, struct arpcom *ac) 808 { 809 struct ether_multi *enm; 810 u_char addrlo[ETHER_ADDR_LEN]; 811 u_char addrhi[ETHER_ADDR_LEN]; 812 int s = splnet(), error; 813 814 error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 815 if (error != 0) { 816 splx(s); 817 return (error); 818 } 819 820 /* 821 * Look up the address in our list. 822 */ 823 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 824 if (enm == NULL) { 825 splx(s); 826 return (ENXIO); 827 } 828 if (--enm->enm_refcount != 0) { 829 /* 830 * Still some claims to this record. 831 */ 832 splx(s); 833 return (0); 834 } 835 /* 836 * No remaining claims to this record; unlink and free it. 837 */ 838 LIST_REMOVE(enm, enm_list); 839 free(enm, M_IFMADDR, sizeof *enm); 840 ac->ac_multicnt--; 841 if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) 842 ac->ac_multirangecnt--; 843 splx(s); 844 /* 845 * Return ENETRESET to inform the driver that the list has changed 846 * and its reception filter should be adjusted accordingly. 847 */ 848 return (ENETRESET); 849 } 850