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