1 /* 2 * Copyright (c) 1982, 1986, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)in.c 7.26 (Berkeley) 10/11/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/ioctl.h> 12 #include <sys/errno.h> 13 #include <sys/malloc.h> 14 #include <sys/socket.h> 15 #include <sys/socketvar.h> 16 17 #include <net/if.h> 18 #include <net/route.h> 19 #include <net/af.h> 20 21 #include <netinet/in_systm.h> 22 #include <netinet/in.h> 23 #include <netinet/in_var.h> 24 25 #ifdef INET 26 /* 27 * Formulate an Internet address from network + host. 28 */ 29 struct in_addr 30 in_makeaddr(net, host) 31 u_long net, host; 32 { 33 register struct in_ifaddr *ia; 34 register u_long mask; 35 u_long addr; 36 37 if (IN_CLASSA(net)) 38 mask = IN_CLASSA_HOST; 39 else if (IN_CLASSB(net)) 40 mask = IN_CLASSB_HOST; 41 else 42 mask = IN_CLASSC_HOST; 43 for (ia = in_ifaddr; ia; ia = ia->ia_next) 44 if ((ia->ia_netmask & net) == ia->ia_net) { 45 mask = ~ia->ia_subnetmask; 46 break; 47 } 48 addr = htonl(net | (host & mask)); 49 return (*(struct in_addr *)&addr); 50 } 51 52 /* 53 * Return the network number from an internet address. 54 */ 55 u_long 56 in_netof(in) 57 struct in_addr in; 58 { 59 register u_long i = ntohl(in.s_addr); 60 register u_long net; 61 register struct in_ifaddr *ia; 62 63 if (IN_CLASSA(i)) 64 net = i & IN_CLASSA_NET; 65 else if (IN_CLASSB(i)) 66 net = i & IN_CLASSB_NET; 67 else if (IN_CLASSC(i)) 68 net = i & IN_CLASSC_NET; 69 #ifdef MULTICAST 70 else if (IN_CLASSD(i)) 71 net = i & IN_CLASSD_NET; 72 #endif 73 else 74 return (0); 75 76 /* 77 * Check whether network is a subnet; 78 * if so, return subnet number. 79 */ 80 for (ia = in_ifaddr; ia; ia = ia->ia_next) 81 if (net == ia->ia_net) 82 return (i & ia->ia_subnetmask); 83 return (net); 84 } 85 86 /* 87 * Compute and save network mask as sockaddr from an internet address. 88 */ 89 in_sockmaskof(in, sockmask) 90 struct in_addr in; 91 register struct sockaddr_in *sockmask; 92 { 93 register u_long net; 94 register u_long mask; 95 { 96 register u_long i = ntohl(in.s_addr); 97 98 if (i == 0) 99 net = 0, mask = 0; 100 else if (IN_CLASSA(i)) 101 net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 102 else if (IN_CLASSB(i)) 103 net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 104 else if (IN_CLASSC(i)) 105 net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 106 else 107 net = i, mask = -1; 108 } 109 { 110 register struct in_ifaddr *ia; 111 /* 112 * Check whether network is a subnet; 113 * if so, return subnet number. 114 */ 115 for (ia = in_ifaddr; ia; ia = ia->ia_next) 116 if (net == ia->ia_net) 117 mask = ia->ia_subnetmask; 118 } 119 { 120 register char *cpbase = (char *)&(sockmask->sin_addr); 121 register char *cp = (char *)(1 + &(sockmask->sin_addr)); 122 123 sockmask->sin_addr.s_addr = htonl(mask); 124 sockmask->sin_len = 0; 125 while (--cp >= cpbase) 126 if (*cp) { 127 sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 128 break; 129 } 130 } 131 } 132 133 /* 134 * Return the host portion of an internet address. 135 */ 136 u_long 137 in_lnaof(in) 138 struct in_addr in; 139 { 140 register u_long i = ntohl(in.s_addr); 141 register u_long net, host; 142 register struct in_ifaddr *ia; 143 144 if (IN_CLASSA(i)) { 145 net = i & IN_CLASSA_NET; 146 host = i & IN_CLASSA_HOST; 147 } else if (IN_CLASSB(i)) { 148 net = i & IN_CLASSB_NET; 149 host = i & IN_CLASSB_HOST; 150 } else if (IN_CLASSC(i)) { 151 net = i & IN_CLASSC_NET; 152 host = i & IN_CLASSC_HOST; 153 #ifdef MULTICAST 154 } else if (IN_CLASSD(i)) { 155 net = i & IN_CLASSD_NET; 156 host = i & IN_CLASSD_HOST; 157 #endif 158 } else 159 return (i); 160 161 /* 162 * Check whether network is a subnet; 163 * if so, use the modified interpretation of `host'. 164 */ 165 for (ia = in_ifaddr; ia; ia = ia->ia_next) 166 if (net == ia->ia_net) 167 return (host &~ ia->ia_subnetmask); 168 return (host); 169 } 170 171 #ifndef SUBNETSARELOCAL 172 #define SUBNETSARELOCAL 1 173 #endif 174 int subnetsarelocal = SUBNETSARELOCAL; 175 /* 176 * Return 1 if an internet address is for a ``local'' host 177 * (one to which we have a connection). If subnetsarelocal 178 * is true, this includes other subnets of the local net. 179 * Otherwise, it includes only the directly-connected (sub)nets. 180 */ 181 in_localaddr(in) 182 struct in_addr in; 183 { 184 register u_long i = ntohl(in.s_addr); 185 register struct in_ifaddr *ia; 186 187 if (subnetsarelocal) { 188 for (ia = in_ifaddr; ia; ia = ia->ia_next) 189 if ((i & ia->ia_netmask) == ia->ia_net) 190 return (1); 191 } else { 192 for (ia = in_ifaddr; ia; ia = ia->ia_next) 193 if ((i & ia->ia_subnetmask) == ia->ia_subnet) 194 return (1); 195 } 196 return (0); 197 } 198 199 /* 200 * Determine whether an IP address is in a reserved set of addresses 201 * that may not be forwarded, or whether datagrams to that destination 202 * may be forwarded. 203 */ 204 in_canforward(in) 205 struct in_addr in; 206 { 207 register u_long i = ntohl(in.s_addr); 208 register u_long net; 209 210 if (IN_EXPERIMENTAL(i)) 211 return (0); 212 if (IN_CLASSA(i)) { 213 net = i & IN_CLASSA_NET; 214 if (net == 0 || net == IN_LOOPBACKNET) 215 return (0); 216 } 217 return (1); 218 } 219 220 int in_interfaces; /* number of external internet interfaces */ 221 extern struct ifnet loif; 222 223 /* 224 * Generic internet control operations (ioctl's). 225 * Ifp is 0 if not an interface-specific ioctl. 226 */ 227 /* ARGSUSED */ 228 in_control(so, cmd, data, ifp) 229 struct socket *so; 230 int cmd; 231 caddr_t data; 232 register struct ifnet *ifp; 233 { 234 register struct ifreq *ifr = (struct ifreq *)data; 235 register struct in_ifaddr *ia = 0; 236 register struct ifaddr *ifa; 237 struct in_ifaddr *oia; 238 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 239 struct sockaddr_in oldaddr; 240 int error, hostIsNew, maskIsNew; 241 u_long i; 242 243 /* 244 * Find address for this interface, if it exists. 245 */ 246 if (ifp) 247 for (ia = in_ifaddr; ia; ia = ia->ia_next) 248 if (ia->ia_ifp == ifp) 249 break; 250 251 switch (cmd) { 252 253 case SIOCAIFADDR: 254 case SIOCDIFADDR: 255 if (ifra->ifra_addr.sin_family == AF_INET) 256 for (oia = ia; ia; ia = ia->ia_next) { 257 if (ia->ia_ifp == ifp && 258 ia->ia_addr.sin_addr.s_addr == 259 ifra->ifra_addr.sin_addr.s_addr) 260 break; 261 } 262 if (cmd == SIOCDIFADDR && ia == 0) 263 return (EADDRNOTAVAIL); 264 /* FALLTHROUGH */ 265 case SIOCSIFADDR: 266 case SIOCSIFNETMASK: 267 case SIOCSIFDSTADDR: 268 if ((so->so_state & SS_PRIV) == 0) 269 return (EPERM); 270 271 if (ifp == 0) 272 panic("in_control"); 273 if (ia == (struct in_ifaddr *)0) { 274 oia = (struct in_ifaddr *) 275 malloc(sizeof *oia, M_IFADDR, M_WAITOK); 276 if (oia == (struct in_ifaddr *)NULL) 277 return (ENOBUFS); 278 bzero((caddr_t)oia, sizeof *oia); 279 if (ia = in_ifaddr) { 280 for ( ; ia->ia_next; ia = ia->ia_next) 281 continue; 282 ia->ia_next = oia; 283 } else 284 in_ifaddr = oia; 285 ia = oia; 286 if (ifa = ifp->if_addrlist) { 287 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 288 continue; 289 ifa->ifa_next = (struct ifaddr *) ia; 290 } else 291 ifp->if_addrlist = (struct ifaddr *) ia; 292 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 293 ia->ia_ifa.ifa_dstaddr 294 = (struct sockaddr *)&ia->ia_dstaddr; 295 ia->ia_ifa.ifa_netmask 296 = (struct sockaddr *)&ia->ia_sockmask; 297 ia->ia_sockmask.sin_len = 8; 298 if (ifp->if_flags & IFF_BROADCAST) { 299 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 300 ia->ia_broadaddr.sin_family = AF_INET; 301 } 302 ia->ia_ifp = ifp; 303 if (ifp != &loif) 304 in_interfaces++; 305 } 306 break; 307 308 case SIOCSIFBRDADDR: 309 if ((so->so_state & SS_PRIV) == 0) 310 return (EPERM); 311 /* FALLTHROUGH */ 312 313 case SIOCGIFADDR: 314 case SIOCGIFNETMASK: 315 case SIOCGIFDSTADDR: 316 case SIOCGIFBRDADDR: 317 if (ia == (struct in_ifaddr *)0) 318 return (EADDRNOTAVAIL); 319 break; 320 } 321 switch (cmd) { 322 323 case SIOCGIFADDR: 324 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 325 break; 326 327 case SIOCGIFBRDADDR: 328 if ((ifp->if_flags & IFF_BROADCAST) == 0) 329 return (EINVAL); 330 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 331 break; 332 333 case SIOCGIFDSTADDR: 334 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 335 return (EINVAL); 336 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 337 break; 338 339 case SIOCGIFNETMASK: 340 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 341 break; 342 343 case SIOCSIFDSTADDR: 344 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 345 return (EINVAL); 346 oldaddr = ia->ia_dstaddr; 347 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 348 if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 349 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 350 ia->ia_dstaddr = oldaddr; 351 return (error); 352 } 353 if (ia->ia_flags & IFA_ROUTE) { 354 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 355 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 356 ia->ia_ifa.ifa_dstaddr = 357 (struct sockaddr *)&ia->ia_dstaddr; 358 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 359 } 360 break; 361 362 case SIOCSIFBRDADDR: 363 if ((ifp->if_flags & IFF_BROADCAST) == 0) 364 return (EINVAL); 365 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 366 break; 367 368 case SIOCSIFADDR: 369 return (in_ifinit(ifp, ia, 370 (struct sockaddr_in *) &ifr->ifr_addr, 1)); 371 372 case SIOCSIFNETMASK: 373 i = ifra->ifra_addr.sin_addr.s_addr; 374 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 375 break; 376 377 case SIOCAIFADDR: 378 maskIsNew = 0; 379 hostIsNew = 1; 380 error = 0; 381 if (ia->ia_addr.sin_family == AF_INET) { 382 if (ifra->ifra_addr.sin_len == 0) { 383 ifra->ifra_addr = ia->ia_addr; 384 hostIsNew = 0; 385 } else if (ifra->ifra_addr.sin_addr.s_addr == 386 ia->ia_addr.sin_addr.s_addr) 387 hostIsNew = 0; 388 } 389 if (ifra->ifra_mask.sin_len) { 390 in_ifscrub(ifp, ia); 391 ia->ia_sockmask = ifra->ifra_mask; 392 ia->ia_subnetmask = 393 ntohl(ia->ia_sockmask.sin_addr.s_addr); 394 maskIsNew = 1; 395 } 396 if ((ifp->if_flags & IFF_POINTOPOINT) && 397 (ifra->ifra_dstaddr.sin_family == AF_INET)) { 398 in_ifscrub(ifp, ia); 399 ia->ia_dstaddr = ifra->ifra_dstaddr; 400 maskIsNew = 1; /* We lie; but the effect's the same */ 401 } 402 if (ifra->ifra_addr.sin_family == AF_INET && 403 (hostIsNew || maskIsNew)) 404 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 405 if ((ifp->if_flags & IFF_BROADCAST) && 406 (ifra->ifra_broadaddr.sin_family == AF_INET)) 407 ia->ia_broadaddr = ifra->ifra_broadaddr; 408 return (error); 409 410 case SIOCDIFADDR: 411 in_ifscrub(ifp, ia); 412 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 413 ifp->if_addrlist = ifa->ifa_next; 414 else { 415 while (ifa->ifa_next && 416 (ifa->ifa_next != (struct ifaddr *)ia)) 417 ifa = ifa->ifa_next; 418 if (ifa->ifa_next) 419 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 420 else 421 printf("Couldn't unlink inifaddr from ifp\n"); 422 } 423 oia = ia; 424 if (oia == (ia = in_ifaddr)) 425 in_ifaddr = ia->ia_next; 426 else { 427 while (ia->ia_next && (ia->ia_next != oia)) 428 ia = ia->ia_next; 429 if (ia->ia_next) 430 ia->ia_next = oia->ia_next; 431 else 432 printf("Didn't unlink inifadr from list\n"); 433 } 434 IFAFREE((&oia->ia_ifa)); 435 break; 436 437 default: 438 if (ifp == 0 || ifp->if_ioctl == 0) 439 return (EOPNOTSUPP); 440 return ((*ifp->if_ioctl)(ifp, cmd, data)); 441 } 442 return (0); 443 } 444 445 /* 446 * Delete any existing route for an interface. 447 */ 448 in_ifscrub(ifp, ia) 449 register struct ifnet *ifp; 450 register struct in_ifaddr *ia; 451 { 452 453 if ((ia->ia_flags & IFA_ROUTE) == 0) 454 return; 455 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 456 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 457 else 458 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 459 ia->ia_flags &= ~IFA_ROUTE; 460 } 461 462 /* 463 * Initialize an interface's internet address 464 * and routing table entry. 465 */ 466 in_ifinit(ifp, ia, sin, scrub) 467 register struct ifnet *ifp; 468 register struct in_ifaddr *ia; 469 struct sockaddr_in *sin; 470 int scrub; 471 { 472 register u_long i = ntohl(sin->sin_addr.s_addr); 473 struct sockaddr_in oldaddr; 474 int s = splimp(), flags = RTF_UP, error, ether_output(); 475 void arp_rtrequest(); 476 477 oldaddr = ia->ia_addr; 478 ia->ia_addr = *sin; 479 /* 480 * Give the interface a chance to initialize 481 * if this is its first address, 482 * and to validate the address if necessary. 483 */ 484 if (ifp->if_ioctl && 485 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 486 splx(s); 487 ia->ia_addr = oldaddr; 488 return (error); 489 } 490 if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 491 ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 492 ia->ia_ifa.ifa_flags |= RTF_CLONING; 493 } 494 splx(s); 495 if (scrub) { 496 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 497 in_ifscrub(ifp, ia); 498 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 499 } 500 if (IN_CLASSA(i)) 501 ia->ia_netmask = IN_CLASSA_NET; 502 else if (IN_CLASSB(i)) 503 ia->ia_netmask = IN_CLASSB_NET; 504 else 505 ia->ia_netmask = IN_CLASSC_NET; 506 ia->ia_net = i & ia->ia_netmask; 507 /* 508 * The subnet mask includes at least the standard network part, 509 * but may already have been set to a larger value. 510 */ 511 ia->ia_subnetmask |= ia->ia_netmask; 512 ia->ia_subnet = i & ia->ia_subnetmask; 513 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 514 { 515 register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 516 register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 517 while (--cp >= cpbase) 518 if (*cp) { 519 ia->ia_sockmask.sin_len = 520 1 + cp - (char *) &(ia->ia_sockmask); 521 break; 522 } 523 } 524 /* 525 * Add route for the network. 526 */ 527 ia->ia_ifa.ifa_metric = ifp->if_metric; 528 if (ifp->if_flags & IFF_BROADCAST) { 529 ia->ia_broadaddr.sin_addr = 530 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 531 ia->ia_netbroadcast.s_addr = 532 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 533 } else if (ifp->if_flags & IFF_LOOPBACK) { 534 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 535 flags |= RTF_HOST; 536 } else if (ifp->if_flags & IFF_POINTOPOINT) { 537 if (ia->ia_dstaddr.sin_family != AF_INET) 538 return (0); 539 flags |= RTF_HOST; 540 } 541 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 542 ia->ia_flags |= IFA_ROUTE; 543 #ifdef MULTICAST 544 /* 545 * If the interface supports multicast, join the "all hosts" 546 * multicast group on that interface. 547 */ 548 if (ifp->if_flags & IFF_MULTICAST) { 549 struct in_addr addr; 550 551 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 552 in_addmulti(&addr, ifp); 553 } 554 #endif 555 return (error); 556 } 557 558 /* 559 * Return address info for specified internet network. 560 */ 561 struct in_ifaddr * 562 in_iaonnetof(net) 563 u_long net; 564 { 565 register struct in_ifaddr *ia; 566 567 for (ia = in_ifaddr; ia; ia = ia->ia_next) 568 if (ia->ia_subnet == net) 569 return (ia); 570 return ((struct in_ifaddr *)0); 571 } 572 573 /* 574 * Return 1 if the address might be a local broadcast address. 575 */ 576 in_broadcast(in) 577 struct in_addr in; 578 { 579 register struct in_ifaddr *ia; 580 u_long t; 581 582 /* 583 * Look through the list of addresses for a match 584 * with a broadcast address. 585 */ 586 for (ia = in_ifaddr; ia; ia = ia->ia_next) 587 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 588 if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 589 return (1); 590 /* 591 * Check for old-style (host 0) broadcast. 592 */ 593 if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 594 return (1); 595 } 596 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 597 return (1); 598 return (0); 599 } 600 601 #ifdef MULTICAST 602 /* 603 * Add an address to the list of IP multicast addresses for a given interface. 604 */ 605 struct in_multi * 606 in_addmulti(ap, ifp) 607 register struct in_addr *ap; 608 register struct ifnet *ifp; 609 { 610 register struct in_multi *inm; 611 struct ifreq ifr; 612 struct in_ifaddr *ia; 613 int s = splnet(); 614 int error; 615 616 /* 617 * See if address already in list. 618 */ 619 IN_LOOKUP_MULTI(*ap, ifp, inm); 620 if (inm != NULL) { 621 /* 622 * Found it; just increment the reference count. 623 */ 624 ++inm->inm_refcount; 625 } 626 else { 627 /* 628 * New address; allocate a new multicast record 629 * and link it into the interface's multicast list. 630 */ 631 inm = (struct in_multi *)malloc(sizeof(*inm), 632 M_IPMADDR, M_NOWAIT); 633 if (inm == NULL) { 634 splx(s); 635 return (NULL); 636 } 637 inm->inm_addr = *ap; 638 inm->inm_ifp = ifp; 639 inm->inm_refcount = 1; 640 IFP_TO_IA(ifp, ia); 641 if (ia == NULL) { 642 free(inm, M_IPMADDR); 643 splx(s); 644 return (NULL); 645 } 646 inm->inm_ia = ia; 647 inm->inm_next = ia->ia_multiaddrs; 648 ia->ia_multiaddrs = inm; 649 /* 650 * Ask the network driver to update its multicast reception 651 * filter appropriately for the new address. 652 */ 653 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; 654 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; 655 if (ifp->if_ioctl == NULL) { 656 free(inm, M_IPMADDR); 657 splx(s); 658 return (NULL); 659 } 660 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr); 661 if (error != 0) { 662 free(inm, M_IPMADDR); 663 splx(s); 664 return (NULL); 665 } 666 /* 667 * Let IGMP know that we have joined a new IP multicast group. 668 */ 669 igmp_joingroup(inm); 670 } 671 splx(s); 672 return (inm); 673 } 674 675 /* 676 * Delete a multicast address record. 677 */ 678 int 679 in_delmulti(inm) 680 register struct in_multi *inm; 681 { 682 register struct in_multi **p; 683 struct ifreq ifr; 684 int s = splnet(); 685 686 if (--inm->inm_refcount == 0) { 687 /* 688 * No remaining claims to this record; let IGMP know that 689 * we are leaving the multicast group. 690 */ 691 igmp_leavegroup(inm); 692 /* 693 * Unlink from list. 694 */ 695 for (p = &inm->inm_ia->ia_multiaddrs; 696 *p != inm; 697 p = &(*p)->inm_next) 698 continue; 699 *p = (*p)->inm_next; 700 /* 701 * Notify the network driver to update its multicast reception 702 * filter. 703 */ 704 ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 705 ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = 706 inm->inm_addr; 707 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, 708 (caddr_t)&ifr); 709 free(inm, M_IPMADDR); 710 } 711 splx(s); 712 } 713 #endif 714 #endif 715