1 /* $NetBSD: in.c,v 1.46 1998/12/19 02:46:12 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Public Access Networks Corporation ("Panix"). It was developed under 9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1982, 1986, 1991, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Berkeley and its contributors. 56 * 4. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 * @(#)in.c 8.4 (Berkeley) 1/9/95 73 */ 74 75 #include "opt_inet.h" 76 #include "opt_mrouting.h" 77 78 #include <sys/param.h> 79 #include <sys/ioctl.h> 80 #include <sys/errno.h> 81 #include <sys/malloc.h> 82 #include <sys/socket.h> 83 #include <sys/socketvar.h> 84 #include <sys/systm.h> 85 #include <sys/proc.h> 86 87 #include <net/if.h> 88 #include <net/route.h> 89 90 #include <net/if_ether.h> 91 92 #include <netinet/in_systm.h> 93 #include <netinet/in.h> 94 #include <netinet/in_var.h> 95 #include <netinet/if_inarp.h> 96 #include <netinet/ip_mroute.h> 97 #include <netinet/igmp_var.h> 98 99 #ifdef INET 100 101 #ifndef SUBNETSARELOCAL 102 #define SUBNETSARELOCAL 1 103 #endif 104 int subnetsarelocal = SUBNETSARELOCAL; 105 106 /* 107 * Return 1 if an internet address is for a ``local'' host 108 * (one to which we have a connection). If subnetsarelocal 109 * is true, this includes other subnets of the local net. 110 * Otherwise, it includes only the directly-connected (sub)nets. 111 */ 112 int 113 in_localaddr(in) 114 struct in_addr in; 115 { 116 register struct in_ifaddr *ia; 117 118 if (subnetsarelocal) { 119 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) 120 if ((in.s_addr & ia->ia_netmask) == ia->ia_net) 121 return (1); 122 } else { 123 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) 124 if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet) 125 return (1); 126 } 127 return (0); 128 } 129 130 /* 131 * Determine whether an IP address is in a reserved set of addresses 132 * that may not be forwarded, or whether datagrams to that destination 133 * may be forwarded. 134 */ 135 int 136 in_canforward(in) 137 struct in_addr in; 138 { 139 register u_int32_t net; 140 141 if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr)) 142 return (0); 143 if (IN_CLASSA(in.s_addr)) { 144 net = in.s_addr & IN_CLASSA_NET; 145 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) 146 return (0); 147 } 148 return (1); 149 } 150 151 /* 152 * Trim a mask in a sockaddr 153 */ 154 void 155 in_socktrim(ap) 156 struct sockaddr_in *ap; 157 { 158 register char *cplim = (char *) &ap->sin_addr; 159 register char *cp = (char *) (&ap->sin_addr + 1); 160 161 ap->sin_len = 0; 162 while (--cp >= cplim) 163 if (*cp) { 164 (ap)->sin_len = cp - (char *) (ap) + 1; 165 break; 166 } 167 } 168 169 /* 170 * Routine to take an Internet address and convert into a 171 * "dotted quad" representation for printing. 172 */ 173 const char * 174 in_fmtaddr(addr) 175 struct in_addr addr; 176 { 177 static char buf[sizeof("123.456.789.123")]; 178 179 addr.s_addr = ntohl(addr.s_addr); 180 181 sprintf(buf, "%d.%d.%d.%d", 182 (addr.s_addr >> 24) & 0xFF, 183 (addr.s_addr >> 16) & 0xFF, 184 (addr.s_addr >> 8) & 0xFF, 185 (addr.s_addr >> 0) & 0xFF); 186 return buf; 187 } 188 189 /* 190 * Maintain the "in_maxmtu" variable, which is the largest 191 * mtu for non-local interfaces with AF_INET addresses assigned 192 * to them that are up. 193 */ 194 unsigned long in_maxmtu; 195 196 void 197 in_setmaxmtu() 198 { 199 register struct in_ifaddr *ia; 200 register struct ifnet *ifp; 201 unsigned long maxmtu = 0; 202 203 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) { 204 if ((ifp = ia->ia_ifp) == 0) 205 continue; 206 if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP) 207 continue; 208 if (ifp->if_mtu > maxmtu) 209 maxmtu = ifp->if_mtu; 210 } 211 if (maxmtu) 212 in_maxmtu = maxmtu; 213 } 214 215 int in_interfaces; /* number of external internet interfaces */ 216 217 /* 218 * Generic internet control operations (ioctl's). 219 * Ifp is 0 if not an interface-specific ioctl. 220 */ 221 /* ARGSUSED */ 222 int 223 in_control(so, cmd, data, ifp, p) 224 struct socket *so; 225 u_long cmd; 226 caddr_t data; 227 register struct ifnet *ifp; 228 struct proc *p; 229 { 230 register struct ifreq *ifr = (struct ifreq *)data; 231 register struct in_ifaddr *ia = 0; 232 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 233 struct sockaddr_in oldaddr; 234 int error, hostIsNew, maskIsNew; 235 236 /* 237 * Find address for this interface, if it exists. 238 */ 239 if (ifp) 240 IFP_TO_IA(ifp, ia); 241 242 switch (cmd) { 243 244 case SIOCAIFADDR: 245 case SIOCDIFADDR: 246 case SIOCGIFALIAS: 247 if (ifra->ifra_addr.sin_family == AF_INET) 248 for (ia = IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr).lh_first; 249 ia != 0; ia = ia->ia_hash.le_next) { 250 if (ia->ia_ifp == ifp && 251 in_hosteq(ia->ia_addr.sin_addr, 252 ifra->ifra_addr.sin_addr)) 253 break; 254 } 255 if (cmd == SIOCDIFADDR && ia == 0) 256 return (EADDRNOTAVAIL); 257 /* FALLTHROUGH */ 258 case SIOCSIFADDR: 259 case SIOCSIFNETMASK: 260 case SIOCSIFDSTADDR: 261 if (ifp == 0) 262 panic("in_control"); 263 264 if (cmd == SIOCGIFALIAS) 265 break; 266 267 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) 268 return (EPERM); 269 270 if (ia == 0) { 271 MALLOC(ia, struct in_ifaddr *, sizeof(*ia), 272 M_IFADDR, M_WAITOK); 273 if (ia == 0) 274 return (ENOBUFS); 275 bzero((caddr_t)ia, sizeof *ia); 276 TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list); 277 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, 278 ifa_list); 279 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 280 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 281 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 282 ia->ia_sockmask.sin_len = 8; 283 if (ifp->if_flags & IFF_BROADCAST) { 284 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 285 ia->ia_broadaddr.sin_family = AF_INET; 286 } 287 ia->ia_ifp = ifp; 288 LIST_INIT(&ia->ia_multiaddrs); 289 if ((ifp->if_flags & IFF_LOOPBACK) == 0) 290 in_interfaces++; 291 } 292 break; 293 294 case SIOCSIFBRDADDR: 295 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) 296 return (EPERM); 297 /* FALLTHROUGH */ 298 299 case SIOCGIFADDR: 300 case SIOCGIFNETMASK: 301 case SIOCGIFDSTADDR: 302 case SIOCGIFBRDADDR: 303 if (ia == 0) 304 return (EADDRNOTAVAIL); 305 break; 306 } 307 switch (cmd) { 308 309 case SIOCGIFADDR: 310 *satosin(&ifr->ifr_addr) = ia->ia_addr; 311 break; 312 313 case SIOCGIFBRDADDR: 314 if ((ifp->if_flags & IFF_BROADCAST) == 0) 315 return (EINVAL); 316 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr; 317 break; 318 319 case SIOCGIFDSTADDR: 320 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 321 return (EINVAL); 322 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr; 323 break; 324 325 case SIOCGIFNETMASK: 326 *satosin(&ifr->ifr_addr) = ia->ia_sockmask; 327 break; 328 329 case SIOCSIFDSTADDR: 330 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 331 return (EINVAL); 332 oldaddr = ia->ia_dstaddr; 333 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr); 334 if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 335 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 336 ia->ia_dstaddr = oldaddr; 337 return (error); 338 } 339 if (ia->ia_flags & IFA_ROUTE) { 340 ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr); 341 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 342 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 343 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 344 } 345 break; 346 347 case SIOCSIFBRDADDR: 348 if ((ifp->if_flags & IFF_BROADCAST) == 0) 349 return (EINVAL); 350 ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr); 351 break; 352 353 case SIOCSIFADDR: 354 return (in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1)); 355 356 case SIOCSIFNETMASK: 357 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr = 358 ifra->ifra_addr.sin_addr.s_addr; 359 break; 360 361 case SIOCAIFADDR: 362 maskIsNew = 0; 363 hostIsNew = 1; 364 error = 0; 365 if (ia->ia_addr.sin_family == AF_INET) { 366 if (ifra->ifra_addr.sin_len == 0) { 367 ifra->ifra_addr = ia->ia_addr; 368 hostIsNew = 0; 369 } else if (in_hosteq(ia->ia_addr.sin_addr, ifra->ifra_addr.sin_addr)) 370 hostIsNew = 0; 371 } 372 if (ifra->ifra_mask.sin_len) { 373 in_ifscrub(ifp, ia); 374 ia->ia_sockmask = ifra->ifra_mask; 375 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr; 376 maskIsNew = 1; 377 } 378 if ((ifp->if_flags & IFF_POINTOPOINT) && 379 (ifra->ifra_dstaddr.sin_family == AF_INET)) { 380 in_ifscrub(ifp, ia); 381 ia->ia_dstaddr = ifra->ifra_dstaddr; 382 maskIsNew = 1; /* We lie; but the effect's the same */ 383 } 384 if (ifra->ifra_addr.sin_family == AF_INET && 385 (hostIsNew || maskIsNew)) 386 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 387 if ((ifp->if_flags & IFF_BROADCAST) && 388 (ifra->ifra_broadaddr.sin_family == AF_INET)) 389 ia->ia_broadaddr = ifra->ifra_broadaddr; 390 return (error); 391 392 case SIOCGIFALIAS: 393 ifra->ifra_mask = ia->ia_sockmask; 394 if ((ifp->if_flags & IFF_POINTOPOINT) && 395 (ia->ia_dstaddr.sin_family == AF_INET)) 396 ifra->ifra_dstaddr = ia->ia_dstaddr; 397 else if ((ifp->if_flags & IFF_BROADCAST) && 398 (ia->ia_broadaddr.sin_family == AF_INET)) 399 ifra->ifra_broadaddr = ia->ia_broadaddr; 400 else 401 memset(&ifra->ifra_broadaddr, 0, 402 sizeof(ifra->ifra_broadaddr)); 403 return 0; 404 405 case SIOCDIFADDR: 406 in_ifscrub(ifp, ia); 407 LIST_REMOVE(ia, ia_hash); 408 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 409 TAILQ_REMOVE(&in_ifaddr, ia, ia_list); 410 IFAFREE((&ia->ia_ifa)); 411 in_setmaxmtu(); 412 break; 413 414 #ifdef MROUTING 415 case SIOCGETVIFCNT: 416 case SIOCGETSGCNT: 417 return (mrt_ioctl(so, cmd, data)); 418 #endif /* MROUTING */ 419 420 default: 421 if (ifp == 0 || ifp->if_ioctl == 0) 422 return (EOPNOTSUPP); 423 error = (*ifp->if_ioctl)(ifp, cmd, data); 424 in_setmaxmtu(); 425 return(error); 426 } 427 return (0); 428 } 429 430 /* 431 * Delete any existing route for an interface. 432 */ 433 void 434 in_ifscrub(ifp, ia) 435 register struct ifnet *ifp; 436 register struct in_ifaddr *ia; 437 { 438 439 if ((ia->ia_flags & IFA_ROUTE) == 0) 440 return; 441 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 442 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 443 else 444 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 445 ia->ia_flags &= ~IFA_ROUTE; 446 } 447 448 /* 449 * Initialize an interface's internet address 450 * and routing table entry. 451 */ 452 int 453 in_ifinit(ifp, ia, sin, scrub) 454 register struct ifnet *ifp; 455 register struct in_ifaddr *ia; 456 struct sockaddr_in *sin; 457 int scrub; 458 { 459 register u_int32_t i = sin->sin_addr.s_addr; 460 struct sockaddr_in oldaddr; 461 int s = splimp(), flags = RTF_UP, error; 462 463 /* 464 * Set up new addresses. 465 */ 466 oldaddr = ia->ia_addr; 467 if (ia->ia_addr.sin_family == AF_INET) 468 LIST_REMOVE(ia, ia_hash); 469 ia->ia_addr = *sin; 470 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash); 471 472 /* 473 * Give the interface a chance to initialize 474 * if this is its first address, 475 * and to validate the address if necessary. 476 */ 477 if (ifp->if_ioctl && 478 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) 479 goto bad; 480 splx(s); 481 if (scrub) { 482 ia->ia_ifa.ifa_addr = sintosa(&oldaddr); 483 in_ifscrub(ifp, ia); 484 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 485 } 486 487 if (IN_CLASSA(i)) 488 ia->ia_netmask = IN_CLASSA_NET; 489 else if (IN_CLASSB(i)) 490 ia->ia_netmask = IN_CLASSB_NET; 491 else 492 ia->ia_netmask = IN_CLASSC_NET; 493 /* 494 * The subnet mask usually includes at least the standard network part, 495 * but may may be smaller in the case of supernetting. 496 * If it is set, we believe it. 497 */ 498 if (ia->ia_subnetmask == 0) { 499 ia->ia_subnetmask = ia->ia_netmask; 500 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask; 501 } else 502 ia->ia_netmask &= ia->ia_subnetmask; 503 504 ia->ia_net = i & ia->ia_netmask; 505 ia->ia_subnet = i & ia->ia_subnetmask; 506 in_socktrim(&ia->ia_sockmask); 507 /* re-calculate the "in_maxmtu" value */ 508 in_setmaxmtu(); 509 /* 510 * Add route for the network. 511 */ 512 ia->ia_ifa.ifa_metric = ifp->if_metric; 513 if (ifp->if_flags & IFF_BROADCAST) { 514 ia->ia_broadaddr.sin_addr.s_addr = 515 ia->ia_subnet | ~ia->ia_subnetmask; 516 ia->ia_netbroadcast.s_addr = 517 ia->ia_net | ~ia->ia_netmask; 518 } else if (ifp->if_flags & IFF_LOOPBACK) { 519 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 520 flags |= RTF_HOST; 521 } else if (ifp->if_flags & IFF_POINTOPOINT) { 522 if (ia->ia_dstaddr.sin_family != AF_INET) 523 return (0); 524 flags |= RTF_HOST; 525 } 526 error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags); 527 if (!error) 528 ia->ia_flags |= IFA_ROUTE; 529 /* 530 * If the interface supports multicast, join the "all hosts" 531 * multicast group on that interface. 532 */ 533 if (ifp->if_flags & IFF_MULTICAST) { 534 struct in_addr addr; 535 536 addr.s_addr = INADDR_ALLHOSTS_GROUP; 537 in_addmulti(&addr, ifp); 538 } 539 return (error); 540 bad: 541 splx(s); 542 LIST_REMOVE(ia, ia_hash); 543 ia->ia_addr = oldaddr; 544 if (ia->ia_addr.sin_family == AF_INET) 545 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), 546 ia, ia_hash); 547 return (error); 548 } 549 550 /* 551 * Return 1 if the address might be a local broadcast address. 552 */ 553 int 554 in_broadcast(in, ifp) 555 struct in_addr in; 556 struct ifnet *ifp; 557 { 558 register struct ifaddr *ifa; 559 560 if (in.s_addr == INADDR_BROADCAST || 561 in_nullhost(in)) 562 return 1; 563 if ((ifp->if_flags & IFF_BROADCAST) == 0) 564 return 0; 565 /* 566 * Look through the list of addresses for a match 567 * with a broadcast address. 568 */ 569 #define ia (ifatoia(ifa)) 570 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) 571 if (ifa->ifa_addr->sa_family == AF_INET && 572 (in_hosteq(in, ia->ia_broadaddr.sin_addr) || 573 in_hosteq(in, ia->ia_netbroadcast) || 574 /* 575 * Check for old-style (host 0) broadcast. 576 */ 577 in.s_addr == ia->ia_subnet || 578 in.s_addr == ia->ia_net)) 579 return 1; 580 return (0); 581 #undef ia 582 } 583 584 /* 585 * Add an address to the list of IP multicast addresses for a given interface. 586 */ 587 struct in_multi * 588 in_addmulti(ap, ifp) 589 register struct in_addr *ap; 590 register struct ifnet *ifp; 591 { 592 register struct in_multi *inm; 593 struct ifreq ifr; 594 struct in_ifaddr *ia; 595 int s = splsoftnet(); 596 597 /* 598 * See if address already in list. 599 */ 600 IN_LOOKUP_MULTI(*ap, ifp, inm); 601 if (inm != NULL) { 602 /* 603 * Found it; just increment the reference count. 604 */ 605 ++inm->inm_refcount; 606 } else { 607 /* 608 * New address; allocate a new multicast record 609 * and link it into the interface's multicast list. 610 */ 611 inm = (struct in_multi *)malloc(sizeof(*inm), 612 M_IPMADDR, M_NOWAIT); 613 if (inm == NULL) { 614 splx(s); 615 return (NULL); 616 } 617 inm->inm_addr = *ap; 618 inm->inm_ifp = ifp; 619 inm->inm_refcount = 1; 620 IFP_TO_IA(ifp, ia); 621 if (ia == NULL) { 622 free(inm, M_IPMADDR); 623 splx(s); 624 return (NULL); 625 } 626 inm->inm_ia = ia; 627 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list); 628 /* 629 * Ask the network driver to update its multicast reception 630 * filter appropriately for the new address. 631 */ 632 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); 633 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 634 satosin(&ifr.ifr_addr)->sin_addr = *ap; 635 if ((ifp->if_ioctl == NULL) || 636 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { 637 LIST_REMOVE(inm, inm_list); 638 free(inm, M_IPMADDR); 639 splx(s); 640 return (NULL); 641 } 642 /* 643 * Let IGMP know that we have joined a new IP multicast group. 644 */ 645 igmp_joingroup(inm); 646 } 647 splx(s); 648 return (inm); 649 } 650 651 /* 652 * Delete a multicast address record. 653 */ 654 void 655 in_delmulti(inm) 656 register struct in_multi *inm; 657 { 658 struct ifreq ifr; 659 int s = splsoftnet(); 660 661 if (--inm->inm_refcount == 0) { 662 /* 663 * No remaining claims to this record; let IGMP know that 664 * we are leaving the multicast group. 665 */ 666 igmp_leavegroup(inm); 667 /* 668 * Unlink from list. 669 */ 670 LIST_REMOVE(inm, inm_list); 671 /* 672 * Notify the network driver to update its multicast reception 673 * filter. 674 */ 675 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 676 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr; 677 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, 678 (caddr_t)&ifr); 679 free(inm, M_IPMADDR); 680 } 681 splx(s); 682 } 683 #endif 684