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 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/malloc.h> 40 #include <sys/mbuf.h> 41 #include <sys/protosw.h> 42 #include <sys/socket.h> 43 #include <sys/ioctl.h> 44 #include <sys/errno.h> 45 #include <sys/syslog.h> 46 47 #include <machine/cpu.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 NS 63 #include <netns/ns.h> 64 #include <netns/ns_if.h> 65 #endif 66 67 #ifdef ISO 68 #include <netiso/argo_debug.h> 69 #include <netiso/iso.h> 70 #include <netiso/iso_var.h> 71 #include <netiso/iso_snpac.h> 72 #endif 73 74 #ifdef LLC 75 #include <netccitt/dll.h> 76 #include <netccitt/llc_var.h> 77 #endif 78 79 #if defined(LLC) && defined(CCITT) 80 extern struct ifqueue pkintrq; 81 #endif 82 83 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 84 extern struct ifnet loif; 85 #define senderr(e) { error = (e); goto bad;} 86 87 /* 88 * Ethernet output routine. 89 * Encapsulate a packet of type family for the local net. 90 * Use trailer local net encapsulation if enough data in first 91 * packet leaves a multiple of 512 bytes of data in remainder. 92 * Assumes that ifp is actually pointer to arpcom structure. 93 */ 94 int 95 ether_output(ifp, m0, dst, rt0) 96 register struct ifnet *ifp; 97 struct mbuf *m0; 98 struct sockaddr *dst; 99 struct rtentry *rt0; 100 { 101 u_short etype; 102 int s, error = 0; 103 u_char edst[6]; 104 register struct mbuf *m = m0; 105 register struct rtentry *rt; 106 struct mbuf *mcopy = (struct mbuf *)0; 107 register struct ether_header *eh; 108 int off, len = m->m_pkthdr.len; 109 struct arpcom *ac = (struct arpcom *)ifp; 110 111 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 112 senderr(ENETDOWN); 113 ifp->if_lastchange = time; 114 if (rt = rt0) { 115 if ((rt->rt_flags & RTF_UP) == 0) { 116 if (rt0 = rt = rtalloc1(dst, 1)) 117 rt->rt_refcnt--; 118 else 119 senderr(EHOSTUNREACH); 120 } 121 if (rt->rt_flags & RTF_GATEWAY) { 122 if (rt->rt_gwroute == 0) 123 goto lookup; 124 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 125 rtfree(rt); rt = rt0; 126 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); 127 if ((rt = rt->rt_gwroute) == 0) 128 senderr(EHOSTUNREACH); 129 } 130 } 131 if (rt->rt_flags & RTF_REJECT) 132 if (rt->rt_rmx.rmx_expire == 0 || 133 time.tv_sec < rt->rt_rmx.rmx_expire) 134 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 135 } 136 switch (dst->sa_family) { 137 138 #ifdef INET 139 case AF_INET: 140 if (!arpresolve(ac, rt, m, dst, edst)) 141 return (0); /* if not yet resolved */ 142 /* If broadcasting on a simplex interface, loopback a copy */ 143 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 144 mcopy = m_copy(m, 0, (int)M_COPYALL); 145 off = m->m_pkthdr.len - m->m_len; 146 etype = ETHERTYPE_IP; 147 break; 148 #endif 149 #ifdef NS 150 case AF_NS: 151 etype = ETHERTYPE_NS; 152 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 153 (caddr_t)edst, sizeof (edst)); 154 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) 155 return (looutput(ifp, m, dst, rt)); 156 /* If broadcasting on a simplex interface, loopback a copy */ 157 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 158 mcopy = m_copy(m, 0, (int)M_COPYALL); 159 break; 160 #endif 161 #ifdef ISO 162 case AF_ISO: { 163 int snpalen; 164 struct llc *l; 165 register struct sockaddr_dl *sdl; 166 167 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 168 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 169 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 170 } else if (error = 171 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 172 (char *)edst, &snpalen)) 173 goto bad; /* Not Resolved */ 174 /* If broadcasting on a simplex interface, loopback a copy */ 175 if (*edst & 1) 176 m->m_flags |= (M_BCAST|M_MCAST); 177 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && 178 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 179 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 180 if (mcopy) { 181 eh = mtod(mcopy, struct ether_header *); 182 bcopy((caddr_t)edst, 183 (caddr_t)eh->ether_dhost, sizeof (edst)); 184 bcopy((caddr_t)ac->ac_enaddr, 185 (caddr_t)eh->ether_shost, sizeof (edst)); 186 } 187 } 188 M_PREPEND(m, 3, M_DONTWAIT); 189 if (m == NULL) 190 return (0); 191 etype = m->m_pkthdr.len; 192 l = mtod(m, struct llc *); 193 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 194 l->llc_control = LLC_UI; 195 len += 3; 196 IFDEBUG(D_ETHER) 197 int i; 198 printf("unoutput: sending pkt to: "); 199 for (i=0; i<6; i++) 200 printf("%x ", edst[i] & 0xff); 201 printf("\n"); 202 ENDDEBUG 203 } break; 204 #endif /* ISO */ 205 #ifdef LLC 206 /* case AF_NSAP: */ 207 case AF_CCITT: { 208 register struct sockaddr_dl *sdl = 209 (struct sockaddr_dl *) rt -> rt_gateway; 210 211 if (sdl && sdl->sdl_family == AF_LINK 212 && sdl->sdl_alen > 0) { 213 bcopy(LLADDR(sdl), (char *)edst, 214 sizeof(edst)); 215 } else goto bad; /* Not a link interface ? Funny ... */ 216 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && 217 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 218 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 219 if (mcopy) { 220 eh = mtod(mcopy, struct ether_header *); 221 bcopy((caddr_t)edst, 222 (caddr_t)eh->ether_dhost, sizeof (edst)); 223 bcopy((caddr_t)ac->ac_enaddr, 224 (caddr_t)eh->ether_shost, sizeof (edst)); 225 } 226 } 227 etype = m->m_pkthdr.len; 228 #ifdef LLC_DEBUG 229 { 230 int i; 231 register struct llc *l = mtod(m, struct llc *); 232 233 printf("ether_output: sending LLC2 pkt to: "); 234 for (i=0; i<6; i++) 235 printf("%x ", edst[i] & 0xff); 236 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 237 etype & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 238 l->llc_control & 0xff); 239 240 } 241 #endif /* LLC_DEBUG */ 242 } break; 243 #endif /* LLC */ 244 245 case AF_UNSPEC: 246 eh = (struct ether_header *)dst->sa_data; 247 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 248 /* AF_UNSPEC doesn't swap the byte order of the ether_type. */ 249 etype = ntohs(eh->ether_type); 250 break; 251 252 default: 253 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 254 dst->sa_family); 255 senderr(EAFNOSUPPORT); 256 } 257 258 259 if (mcopy) 260 (void) looutput(ifp, mcopy, dst, rt); 261 /* 262 * Add local net header. If no space in first mbuf, 263 * allocate another. 264 */ 265 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 266 if (m == 0) 267 senderr(ENOBUFS); 268 eh = mtod(m, struct ether_header *); 269 etype = htons(etype); 270 bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type, 271 sizeof(eh->ether_type)); 272 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 273 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, 274 sizeof(eh->ether_shost)); 275 s = splimp(); 276 /* 277 * Queue message on interface, and start output if interface 278 * not yet active. 279 */ 280 if (IF_QFULL(&ifp->if_snd)) { 281 IF_DROP(&ifp->if_snd); 282 splx(s); 283 senderr(ENOBUFS); 284 } 285 IF_ENQUEUE(&ifp->if_snd, m); 286 if ((ifp->if_flags & IFF_OACTIVE) == 0) 287 (*ifp->if_start)(ifp); 288 splx(s); 289 ifp->if_obytes += len + sizeof (struct ether_header); 290 if (m->m_flags & M_MCAST) 291 ifp->if_omcasts++; 292 return (error); 293 294 bad: 295 if (m) 296 m_freem(m); 297 return (error); 298 } 299 300 /* 301 * Process a received Ethernet packet; 302 * the packet is in the mbuf chain m without 303 * the ether header, which is provided separately. 304 */ 305 void 306 ether_input(ifp, eh, m) 307 struct ifnet *ifp; 308 register struct ether_header *eh; 309 struct mbuf *m; 310 { 311 register struct ifqueue *inq; 312 register struct llc *l; 313 u_short etype; 314 struct arpcom *ac = (struct arpcom *)ifp; 315 int s; 316 317 if ((ifp->if_flags & IFF_UP) == 0) { 318 m_freem(m); 319 return; 320 } 321 ifp->if_lastchange = time; 322 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 323 if (eh->ether_dhost[0] & 1) { 324 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 325 sizeof(etherbroadcastaddr)) == 0) 326 m->m_flags |= M_BCAST; 327 else 328 m->m_flags |= M_MCAST; 329 } 330 if (m->m_flags & (M_BCAST|M_MCAST)) 331 ifp->if_imcasts++; 332 333 etype = ntohs(eh->ether_type); 334 switch (etype) { 335 #ifdef INET 336 case ETHERTYPE_IP: 337 schednetisr(NETISR_IP); 338 inq = &ipintrq; 339 break; 340 341 case ETHERTYPE_ARP: 342 schednetisr(NETISR_ARP); 343 inq = &arpintrq; 344 break; 345 346 case ETHERTYPE_REVARP: 347 revarpinput(m); /* XXX queue? */ 348 return; 349 #endif 350 #ifdef NS 351 case ETHERTYPE_NS: 352 schednetisr(NETISR_NS); 353 inq = &nsintrq; 354 break; 355 356 #endif 357 default: 358 #if defined (ISO) || defined (LLC) 359 if (eh->ether_type > ETHERMTU) 360 goto dropanyway; 361 l = mtod(m, struct llc *); 362 switch (l->llc_dsap) { 363 #ifdef ISO 364 case LLC_ISO_LSAP: 365 switch (l->llc_control) { 366 case LLC_UI: 367 /* LLC_UI_P forbidden in class 1 service */ 368 if ((l->llc_dsap == LLC_ISO_LSAP) && 369 (l->llc_ssap == LLC_ISO_LSAP)) { 370 /* LSAP for ISO */ 371 if (m->m_pkthdr.len > eh->ether_type) 372 m_adj(m, eh->ether_type - m->m_pkthdr.len); 373 m->m_data += 3; /* XXX */ 374 m->m_len -= 3; /* XXX */ 375 m->m_pkthdr.len -= 3; /* XXX */ 376 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 377 if (m == 0) 378 return; 379 *mtod(m, struct ether_header *) = *eh; 380 IFDEBUG(D_ETHER) 381 printf("clnp packet"); 382 ENDDEBUG 383 schednetisr(NETISR_ISO); 384 inq = &clnlintrq; 385 break; 386 } 387 goto dropanyway; 388 389 case LLC_XID: 390 case LLC_XID_P: 391 if(m->m_len < 6) 392 goto dropanyway; 393 l->llc_window = 0; 394 l->llc_fid = 9; 395 l->llc_class = 1; 396 l->llc_dsap = l->llc_ssap = 0; 397 /* Fall through to */ 398 case LLC_TEST: 399 case LLC_TEST_P: 400 { 401 struct sockaddr sa; 402 register struct ether_header *eh2; 403 int i; 404 u_char c = l->llc_dsap; 405 406 l->llc_dsap = l->llc_ssap; 407 l->llc_ssap = c; 408 if (m->m_flags & (M_BCAST | M_MCAST)) 409 bcopy((caddr_t)ac->ac_enaddr, 410 (caddr_t)eh->ether_dhost, 6); 411 sa.sa_family = AF_UNSPEC; 412 sa.sa_len = sizeof(sa); 413 eh2 = (struct ether_header *)sa.sa_data; 414 for (i = 0; i < 6; i++) { 415 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 416 eh2->ether_dhost[i] = 417 eh->ether_dhost[i] = eh->ether_shost[i]; 418 eh->ether_shost[i] = c; 419 } 420 ifp->if_output(ifp, m, &sa, NULL); 421 return; 422 } 423 default: 424 m_freem(m); 425 return; 426 } 427 break; 428 #endif /* ISO */ 429 #ifdef LLC 430 case LLC_X25_LSAP: 431 { 432 if (m->m_pkthdr.len > eh->ether_type) 433 m_adj(m, eh->ether_type - m->m_pkthdr.len); 434 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 435 if (m == 0) 436 return; 437 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 438 eh->ether_dhost, LLC_X25_LSAP, 6, 439 mtod(m, struct sdl_hdr *))) 440 panic("ETHER cons addr failure"); 441 mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type; 442 #ifdef LLC_DEBUG 443 printf("llc packet\n"); 444 #endif /* LLC_DEBUG */ 445 schednetisr(NETISR_CCITT); 446 inq = &llcintrq; 447 break; 448 } 449 #endif /* LLC */ 450 dropanyway: 451 default: 452 m_freem(m); 453 return; 454 } 455 #else /* ISO || LLC */ 456 m_freem(m); 457 return; 458 #endif /* ISO || LLC */ 459 } 460 461 s = splimp(); 462 if (IF_QFULL(inq)) { 463 IF_DROP(inq); 464 m_freem(m); 465 } else 466 IF_ENQUEUE(inq, m); 467 splx(s); 468 } 469 470 /* 471 * Convert Ethernet address to printable (loggable) representation. 472 */ 473 static char digits[] = "0123456789abcdef"; 474 char * 475 ether_sprintf(ap) 476 register u_char *ap; 477 { 478 register i; 479 static char etherbuf[18]; 480 register char *cp = etherbuf; 481 482 for (i = 0; i < 6; i++) { 483 *cp++ = digits[*ap >> 4]; 484 *cp++ = digits[*ap++ & 0xf]; 485 *cp++ = ':'; 486 } 487 *--cp = 0; 488 return (etherbuf); 489 } 490 491 /* 492 * Perform common duties while attaching to interface list 493 */ 494 void 495 ether_ifattach(ifp) 496 register struct ifnet *ifp; 497 { 498 register struct ifaddr *ifa; 499 register struct sockaddr_dl *sdl; 500 501 ifp->if_type = IFT_ETHER; 502 ifp->if_addrlen = 6; 503 ifp->if_hdrlen = 14; 504 ifp->if_mtu = ETHERMTU; 505 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 506 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 507 sdl->sdl_family == AF_LINK) { 508 sdl->sdl_type = IFT_ETHER; 509 sdl->sdl_alen = ifp->if_addrlen; 510 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 511 LLADDR(sdl), ifp->if_addrlen); 512 break; 513 } 514 } 515 516 u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 517 u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 518 /* 519 * Add an Ethernet multicast address or range of addresses to the list for a 520 * given interface. 521 */ 522 int 523 ether_addmulti(ifr, ac) 524 struct ifreq *ifr; 525 register struct arpcom *ac; 526 { 527 register struct ether_multi *enm; 528 struct sockaddr_in *sin; 529 u_char addrlo[6]; 530 u_char addrhi[6]; 531 int s = splimp(); 532 533 switch (ifr->ifr_addr.sa_family) { 534 535 case AF_UNSPEC: 536 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 537 bcopy(addrlo, addrhi, 6); 538 break; 539 540 #ifdef INET 541 case AF_INET: 542 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 543 if (sin->sin_addr.s_addr == INADDR_ANY) { 544 /* 545 * An IP address of INADDR_ANY means listen to all 546 * of the Ethernet multicast addresses used for IP. 547 * (This is for the sake of IP multicast routers.) 548 */ 549 bcopy(ether_ipmulticast_min, addrlo, 6); 550 bcopy(ether_ipmulticast_max, addrhi, 6); 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 /* 601 * Return ENETRESET to inform the driver that the list has changed 602 * and its reception filter should be adjusted accordingly. 603 */ 604 return (ENETRESET); 605 } 606 607 /* 608 * Delete a multicast address record. 609 */ 610 int 611 ether_delmulti(ifr, ac) 612 struct ifreq *ifr; 613 register struct arpcom *ac; 614 { 615 register struct ether_multi *enm; 616 register struct ether_multi **p; 617 struct sockaddr_in *sin; 618 u_char addrlo[6]; 619 u_char addrhi[6]; 620 int s = splimp(); 621 622 switch (ifr->ifr_addr.sa_family) { 623 624 case AF_UNSPEC: 625 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 626 bcopy(addrlo, addrhi, 6); 627 break; 628 629 #ifdef INET 630 case AF_INET: 631 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 632 if (sin->sin_addr.s_addr == INADDR_ANY) { 633 /* 634 * An IP address of INADDR_ANY means stop listening 635 * to the range of Ethernet multicast addresses used 636 * for IP. 637 */ 638 bcopy(ether_ipmulticast_min, addrlo, 6); 639 bcopy(ether_ipmulticast_max, addrhi, 6); 640 } 641 else { 642 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 643 bcopy(addrlo, addrhi, 6); 644 } 645 break; 646 #endif 647 648 default: 649 splx(s); 650 return (EAFNOSUPPORT); 651 } 652 653 /* 654 * Look up the address in our list. 655 */ 656 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 657 if (enm == NULL) { 658 splx(s); 659 return (ENXIO); 660 } 661 if (--enm->enm_refcount != 0) { 662 /* 663 * Still some claims to this record. 664 */ 665 splx(s); 666 return (0); 667 } 668 /* 669 * No remaining claims to this record; unlink and free it. 670 */ 671 for (p = &enm->enm_ac->ac_multiaddrs; 672 *p != enm; 673 p = &(*p)->enm_next) 674 continue; 675 *p = (*p)->enm_next; 676 free(enm, M_IFMADDR); 677 ac->ac_multicnt--; 678 splx(s); 679 /* 680 * Return ENETRESET to inform the driver that the list has changed 681 * and its reception filter should be adjusted accordingly. 682 */ 683 return (ENETRESET); 684 } 685