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