1129198Scognet/* 2129198Scognet * Copyright (C) 2004-2009, 2014 Internet Systems Consortium, Inc. ("ISC") 3139735Simp * Copyright (C) 1999-2003 Internet Software Consortium. 4129198Scognet * 5129198Scognet * Permission to use, copy, modify, and/or distribute this software for any 6129198Scognet * purpose with or without fee is hereby granted, provided that the above 7129198Scognet * copyright notice and this permission notice appear in all copies. 8129198Scognet * 9129198Scognet * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10129198Scognet * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11129198Scognet * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12129198Scognet * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13129198Scognet * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14129198Scognet * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15129198Scognet * PERFORMANCE OF THIS SOFTWARE. 16129198Scognet */ 17129198Scognet 18129198Scognet/* $Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp $ */ 19129198Scognet 20129198Scognet/*! \file 21129198Scognet * \brief 22129198Scognet * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. 23129198Scognet * See netintro(4). 24129198Scognet */ 25129198Scognet 26129198Scognet#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 27129198Scognet#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF 28129198Scognet#define lifc_len iflc_len 29129198Scognet#define lifc_buf iflc_buf 30129198Scognet#define lifc_req iflc_req 31129198Scognet#define LIFCONF if_laddrconf 32129198Scognet#else 33129198Scognet#define ISC_HAVE_LIFC_FAMILY 1 34236991Simp#define ISC_HAVE_LIFC_FLAGS 1 35129198Scognet#define LIFCONF lifconf 36129198Scognet#endif 37129198Scognet 38129198Scognet#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ 39129198Scognet#define lifr_addr iflr_addr 40129198Scognet#define lifr_name iflr_name 41129198Scognet#define lifr_dstaddr iflr_dstaddr 42129198Scognet#define lifr_flags iflr_flags 43129198Scognet#define ss_family sa_family 44129198Scognet#define LIFREQ if_laddrreq 45129198Scognet#else 46129198Scognet#define LIFREQ lifreq 47129198Scognet#endif 48129198Scognet#endif 49129198Scognet 50129198Scognet#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') 51129198Scognet#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) 52129198Scognet 53248361Sandrewstruct isc_interfaceiter { 54129198Scognet unsigned int magic; /* Magic number. */ 55129198Scognet isc_mem_t *mctx; 56129198Scognet int mode; 57129198Scognet int socket; 58129198Scognet struct ifconf ifc; 59129198Scognet void *buf; /* Buffer for sysctl data. */ 60129198Scognet unsigned int bufsize; /* Bytes allocated. */ 61129198Scognet unsigned int pos; /* Current offset in 62248361Sandrew SIOCGIFCONF data */ 63129198Scognet#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 64129198Scognet int socket6; 65129198Scognet struct LIFCONF lifc; 66129198Scognet void *buf6; /* Buffer for sysctl data. */ 67248361Sandrew unsigned int bufsize6; /* Bytes allocated. */ 68129198Scognet unsigned int pos6; /* Current offset in 69129198Scognet SIOCGLIFCONF data */ 70129198Scognet isc_result_t result6; /* Last result code. */ 71129198Scognet isc_boolean_t first6; 72129198Scognet#endif 73129198Scognet#ifdef HAVE_TRUCLUSTER 74129198Scognet int clua_context; /* Cluster alias context */ 75129198Scognet isc_boolean_t clua_done; 76129198Scognet struct sockaddr clua_sa; 77129198Scognet#endif 78129198Scognet#ifdef __linux 79129198Scognet FILE * proc; 80129198Scognet char entry[ISC_IF_INET6_SZ]; 81129198Scognet isc_result_t valid; 82129198Scognet#endif 83129198Scognet isc_interface_t current; /* Current interface data. */ 84129198Scognet isc_result_t result; /* Last result code. */ 85129198Scognet}; 86129198Scognet 87129198Scognet#ifdef HAVE_TRUCLUSTER 88129198Scognet#include <clua/clua.h> 89129198Scognet#include <sys/socket.h> 90129198Scognet#endif 91129198Scognet 92246001Sian 93129198Scognet/*% 94129198Scognet * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system 95248361Sandrew * will have more than a megabyte of interface configuration data. 96129198Scognet */ 97129198Scognet#define IFCONF_BUFSIZE_INITIAL 4096 98129198Scognet#define IFCONF_BUFSIZE_MAX 1048576 99129198Scognet 100129198Scognet#ifdef __linux 101129198Scognet#ifndef IF_NAMESIZE 102129198Scognet# ifdef IFNAMSIZ 103129198Scognet# define IF_NAMESIZE IFNAMSIZ 104129198Scognet# else 105129198Scognet# define IF_NAMESIZE 16 106129198Scognet# endif 107129198Scognet#endif 108129198Scognet#endif 109129198Scognet 110129198Scognetstatic isc_result_t 111129198Scognetgetbuf4(isc_interfaceiter_t *iter) { 112129198Scognet char strbuf[ISC_STRERRORSIZE]; 113129198Scognet 114246001Sian iter->bufsize = IFCONF_BUFSIZE_INITIAL; 115246001Sian 116129198Scognet for (;;) { 117246001Sian iter->buf = isc_mem_get(iter->mctx, iter->bufsize); 118129198Scognet if (iter->buf == NULL) 119129198Scognet return (ISC_R_NOMEMORY); 120248361Sandrew 121129198Scognet memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); 122129198Scognet iter->ifc.ifc_len = iter->bufsize; 123129198Scognet iter->ifc.ifc_buf = iter->buf; 124129198Scognet /* 125129198Scognet * Ignore the HP/UX warning about "integer overflow during 126129198Scognet * conversion". It comes from its own macro definition, 127129198Scognet * and is really hard to shut up. 128129198Scognet */ 129129198Scognet if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) 130129198Scognet == -1) { 131129198Scognet if (errno != EINVAL) { 132129198Scognet isc__strerror(errno, strbuf, sizeof(strbuf)); 133129198Scognet UNEXPECTED_ERROR(__FILE__, __LINE__, 134129198Scognet isc_msgcat_get(isc_msgcat, 135129198Scognet ISC_MSGSET_IFITERIOCTL, 136129198Scognet ISC_MSG_GETIFCONFIG, 137129198Scognet "get interface " 138246001Sian "configuration: %s"), 139129198Scognet strbuf); 140129198Scognet goto unexpected; 141248361Sandrew } 142129198Scognet /* 143129198Scognet * EINVAL. Retry with a bigger buffer. 144129198Scognet */ 145129198Scognet } else { 146129198Scognet /* 147129198Scognet * The ioctl succeeded. 148129198Scognet * Some OS's just return what will fit rather 149129198Scognet * than set EINVAL if the buffer is too small 150129198Scognet * to fit all the interfaces in. If 151129198Scognet * ifc.lifc_len is too near to the end of the 152129198Scognet * buffer we will grow it just in case and 153129198Scognet * retry. 154129198Scognet */ 155129198Scognet if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) 156246001Sian < iter->bufsize) 157129198Scognet break; 158129198Scognet } 159248361Sandrew if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { 160129198Scognet UNEXPECTED_ERROR(__FILE__, __LINE__, 161129198Scognet isc_msgcat_get(isc_msgcat, 162129198Scognet ISC_MSGSET_IFITERIOCTL, 163129198Scognet ISC_MSG_BUFFERMAX, 164129198Scognet "get interface " 165129198Scognet "configuration: " 166129198Scognet "maximum buffer " 167129198Scognet "size exceeded")); 168129198Scognet goto unexpected; 169129198Scognet } 170129198Scognet isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 171129198Scognet 172129198Scognet iter->bufsize *= 2; 173129198Scognet } 174129198Scognet return (ISC_R_SUCCESS); 175129198Scognet 176129198Scognet unexpected: 177129198Scognet isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 178246001Sian iter->buf = NULL; 179129198Scognet return (ISC_R_UNEXPECTED); 180129198Scognet} 181248361Sandrew 182129198Scognet#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 183129198Scognetstatic isc_result_t 184129198Scognetgetbuf6(isc_interfaceiter_t *iter) { 185129198Scognet char strbuf[ISC_STRERRORSIZE]; 186129198Scognet isc_result_t result; 187129198Scognet 188129198Scognet iter->bufsize6 = IFCONF_BUFSIZE_INITIAL; 189129198Scognet 190129198Scognet for (;;) { 191129198Scognet iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6); 192129198Scognet if (iter->buf6 == NULL) 193129198Scognet return (ISC_R_NOMEMORY); 194129198Scognet 195129198Scognet memset(&iter->lifc, 0, sizeof(iter->lifc)); 196129198Scognet#ifdef ISC_HAVE_LIFC_FAMILY 197246001Sian iter->lifc.lifc_family = AF_INET6; 198129198Scognet#endif 199129198Scognet#ifdef ISC_HAVE_LIFC_FLAGS 200248361Sandrew iter->lifc.lifc_flags = 0; 201129198Scognet#endif 202129198Scognet iter->lifc.lifc_len = iter->bufsize6; 203129198Scognet iter->lifc.lifc_buf = iter->buf6; 204129198Scognet /* 205129198Scognet * Ignore the HP/UX warning about "integer overflow during 206129198Scognet * conversion". It comes from its own macro definition, 207129198Scognet * and is really hard to shut up. 208129198Scognet */ 209129198Scognet if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc) 210129198Scognet == -1) { 211129198Scognet#ifdef __hpux 212269796Sian /* 213129198Scognet * IPv6 interface scanning is not available on all 214129198Scognet * kernels w/ IPv6 sockets. 215129198Scognet */ 216129198Scognet if (errno == ENOENT) { 217129198Scognet isc__strerror(errno, strbuf, sizeof(strbuf)); 218129198Scognet isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 219129198Scognet ISC_LOGMODULE_INTERFACE, 220246001Sian ISC_LOG_DEBUG(1), 221246001Sian isc_msgcat_get(isc_msgcat, 222129198Scognet ISC_MSGSET_IFITERIOCTL, 223246001Sian ISC_MSG_GETIFCONFIG, 224129198Scognet "get interface " 225129198Scognet "configuration: %s"), 226269796Sian strbuf); 227248361Sandrew result = ISC_R_FAILURE; 228129198Scognet goto cleanup; 229129198Scognet } 230129198Scognet#endif 231129198Scognet if (errno != EINVAL) { 232129198Scognet isc__strerror(errno, strbuf, sizeof(strbuf)); 233129198Scognet UNEXPECTED_ERROR(__FILE__, __LINE__, 234129198Scognet isc_msgcat_get(isc_msgcat, 235129198Scognet ISC_MSGSET_IFITERIOCTL, 236129198Scognet ISC_MSG_GETIFCONFIG, 237129198Scognet "get interface " 238129198Scognet "configuration: %s"), 239129198Scognet strbuf); 240129198Scognet result = ISC_R_UNEXPECTED; 241129198Scognet goto cleanup; 242129198Scognet } 243129198Scognet /* 244129198Scognet * EINVAL. Retry with a bigger buffer. 245129198Scognet */ 246129198Scognet } else { 247129198Scognet /* 248129198Scognet * The ioctl succeeded. 249129198Scognet * Some OS's just return what will fit rather 250129198Scognet * than set EINVAL if the buffer is too small 251129198Scognet * to fit all the interfaces in. If 252129198Scognet * ifc.ifc_len is too near to the end of the 253129198Scognet * buffer we will grow it just in case and 254129198Scognet * retry. 255248361Sandrew */ 256129198Scognet if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) 257129198Scognet < iter->bufsize6) 258129198Scognet break; 259129198Scognet } 260129198Scognet if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) { 261129198Scognet UNEXPECTED_ERROR(__FILE__, __LINE__, 262129198Scognet isc_msgcat_get(isc_msgcat, 263129198Scognet ISC_MSGSET_IFITERIOCTL, 264129198Scognet ISC_MSG_BUFFERMAX, 265236991Simp "get interface " 266129198Scognet "configuration: " 267129198Scognet "maximum buffer " 268129198Scognet "size exceeded")); 269129198Scognet result = ISC_R_UNEXPECTED; 270129198Scognet goto cleanup; 271129198Scognet } 272129198Scognet isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 273129198Scognet 274129198Scognet iter->bufsize6 *= 2; 275129198Scognet } 276129198Scognet 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 memmove(&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 memmove(&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 memmove(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 memmove(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name)); 528 memmove(&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 memmove(&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 memmove(&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 memmove(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 memmove(&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