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