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