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