1 /* $OpenBSD: in.c,v 1.160 2018/07/11 21:18:23 nayden Exp $ */ 2 /* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */ 3 4 /* 5 * Copyright (C) 2001 WIDE Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1982, 1986, 1991, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)in.c 8.2 (Berkeley) 11/15/93 61 */ 62 63 #include <sys/param.h> 64 #include <sys/systm.h> 65 #include <sys/ioctl.h> 66 #include <sys/malloc.h> 67 #include <sys/socket.h> 68 #include <sys/socketvar.h> 69 70 #include <net/if.h> 71 #include <net/if_var.h> 72 #include <net/route.h> 73 74 #include <netinet/in.h> 75 #include <netinet/in_var.h> 76 #include <netinet/igmp_var.h> 77 78 #ifdef MROUTING 79 #include <netinet/ip_mroute.h> 80 #endif 81 82 #include "ether.h" 83 84 85 void in_socktrim(struct sockaddr_in *); 86 87 int in_ioctl_sifaddr(u_long, caddr_t, struct ifnet *, int); 88 int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *, int); 89 int in_ioctl_get(u_long, caddr_t, struct ifnet *); 90 void in_purgeaddr(struct ifaddr *); 91 int in_addhost(struct in_ifaddr *, struct sockaddr_in *); 92 int in_scrubhost(struct in_ifaddr *, struct sockaddr_in *); 93 int in_insert_prefix(struct in_ifaddr *); 94 void in_remove_prefix(struct in_ifaddr *); 95 96 /* 97 * Determine whether an IP address is in a reserved set of addresses 98 * that may not be forwarded, or whether datagrams to that destination 99 * may be forwarded. 100 */ 101 int 102 in_canforward(struct in_addr in) 103 { 104 u_int32_t net; 105 106 if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr)) 107 return (0); 108 if (IN_CLASSA(in.s_addr)) { 109 net = in.s_addr & IN_CLASSA_NET; 110 if (net == 0 || 111 net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) 112 return (0); 113 } 114 return (1); 115 } 116 117 /* 118 * Trim a mask in a sockaddr 119 */ 120 void 121 in_socktrim(struct sockaddr_in *ap) 122 { 123 char *cplim = (char *) &ap->sin_addr; 124 char *cp = (char *) (&ap->sin_addr + 1); 125 126 ap->sin_len = 0; 127 while (--cp >= cplim) 128 if (*cp) { 129 (ap)->sin_len = cp - (char *) (ap) + 1; 130 break; 131 } 132 } 133 134 int 135 in_mask2len(struct in_addr *mask) 136 { 137 int x, y; 138 u_char *p; 139 140 p = (u_char *)mask; 141 for (x = 0; x < sizeof(*mask); x++) { 142 if (p[x] != 0xff) 143 break; 144 } 145 y = 0; 146 if (x < sizeof(*mask)) { 147 for (y = 0; y < 8; y++) { 148 if ((p[x] & (0x80 >> y)) == 0) 149 break; 150 } 151 } 152 return x * 8 + y; 153 } 154 155 void 156 in_len2mask(struct in_addr *mask, int len) 157 { 158 int i; 159 u_char *p; 160 161 p = (u_char *)mask; 162 bzero(mask, sizeof(*mask)); 163 for (i = 0; i < len / 8; i++) 164 p[i] = 0xff; 165 if (len % 8) 166 p[i] = (0xff00 >> (len % 8)) & 0xff; 167 } 168 169 int 170 in_nam2sin(const struct mbuf *nam, struct sockaddr_in **sin) 171 { 172 struct sockaddr *sa = mtod(nam, struct sockaddr *); 173 174 if (nam->m_len < offsetof(struct sockaddr, sa_data)) 175 return EINVAL; 176 if (sa->sa_family != AF_INET) 177 return EAFNOSUPPORT; 178 if (sa->sa_len != nam->m_len) 179 return EINVAL; 180 if (sa->sa_len != sizeof(struct sockaddr_in)) 181 return EINVAL; 182 *sin = satosin(sa); 183 184 return 0; 185 } 186 187 int 188 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) 189 { 190 int privileged; 191 int error; 192 193 privileged = 0; 194 if ((so->so_state & SS_PRIV) != 0) 195 privileged++; 196 197 switch (cmd) { 198 #ifdef MROUTING 199 case SIOCGETVIFCNT: 200 case SIOCGETSGCNT: 201 error = mrt_ioctl(so, cmd, data); 202 break; 203 #endif /* MROUTING */ 204 default: 205 error = in_ioctl(cmd, data, ifp, privileged); 206 break; 207 } 208 209 return error; 210 } 211 212 int 213 in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged) 214 { 215 struct ifreq *ifr = (struct ifreq *)data; 216 struct ifaddr *ifa; 217 struct in_ifaddr *ia = NULL; 218 struct sockaddr_in oldaddr; 219 int error = 0; 220 221 if (ifp == NULL) 222 return (ENXIO); 223 224 switch (cmd) { 225 case SIOCGIFADDR: 226 case SIOCGIFNETMASK: 227 case SIOCGIFDSTADDR: 228 case SIOCGIFBRDADDR: 229 return in_ioctl_get(cmd, data, ifp); 230 case SIOCSIFADDR: 231 return in_ioctl_sifaddr(cmd, data, ifp, privileged); 232 case SIOCAIFADDR: 233 case SIOCDIFADDR: 234 return in_ioctl_change_ifaddr(cmd, data, ifp, privileged); 235 case SIOCSIFNETMASK: 236 case SIOCSIFDSTADDR: 237 case SIOCSIFBRDADDR: 238 break; 239 default: 240 return (EOPNOTSUPP); 241 } 242 243 NET_LOCK(); 244 245 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 246 if (ifa->ifa_addr->sa_family == AF_INET) { 247 ia = ifatoia(ifa); 248 break; 249 } 250 } 251 252 if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) { 253 for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) { 254 if ((ifa->ifa_addr->sa_family == AF_INET) && 255 ifatoia(ifa)->ia_addr.sin_addr.s_addr == 256 satosin(&ifr->ifr_addr)->sin_addr.s_addr) { 257 ia = ifatoia(ifa); 258 break; 259 } 260 } 261 } 262 if (ia == NULL) { 263 NET_UNLOCK(); 264 return (EADDRNOTAVAIL); 265 } 266 267 switch (cmd) { 268 case SIOCSIFDSTADDR: 269 if (!privileged) { 270 error = EPERM; 271 break; 272 } 273 274 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 275 error = EINVAL; 276 break; 277 } 278 oldaddr = ia->ia_dstaddr; 279 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr); 280 error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia); 281 if (error) { 282 ia->ia_dstaddr = oldaddr; 283 break; 284 } 285 in_scrubhost(ia, &oldaddr); 286 in_addhost(ia, &ia->ia_dstaddr); 287 break; 288 289 case SIOCSIFBRDADDR: 290 if (!privileged) { 291 error = EPERM; 292 break; 293 } 294 295 if ((ifp->if_flags & IFF_BROADCAST) == 0) { 296 error = EINVAL; 297 break; 298 } 299 ifa_update_broadaddr(ifp, &ia->ia_ifa, &ifr->ifr_broadaddr); 300 break; 301 302 case SIOCSIFNETMASK: 303 if (!privileged) { 304 error = EPERM; 305 break; 306 } 307 308 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr = 309 satosin(&ifr->ifr_addr)->sin_addr.s_addr; 310 break; 311 } 312 313 NET_UNLOCK(); 314 return (error); 315 } 316 317 int 318 in_ioctl_sifaddr(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged) 319 { 320 struct ifreq *ifr = (struct ifreq *)data; 321 struct ifaddr *ifa; 322 struct in_ifaddr *ia = NULL; 323 int error = 0; 324 int newifaddr; 325 326 if (cmd != SIOCSIFADDR) 327 panic("%s: invalid ioctl %lu", __func__, cmd); 328 329 if (!privileged) 330 return (EPERM); 331 332 NET_LOCK(); 333 334 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 335 if (ifa->ifa_addr->sa_family == AF_INET) { 336 ia = ifatoia(ifa); 337 break; 338 } 339 } 340 341 if (ia == NULL) { 342 ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); 343 ia->ia_addr.sin_family = AF_INET; 344 ia->ia_addr.sin_len = sizeof(ia->ia_addr); 345 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 346 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 347 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 348 ia->ia_sockmask.sin_len = 8; 349 if (ifp->if_flags & IFF_BROADCAST) { 350 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 351 ia->ia_broadaddr.sin_family = AF_INET; 352 } 353 ia->ia_ifp = ifp; 354 355 newifaddr = 1; 356 } else 357 newifaddr = 0; 358 359 in_ifscrub(ifp, ia); 360 error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), newifaddr); 361 if (!error) 362 dohooks(ifp->if_addrhooks, 0); 363 364 NET_UNLOCK(); 365 return error; 366 } 367 368 int 369 in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp, 370 int privileged) 371 { 372 struct ifaddr *ifa; 373 struct in_ifaddr *ia = NULL; 374 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 375 int error = 0; 376 int newifaddr; 377 378 NET_LOCK(); 379 380 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 381 if (ifa->ifa_addr->sa_family == AF_INET) { 382 ia = ifatoia(ifa); 383 break; 384 } 385 } 386 387 if (ifra->ifra_addr.sin_family == AF_INET) { 388 for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) { 389 if ((ifa->ifa_addr->sa_family == AF_INET) && 390 ifatoia(ifa)->ia_addr.sin_addr.s_addr == 391 ifra->ifra_addr.sin_addr.s_addr) 392 break; 393 } 394 ia = ifatoia(ifa); 395 } 396 397 switch (cmd) { 398 case SIOCAIFADDR: { 399 int needinit = 0; 400 401 if (!privileged) { 402 error = EPERM; 403 break; 404 } 405 406 if (ia == NULL) { 407 ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); 408 ia->ia_addr.sin_family = AF_INET; 409 ia->ia_addr.sin_len = sizeof(ia->ia_addr); 410 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 411 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 412 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 413 ia->ia_sockmask.sin_len = 8; 414 if (ifp->if_flags & IFF_BROADCAST) { 415 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 416 ia->ia_broadaddr.sin_family = AF_INET; 417 } 418 ia->ia_ifp = ifp; 419 420 newifaddr = 1; 421 } else 422 newifaddr = 0; 423 424 if (ia->ia_addr.sin_family == AF_INET) { 425 if (ifra->ifra_addr.sin_len == 0) 426 ifra->ifra_addr = ia->ia_addr; 427 else if (ifra->ifra_addr.sin_addr.s_addr != 428 ia->ia_addr.sin_addr.s_addr || newifaddr) 429 needinit = 1; 430 } 431 if (ifra->ifra_mask.sin_len) { 432 in_ifscrub(ifp, ia); 433 ia->ia_sockmask = ifra->ifra_mask; 434 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr; 435 needinit = 1; 436 } 437 if ((ifp->if_flags & IFF_POINTOPOINT) && 438 (ifra->ifra_dstaddr.sin_family == AF_INET)) { 439 in_ifscrub(ifp, ia); 440 ia->ia_dstaddr = ifra->ifra_dstaddr; 441 needinit = 1; 442 } 443 if ((ifp->if_flags & IFF_BROADCAST) && 444 (ifra->ifra_broadaddr.sin_family == AF_INET)) { 445 if (newifaddr) 446 ia->ia_broadaddr = ifra->ifra_broadaddr; 447 else 448 ifa_update_broadaddr(ifp, &ia->ia_ifa, 449 sintosa(&ifra->ifra_broadaddr)); 450 } 451 if (ifra->ifra_addr.sin_family == AF_INET && needinit) { 452 error = in_ifinit(ifp, ia, &ifra->ifra_addr, newifaddr); 453 } 454 if (error) 455 break; 456 dohooks(ifp->if_addrhooks, 0); 457 break; 458 } 459 case SIOCDIFADDR: 460 if (!privileged) { 461 error = EPERM; 462 break; 463 } 464 465 if (ia == NULL) { 466 error = EADDRNOTAVAIL; 467 break; 468 } 469 /* 470 * Even if the individual steps were safe, shouldn't 471 * these kinds of changes happen atomically? What 472 * should happen to a packet that was routed after 473 * the scrub but before the other steps? 474 */ 475 in_purgeaddr(&ia->ia_ifa); 476 dohooks(ifp->if_addrhooks, 0); 477 break; 478 479 default: 480 panic("%s: invalid ioctl %lu", __func__, cmd); 481 } 482 483 NET_UNLOCK(); 484 return (error); 485 } 486 487 int 488 in_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp) 489 { 490 struct ifreq *ifr = (struct ifreq *)data; 491 struct ifaddr *ifa; 492 struct in_ifaddr *ia = NULL; 493 int error = 0; 494 495 NET_RLOCK(); 496 497 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 498 if (ifa->ifa_addr->sa_family == AF_INET) { 499 ia = ifatoia(ifa); 500 break; 501 } 502 } 503 504 if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) { 505 for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) { 506 if ((ifa->ifa_addr->sa_family == AF_INET) && 507 ifatoia(ifa)->ia_addr.sin_addr.s_addr == 508 satosin(&ifr->ifr_addr)->sin_addr.s_addr) { 509 ia = ifatoia(ifa); 510 break; 511 } 512 } 513 } 514 if (ia == NULL) { 515 error = EADDRNOTAVAIL; 516 goto err; 517 } 518 519 switch(cmd) { 520 case SIOCGIFADDR: 521 *satosin(&ifr->ifr_addr) = ia->ia_addr; 522 break; 523 524 case SIOCGIFBRDADDR: 525 if ((ifp->if_flags & IFF_BROADCAST) == 0) { 526 error = EINVAL; 527 break; 528 } 529 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr; 530 break; 531 532 case SIOCGIFDSTADDR: 533 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 534 error = EINVAL; 535 break; 536 } 537 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr; 538 break; 539 540 case SIOCGIFNETMASK: 541 *satosin(&ifr->ifr_addr) = ia->ia_sockmask; 542 break; 543 544 default: 545 panic("%s: invalid ioctl %lu", __func__, cmd); 546 } 547 548 err: 549 NET_RUNLOCK(); 550 return (error); 551 } 552 553 /* 554 * Delete any existing route for an interface. 555 */ 556 void 557 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia) 558 { 559 if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) 560 in_scrubhost(ia, &ia->ia_dstaddr); 561 else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) 562 in_remove_prefix(ia); 563 } 564 565 /* 566 * Initialize an interface's internet address 567 * and routing table entry. 568 */ 569 int 570 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, 571 int newaddr) 572 { 573 u_int32_t i = sin->sin_addr.s_addr; 574 struct sockaddr_in oldaddr; 575 int error = 0, rterror; 576 577 NET_ASSERT_LOCKED(); 578 579 /* 580 * Always remove the address from the tree to make sure its 581 * position gets updated in case the key changes. 582 */ 583 if (!newaddr) { 584 rt_ifa_dellocal(&ia->ia_ifa); 585 ifa_del(ifp, &ia->ia_ifa); 586 } 587 oldaddr = ia->ia_addr; 588 ia->ia_addr = *sin; 589 590 if (ia->ia_netmask == 0) { 591 if (IN_CLASSA(i)) 592 ia->ia_netmask = IN_CLASSA_NET; 593 else if (IN_CLASSB(i)) 594 ia->ia_netmask = IN_CLASSB_NET; 595 else 596 ia->ia_netmask = IN_CLASSC_NET; 597 ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask; 598 } 599 600 /* 601 * Give the interface a chance to initialize 602 * if this is its first address, 603 * and to validate the address if necessary. 604 */ 605 if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 606 ia->ia_addr = oldaddr; 607 } 608 609 /* 610 * Add the address to the local list and the global tree. If an 611 * error occured, put back the original address. 612 */ 613 ifa_add(ifp, &ia->ia_ifa); 614 rterror = rt_ifa_addlocal(&ia->ia_ifa); 615 616 if (rterror) { 617 if (!newaddr) 618 ifa_del(ifp, &ia->ia_ifa); 619 if (!error) 620 error = rterror; 621 goto out; 622 } 623 if (error) 624 goto out; 625 626 627 ia->ia_net = i & ia->ia_netmask; 628 in_socktrim(&ia->ia_sockmask); 629 /* 630 * Add route for the network. 631 */ 632 ia->ia_ifa.ifa_metric = ifp->if_metric; 633 if (ISSET(ifp->if_flags, IFF_BROADCAST)) { 634 if (IN_RFC3021_SUBNET(ia->ia_netmask)) 635 ia->ia_broadaddr.sin_addr.s_addr = 0; 636 else { 637 ia->ia_broadaddr.sin_addr.s_addr = 638 ia->ia_net | ~ia->ia_netmask; 639 } 640 } 641 642 if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) { 643 /* XXX We should not even call in_ifinit() in this case. */ 644 if (ia->ia_dstaddr.sin_family != AF_INET) 645 goto out; 646 error = in_addhost(ia, &ia->ia_dstaddr); 647 } else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) { 648 error = in_insert_prefix(ia); 649 } 650 651 /* 652 * If the interface supports multicast, join the "all hosts" 653 * multicast group on that interface. 654 */ 655 if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) { 656 struct in_addr addr; 657 658 addr.s_addr = INADDR_ALLHOSTS_GROUP; 659 ia->ia_allhosts = in_addmulti(&addr, ifp); 660 } 661 662 out: 663 if (error && newaddr) 664 in_purgeaddr(&ia->ia_ifa); 665 666 return (error); 667 } 668 669 void 670 in_purgeaddr(struct ifaddr *ifa) 671 { 672 struct ifnet *ifp = ifa->ifa_ifp; 673 struct in_ifaddr *ia = ifatoia(ifa); 674 extern int ifatrash; 675 676 NET_ASSERT_LOCKED(); 677 678 in_ifscrub(ifp, ia); 679 680 rt_ifa_dellocal(&ia->ia_ifa); 681 rt_ifa_purge(&ia->ia_ifa); 682 ifa_del(ifp, &ia->ia_ifa); 683 684 if (ia->ia_allhosts != NULL) { 685 in_delmulti(ia->ia_allhosts); 686 ia->ia_allhosts = NULL; 687 } 688 689 ifatrash++; 690 ia->ia_ifp = NULL; 691 ifafree(&ia->ia_ifa); 692 } 693 694 int 695 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst) 696 { 697 return rt_ifa_add(&ia->ia_ifa, RTF_HOST, sintosa(dst)); 698 } 699 700 int 701 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst) 702 { 703 return rt_ifa_del(&ia->ia_ifa, RTF_HOST, sintosa(dst)); 704 } 705 706 /* 707 * Insert the cloning and broadcast routes for this subnet. 708 */ 709 int 710 in_insert_prefix(struct in_ifaddr *ia) 711 { 712 struct ifaddr *ifa = &ia->ia_ifa; 713 int error; 714 715 error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr); 716 if (error) 717 return (error); 718 719 if (ia->ia_broadaddr.sin_addr.s_addr != 0) 720 error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST, 721 ifa->ifa_broadaddr); 722 723 return (error); 724 } 725 726 void 727 in_remove_prefix(struct in_ifaddr *ia) 728 { 729 struct ifaddr *ifa = &ia->ia_ifa; 730 731 rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr); 732 733 if (ia->ia_broadaddr.sin_addr.s_addr != 0) 734 rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, ifa->ifa_broadaddr); 735 } 736 737 /* 738 * Return 1 if the address is a local broadcast address. 739 */ 740 int 741 in_broadcast(struct in_addr in, u_int rtableid) 742 { 743 struct ifnet *ifn; 744 struct ifaddr *ifa; 745 u_int rdomain; 746 747 rdomain = rtable_l2(rtableid); 748 749 #define ia (ifatoia(ifa)) 750 TAILQ_FOREACH(ifn, &ifnet, if_list) { 751 if (ifn->if_rdomain != rdomain) 752 continue; 753 if ((ifn->if_flags & IFF_BROADCAST) == 0) 754 continue; 755 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) 756 if (ifa->ifa_addr->sa_family == AF_INET && 757 in.s_addr != ia->ia_addr.sin_addr.s_addr && 758 in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) 759 return 1; 760 } 761 return (0); 762 #undef ia 763 } 764 765 /* 766 * Add an address to the list of IP multicast addresses for a given interface. 767 */ 768 struct in_multi * 769 in_addmulti(struct in_addr *ap, struct ifnet *ifp) 770 { 771 struct in_multi *inm; 772 struct ifreq ifr; 773 774 /* 775 * See if address already in list. 776 */ 777 IN_LOOKUP_MULTI(*ap, ifp, inm); 778 if (inm != NULL) { 779 /* 780 * Found it; just increment the reference count. 781 */ 782 ++inm->inm_refcnt; 783 } else { 784 /* 785 * New address; allocate a new multicast record 786 * and link it into the interface's multicast list. 787 */ 788 inm = malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO); 789 if (inm == NULL) 790 return (NULL); 791 792 inm->inm_sin.sin_len = sizeof(struct sockaddr_in); 793 inm->inm_sin.sin_family = AF_INET; 794 inm->inm_sin.sin_addr = *ap; 795 inm->inm_refcnt = 1; 796 inm->inm_ifidx = ifp->if_index; 797 inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin); 798 799 /* 800 * Ask the network driver to update its multicast reception 801 * filter appropriately for the new address. 802 */ 803 memset(&ifr, 0, sizeof(ifr)); 804 memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin)); 805 if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { 806 free(inm, M_IPMADDR, sizeof(*inm)); 807 return (NULL); 808 } 809 810 TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma, 811 ifma_list); 812 813 /* 814 * Let IGMP know that we have joined a new IP multicast group. 815 */ 816 igmp_joingroup(inm); 817 } 818 819 return (inm); 820 } 821 822 /* 823 * Delete a multicast address record. 824 */ 825 void 826 in_delmulti(struct in_multi *inm) 827 { 828 struct ifreq ifr; 829 struct ifnet *ifp; 830 831 NET_ASSERT_LOCKED(); 832 833 if (--inm->inm_refcnt == 0) { 834 /* 835 * No remaining claims to this record; let IGMP know that 836 * we are leaving the multicast group. 837 */ 838 igmp_leavegroup(inm); 839 ifp = if_get(inm->inm_ifidx); 840 841 /* 842 * Notify the network driver to update its multicast 843 * reception filter. 844 */ 845 if (ifp != NULL) { 846 memset(&ifr, 0, sizeof(ifr)); 847 satosin(&ifr.ifr_addr)->sin_len = 848 sizeof(struct sockaddr_in); 849 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 850 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr; 851 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); 852 853 TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma, 854 ifma_list); 855 } 856 if_put(ifp); 857 858 free(inm, M_IPMADDR, sizeof(*inm)); 859 } 860 } 861 862 /* 863 * Return 1 if the multicast group represented by ``ap'' has been 864 * joined by interface ``ifp'', 0 otherwise. 865 */ 866 int 867 in_hasmulti(struct in_addr *ap, struct ifnet *ifp) 868 { 869 struct in_multi *inm; 870 int joined; 871 872 IN_LOOKUP_MULTI(*ap, ifp, inm); 873 joined = (inm != NULL); 874 875 return (joined); 876 } 877 878 void 879 in_ifdetach(struct ifnet *ifp) 880 { 881 struct ifaddr *ifa, *next; 882 883 /* nuke any of IPv4 addresses we have */ 884 TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) { 885 if (ifa->ifa_addr->sa_family != AF_INET) 886 continue; 887 in_purgeaddr(ifa); 888 dohooks(ifp->if_addrhooks, 0); 889 } 890 } 891 892 void 893 in_prefixlen2mask(struct in_addr *maskp, int plen) 894 { 895 if (plen == 0) 896 maskp->s_addr = 0; 897 else 898 maskp->s_addr = htonl(0xffffffff << (32 - plen)); 899 } 900