1 /* 2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* $Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp $ */ 19 20 /*! \file 21 * \brief 22 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. 23 * See netintro(4). 24 */ 25 26 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 27 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF 28 #define lifc_len iflc_len 29 #define lifc_buf iflc_buf 30 #define lifc_req iflc_req 31 #define LIFCONF if_laddrconf 32 #else 33 #define ISC_HAVE_LIFC_FAMILY 1 34 #define ISC_HAVE_LIFC_FLAGS 1 35 #define LIFCONF lifconf 36 #endif 37 38 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ 39 #define lifr_addr iflr_addr 40 #define lifr_name iflr_name 41 #define lifr_dstaddr iflr_dstaddr 42 #define lifr_broadaddr iflr_broadaddr 43 #define lifr_flags iflr_flags 44 #define lifr_index iflr_index 45 #define ss_family sa_family 46 #define LIFREQ if_laddrreq 47 #else 48 #define LIFREQ lifreq 49 #endif 50 #endif 51 52 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') 53 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) 54 55 struct isc_interfaceiter { 56 unsigned int magic; /* Magic number. */ 57 isc_mem_t *mctx; 58 int mode; 59 int socket; 60 struct ifconf ifc; 61 void *buf; /* Buffer for sysctl data. */ 62 unsigned int bufsize; /* Bytes allocated. */ 63 unsigned int pos; /* Current offset in 64 SIOCGIFCONF data */ 65 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 66 int socket6; 67 struct LIFCONF lifc; 68 void *buf6; /* Buffer for sysctl data. */ 69 unsigned int bufsize6; /* Bytes allocated. */ 70 unsigned int pos6; /* Current offset in 71 SIOCGLIFCONF data */ 72 isc_result_t result6; /* Last result code. */ 73 isc_boolean_t first6; 74 #endif 75 #ifdef HAVE_TRUCLUSTER 76 int clua_context; /* Cluster alias context */ 77 isc_boolean_t clua_done; 78 struct sockaddr clua_sa; 79 #endif 80 #ifdef __linux 81 FILE * proc; 82 char entry[ISC_IF_INET6_SZ]; 83 isc_result_t valid; 84 #endif 85 isc_interface_t current; /* Current interface data. */ 86 isc_result_t result; /* Last result code. */ 87 }; 88 89 #ifdef HAVE_TRUCLUSTER 90 #include <clua/clua.h> 91 #include <sys/socket.h> 92 #endif 93 94 95 /*% 96 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system 97 * will have more than a megabyte of interface configuration data. 98 */ 99 #define IFCONF_BUFSIZE_INITIAL 4096 100 #define IFCONF_BUFSIZE_MAX 1048576 101 102 #ifdef __linux 103 #ifndef IF_NAMESIZE 104 # ifdef IFNAMSIZ 105 # define IF_NAMESIZE IFNAMSIZ 106 # else 107 # define IF_NAMESIZE 16 108 # endif 109 #endif 110 #endif 111 112 /* Silence a warning when this file is #included */ 113 int 114 isc_ioctl(int fildes, int req, char *arg); 115 116 int 117 isc_ioctl(int fildes, int req, char *arg) { 118 int trys; 119 int ret; 120 121 for (trys = 0; trys < 3; trys++) { 122 if ((ret = ioctl(fildes, req, arg)) < 0) { 123 if (errno == EINTR) 124 continue; 125 } 126 break; 127 } 128 return (ret); 129 } 130 131 static isc_result_t 132 getbuf4(isc_interfaceiter_t *iter) { 133 char strbuf[ISC_STRERRORSIZE]; 134 135 iter->bufsize = IFCONF_BUFSIZE_INITIAL; 136 137 for (;;) { 138 iter->buf = isc_mem_get(iter->mctx, iter->bufsize); 139 if (iter->buf == NULL) 140 return (ISC_R_NOMEMORY); 141 142 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); 143 iter->ifc.ifc_len = iter->bufsize; 144 iter->ifc.ifc_buf = iter->buf; 145 /* 146 * Ignore the HP/UX warning about "integer overflow during 147 * conversion". It comes from its own macro definition, 148 * and is really hard to shut up. 149 */ 150 if (isc_ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) 151 == -1) { 152 if (errno != EINVAL) { 153 isc__strerror(errno, strbuf, sizeof(strbuf)); 154 UNEXPECTED_ERROR(__FILE__, __LINE__, 155 isc_msgcat_get(isc_msgcat, 156 ISC_MSGSET_IFITERIOCTL, 157 ISC_MSG_GETIFCONFIG, 158 "get interface " 159 "configuration: %s"), 160 strbuf); 161 goto unexpected; 162 } 163 /* 164 * EINVAL. Retry with a bigger buffer. 165 */ 166 } else { 167 /* 168 * The ioctl succeeded. 169 * Some OS's just return what will fit rather 170 * than set EINVAL if the buffer is too small 171 * to fit all the interfaces in. If 172 * ifc.lifc_len is too near to the end of the 173 * buffer we will grow it just in case and 174 * retry. 175 */ 176 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) 177 < iter->bufsize) 178 break; 179 } 180 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { 181 UNEXPECTED_ERROR(__FILE__, __LINE__, 182 isc_msgcat_get(isc_msgcat, 183 ISC_MSGSET_IFITERIOCTL, 184 ISC_MSG_BUFFERMAX, 185 "get interface " 186 "configuration: " 187 "maximum buffer " 188 "size exceeded")); 189 goto unexpected; 190 } 191 isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 192 193 iter->bufsize *= 2; 194 } 195 return (ISC_R_SUCCESS); 196 197 unexpected: 198 isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 199 iter->buf = NULL; 200 return (ISC_R_UNEXPECTED); 201 } 202 203 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 204 static isc_result_t 205 getbuf6(isc_interfaceiter_t *iter) { 206 char strbuf[ISC_STRERRORSIZE]; 207 isc_result_t result; 208 209 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL; 210 211 for (;;) { 212 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6); 213 if (iter->buf6 == NULL) 214 return (ISC_R_NOMEMORY); 215 216 memset(&iter->lifc, 0, sizeof(iter->lifc)); 217 #ifdef ISC_HAVE_LIFC_FAMILY 218 iter->lifc.lifc_family = AF_INET6; 219 #endif 220 #ifdef ISC_HAVE_LIFC_FLAGS 221 iter->lifc.lifc_flags = 0; 222 #endif 223 iter->lifc.lifc_len = iter->bufsize6; 224 iter->lifc.lifc_buf = iter->buf6; 225 /* 226 * Ignore the HP/UX warning about "integer overflow during 227 * conversion". It comes from its own macro definition, 228 * and is really hard to shut up. 229 */ 230 if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc) 231 == -1) { 232 #ifdef __hpux 233 /* 234 * IPv6 interface scanning is not available on all 235 * kernels w/ IPv6 sockets. 236 */ 237 if (errno == ENOENT) { 238 isc__strerror(errno, strbuf, sizeof(strbuf)); 239 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 240 ISC_LOGMODULE_INTERFACE, 241 ISC_LOG_DEBUG(1), 242 isc_msgcat_get(isc_msgcat, 243 ISC_MSGSET_IFITERIOCTL, 244 ISC_MSG_GETIFCONFIG, 245 "get interface " 246 "configuration: %s"), 247 strbuf); 248 result = ISC_R_FAILURE; 249 goto cleanup; 250 } 251 #endif 252 if (errno != EINVAL) { 253 isc__strerror(errno, strbuf, sizeof(strbuf)); 254 UNEXPECTED_ERROR(__FILE__, __LINE__, 255 isc_msgcat_get(isc_msgcat, 256 ISC_MSGSET_IFITERIOCTL, 257 ISC_MSG_GETIFCONFIG, 258 "get interface " 259 "configuration: %s"), 260 strbuf); 261 result = ISC_R_UNEXPECTED; 262 goto cleanup; 263 } 264 /* 265 * EINVAL. Retry with a bigger buffer. 266 */ 267 } else { 268 /* 269 * The ioctl succeeded. 270 * Some OS's just return what will fit rather 271 * than set EINVAL if the buffer is too small 272 * to fit all the interfaces in. If 273 * ifc.ifc_len is too near to the end of the 274 * buffer we will grow it just in case and 275 * retry. 276 */ 277 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) 278 < iter->bufsize6) 279 break; 280 } 281 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) { 282 UNEXPECTED_ERROR(__FILE__, __LINE__, 283 isc_msgcat_get(isc_msgcat, 284 ISC_MSGSET_IFITERIOCTL, 285 ISC_MSG_BUFFERMAX, 286 "get interface " 287 "configuration: " 288 "maximum buffer " 289 "size exceeded")); 290 result = ISC_R_UNEXPECTED; 291 goto cleanup; 292 } 293 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 294 295 iter->bufsize6 *= 2; 296 } 297 298 if (iter->lifc.lifc_len != 0) 299 iter->mode = 6; 300 return (ISC_R_SUCCESS); 301 302 cleanup: 303 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 304 iter->buf6 = NULL; 305 return (result); 306 } 307 #endif 308 309 isc_result_t 310 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { 311 isc_interfaceiter_t *iter; 312 isc_result_t result; 313 char strbuf[ISC_STRERRORSIZE]; 314 315 REQUIRE(mctx != NULL); 316 REQUIRE(iterp != NULL); 317 REQUIRE(*iterp == NULL); 318 319 iter = isc_mem_get(mctx, sizeof(*iter)); 320 if (iter == NULL) 321 return (ISC_R_NOMEMORY); 322 323 iter->mctx = mctx; 324 iter->mode = 4; 325 iter->buf = NULL; 326 iter->pos = (unsigned int) -1; 327 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 328 iter->buf6 = NULL; 329 iter->pos6 = (unsigned int) -1; 330 iter->result6 = ISC_R_NOMORE; 331 iter->socket6 = -1; 332 iter->first6 = ISC_FALSE; 333 #endif 334 335 /* 336 * Get the interface configuration, allocating more memory if 337 * necessary. 338 */ 339 340 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 341 result = isc_net_probeipv6(); 342 if (result == ISC_R_SUCCESS) { 343 /* 344 * Create an unbound datagram socket to do the SIOCGLIFCONF 345 * ioctl on. HP/UX requires an AF_INET6 socket for 346 * SIOCGLIFCONF to get IPv6 addresses. 347 */ 348 if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 349 isc__strerror(errno, strbuf, sizeof(strbuf)); 350 UNEXPECTED_ERROR(__FILE__, __LINE__, 351 isc_msgcat_get(isc_msgcat, 352 ISC_MSGSET_IFITERIOCTL, 353 ISC_MSG_MAKESCANSOCKET, 354 "making interface " 355 "scan socket: %s"), 356 strbuf); 357 result = ISC_R_UNEXPECTED; 358 goto socket6_failure; 359 } 360 result = iter->result6 = getbuf6(iter); 361 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS) 362 goto ioctl6_failure; 363 } 364 #endif 365 if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 366 isc__strerror(errno, strbuf, sizeof(strbuf)); 367 UNEXPECTED_ERROR(__FILE__, __LINE__, 368 isc_msgcat_get(isc_msgcat, 369 ISC_MSGSET_IFITERIOCTL, 370 ISC_MSG_MAKESCANSOCKET, 371 "making interface " 372 "scan socket: %s"), 373 strbuf); 374 result = ISC_R_UNEXPECTED; 375 goto socket_failure; 376 } 377 result = getbuf4(iter); 378 if (result != ISC_R_SUCCESS) 379 goto ioctl_failure; 380 381 /* 382 * A newly created iterator has an undefined position 383 * until isc_interfaceiter_first() is called. 384 */ 385 #ifdef HAVE_TRUCLUSTER 386 iter->clua_context = -1; 387 iter->clua_done = ISC_TRUE; 388 #endif 389 #ifdef __linux 390 iter->proc = fopen("/proc/net/if_inet6", "r"); 391 iter->valid = ISC_R_FAILURE; 392 #endif 393 iter->result = ISC_R_FAILURE; 394 395 iter->magic = IFITER_MAGIC; 396 *iterp = iter; 397 return (ISC_R_SUCCESS); 398 399 ioctl_failure: 400 if (iter->buf != NULL) 401 isc_mem_put(mctx, iter->buf, iter->bufsize); 402 (void) close(iter->socket); 403 404 socket_failure: 405 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 406 if (iter->buf6 != NULL) 407 isc_mem_put(mctx, iter->buf6, iter->bufsize6); 408 ioctl6_failure: 409 if (iter->socket6 != -1) 410 (void) close(iter->socket6); 411 socket6_failure: 412 #endif 413 414 isc_mem_put(mctx, iter, sizeof(*iter)); 415 return (result); 416 } 417 418 #ifdef HAVE_TRUCLUSTER 419 static void 420 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) { 421 dst->family = AF_INET; 422 memcpy(&dst->type.in, src, sizeof(struct in_addr)); 423 } 424 425 static isc_result_t 426 internal_current_clusteralias(isc_interfaceiter_t *iter) { 427 struct clua_info ci; 428 if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS) 429 return (ISC_R_IGNORE); 430 memset(&iter->current, 0, sizeof(iter->current)); 431 iter->current.af = iter->clua_sa.sa_family; 432 memset(iter->current.name, 0, sizeof(iter->current.name)); 433 sprintf(iter->current.name, "clua%d", ci.aliasid); 434 iter->current.flags = INTERFACE_F_UP; 435 get_inaddr(&iter->current.address, &ci.addr); 436 get_inaddr(&iter->current.netmask, &ci.netmask); 437 return (ISC_R_SUCCESS); 438 } 439 #endif 440 441 /* 442 * Get information about the current interface to iter->current. 443 * If successful, return ISC_R_SUCCESS. 444 * If the interface has an unsupported address family, or if 445 * some operation on it fails, return ISC_R_IGNORE to make 446 * the higher-level iterator code ignore it. 447 */ 448 449 static isc_result_t 450 internal_current4(isc_interfaceiter_t *iter) { 451 struct ifreq *ifrp; 452 struct ifreq ifreq; 453 int family; 454 char strbuf[ISC_STRERRORSIZE]; 455 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) 456 struct lifreq lifreq; 457 #else 458 char sabuf[256]; 459 #endif 460 int i, bits, prefixlen; 461 462 REQUIRE(VALID_IFITER(iter)); 463 464 if (iter->ifc.ifc_len == 0 || 465 iter->pos == (unsigned int)iter->ifc.ifc_len) { 466 #ifdef __linux 467 return (linux_if_inet6_current(iter)); 468 #else 469 return (ISC_R_NOMORE); 470 #endif 471 } 472 473 INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len); 474 475 ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos); 476 477 memset(&ifreq, 0, sizeof(ifreq)); 478 memcpy(&ifreq, ifrp, sizeof(ifreq)); 479 480 family = ifreq.ifr_addr.sa_family; 481 #if defined(ISC_PLATFORM_HAVEIPV6) 482 if (family != AF_INET && family != AF_INET6) 483 #else 484 if (family != AF_INET) 485 #endif 486 return (ISC_R_IGNORE); 487 488 memset(&iter->current, 0, sizeof(iter->current)); 489 iter->current.af = family; 490 491 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); 492 memset(iter->current.name, 0, sizeof(iter->current.name)); 493 memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name)); 494 495 get_addr(family, &iter->current.address, 496 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name); 497 498 /* 499 * If the interface does not have a address ignore it. 500 */ 501 switch (family) { 502 case AF_INET: 503 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) 504 return (ISC_R_IGNORE); 505 break; 506 case AF_INET6: 507 if (memcmp(&iter->current.address.type.in6, &in6addr_any, 508 sizeof(in6addr_any)) == 0) 509 return (ISC_R_IGNORE); 510 break; 511 } 512 513 /* 514 * Get interface flags. 515 */ 516 517 iter->current.flags = 0; 518 519 /* 520 * Ignore the HP/UX warning about "integer overflow during 521 * conversion. It comes from its own macro definition, 522 * and is really hard to shut up. 523 */ 524 if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { 525 isc__strerror(errno, strbuf, sizeof(strbuf)); 526 UNEXPECTED_ERROR(__FILE__, __LINE__, 527 "%s: getting interface flags: %s", 528 ifreq.ifr_name, strbuf); 529 return (ISC_R_IGNORE); 530 } 531 532 if ((ifreq.ifr_flags & IFF_UP) != 0) 533 iter->current.flags |= INTERFACE_F_UP; 534 535 #ifdef IFF_POINTOPOINT 536 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) 537 iter->current.flags |= INTERFACE_F_POINTTOPOINT; 538 #endif 539 540 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) 541 iter->current.flags |= INTERFACE_F_LOOPBACK; 542 543 if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) 544 iter->current.flags |= INTERFACE_F_BROADCAST; 545 546 #ifdef IFF_MULTICAST 547 if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) 548 iter->current.flags |= INTERFACE_F_MULTICAST; 549 #endif 550 551 if (family == AF_INET) 552 goto inet; 553 554 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) 555 memset(&lifreq, 0, sizeof(lifreq)); 556 memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name)); 557 memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6, 558 sizeof(iter->current.address.type.in6)); 559 560 if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) { 561 isc__strerror(errno, strbuf, sizeof(strbuf)); 562 UNEXPECTED_ERROR(__FILE__, __LINE__, 563 "%s: getting interface address: %s", 564 ifreq.ifr_name, strbuf); 565 return (ISC_R_IGNORE); 566 } 567 prefixlen = lifreq.lifr_addrlen; 568 #else 569 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf)); 570 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 571 ISC_LOGMODULE_INTERFACE, 572 ISC_LOG_INFO, 573 isc_msgcat_get(isc_msgcat, 574 ISC_MSGSET_IFITERIOCTL, 575 ISC_MSG_GETIFCONFIG, 576 "prefix length for %s is unknown " 577 "(assume 128)"), sabuf); 578 prefixlen = 128; 579 #endif 580 581 /* 582 * Netmask already zeroed. 583 */ 584 iter->current.netmask.family = family; 585 for (i = 0; i < 16; i++) { 586 if (prefixlen > 8) { 587 bits = 0; 588 prefixlen -= 8; 589 } else { 590 bits = 8 - prefixlen; 591 prefixlen = 0; 592 } 593 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff; 594 } 595 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 596 iter->current.ifindex = if_nametoindex(iter->current.name); 597 #endif 598 return (ISC_R_SUCCESS); 599 600 inet: 601 if (family != AF_INET) 602 return (ISC_R_IGNORE); 603 #ifdef IFF_POINTOPOINT 604 /* 605 * If the interface is point-to-point, get the destination address. 606 */ 607 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { 608 /* 609 * Ignore the HP/UX warning about "integer overflow during 610 * conversion. It comes from its own macro definition, 611 * and is really hard to shut up. 612 */ 613 if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq) 614 < 0) { 615 isc__strerror(errno, strbuf, sizeof(strbuf)); 616 UNEXPECTED_ERROR(__FILE__, __LINE__, 617 isc_msgcat_get(isc_msgcat, 618 ISC_MSGSET_IFITERIOCTL, 619 ISC_MSG_GETDESTADDR, 620 "%s: getting " 621 "destination address: %s"), 622 ifreq.ifr_name, strbuf); 623 return (ISC_R_IGNORE); 624 } 625 get_addr(family, &iter->current.dstaddress, 626 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name); 627 } 628 #endif 629 630 if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { 631 /* 632 * Ignore the HP/UX warning about "integer overflow during 633 * conversion. It comes from its own macro definition, 634 * and is really hard to shut up. 635 */ 636 if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq) 637 < 0) { 638 isc__strerror(errno, strbuf, sizeof(strbuf)); 639 UNEXPECTED_ERROR(__FILE__, __LINE__, 640 isc_msgcat_get(isc_msgcat, 641 ISC_MSGSET_IFITERIOCTL, 642 ISC_MSG_GETBCSTADDR, 643 "%s: getting " 644 "broadcast address: %s"), 645 ifreq.ifr_name, strbuf); 646 return (ISC_R_IGNORE); 647 } 648 get_addr(family, &iter->current.broadcast, 649 (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name); 650 } 651 652 /* 653 * Get the network mask. 654 */ 655 memset(&ifreq, 0, sizeof(ifreq)); 656 memcpy(&ifreq, ifrp, sizeof(ifreq)); 657 /* 658 * Ignore the HP/UX warning about "integer overflow during 659 * conversion. It comes from its own macro definition, 660 * and is really hard to shut up. 661 */ 662 if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) { 663 isc__strerror(errno, strbuf, sizeof(strbuf)); 664 UNEXPECTED_ERROR(__FILE__, __LINE__, 665 isc_msgcat_get(isc_msgcat, 666 ISC_MSGSET_IFITERIOCTL, 667 ISC_MSG_GETNETMASK, 668 "%s: getting netmask: %s"), 669 ifreq.ifr_name, strbuf); 670 return (ISC_R_IGNORE); 671 } 672 get_addr(family, &iter->current.netmask, 673 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name); 674 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 675 iter->current.ifindex = if_nametoindex(iter->current.name); 676 #endif 677 return (ISC_R_SUCCESS); 678 } 679 680 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 681 static isc_result_t 682 internal_current6(isc_interfaceiter_t *iter) { 683 struct LIFREQ *ifrp; 684 struct LIFREQ lifreq; 685 int family; 686 char strbuf[ISC_STRERRORSIZE]; 687 int fd; 688 689 REQUIRE(VALID_IFITER(iter)); 690 if (iter->result6 != ISC_R_SUCCESS) 691 return (iter->result6); 692 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); 693 694 ifrp = (void *)((char *)iter->lifc.lifc_req + iter->pos6); 695 696 memset(&lifreq, 0, sizeof(lifreq)); 697 memcpy(&lifreq, ifrp, sizeof(lifreq)); 698 699 family = lifreq.lifr_addr.ss_family; 700 #ifdef ISC_PLATFORM_HAVEIPV6 701 if (family != AF_INET && family != AF_INET6) 702 #else 703 if (family != AF_INET) 704 #endif 705 return (ISC_R_IGNORE); 706 707 memset(&iter->current, 0, sizeof(iter->current)); 708 iter->current.af = family; 709 710 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name)); 711 memset(iter->current.name, 0, sizeof(iter->current.name)); 712 memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name)); 713 714 get_addr(family, &iter->current.address, 715 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); 716 717 if (isc_netaddr_islinklocal(&iter->current.address)) 718 isc_netaddr_setzone(&iter->current.address, 719 (isc_uint32_t)lifreq.lifr_index); 720 721 /* 722 * If the interface does not have a address ignore it. 723 */ 724 switch (family) { 725 case AF_INET: 726 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) 727 return (ISC_R_IGNORE); 728 break; 729 case AF_INET6: 730 if (memcmp(&iter->current.address.type.in6, &in6addr_any, 731 sizeof(in6addr_any)) == 0) 732 return (ISC_R_IGNORE); 733 break; 734 } 735 736 /* 737 * Get interface flags. 738 */ 739 740 iter->current.flags = 0; 741 742 if (family == AF_INET6) 743 fd = iter->socket6; 744 else 745 fd = iter->socket; 746 747 /* 748 * Ignore the HP/UX warning about "integer overflow during 749 * conversion. It comes from its own macro definition, 750 * and is really hard to shut up. 751 */ 752 if (isc_ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) { 753 isc__strerror(errno, strbuf, sizeof(strbuf)); 754 UNEXPECTED_ERROR(__FILE__, __LINE__, 755 "%s: getting interface flags: %s", 756 lifreq.lifr_name, strbuf); 757 return (ISC_R_IGNORE); 758 } 759 760 if ((lifreq.lifr_flags & IFF_UP) != 0) 761 iter->current.flags |= INTERFACE_F_UP; 762 763 #ifdef IFF_POINTOPOINT 764 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0) 765 iter->current.flags |= INTERFACE_F_POINTTOPOINT; 766 #endif 767 768 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0) 769 iter->current.flags |= INTERFACE_F_LOOPBACK; 770 771 if ((lifreq.lifr_flags & IFF_BROADCAST) != 0) { 772 iter->current.flags |= INTERFACE_F_BROADCAST; 773 } 774 775 #ifdef IFF_MULTICAST 776 if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) { 777 iter->current.flags |= INTERFACE_F_MULTICAST; 778 } 779 #endif 780 781 #ifdef IFF_POINTOPOINT 782 /* 783 * If the interface is point-to-point, get the destination address. 784 */ 785 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { 786 /* 787 * Ignore the HP/UX warning about "integer overflow during 788 * conversion. It comes from its own macro definition, 789 * and is really hard to shut up. 790 */ 791 if (isc_ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq) 792 < 0) { 793 isc__strerror(errno, strbuf, sizeof(strbuf)); 794 UNEXPECTED_ERROR(__FILE__, __LINE__, 795 isc_msgcat_get(isc_msgcat, 796 ISC_MSGSET_IFITERIOCTL, 797 ISC_MSG_GETDESTADDR, 798 "%s: getting " 799 "destination address: %s"), 800 lifreq.lifr_name, strbuf); 801 return (ISC_R_IGNORE); 802 } 803 get_addr(family, &iter->current.dstaddress, 804 (struct sockaddr *)&lifreq.lifr_dstaddr, 805 lifreq.lifr_name); 806 } 807 #endif 808 809 #ifdef SIOCGLIFBRDADDR 810 if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { 811 /* 812 * Ignore the HP/UX warning about "integer overflow during 813 * conversion. It comes from its own macro definition, 814 * and is really hard to shut up. 815 */ 816 if (isc_ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq) 817 < 0) { 818 isc__strerror(errno, strbuf, sizeof(strbuf)); 819 UNEXPECTED_ERROR(__FILE__, __LINE__, 820 isc_msgcat_get(isc_msgcat, 821 ISC_MSGSET_IFITERIOCTL, 822 ISC_MSG_GETBCSTADDR, 823 "%s: getting " 824 "broadcast address: %s"), 825 lifreq.lifr_name, strbuf); 826 return (ISC_R_IGNORE); 827 } 828 get_addr(family, &iter->current.broadcast, 829 (struct sockaddr *)&lifreq.lifr_broadaddr, 830 lifreq.lifr_name); 831 } 832 #endif /* SIOCGLIFBRDADDR */ 833 834 /* 835 * Get the network mask. Netmask already zeroed. 836 */ 837 memset(&lifreq, 0, sizeof(lifreq)); 838 memcpy(&lifreq, ifrp, sizeof(lifreq)); 839 840 #ifdef lifr_addrlen 841 /* 842 * Special case: if the system provides lifr_addrlen member, the 843 * netmask of an IPv6 address can be derived from the length, since 844 * an IPv6 address always has a contiguous mask. 845 */ 846 if (family == AF_INET6) { 847 int i, bits; 848 849 iter->current.netmask.family = family; 850 for (i = 0; i < lifreq.lifr_addrlen; i += 8) { 851 bits = lifreq.lifr_addrlen - i; 852 bits = (bits < 8) ? (8 - bits) : 0; 853 iter->current.netmask.type.in6.s6_addr[i / 8] = 854 (~0 << bits) & 0xff; 855 } 856 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 857 iter->current.ifindex = if_nametoindex(iter->current.name); 858 #endif 859 return (ISC_R_SUCCESS); 860 } 861 #endif 862 863 /* 864 * Ignore the HP/UX warning about "integer overflow during 865 * conversion. It comes from its own macro definition, 866 * and is really hard to shut up. 867 */ 868 if (isc_ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) { 869 isc__strerror(errno, strbuf, sizeof(strbuf)); 870 UNEXPECTED_ERROR(__FILE__, __LINE__, 871 isc_msgcat_get(isc_msgcat, 872 ISC_MSGSET_IFITERIOCTL, 873 ISC_MSG_GETNETMASK, 874 "%s: getting netmask: %s"), 875 lifreq.lifr_name, strbuf); 876 return (ISC_R_IGNORE); 877 } 878 get_addr(family, &iter->current.netmask, 879 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); 880 881 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 882 iter->current.ifindex = if_nametoindex(iter->current.name); 883 #endif 884 return (ISC_R_SUCCESS); 885 } 886 #endif 887 888 static isc_result_t 889 internal_current(isc_interfaceiter_t *iter) { 890 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 891 if (iter->mode == 6) { 892 iter->result6 = internal_current6(iter); 893 if (iter->result6 != ISC_R_NOMORE) 894 return (iter->result6); 895 } 896 #endif 897 #ifdef HAVE_TRUCLUSTER 898 if (!iter->clua_done) 899 return(internal_current_clusteralias(iter)); 900 #endif 901 return (internal_current4(iter)); 902 } 903 904 /* 905 * Step the iterator to the next interface. Unlike 906 * isc_interfaceiter_next(), this may leave the iterator 907 * positioned on an interface that will ultimately 908 * be ignored. Return ISC_R_NOMORE if there are no more 909 * interfaces, otherwise ISC_R_SUCCESS. 910 */ 911 static isc_result_t 912 internal_next4(isc_interfaceiter_t *iter) { 913 #ifdef ISC_PLATFORM_HAVESALEN 914 struct ifreq *ifrp; 915 #endif 916 917 if (iter->pos < (unsigned int) iter->ifc.ifc_len) { 918 #ifdef ISC_PLATFORM_HAVESALEN 919 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); 920 921 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) 922 iter->pos += sizeof(ifrp->ifr_name) + 923 ifrp->ifr_addr.sa_len; 924 else 925 #endif 926 iter->pos += sizeof(struct ifreq); 927 928 } else { 929 INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len); 930 #ifdef __linux 931 return (linux_if_inet6_next(iter)); 932 #else 933 return (ISC_R_NOMORE); 934 #endif 935 } 936 return (ISC_R_SUCCESS); 937 } 938 939 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 940 static isc_result_t 941 internal_next6(isc_interfaceiter_t *iter) { 942 #ifdef ISC_PLATFORM_HAVESALEN 943 struct LIFREQ *ifrp; 944 #endif 945 946 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE) 947 return (iter->result6); 948 949 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); 950 951 #ifdef ISC_PLATFORM_HAVESALEN 952 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6); 953 954 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr)) 955 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len; 956 else 957 #endif 958 iter->pos6 += sizeof(struct LIFREQ); 959 960 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len) 961 return (ISC_R_NOMORE); 962 963 return (ISC_R_SUCCESS); 964 } 965 #endif 966 967 static isc_result_t 968 internal_next(isc_interfaceiter_t *iter) { 969 #ifdef HAVE_TRUCLUSTER 970 int clua_result; 971 #endif 972 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 973 if (iter->mode == 6) { 974 iter->result6 = internal_next6(iter); 975 if (iter->result6 != ISC_R_NOMORE) 976 return (iter->result6); 977 if (iter->first6) { 978 iter->first6 = ISC_FALSE; 979 return (ISC_R_SUCCESS); 980 } 981 } 982 #endif 983 #ifdef HAVE_TRUCLUSTER 984 if (!iter->clua_done) { 985 clua_result = clua_getaliasaddress(&iter->clua_sa, 986 &iter->clua_context); 987 if (clua_result != CLUA_SUCCESS) 988 iter->clua_done = ISC_TRUE; 989 return (ISC_R_SUCCESS); 990 } 991 #endif 992 return (internal_next4(iter)); 993 } 994 995 static void 996 internal_destroy(isc_interfaceiter_t *iter) { 997 (void) close(iter->socket); 998 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 999 if (iter->socket6 != -1) 1000 (void) close(iter->socket6); 1001 if (iter->buf6 != NULL) { 1002 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 1003 } 1004 #endif 1005 #ifdef __linux 1006 if (iter->proc != NULL) 1007 fclose(iter->proc); 1008 #endif 1009 } 1010 1011 static 1012 void internal_first(isc_interfaceiter_t *iter) { 1013 #ifdef HAVE_TRUCLUSTER 1014 int clua_result; 1015 #endif 1016 iter->pos = 0; 1017 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 1018 iter->pos6 = 0; 1019 if (iter->result6 == ISC_R_NOMORE) 1020 iter->result6 = ISC_R_SUCCESS; 1021 iter->first6 = ISC_TRUE; 1022 #endif 1023 #ifdef HAVE_TRUCLUSTER 1024 iter->clua_context = 0; 1025 clua_result = clua_getaliasaddress(&iter->clua_sa, 1026 &iter->clua_context); 1027 iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS); 1028 #endif 1029 #ifdef __linux 1030 linux_if_inet6_first(iter); 1031 #endif 1032 } 1033