1 /* $OpenBSD: in.c,v 1.179 2022/12/06 22:19:39 mvs 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_set_ifaddr(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_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_sa2sin(struct sockaddr *sa, struct sockaddr_in **sin) 189 { 190 if (sa->sa_family != AF_INET) 191 return EAFNOSUPPORT; 192 if (sa->sa_len != sizeof(struct sockaddr_in)) 193 return EINVAL; 194 *sin = satosin(sa); 195 196 return 0; 197 } 198 199 int 200 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) 201 { 202 int privileged; 203 int error; 204 205 privileged = 0; 206 if ((so->so_state & SS_PRIV) != 0) 207 privileged++; 208 209 switch (cmd) { 210 #ifdef MROUTING 211 case SIOCGETVIFCNT: 212 case SIOCGETSGCNT: 213 KERNEL_LOCK(); 214 error = mrt_ioctl(so, cmd, data); 215 KERNEL_UNLOCK(); 216 break; 217 #endif /* MROUTING */ 218 default: 219 KERNEL_LOCK(); 220 error = in_ioctl(cmd, data, ifp, privileged); 221 KERNEL_UNLOCK(); 222 break; 223 } 224 225 return error; 226 } 227 228 int 229 in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged) 230 { 231 struct ifreq *ifr = (struct ifreq *)data; 232 struct ifaddr *ifa; 233 struct in_ifaddr *ia = NULL; 234 struct sockaddr_in *sin = NULL, oldaddr; 235 int error = 0; 236 237 if (ifp == NULL) 238 return (ENXIO); 239 240 switch (cmd) { 241 case SIOCGIFADDR: 242 case SIOCGIFNETMASK: 243 case SIOCGIFDSTADDR: 244 case SIOCGIFBRDADDR: 245 return in_ioctl_get(cmd, data, ifp); 246 case SIOCSIFADDR: 247 return in_ioctl_set_ifaddr(cmd, data, ifp, privileged); 248 case SIOCAIFADDR: 249 case SIOCDIFADDR: 250 return in_ioctl_change_ifaddr(cmd, data, ifp, privileged); 251 case SIOCSIFNETMASK: 252 case SIOCSIFDSTADDR: 253 case SIOCSIFBRDADDR: 254 break; 255 default: 256 return (EOPNOTSUPP); 257 } 258 259 if (ifr->ifr_addr.sa_family == AF_INET) { 260 error = in_sa2sin(&ifr->ifr_addr, &sin); 261 if (error) 262 return (error); 263 } 264 265 NET_LOCK(); 266 267 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 268 if (ifa->ifa_addr->sa_family != AF_INET) 269 continue; 270 /* find first address or exact match */ 271 if (ia == NULL) 272 ia = ifatoia(ifa); 273 if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY) 274 break; 275 if (ifatoia(ifa)->ia_addr.sin_addr.s_addr == 276 sin->sin_addr.s_addr) { 277 ia = ifatoia(ifa); 278 break; 279 } 280 } 281 if (ia == NULL) { 282 error = EADDRNOTAVAIL; 283 goto err; 284 } 285 286 switch (cmd) { 287 case SIOCSIFDSTADDR: 288 if (!privileged) { 289 error = EPERM; 290 break; 291 } 292 293 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 294 error = EINVAL; 295 break; 296 } 297 error = in_sa2sin(&ifr->ifr_dstaddr, &sin); 298 if (error) 299 break; 300 oldaddr = ia->ia_dstaddr; 301 ia->ia_dstaddr = *sin; 302 error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia); 303 if (error) { 304 ia->ia_dstaddr = oldaddr; 305 break; 306 } 307 in_scrubhost(ia, &oldaddr); 308 in_addhost(ia, &ia->ia_dstaddr); 309 break; 310 311 case SIOCSIFBRDADDR: 312 if (!privileged) { 313 error = EPERM; 314 break; 315 } 316 317 if ((ifp->if_flags & IFF_BROADCAST) == 0) { 318 error = EINVAL; 319 break; 320 } 321 error = in_sa2sin(&ifr->ifr_broadaddr, &sin); 322 if (error) 323 break; 324 ifa_update_broadaddr(ifp, &ia->ia_ifa, sintosa(sin)); 325 break; 326 327 case SIOCSIFNETMASK: 328 if (!privileged) { 329 error = EPERM; 330 break; 331 } 332 333 if (ifr->ifr_addr.sa_len < 8) { 334 error = EINVAL; 335 break; 336 } 337 /* do not check inet family or strict len */ 338 sin = satosin(&ifr->ifr_addr); 339 if (ntohl(sin->sin_addr.s_addr) & 340 (~ntohl(sin->sin_addr.s_addr) >> 1)) { 341 /* non-contiguous netmask */ 342 error = EINVAL; 343 break; 344 } 345 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr = 346 sin->sin_addr.s_addr; 347 break; 348 } 349 err: 350 NET_UNLOCK(); 351 return (error); 352 } 353 354 int 355 in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp, 356 int privileged) 357 { 358 struct ifreq *ifr = (struct ifreq *)data; 359 struct ifaddr *ifa; 360 struct in_ifaddr *ia = NULL; 361 struct sockaddr_in *sin; 362 int error = 0; 363 int newifaddr; 364 365 if (cmd != SIOCSIFADDR) 366 panic("%s: invalid ioctl %lu", __func__, cmd); 367 368 if (!privileged) 369 return (EPERM); 370 371 error = in_sa2sin(&ifr->ifr_addr, &sin); 372 if (error) 373 return (error); 374 375 NET_LOCK(); 376 377 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 378 if (ifa->ifa_addr->sa_family != AF_INET) 379 continue; 380 /* find first address */ 381 ia = ifatoia(ifa); 382 break; 383 } 384 if (ia == NULL) { 385 ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); 386 refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR); 387 ia->ia_addr.sin_family = AF_INET; 388 ia->ia_addr.sin_len = sizeof(ia->ia_addr); 389 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 390 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 391 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 392 ia->ia_sockmask.sin_len = 8; 393 if (ifp->if_flags & IFF_BROADCAST) { 394 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 395 ia->ia_broadaddr.sin_family = AF_INET; 396 } 397 ia->ia_ifp = ifp; 398 399 newifaddr = 1; 400 } else 401 newifaddr = 0; 402 403 in_ifscrub(ifp, ia); 404 error = in_ifinit(ifp, ia, sin, newifaddr); 405 if (!error) 406 if_addrhooks_run(ifp); 407 408 NET_UNLOCK(); 409 return error; 410 } 411 412 int 413 in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp, 414 int privileged) 415 { 416 struct ifaddr *ifa; 417 struct in_ifaddr *ia = NULL; 418 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 419 struct sockaddr_in *sin = NULL, *dstsin = NULL, *broadsin = NULL; 420 struct sockaddr_in *masksin = NULL; 421 int error = 0; 422 int newifaddr; 423 424 if (ifra->ifra_addr.sin_family == AF_INET) { 425 error = in_sa2sin(sintosa(&ifra->ifra_addr), &sin); 426 if (error) 427 return (error); 428 } 429 430 NET_LOCK(); 431 432 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 433 if (ifa->ifa_addr->sa_family != AF_INET) 434 continue; 435 /* find first address, if no exact match wanted */ 436 if (sin == NULL || sin->sin_addr.s_addr == 437 ifatoia(ifa)->ia_addr.sin_addr.s_addr) { 438 ia = ifatoia(ifa); 439 break; 440 } 441 } 442 443 switch (cmd) { 444 case SIOCAIFADDR: { 445 int needinit = 0; 446 447 if (!privileged) { 448 error = EPERM; 449 break; 450 } 451 452 if (ifra->ifra_mask.sin_len) { 453 if (ifra->ifra_mask.sin_len < 8) { 454 error = EINVAL; 455 break; 456 } 457 /* do not check inet family or strict len */ 458 masksin = &ifra->ifra_mask; 459 if (ntohl(masksin->sin_addr.s_addr) & 460 (~ntohl(masksin->sin_addr.s_addr) >> 1)) { 461 /* non-contiguous netmask */ 462 error = EINVAL; 463 break; 464 } 465 } 466 if ((ifp->if_flags & IFF_POINTOPOINT) && 467 ifra->ifra_dstaddr.sin_family == AF_INET) { 468 error = in_sa2sin(sintosa(&ifra->ifra_dstaddr), 469 &dstsin); 470 if (error) 471 break; 472 } 473 if ((ifp->if_flags & IFF_BROADCAST) && 474 ifra->ifra_broadaddr.sin_family == AF_INET) { 475 error = in_sa2sin(sintosa(&ifra->ifra_broadaddr), 476 &broadsin); 477 if (error) 478 break; 479 } 480 481 if (ia == NULL) { 482 ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); 483 refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, 484 DT_REFCNT_IDX_IFADDR); 485 ia->ia_addr.sin_family = AF_INET; 486 ia->ia_addr.sin_len = sizeof(ia->ia_addr); 487 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 488 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 489 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 490 ia->ia_sockmask.sin_len = 8; 491 if (ifp->if_flags & IFF_BROADCAST) { 492 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 493 ia->ia_broadaddr.sin_family = AF_INET; 494 } 495 ia->ia_ifp = ifp; 496 497 newifaddr = 1; 498 } else 499 newifaddr = 0; 500 501 if (sin == NULL) { 502 sin = &ia->ia_addr; 503 } else if (newifaddr || 504 sin->sin_addr.s_addr != ia->ia_addr.sin_addr.s_addr) { 505 needinit = 1; 506 } 507 if (masksin != NULL) { 508 in_ifscrub(ifp, ia); 509 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr = 510 masksin->sin_addr.s_addr; 511 needinit = 1; 512 } 513 if (dstsin != NULL) { 514 in_ifscrub(ifp, ia); 515 ia->ia_dstaddr = *dstsin; 516 needinit = 1; 517 } 518 if (broadsin != NULL) { 519 if (newifaddr) 520 ia->ia_broadaddr = *broadsin; 521 else 522 ifa_update_broadaddr(ifp, &ia->ia_ifa, 523 sintosa(broadsin)); 524 } 525 if (needinit) { 526 error = in_ifinit(ifp, ia, sin, newifaddr); 527 if (error) 528 break; 529 } 530 if_addrhooks_run(ifp); 531 break; 532 } 533 case SIOCDIFADDR: 534 if (!privileged) { 535 error = EPERM; 536 break; 537 } 538 539 if (ia == NULL) { 540 error = EADDRNOTAVAIL; 541 break; 542 } 543 /* 544 * Even if the individual steps were safe, shouldn't 545 * these kinds of changes happen atomically? What 546 * should happen to a packet that was routed after 547 * the scrub but before the other steps? 548 */ 549 in_purgeaddr(&ia->ia_ifa); 550 if_addrhooks_run(ifp); 551 break; 552 553 default: 554 panic("%s: invalid ioctl %lu", __func__, cmd); 555 } 556 557 NET_UNLOCK(); 558 return (error); 559 } 560 561 int 562 in_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp) 563 { 564 struct ifreq *ifr = (struct ifreq *)data; 565 struct ifaddr *ifa; 566 struct in_ifaddr *ia = NULL; 567 struct sockaddr *sa; 568 struct sockaddr_in *sin = NULL; 569 int error = 0; 570 571 sa = &ifr->ifr_addr; 572 if (sa->sa_family == AF_INET) { 573 sa->sa_len = sizeof(struct sockaddr_in); 574 error = in_sa2sin(sa, &sin); 575 if (error) 576 return (error); 577 } 578 579 NET_LOCK_SHARED(); 580 581 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 582 if (ifa->ifa_addr->sa_family != AF_INET) 583 continue; 584 /* find first address or exact match */ 585 if (ia == NULL) 586 ia = ifatoia(ifa); 587 if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY) 588 break; 589 if (ifatoia(ifa)->ia_addr.sin_addr.s_addr == 590 sin->sin_addr.s_addr) { 591 ia = ifatoia(ifa); 592 break; 593 } 594 } 595 if (ia == NULL) { 596 error = EADDRNOTAVAIL; 597 goto err; 598 } 599 600 switch(cmd) { 601 case SIOCGIFADDR: 602 *satosin(&ifr->ifr_addr) = ia->ia_addr; 603 break; 604 605 case SIOCGIFBRDADDR: 606 if ((ifp->if_flags & IFF_BROADCAST) == 0) { 607 error = EINVAL; 608 break; 609 } 610 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr; 611 break; 612 613 case SIOCGIFDSTADDR: 614 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 615 error = EINVAL; 616 break; 617 } 618 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr; 619 break; 620 621 case SIOCGIFNETMASK: 622 *satosin(&ifr->ifr_addr) = ia->ia_sockmask; 623 break; 624 625 default: 626 panic("%s: invalid ioctl %lu", __func__, cmd); 627 } 628 629 err: 630 NET_UNLOCK_SHARED(); 631 return (error); 632 } 633 634 /* 635 * Delete any existing route for an interface. 636 */ 637 void 638 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia) 639 { 640 if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) 641 in_scrubhost(ia, &ia->ia_dstaddr); 642 else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) 643 in_remove_prefix(ia); 644 } 645 646 /* 647 * Initialize an interface's internet address 648 * and routing table entry. 649 */ 650 int 651 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, 652 int newaddr) 653 { 654 u_int32_t i = sin->sin_addr.s_addr; 655 struct sockaddr_in oldaddr; 656 int error = 0, rterror; 657 658 NET_ASSERT_LOCKED(); 659 660 /* 661 * Always remove the address from the tree to make sure its 662 * position gets updated in case the key changes. 663 */ 664 if (!newaddr) { 665 rt_ifa_dellocal(&ia->ia_ifa); 666 ifa_del(ifp, &ia->ia_ifa); 667 } 668 oldaddr = ia->ia_addr; 669 ia->ia_addr = *sin; 670 671 if (ia->ia_netmask == 0) { 672 if (IN_CLASSA(i)) 673 ia->ia_netmask = IN_CLASSA_NET; 674 else if (IN_CLASSB(i)) 675 ia->ia_netmask = IN_CLASSB_NET; 676 else 677 ia->ia_netmask = IN_CLASSC_NET; 678 ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask; 679 } 680 681 /* 682 * Give the interface a chance to initialize 683 * if this is its first address, 684 * and to validate the address if necessary. 685 */ 686 if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 687 ia->ia_addr = oldaddr; 688 } 689 690 /* 691 * Add the address to the local list and the global tree. If an 692 * error occurred, put back the original address. 693 */ 694 ifa_add(ifp, &ia->ia_ifa); 695 rterror = rt_ifa_addlocal(&ia->ia_ifa); 696 697 if (rterror) { 698 if (!newaddr) 699 ifa_del(ifp, &ia->ia_ifa); 700 if (!error) 701 error = rterror; 702 goto out; 703 } 704 if (error) 705 goto out; 706 707 708 ia->ia_net = i & ia->ia_netmask; 709 in_socktrim(&ia->ia_sockmask); 710 /* 711 * Add route for the network. 712 */ 713 ia->ia_ifa.ifa_metric = ifp->if_metric; 714 if (ISSET(ifp->if_flags, IFF_BROADCAST)) { 715 if (IN_RFC3021_SUBNET(ia->ia_netmask)) 716 ia->ia_broadaddr.sin_addr.s_addr = 0; 717 else { 718 ia->ia_broadaddr.sin_addr.s_addr = 719 ia->ia_net | ~ia->ia_netmask; 720 } 721 } 722 723 if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) { 724 /* XXX We should not even call in_ifinit() in this case. */ 725 if (ia->ia_dstaddr.sin_family != AF_INET) 726 goto out; 727 error = in_addhost(ia, &ia->ia_dstaddr); 728 } else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) { 729 error = in_insert_prefix(ia); 730 } 731 732 /* 733 * If the interface supports multicast, join the "all hosts" 734 * multicast group on that interface. 735 */ 736 if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) { 737 struct in_addr addr; 738 739 addr.s_addr = INADDR_ALLHOSTS_GROUP; 740 ia->ia_allhosts = in_addmulti(&addr, ifp); 741 } 742 743 out: 744 if (error && newaddr) 745 in_purgeaddr(&ia->ia_ifa); 746 747 return (error); 748 } 749 750 void 751 in_purgeaddr(struct ifaddr *ifa) 752 { 753 struct ifnet *ifp = ifa->ifa_ifp; 754 struct in_ifaddr *ia = ifatoia(ifa); 755 756 NET_ASSERT_LOCKED(); 757 758 in_ifscrub(ifp, ia); 759 760 rt_ifa_dellocal(&ia->ia_ifa); 761 rt_ifa_purge(&ia->ia_ifa); 762 ifa_del(ifp, &ia->ia_ifa); 763 764 if (ia->ia_allhosts != NULL) { 765 in_delmulti(ia->ia_allhosts); 766 ia->ia_allhosts = NULL; 767 } 768 769 ia->ia_ifp = NULL; 770 ifafree(&ia->ia_ifa); 771 } 772 773 int 774 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst) 775 { 776 return rt_ifa_add(&ia->ia_ifa, RTF_HOST | RTF_MPATH, 777 sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain); 778 } 779 780 int 781 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst) 782 { 783 return rt_ifa_del(&ia->ia_ifa, RTF_HOST, 784 sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain); 785 } 786 787 /* 788 * Insert the cloning and broadcast routes for this subnet. 789 */ 790 int 791 in_insert_prefix(struct in_ifaddr *ia) 792 { 793 struct ifaddr *ifa = &ia->ia_ifa; 794 int error; 795 796 error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED | RTF_MPATH, 797 ifa->ifa_addr, ifa->ifa_ifp->if_rdomain); 798 if (error) 799 return (error); 800 801 if (ia->ia_broadaddr.sin_addr.s_addr != 0) { 802 error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST | RTF_MPATH, 803 ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain); 804 } 805 806 return (error); 807 } 808 809 void 810 in_remove_prefix(struct in_ifaddr *ia) 811 { 812 struct ifaddr *ifa = &ia->ia_ifa; 813 814 rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, 815 ifa->ifa_addr, ifa->ifa_ifp->if_rdomain); 816 817 if (ia->ia_broadaddr.sin_addr.s_addr != 0) { 818 rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, 819 ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain); 820 } 821 } 822 823 /* 824 * Return 1 if the address is a local broadcast address. 825 */ 826 int 827 in_broadcast(struct in_addr in, u_int rtableid) 828 { 829 struct ifnet *ifn; 830 struct ifaddr *ifa; 831 u_int rdomain; 832 833 rdomain = rtable_l2(rtableid); 834 835 #define ia (ifatoia(ifa)) 836 TAILQ_FOREACH(ifn, &ifnetlist, if_list) { 837 if (ifn->if_rdomain != rdomain) 838 continue; 839 if ((ifn->if_flags & IFF_BROADCAST) == 0) 840 continue; 841 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) 842 if (ifa->ifa_addr->sa_family == AF_INET && 843 in.s_addr != ia->ia_addr.sin_addr.s_addr && 844 in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) 845 return 1; 846 } 847 return (0); 848 #undef ia 849 } 850 851 /* 852 * Add an address to the list of IP multicast addresses for a given interface. 853 */ 854 struct in_multi * 855 in_addmulti(struct in_addr *ap, struct ifnet *ifp) 856 { 857 struct in_multi *inm; 858 struct ifreq ifr; 859 860 /* 861 * See if address already in list. 862 */ 863 IN_LOOKUP_MULTI(*ap, ifp, inm); 864 if (inm != NULL) { 865 /* 866 * Found it; just increment the reference count. 867 */ 868 ++inm->inm_refcnt; 869 } else { 870 /* 871 * New address; allocate a new multicast record 872 * and link it into the interface's multicast list. 873 */ 874 inm = malloc(sizeof(*inm), M_IPMADDR, M_WAITOK | M_ZERO); 875 inm->inm_sin.sin_len = sizeof(struct sockaddr_in); 876 inm->inm_sin.sin_family = AF_INET; 877 inm->inm_sin.sin_addr = *ap; 878 inm->inm_refcnt = 1; 879 inm->inm_ifidx = ifp->if_index; 880 inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin); 881 882 /* 883 * Ask the network driver to update its multicast reception 884 * filter appropriately for the new address. 885 */ 886 memset(&ifr, 0, sizeof(ifr)); 887 memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin)); 888 KERNEL_LOCK(); 889 if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { 890 KERNEL_UNLOCK(); 891 free(inm, M_IPMADDR, sizeof(*inm)); 892 return (NULL); 893 } 894 KERNEL_UNLOCK(); 895 896 TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma, 897 ifma_list); 898 899 /* 900 * Let IGMP know that we have joined a new IP multicast group. 901 */ 902 igmp_joingroup(inm, ifp); 903 } 904 905 return (inm); 906 } 907 908 /* 909 * Delete a multicast address record. 910 */ 911 void 912 in_delmulti(struct in_multi *inm) 913 { 914 struct ifreq ifr; 915 struct ifnet *ifp; 916 917 NET_ASSERT_LOCKED(); 918 919 if (--inm->inm_refcnt != 0) 920 return; 921 922 ifp = if_get(inm->inm_ifidx); 923 if (ifp != NULL) { 924 /* 925 * No remaining claims to this record; let IGMP know that 926 * we are leaving the multicast group. 927 */ 928 igmp_leavegroup(inm, ifp); 929 930 /* 931 * Notify the network driver to update its multicast 932 * reception filter. 933 */ 934 memset(&ifr, 0, sizeof(ifr)); 935 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); 936 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 937 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr; 938 KERNEL_LOCK(); 939 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); 940 KERNEL_UNLOCK(); 941 942 TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma, ifma_list); 943 } 944 if_put(ifp); 945 946 free(inm, M_IPMADDR, sizeof(*inm)); 947 } 948 949 /* 950 * Return 1 if the multicast group represented by ``ap'' has been 951 * joined by interface ``ifp'', 0 otherwise. 952 */ 953 int 954 in_hasmulti(struct in_addr *ap, struct ifnet *ifp) 955 { 956 struct in_multi *inm; 957 int joined; 958 959 IN_LOOKUP_MULTI(*ap, ifp, inm); 960 joined = (inm != NULL); 961 962 return (joined); 963 } 964 965 void 966 in_ifdetach(struct ifnet *ifp) 967 { 968 struct ifaddr *ifa, *next; 969 970 /* nuke any of IPv4 addresses we have */ 971 TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) { 972 if (ifa->ifa_addr->sa_family != AF_INET) 973 continue; 974 in_purgeaddr(ifa); 975 if_addrhooks_run(ifp); 976 } 977 978 if (ifp->if_xflags & IFXF_AUTOCONF4) 979 ifp->if_xflags &= ~IFXF_AUTOCONF4; 980 } 981 982 void 983 in_prefixlen2mask(struct in_addr *maskp, int plen) 984 { 985 if (plen == 0) 986 maskp->s_addr = 0; 987 else 988 maskp->s_addr = htonl(0xffffffff << (32 - plen)); 989 } 990