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