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 short type; 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 type = ETHERTYPE_IP; 147 break; 148 #endif 149 #ifdef NS 150 case AF_NS: 151 type = 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 type = 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 type = 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 type & 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 type = eh->ether_type; 249 break; 250 251 default: 252 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 253 dst->sa_family); 254 senderr(EAFNOSUPPORT); 255 } 256 257 258 if (mcopy) 259 (void) looutput(ifp, mcopy, dst, rt); 260 /* 261 * Add local net header. If no space in first mbuf, 262 * allocate another. 263 */ 264 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 265 if (m == 0) 266 senderr(ENOBUFS); 267 eh = mtod(m, struct ether_header *); 268 type = htons((u_short)type); 269 bcopy((caddr_t)&type,(caddr_t)&eh->ether_type, 270 sizeof(eh->ether_type)); 271 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 272 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, 273 sizeof(eh->ether_shost)); 274 s = splimp(); 275 /* 276 * Queue message on interface, and start output if interface 277 * not yet active. 278 */ 279 if (IF_QFULL(&ifp->if_snd)) { 280 IF_DROP(&ifp->if_snd); 281 splx(s); 282 senderr(ENOBUFS); 283 } 284 IF_ENQUEUE(&ifp->if_snd, m); 285 if ((ifp->if_flags & IFF_OACTIVE) == 0) 286 (*ifp->if_start)(ifp); 287 splx(s); 288 ifp->if_obytes += len + sizeof (struct ether_header); 289 if (m->m_flags & M_MCAST) 290 ifp->if_omcasts++; 291 return (error); 292 293 bad: 294 if (m) 295 m_freem(m); 296 return (error); 297 } 298 299 /* 300 * Process a received Ethernet packet; 301 * the packet is in the mbuf chain m without 302 * the ether header, which is provided separately. 303 */ 304 void 305 ether_input(ifp, eh, m) 306 struct ifnet *ifp; 307 register struct ether_header *eh; 308 struct mbuf *m; 309 { 310 register struct ifqueue *inq; 311 register struct llc *l; 312 struct arpcom *ac = (struct arpcom *)ifp; 313 int s; 314 315 if ((ifp->if_flags & IFF_UP) == 0) { 316 m_freem(m); 317 return; 318 } 319 ifp->if_lastchange = time; 320 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 321 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 322 sizeof(etherbroadcastaddr)) == 0) 323 m->m_flags |= M_BCAST; 324 else if (eh->ether_dhost[0] & 1) 325 m->m_flags |= M_MCAST; 326 if (m->m_flags & (M_BCAST|M_MCAST)) 327 ifp->if_imcasts++; 328 329 switch (eh->ether_type) { 330 #ifdef INET 331 case ETHERTYPE_IP: 332 schednetisr(NETISR_IP); 333 inq = &ipintrq; 334 break; 335 336 case ETHERTYPE_ARP: 337 schednetisr(NETISR_ARP); 338 inq = &arpintrq; 339 break; 340 #endif 341 #ifdef NS 342 case ETHERTYPE_NS: 343 schednetisr(NETISR_NS); 344 inq = &nsintrq; 345 break; 346 347 #endif 348 default: 349 #if defined (ISO) || defined (LLC) 350 if (eh->ether_type > ETHERMTU) 351 goto dropanyway; 352 l = mtod(m, struct llc *); 353 switch (l->llc_dsap) { 354 #ifdef ISO 355 case LLC_ISO_LSAP: 356 switch (l->llc_control) { 357 case LLC_UI: 358 /* LLC_UI_P forbidden in class 1 service */ 359 if ((l->llc_dsap == LLC_ISO_LSAP) && 360 (l->llc_ssap == LLC_ISO_LSAP)) { 361 /* LSAP for ISO */ 362 if (m->m_pkthdr.len > eh->ether_type) 363 m_adj(m, eh->ether_type - m->m_pkthdr.len); 364 m->m_data += 3; /* XXX */ 365 m->m_len -= 3; /* XXX */ 366 m->m_pkthdr.len -= 3; /* XXX */ 367 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 368 if (m == 0) 369 return; 370 *mtod(m, struct ether_header *) = *eh; 371 IFDEBUG(D_ETHER) 372 printf("clnp packet"); 373 ENDDEBUG 374 schednetisr(NETISR_ISO); 375 inq = &clnlintrq; 376 break; 377 } 378 goto dropanyway; 379 380 case LLC_XID: 381 case LLC_XID_P: 382 if(m->m_len < 6) 383 goto dropanyway; 384 l->llc_window = 0; 385 l->llc_fid = 9; 386 l->llc_class = 1; 387 l->llc_dsap = l->llc_ssap = 0; 388 /* Fall through to */ 389 case LLC_TEST: 390 case LLC_TEST_P: 391 { 392 struct sockaddr sa; 393 register struct ether_header *eh2; 394 int i; 395 u_char c = l->llc_dsap; 396 397 l->llc_dsap = l->llc_ssap; 398 l->llc_ssap = c; 399 if (m->m_flags & (M_BCAST | M_MCAST)) 400 bcopy((caddr_t)ac->ac_enaddr, 401 (caddr_t)eh->ether_dhost, 6); 402 sa.sa_family = AF_UNSPEC; 403 sa.sa_len = sizeof(sa); 404 eh2 = (struct ether_header *)sa.sa_data; 405 for (i = 0; i < 6; i++) { 406 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 407 eh2->ether_dhost[i] = 408 eh->ether_dhost[i] = eh->ether_shost[i]; 409 eh->ether_shost[i] = c; 410 } 411 ifp->if_output(ifp, m, &sa, NULL); 412 return; 413 } 414 default: 415 m_freem(m); 416 return; 417 } 418 break; 419 #endif /* ISO */ 420 #ifdef LLC 421 case LLC_X25_LSAP: 422 { 423 if (m->m_pkthdr.len > eh->ether_type) 424 m_adj(m, eh->ether_type - m->m_pkthdr.len); 425 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 426 if (m == 0) 427 return; 428 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 429 eh->ether_dhost, LLC_X25_LSAP, 6, 430 mtod(m, struct sdl_hdr *))) 431 panic("ETHER cons addr failure"); 432 mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type; 433 #ifdef LLC_DEBUG 434 printf("llc packet\n"); 435 #endif /* LLC_DEBUG */ 436 schednetisr(NETISR_CCITT); 437 inq = &llcintrq; 438 break; 439 } 440 #endif /* LLC */ 441 dropanyway: 442 default: 443 m_freem(m); 444 return; 445 } 446 #else /* ISO || LLC */ 447 m_freem(m); 448 return; 449 #endif /* ISO || LLC */ 450 } 451 452 s = splimp(); 453 if (IF_QFULL(inq)) { 454 IF_DROP(inq); 455 m_freem(m); 456 } else 457 IF_ENQUEUE(inq, m); 458 splx(s); 459 } 460 461 /* 462 * Convert Ethernet address to printable (loggable) representation. 463 */ 464 static char digits[] = "0123456789abcdef"; 465 char * 466 ether_sprintf(ap) 467 register u_char *ap; 468 { 469 register i; 470 static char etherbuf[18]; 471 register char *cp = etherbuf; 472 473 for (i = 0; i < 6; i++) { 474 *cp++ = digits[*ap >> 4]; 475 *cp++ = digits[*ap++ & 0xf]; 476 *cp++ = ':'; 477 } 478 *--cp = 0; 479 return (etherbuf); 480 } 481 482 /* 483 * Perform common duties while attaching to interface list 484 */ 485 void 486 ether_ifattach(ifp) 487 register struct ifnet *ifp; 488 { 489 register struct ifaddr *ifa; 490 register struct sockaddr_dl *sdl; 491 492 ifp->if_type = IFT_ETHER; 493 ifp->if_addrlen = 6; 494 ifp->if_hdrlen = 14; 495 ifp->if_mtu = ETHERMTU; 496 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 497 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 498 sdl->sdl_family == AF_LINK) { 499 sdl->sdl_type = IFT_ETHER; 500 sdl->sdl_alen = ifp->if_addrlen; 501 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 502 LLADDR(sdl), ifp->if_addrlen); 503 break; 504 } 505 } 506 507 u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 508 u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 509 /* 510 * Add an Ethernet multicast address or range of addresses to the list for a 511 * given interface. 512 */ 513 int 514 ether_addmulti(ifr, ac) 515 struct ifreq *ifr; 516 register struct arpcom *ac; 517 { 518 register struct ether_multi *enm; 519 struct sockaddr_in *sin; 520 u_char addrlo[6]; 521 u_char addrhi[6]; 522 int s = splimp(); 523 524 switch (ifr->ifr_addr.sa_family) { 525 526 case AF_UNSPEC: 527 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 528 bcopy(addrlo, addrhi, 6); 529 break; 530 531 #ifdef INET 532 case AF_INET: 533 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 534 if (sin->sin_addr.s_addr == INADDR_ANY) { 535 /* 536 * An IP address of INADDR_ANY means listen to all 537 * of the Ethernet multicast addresses used for IP. 538 * (This is for the sake of IP multicast routers.) 539 */ 540 bcopy(ether_ipmulticast_min, addrlo, 6); 541 bcopy(ether_ipmulticast_max, addrhi, 6); 542 } 543 else { 544 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 545 bcopy(addrlo, addrhi, 6); 546 } 547 break; 548 #endif 549 550 default: 551 splx(s); 552 return (EAFNOSUPPORT); 553 } 554 555 /* 556 * Verify that we have valid Ethernet multicast addresses. 557 */ 558 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 559 splx(s); 560 return (EINVAL); 561 } 562 /* 563 * See if the address range is already in the list. 564 */ 565 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 566 if (enm != NULL) { 567 /* 568 * Found it; just increment the reference count. 569 */ 570 ++enm->enm_refcount; 571 splx(s); 572 return (0); 573 } 574 /* 575 * New address or range; malloc a new multicast record 576 * and link it into the interface's multicast list. 577 */ 578 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 579 if (enm == NULL) { 580 splx(s); 581 return (ENOBUFS); 582 } 583 bcopy(addrlo, enm->enm_addrlo, 6); 584 bcopy(addrhi, enm->enm_addrhi, 6); 585 enm->enm_ac = ac; 586 enm->enm_refcount = 1; 587 enm->enm_next = ac->ac_multiaddrs; 588 ac->ac_multiaddrs = enm; 589 ac->ac_multicnt++; 590 splx(s); 591 /* 592 * Return ENETRESET to inform the driver that the list has changed 593 * and its reception filter should be adjusted accordingly. 594 */ 595 return (ENETRESET); 596 } 597 598 /* 599 * Delete a multicast address record. 600 */ 601 int 602 ether_delmulti(ifr, ac) 603 struct ifreq *ifr; 604 register struct arpcom *ac; 605 { 606 register struct ether_multi *enm; 607 register struct ether_multi **p; 608 struct sockaddr_in *sin; 609 u_char addrlo[6]; 610 u_char addrhi[6]; 611 int s = splimp(); 612 613 switch (ifr->ifr_addr.sa_family) { 614 615 case AF_UNSPEC: 616 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 617 bcopy(addrlo, addrhi, 6); 618 break; 619 620 #ifdef INET 621 case AF_INET: 622 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 623 if (sin->sin_addr.s_addr == INADDR_ANY) { 624 /* 625 * An IP address of INADDR_ANY means stop listening 626 * to the range of Ethernet multicast addresses used 627 * for IP. 628 */ 629 bcopy(ether_ipmulticast_min, addrlo, 6); 630 bcopy(ether_ipmulticast_max, addrhi, 6); 631 } 632 else { 633 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 634 bcopy(addrlo, addrhi, 6); 635 } 636 break; 637 #endif 638 639 default: 640 splx(s); 641 return (EAFNOSUPPORT); 642 } 643 644 /* 645 * Look up the address in our list. 646 */ 647 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); 648 if (enm == NULL) { 649 splx(s); 650 return (ENXIO); 651 } 652 if (--enm->enm_refcount != 0) { 653 /* 654 * Still some claims to this record. 655 */ 656 splx(s); 657 return (0); 658 } 659 /* 660 * No remaining claims to this record; unlink and free it. 661 */ 662 for (p = &enm->enm_ac->ac_multiaddrs; 663 *p != enm; 664 p = &(*p)->enm_next) 665 continue; 666 *p = (*p)->enm_next; 667 free(enm, M_IFMADDR); 668 ac->ac_multicnt--; 669 splx(s); 670 /* 671 * Return ENETRESET to inform the driver that the list has changed 672 * and its reception filter should be adjusted accordingly. 673 */ 674 return (ENETRESET); 675 } 676