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