1 /* 2 * Copyright (c) 1982, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 34 * $Id: if_ethersubr.c,v 1.14 1996/01/24 21:09:06 phk Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/malloc.h> 41 #include <sys/mbuf.h> 42 #include <sys/protosw.h> 43 #include <sys/socket.h> 44 #include <sys/ioctl.h> 45 #include <sys/errno.h> 46 #include <sys/syslog.h> 47 #include <sys/sysctl.h> 48 49 #include <net/if.h> 50 #include <net/netisr.h> 51 #include <net/route.h> 52 #include <net/if_llc.h> 53 #include <net/if_dl.h> 54 #include <net/if_types.h> 55 56 #ifdef INET 57 #include <netinet/in.h> 58 #include <netinet/in_var.h> 59 #endif 60 #include <netinet/if_ether.h> 61 62 #ifdef IPX 63 #include <netipx/ipx.h> 64 #include <netipx/ipx_if.h> 65 #endif 66 67 #ifdef NS 68 #include <netns/ns.h> 69 #include <netns/ns_if.h> 70 #endif 71 72 #ifdef ISO 73 #include <netiso/argo_debug.h> 74 #include <netiso/iso.h> 75 #include <netiso/iso_var.h> 76 #include <netiso/iso_snpac.h> 77 #endif 78 79 #ifdef LLC 80 #include <netccitt/dll.h> 81 #include <netccitt/llc_var.h> 82 #endif 83 84 #if defined(LLC) && defined(CCITT) 85 extern struct ifqueue pkintrq; 86 #endif 87 88 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 89 #define senderr(e) { error = (e); goto bad;} 90 91 /* 92 * Ethernet output routine. 93 * Encapsulate a packet of type family for the local net. 94 * Use trailer local net encapsulation if enough data in first 95 * packet leaves a multiple of 512 bytes of data in remainder. 96 * Assumes that ifp is actually pointer to arpcom structure. 97 */ 98 int 99 ether_output(ifp, m0, dst, rt0) 100 register struct ifnet *ifp; 101 struct mbuf *m0; 102 struct sockaddr *dst; 103 struct rtentry *rt0; 104 { 105 short type; 106 int s, error = 0; 107 u_char edst[6]; 108 register struct mbuf *m = m0; 109 register struct rtentry *rt; 110 struct mbuf *mcopy = (struct mbuf *)0; 111 register struct ether_header *eh; 112 int off, len = m->m_pkthdr.len; 113 struct arpcom *ac = (struct arpcom *)ifp; 114 115 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 116 senderr(ENETDOWN); 117 ifp->if_lastchange = time; 118 rt = rt0; 119 if (rt) { 120 if ((rt->rt_flags & RTF_UP) == 0) { 121 rt0 = rt = rtalloc1(dst, 1, 0UL); 122 if (rt0) 123 rt->rt_refcnt--; 124 else 125 senderr(EHOSTUNREACH); 126 } 127 if (rt->rt_flags & RTF_GATEWAY) { 128 if (rt->rt_gwroute == 0) 129 goto lookup; 130 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 131 rtfree(rt); rt = rt0; 132 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 133 0UL); 134 if ((rt = rt->rt_gwroute) == 0) 135 senderr(EHOSTUNREACH); 136 } 137 } 138 if (rt->rt_flags & RTF_REJECT) 139 if (rt->rt_rmx.rmx_expire == 0 || 140 time.tv_sec < rt->rt_rmx.rmx_expire) 141 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 142 } 143 switch (dst->sa_family) { 144 145 #ifdef INET 146 case AF_INET: 147 if (!arpresolve(ac, rt, m, dst, edst, rt0)) 148 return (0); /* if not yet resolved */ 149 /* If broadcasting on a simplex interface, loopback a copy */ 150 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 151 mcopy = m_copy(m, 0, (int)M_COPYALL); 152 off = m->m_pkthdr.len - m->m_len; 153 type = ETHERTYPE_IP; 154 break; 155 #endif 156 #ifdef IPX 157 case AF_IPX: 158 type = ETHERTYPE_IPX; 159 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 160 (caddr_t)edst, sizeof (edst)); 161 if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst))) 162 return (looutput(ifp, m, dst, rt)); 163 /* If broadcasting on a simplex interface, loopback a copy */ 164 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 165 mcopy = m_copy(m, 0, (int)M_COPYALL); 166 break; 167 #endif 168 #ifdef NS 169 case AF_NS: 170 type = ETHERTYPE_NS; 171 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 172 (caddr_t)edst, sizeof (edst)); 173 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) 174 return (looutput(ifp, m, dst, rt)); 175 /* If broadcasting on a simplex interface, loopback a copy */ 176 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 177 mcopy = m_copy(m, 0, (int)M_COPYALL); 178 break; 179 #endif 180 #ifdef ISO 181 case AF_ISO: { 182 int snpalen; 183 struct llc *l; 184 register struct sockaddr_dl *sdl; 185 186 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 187 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 188 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 189 } else if (error = 190 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 191 (char *)edst, &snpalen)) 192 goto bad; /* Not Resolved */ 193 /* If broadcasting on a simplex interface, loopback a copy */ 194 if (*edst & 1) 195 m->m_flags |= (M_BCAST|M_MCAST); 196 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && 197 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 198 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 199 if (mcopy) { 200 eh = mtod(mcopy, struct ether_header *); 201 bcopy((caddr_t)edst, 202 (caddr_t)eh->ether_dhost, sizeof (edst)); 203 bcopy((caddr_t)ac->ac_enaddr, 204 (caddr_t)eh->ether_shost, sizeof (edst)); 205 } 206 } 207 M_PREPEND(m, 3, M_DONTWAIT); 208 if (m == NULL) 209 return (0); 210 type = m->m_pkthdr.len; 211 l = mtod(m, struct llc *); 212 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 213 l->llc_control = LLC_UI; 214 len += 3; 215 IFDEBUG(D_ETHER) 216 int i; 217 printf("unoutput: sending pkt to: "); 218 for (i=0; i<6; i++) 219 printf("%x ", edst[i] & 0xff); 220 printf("\n"); 221 ENDDEBUG 222 } break; 223 #endif /* ISO */ 224 #ifdef LLC 225 /* case AF_NSAP: */ 226 case AF_CCITT: { 227 register struct sockaddr_dl *sdl = 228 (struct sockaddr_dl *) rt -> rt_gateway; 229 230 if (sdl && sdl->sdl_family == AF_LINK 231 && sdl->sdl_alen > 0) { 232 bcopy(LLADDR(sdl), (char *)edst, 233 sizeof(edst)); 234 } else goto bad; /* Not a link interface ? Funny ... */ 235 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && 236 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 237 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 238 if (mcopy) { 239 eh = mtod(mcopy, struct ether_header *); 240 bcopy((caddr_t)edst, 241 (caddr_t)eh->ether_dhost, sizeof (edst)); 242 bcopy((caddr_t)ac->ac_enaddr, 243 (caddr_t)eh->ether_shost, sizeof (edst)); 244 } 245 } 246 type = m->m_pkthdr.len; 247 #ifdef LLC_DEBUG 248 { 249 int i; 250 register struct llc *l = mtod(m, struct llc *); 251 252 printf("ether_output: sending LLC2 pkt to: "); 253 for (i=0; i<6; i++) 254 printf("%x ", edst[i] & 0xff); 255 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 256 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 257 l->llc_control & 0xff); 258 259 } 260 #endif /* LLC_DEBUG */ 261 } break; 262 #endif /* LLC */ 263 264 case AF_UNSPEC: 265 eh = (struct ether_header *)dst->sa_data; 266 (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); 267 type = eh->ether_type; 268 break; 269 270 default: 271 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 272 dst->sa_family); 273 senderr(EAFNOSUPPORT); 274 } 275 276 277 if (mcopy) 278 (void) looutput(ifp, mcopy, dst, rt); 279 /* 280 * Add local net header. If no space in first mbuf, 281 * allocate another. 282 */ 283 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 284 if (m == 0) 285 senderr(ENOBUFS); 286 eh = mtod(m, struct ether_header *); 287 type = htons((u_short)type); 288 (void)memcpy(&eh->ether_type, &type, 289 sizeof(eh->ether_type)); 290 (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); 291 (void)memcpy(eh->ether_shost, ac->ac_enaddr, 292 sizeof(eh->ether_shost)); 293 s = splimp(); 294 /* 295 * Queue message on interface, and start output if interface 296 * not yet active. 297 */ 298 if (IF_QFULL(&ifp->if_snd)) { 299 IF_DROP(&ifp->if_snd); 300 splx(s); 301 senderr(ENOBUFS); 302 } 303 IF_ENQUEUE(&ifp->if_snd, m); 304 if ((ifp->if_flags & IFF_OACTIVE) == 0) 305 (*ifp->if_start)(ifp); 306 splx(s); 307 ifp->if_obytes += len + sizeof (struct ether_header); 308 if (m->m_flags & M_MCAST) 309 ifp->if_omcasts++; 310 return (error); 311 312 bad: 313 if (m) 314 m_freem(m); 315 return (error); 316 } 317 318 /* 319 * Process a received Ethernet packet; 320 * the packet is in the mbuf chain m without 321 * the ether header, which is provided separately. 322 */ 323 void 324 ether_input(ifp, eh, m) 325 struct ifnet *ifp; 326 register struct ether_header *eh; 327 struct mbuf *m; 328 { 329 register struct ifqueue *inq; 330 register struct llc *l; 331 u_short ether_type; 332 int s; 333 334 if ((ifp->if_flags & IFF_UP) == 0) { 335 m_freem(m); 336 return; 337 } 338 ifp->if_lastchange = time; 339 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 340 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 341 sizeof(etherbroadcastaddr)) == 0) 342 m->m_flags |= M_BCAST; 343 else if (eh->ether_dhost[0] & 1) 344 m->m_flags |= M_MCAST; 345 if (m->m_flags & (M_BCAST|M_MCAST)) 346 ifp->if_imcasts++; 347 348 ether_type = ntohs(eh->ether_type); 349 350 switch (ether_type) { 351 #ifdef INET 352 case ETHERTYPE_IP: 353 schednetisr(NETISR_IP); 354 inq = &ipintrq; 355 break; 356 357 case ETHERTYPE_ARP: 358 schednetisr(NETISR_ARP); 359 inq = &arpintrq; 360 break; 361 #endif 362 #ifdef IPX 363 case ETHERTYPE_IPX: 364 schednetisr(NETISR_IPX); 365 inq = &ipxintrq; 366 break; 367 #endif 368 #ifdef NS 369 case ETHERTYPE_NS: 370 schednetisr(NETISR_NS); 371 inq = &nsintrq; 372 break; 373 #endif 374 default: 375 #if defined (ISO) || defined (LLC) 376 if (ether_type > ETHERMTU) 377 goto dropanyway; 378 l = mtod(m, struct llc *); 379 switch (l->llc_dsap) { 380 #ifdef ISO 381 case LLC_ISO_LSAP: 382 switch (l->llc_control) { 383 case LLC_UI: 384 /* LLC_UI_P forbidden in class 1 service */ 385 if ((l->llc_dsap == LLC_ISO_LSAP) && 386 (l->llc_ssap == LLC_ISO_LSAP)) { 387 /* LSAP for ISO */ 388 if (m->m_pkthdr.len > ether_type) 389 m_adj(m, ether_type - m->m_pkthdr.len); 390 m->m_data += 3; /* XXX */ 391 m->m_len -= 3; /* XXX */ 392 m->m_pkthdr.len -= 3; /* XXX */ 393 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 394 if (m == 0) 395 return; 396 *mtod(m, struct ether_header *) = *eh; 397 IFDEBUG(D_ETHER) 398 printf("clnp packet"); 399 ENDDEBUG 400 schednetisr(NETISR_ISO); 401 inq = &clnlintrq; 402 break; 403 } 404 goto dropanyway; 405 406 case LLC_XID: 407 case LLC_XID_P: 408 if(m->m_len < 6) 409 goto dropanyway; 410 l->llc_window = 0; 411 l->llc_fid = 9; 412 l->llc_class = 1; 413 l->llc_dsap = l->llc_ssap = 0; 414 /* Fall through to */ 415 case LLC_TEST: 416 case LLC_TEST_P: 417 { 418 struct sockaddr sa; 419 register struct ether_header *eh2; 420 int i; 421 u_char c = l->llc_dsap; 422 423 l->llc_dsap = l->llc_ssap; 424 l->llc_ssap = c; 425 if (m->m_flags & (M_BCAST | M_MCAST)) 426 bcopy((caddr_t)ac->ac_enaddr, 427 (caddr_t)eh->ether_dhost, 6); 428 sa.sa_family = AF_UNSPEC; 429 sa.sa_len = sizeof(sa); 430 eh2 = (struct ether_header *)sa.sa_data; 431 for (i = 0; i < 6; i++) { 432 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 433 eh2->ether_dhost[i] = 434 eh->ether_dhost[i] = eh->ether_shost[i]; 435 eh->ether_shost[i] = c; 436 } 437 ifp->if_output(ifp, m, &sa, NULL); 438 return; 439 } 440 default: 441 m_freem(m); 442 return; 443 } 444 break; 445 #endif /* ISO */ 446 #ifdef LLC 447 case LLC_X25_LSAP: 448 { 449 if (m->m_pkthdr.len > ether_type) 450 m_adj(m, ether_type - m->m_pkthdr.len); 451 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 452 if (m == 0) 453 return; 454 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 455 eh->ether_dhost, LLC_X25_LSAP, 6, 456 mtod(m, struct sdl_hdr *))) 457 panic("ETHER cons addr failure"); 458 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type; 459 #ifdef LLC_DEBUG 460 printf("llc packet\n"); 461 #endif /* LLC_DEBUG */ 462 schednetisr(NETISR_CCITT); 463 inq = &llcintrq; 464 break; 465 } 466 #endif /* LLC */ 467 dropanyway: 468 default: 469 m_freem(m); 470 return; 471 } 472 #else /* ISO || LLC */ 473 m_freem(m); 474 return; 475 #endif /* ISO || LLC */ 476 } 477 478 s = splimp(); 479 if (IF_QFULL(inq)) { 480 IF_DROP(inq); 481 m_freem(m); 482 } else 483 IF_ENQUEUE(inq, m); 484 splx(s); 485 } 486 487 /* 488 * Perform common duties while attaching to interface list 489 */ 490 void 491 ether_ifattach(ifp) 492 register struct ifnet *ifp; 493 { 494 register struct ifaddr *ifa; 495 register struct sockaddr_dl *sdl; 496 497 ifp->if_type = IFT_ETHER; 498 ifp->if_addrlen = 6; 499 ifp->if_hdrlen = 14; 500 ifp->if_mtu = ETHERMTU; 501 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 502 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 503 sdl->sdl_family == AF_LINK) { 504 sdl->sdl_type = IFT_ETHER; 505 sdl->sdl_alen = ifp->if_addrlen; 506 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 507 LLADDR(sdl), ifp->if_addrlen); 508 break; 509 } 510 } 511 512 static u_char ether_ipmulticast_min[6] = 513 { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 514 static u_char ether_ipmulticast_max[6] = 515 { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 516 /* 517 * Add an Ethernet multicast address or range of addresses to the list for a 518 * given interface. 519 */ 520 int 521 ether_addmulti(ifr, ac) 522 struct ifreq *ifr; 523 register struct arpcom *ac; 524 { 525 register struct ether_multi *enm; 526 struct sockaddr_in *sin; 527 u_char addrlo[6]; 528 u_char addrhi[6]; 529 int set_allmulti = 0; 530 int s = splimp(); 531 532 switch (ifr->ifr_addr.sa_family) { 533 534 case AF_UNSPEC: 535 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 536 bcopy(addrlo, addrhi, 6); 537 break; 538 539 #ifdef INET 540 case AF_INET: 541 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 542 if (sin->sin_addr.s_addr == INADDR_ANY) { 543 /* 544 * An IP address of INADDR_ANY means listen to all 545 * of the Ethernet multicast addresses used for IP. 546 * (This is for the sake of IP multicast routers.) 547 */ 548 bcopy(ether_ipmulticast_min, addrlo, 6); 549 bcopy(ether_ipmulticast_max, addrhi, 6); 550 set_allmulti = 1; 551 } 552 else { 553 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 554 bcopy(addrlo, addrhi, 6); 555 } 556 break; 557 #endif 558 559 default: 560 splx(s); 561 return (EAFNOSUPPORT); 562 } 563 564 /* 565 * Verify that we have valid Ethernet multicast addresses. 566 */ 567 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 568 splx(s); 569 return (EINVAL); 570 } 571 /* 572 * See if the address range is already in the list. 573 */ 574 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 575 if (enm != NULL) { 576 /* 577 * Found it; just increment the reference count. 578 */ 579 ++enm->enm_refcount; 580 splx(s); 581 return (0); 582 } 583 /* 584 * New address or range; malloc a new multicast record 585 * and link it into the interface's multicast list. 586 */ 587 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 588 if (enm == NULL) { 589 splx(s); 590 return (ENOBUFS); 591 } 592 bcopy(addrlo, enm->enm_addrlo, 6); 593 bcopy(addrhi, enm->enm_addrhi, 6); 594 enm->enm_ac = ac; 595 enm->enm_refcount = 1; 596 enm->enm_next = ac->ac_multiaddrs; 597 ac->ac_multiaddrs = enm; 598 ac->ac_multicnt++; 599 splx(s); 600 if (set_allmulti) 601 ac->ac_if.if_flags |= IFF_ALLMULTI; 602 603 /* 604 * Return ENETRESET to inform the driver that the list has changed 605 * and its reception filter should be adjusted accordingly. 606 */ 607 return (ENETRESET); 608 } 609 610 /* 611 * Delete a multicast address record. 612 */ 613 int 614 ether_delmulti(ifr, ac) 615 struct ifreq *ifr; 616 register struct arpcom *ac; 617 { 618 register struct ether_multi *enm; 619 register struct ether_multi **p; 620 struct sockaddr_in *sin; 621 u_char addrlo[6]; 622 u_char addrhi[6]; 623 int unset_allmulti = 0; 624 int s = splimp(); 625 626 switch (ifr->ifr_addr.sa_family) { 627 628 case AF_UNSPEC: 629 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 630 bcopy(addrlo, addrhi, 6); 631 break; 632 633 #ifdef INET 634 case AF_INET: 635 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 636 if (sin->sin_addr.s_addr == INADDR_ANY) { 637 /* 638 * An IP address of INADDR_ANY means stop listening 639 * to the range of Ethernet multicast addresses used 640 * for IP. 641 */ 642 bcopy(ether_ipmulticast_min, addrlo, 6); 643 bcopy(ether_ipmulticast_max, addrhi, 6); 644 unset_allmulti = 1; 645 } 646 else { 647 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 648 bcopy(addrlo, addrhi, 6); 649 } 650 break; 651 #endif 652 653 default: 654 splx(s); 655 return (EAFNOSUPPORT); 656 } 657 658 /* 659 * Look up the address in our list. 660 */ 661 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 662 if (enm == NULL) { 663 splx(s); 664 return (ENXIO); 665 } 666 if (--enm->enm_refcount != 0) { 667 /* 668 * Still some claims to this record. 669 */ 670 splx(s); 671 return (0); 672 } 673 /* 674 * No remaining claims to this record; unlink and free it. 675 */ 676 for (p = &enm->enm_ac->ac_multiaddrs; 677 *p != enm; 678 p = &(*p)->enm_next) 679 continue; 680 *p = (*p)->enm_next; 681 free(enm, M_IFMADDR); 682 ac->ac_multicnt--; 683 splx(s); 684 if (unset_allmulti) 685 ac->ac_if.if_flags &= ~IFF_ALLMULTI; 686 687 /* 688 * Return ENETRESET to inform the driver that the list has changed 689 * and its reception filter should be adjusted accordingly. 690 */ 691 return (ENETRESET); 692 } 693 694 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); 695