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