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