1258945Sroberto/* 2258945Sroberto * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1999-2003 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp $ */ 19258945Sroberto 20258945Sroberto/*! \file 21258945Sroberto * \brief 22258945Sroberto * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. 23258945Sroberto * See netintro(4). 24258945Sroberto */ 25258945Sroberto 26258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 27258945Sroberto#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF 28258945Sroberto#define lifc_len iflc_len 29258945Sroberto#define lifc_buf iflc_buf 30258945Sroberto#define lifc_req iflc_req 31258945Sroberto#define LIFCONF if_laddrconf 32258945Sroberto#else 33258945Sroberto#define ISC_HAVE_LIFC_FAMILY 1 34258945Sroberto#define ISC_HAVE_LIFC_FLAGS 1 35258945Sroberto#define LIFCONF lifconf 36258945Sroberto#endif 37258945Sroberto 38258945Sroberto#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ 39258945Sroberto#define lifr_addr iflr_addr 40258945Sroberto#define lifr_name iflr_name 41258945Sroberto#define lifr_dstaddr iflr_dstaddr 42258945Sroberto#define lifr_broadaddr iflr_broadaddr 43258945Sroberto#define lifr_flags iflr_flags 44258945Sroberto#define lifr_index iflr_index 45258945Sroberto#define ss_family sa_family 46258945Sroberto#define LIFREQ if_laddrreq 47258945Sroberto#else 48258945Sroberto#define LIFREQ lifreq 49258945Sroberto#endif 50258945Sroberto#endif 51258945Sroberto 52258945Sroberto#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') 53258945Sroberto#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) 54258945Sroberto 55258945Srobertostruct isc_interfaceiter { 56258945Sroberto unsigned int magic; /* Magic number. */ 57258945Sroberto isc_mem_t *mctx; 58258945Sroberto int mode; 59258945Sroberto int socket; 60258945Sroberto struct ifconf ifc; 61258945Sroberto void *buf; /* Buffer for sysctl data. */ 62258945Sroberto unsigned int bufsize; /* Bytes allocated. */ 63258945Sroberto unsigned int pos; /* Current offset in 64258945Sroberto SIOCGIFCONF data */ 65258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 66258945Sroberto int socket6; 67258945Sroberto struct LIFCONF lifc; 68258945Sroberto void *buf6; /* Buffer for sysctl data. */ 69258945Sroberto unsigned int bufsize6; /* Bytes allocated. */ 70258945Sroberto unsigned int pos6; /* Current offset in 71258945Sroberto SIOCGLIFCONF data */ 72258945Sroberto isc_result_t result6; /* Last result code. */ 73258945Sroberto isc_boolean_t first6; 74258945Sroberto#endif 75258945Sroberto#ifdef HAVE_TRUCLUSTER 76258945Sroberto int clua_context; /* Cluster alias context */ 77258945Sroberto isc_boolean_t clua_done; 78258945Sroberto struct sockaddr clua_sa; 79258945Sroberto#endif 80258945Sroberto#ifdef __linux 81258945Sroberto FILE * proc; 82258945Sroberto char entry[ISC_IF_INET6_SZ]; 83258945Sroberto isc_result_t valid; 84258945Sroberto#endif 85258945Sroberto isc_interface_t current; /* Current interface data. */ 86258945Sroberto isc_result_t result; /* Last result code. */ 87258945Sroberto}; 88258945Sroberto 89258945Sroberto#ifdef HAVE_TRUCLUSTER 90258945Sroberto#include <clua/clua.h> 91258945Sroberto#include <sys/socket.h> 92258945Sroberto#endif 93258945Sroberto 94258945Sroberto 95258945Sroberto/*% 96258945Sroberto * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system 97258945Sroberto * will have more than a megabyte of interface configuration data. 98258945Sroberto */ 99258945Sroberto#define IFCONF_BUFSIZE_INITIAL 4096 100258945Sroberto#define IFCONF_BUFSIZE_MAX 1048576 101258945Sroberto 102258945Sroberto#ifdef __linux 103258945Sroberto#ifndef IF_NAMESIZE 104258945Sroberto# ifdef IFNAMSIZ 105258945Sroberto# define IF_NAMESIZE IFNAMSIZ 106258945Sroberto# else 107258945Sroberto# define IF_NAMESIZE 16 108258945Sroberto# endif 109258945Sroberto#endif 110258945Sroberto#endif 111258945Sroberto 112282408Scy/* Silence a warning when this file is #included */ 113280849Scyint 114282408Scyisc_ioctl(int fildes, int req, char *arg); 115282408Scy 116282408Scyint 117280849Scyisc_ioctl(int fildes, int req, char *arg) { 118280849Scy int trys; 119280849Scy int ret; 120280849Scy 121280849Scy for (trys = 0; trys < 3; trys++) { 122280849Scy if ((ret = ioctl(fildes, req, arg)) < 0) { 123280849Scy if (errno == EINTR) 124280849Scy continue; 125280849Scy } 126280849Scy break; 127280849Scy } 128280849Scy return (ret); 129280849Scy} 130280849Scy 131258945Srobertostatic isc_result_t 132258945Srobertogetbuf4(isc_interfaceiter_t *iter) { 133258945Sroberto char strbuf[ISC_STRERRORSIZE]; 134258945Sroberto 135258945Sroberto iter->bufsize = IFCONF_BUFSIZE_INITIAL; 136258945Sroberto 137258945Sroberto for (;;) { 138258945Sroberto iter->buf = isc_mem_get(iter->mctx, iter->bufsize); 139258945Sroberto if (iter->buf == NULL) 140258945Sroberto return (ISC_R_NOMEMORY); 141258945Sroberto 142258945Sroberto memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); 143258945Sroberto iter->ifc.ifc_len = iter->bufsize; 144258945Sroberto iter->ifc.ifc_buf = iter->buf; 145258945Sroberto /* 146258945Sroberto * Ignore the HP/UX warning about "integer overflow during 147258945Sroberto * conversion". It comes from its own macro definition, 148258945Sroberto * and is really hard to shut up. 149258945Sroberto */ 150280849Scy if (isc_ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) 151258945Sroberto == -1) { 152258945Sroberto if (errno != EINVAL) { 153258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 154258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 155258945Sroberto isc_msgcat_get(isc_msgcat, 156258945Sroberto ISC_MSGSET_IFITERIOCTL, 157258945Sroberto ISC_MSG_GETIFCONFIG, 158258945Sroberto "get interface " 159258945Sroberto "configuration: %s"), 160258945Sroberto strbuf); 161258945Sroberto goto unexpected; 162258945Sroberto } 163258945Sroberto /* 164258945Sroberto * EINVAL. Retry with a bigger buffer. 165258945Sroberto */ 166258945Sroberto } else { 167258945Sroberto /* 168258945Sroberto * The ioctl succeeded. 169258945Sroberto * Some OS's just return what will fit rather 170258945Sroberto * than set EINVAL if the buffer is too small 171258945Sroberto * to fit all the interfaces in. If 172258945Sroberto * ifc.lifc_len is too near to the end of the 173258945Sroberto * buffer we will grow it just in case and 174258945Sroberto * retry. 175258945Sroberto */ 176258945Sroberto if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) 177258945Sroberto < iter->bufsize) 178258945Sroberto break; 179258945Sroberto } 180258945Sroberto if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { 181258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 182258945Sroberto isc_msgcat_get(isc_msgcat, 183258945Sroberto ISC_MSGSET_IFITERIOCTL, 184258945Sroberto ISC_MSG_BUFFERMAX, 185258945Sroberto "get interface " 186258945Sroberto "configuration: " 187258945Sroberto "maximum buffer " 188258945Sroberto "size exceeded")); 189258945Sroberto goto unexpected; 190258945Sroberto } 191258945Sroberto isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 192258945Sroberto 193258945Sroberto iter->bufsize *= 2; 194258945Sroberto } 195258945Sroberto return (ISC_R_SUCCESS); 196258945Sroberto 197258945Sroberto unexpected: 198258945Sroberto isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 199258945Sroberto iter->buf = NULL; 200258945Sroberto return (ISC_R_UNEXPECTED); 201258945Sroberto} 202258945Sroberto 203258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 204258945Srobertostatic isc_result_t 205258945Srobertogetbuf6(isc_interfaceiter_t *iter) { 206258945Sroberto char strbuf[ISC_STRERRORSIZE]; 207258945Sroberto isc_result_t result; 208258945Sroberto 209258945Sroberto iter->bufsize6 = IFCONF_BUFSIZE_INITIAL; 210258945Sroberto 211258945Sroberto for (;;) { 212258945Sroberto iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6); 213258945Sroberto if (iter->buf6 == NULL) 214258945Sroberto return (ISC_R_NOMEMORY); 215258945Sroberto 216258945Sroberto memset(&iter->lifc, 0, sizeof(iter->lifc)); 217258945Sroberto#ifdef ISC_HAVE_LIFC_FAMILY 218258945Sroberto iter->lifc.lifc_family = AF_INET6; 219258945Sroberto#endif 220258945Sroberto#ifdef ISC_HAVE_LIFC_FLAGS 221258945Sroberto iter->lifc.lifc_flags = 0; 222258945Sroberto#endif 223258945Sroberto iter->lifc.lifc_len = iter->bufsize6; 224258945Sroberto iter->lifc.lifc_buf = iter->buf6; 225258945Sroberto /* 226258945Sroberto * Ignore the HP/UX warning about "integer overflow during 227258945Sroberto * conversion". It comes from its own macro definition, 228258945Sroberto * and is really hard to shut up. 229258945Sroberto */ 230280849Scy if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc) 231258945Sroberto == -1) { 232258945Sroberto#ifdef __hpux 233258945Sroberto /* 234258945Sroberto * IPv6 interface scanning is not available on all 235258945Sroberto * kernels w/ IPv6 sockets. 236258945Sroberto */ 237258945Sroberto if (errno == ENOENT) { 238258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 239258945Sroberto isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 240258945Sroberto ISC_LOGMODULE_INTERFACE, 241258945Sroberto ISC_LOG_DEBUG(1), 242258945Sroberto isc_msgcat_get(isc_msgcat, 243258945Sroberto ISC_MSGSET_IFITERIOCTL, 244258945Sroberto ISC_MSG_GETIFCONFIG, 245258945Sroberto "get interface " 246258945Sroberto "configuration: %s"), 247258945Sroberto strbuf); 248258945Sroberto result = ISC_R_FAILURE; 249258945Sroberto goto cleanup; 250258945Sroberto } 251258945Sroberto#endif 252258945Sroberto if (errno != EINVAL) { 253258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 254258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 255258945Sroberto isc_msgcat_get(isc_msgcat, 256258945Sroberto ISC_MSGSET_IFITERIOCTL, 257258945Sroberto ISC_MSG_GETIFCONFIG, 258258945Sroberto "get interface " 259258945Sroberto "configuration: %s"), 260258945Sroberto strbuf); 261258945Sroberto result = ISC_R_UNEXPECTED; 262258945Sroberto goto cleanup; 263258945Sroberto } 264258945Sroberto /* 265258945Sroberto * EINVAL. Retry with a bigger buffer. 266258945Sroberto */ 267258945Sroberto } else { 268258945Sroberto /* 269258945Sroberto * The ioctl succeeded. 270258945Sroberto * Some OS's just return what will fit rather 271258945Sroberto * than set EINVAL if the buffer is too small 272258945Sroberto * to fit all the interfaces in. If 273258945Sroberto * ifc.ifc_len is too near to the end of the 274258945Sroberto * buffer we will grow it just in case and 275258945Sroberto * retry. 276258945Sroberto */ 277258945Sroberto if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) 278258945Sroberto < iter->bufsize6) 279258945Sroberto break; 280258945Sroberto } 281258945Sroberto if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) { 282258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 283258945Sroberto isc_msgcat_get(isc_msgcat, 284258945Sroberto ISC_MSGSET_IFITERIOCTL, 285258945Sroberto ISC_MSG_BUFFERMAX, 286258945Sroberto "get interface " 287258945Sroberto "configuration: " 288258945Sroberto "maximum buffer " 289258945Sroberto "size exceeded")); 290258945Sroberto result = ISC_R_UNEXPECTED; 291258945Sroberto goto cleanup; 292258945Sroberto } 293258945Sroberto isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 294258945Sroberto 295258945Sroberto iter->bufsize6 *= 2; 296258945Sroberto } 297258945Sroberto 298258945Sroberto if (iter->lifc.lifc_len != 0) 299258945Sroberto iter->mode = 6; 300258945Sroberto return (ISC_R_SUCCESS); 301258945Sroberto 302258945Sroberto cleanup: 303258945Sroberto isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 304258945Sroberto iter->buf6 = NULL; 305258945Sroberto return (result); 306258945Sroberto} 307258945Sroberto#endif 308258945Sroberto 309258945Srobertoisc_result_t 310258945Srobertoisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { 311258945Sroberto isc_interfaceiter_t *iter; 312258945Sroberto isc_result_t result; 313258945Sroberto char strbuf[ISC_STRERRORSIZE]; 314258945Sroberto 315258945Sroberto REQUIRE(mctx != NULL); 316258945Sroberto REQUIRE(iterp != NULL); 317258945Sroberto REQUIRE(*iterp == NULL); 318258945Sroberto 319258945Sroberto iter = isc_mem_get(mctx, sizeof(*iter)); 320258945Sroberto if (iter == NULL) 321258945Sroberto return (ISC_R_NOMEMORY); 322258945Sroberto 323258945Sroberto iter->mctx = mctx; 324258945Sroberto iter->mode = 4; 325258945Sroberto iter->buf = NULL; 326258945Sroberto iter->pos = (unsigned int) -1; 327258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 328258945Sroberto iter->buf6 = NULL; 329258945Sroberto iter->pos6 = (unsigned int) -1; 330258945Sroberto iter->result6 = ISC_R_NOMORE; 331258945Sroberto iter->socket6 = -1; 332258945Sroberto iter->first6 = ISC_FALSE; 333258945Sroberto#endif 334258945Sroberto 335258945Sroberto /* 336258945Sroberto * Get the interface configuration, allocating more memory if 337258945Sroberto * necessary. 338258945Sroberto */ 339258945Sroberto 340258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 341258945Sroberto result = isc_net_probeipv6(); 342258945Sroberto if (result == ISC_R_SUCCESS) { 343258945Sroberto /* 344258945Sroberto * Create an unbound datagram socket to do the SIOCGLIFCONF 345258945Sroberto * ioctl on. HP/UX requires an AF_INET6 socket for 346258945Sroberto * SIOCGLIFCONF to get IPv6 addresses. 347258945Sroberto */ 348258945Sroberto if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 349258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 350258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 351258945Sroberto isc_msgcat_get(isc_msgcat, 352258945Sroberto ISC_MSGSET_IFITERIOCTL, 353258945Sroberto ISC_MSG_MAKESCANSOCKET, 354258945Sroberto "making interface " 355258945Sroberto "scan socket: %s"), 356258945Sroberto strbuf); 357258945Sroberto result = ISC_R_UNEXPECTED; 358258945Sroberto goto socket6_failure; 359258945Sroberto } 360258945Sroberto result = iter->result6 = getbuf6(iter); 361258945Sroberto if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS) 362258945Sroberto goto ioctl6_failure; 363258945Sroberto } 364258945Sroberto#endif 365258945Sroberto if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 366258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 367258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 368258945Sroberto isc_msgcat_get(isc_msgcat, 369258945Sroberto ISC_MSGSET_IFITERIOCTL, 370258945Sroberto ISC_MSG_MAKESCANSOCKET, 371258945Sroberto "making interface " 372258945Sroberto "scan socket: %s"), 373258945Sroberto strbuf); 374258945Sroberto result = ISC_R_UNEXPECTED; 375258945Sroberto goto socket_failure; 376258945Sroberto } 377258945Sroberto result = getbuf4(iter); 378258945Sroberto if (result != ISC_R_SUCCESS) 379258945Sroberto goto ioctl_failure; 380258945Sroberto 381258945Sroberto /* 382258945Sroberto * A newly created iterator has an undefined position 383258945Sroberto * until isc_interfaceiter_first() is called. 384258945Sroberto */ 385258945Sroberto#ifdef HAVE_TRUCLUSTER 386258945Sroberto iter->clua_context = -1; 387258945Sroberto iter->clua_done = ISC_TRUE; 388258945Sroberto#endif 389258945Sroberto#ifdef __linux 390258945Sroberto iter->proc = fopen("/proc/net/if_inet6", "r"); 391258945Sroberto iter->valid = ISC_R_FAILURE; 392258945Sroberto#endif 393258945Sroberto iter->result = ISC_R_FAILURE; 394258945Sroberto 395258945Sroberto iter->magic = IFITER_MAGIC; 396258945Sroberto *iterp = iter; 397258945Sroberto return (ISC_R_SUCCESS); 398258945Sroberto 399258945Sroberto ioctl_failure: 400258945Sroberto if (iter->buf != NULL) 401258945Sroberto isc_mem_put(mctx, iter->buf, iter->bufsize); 402258945Sroberto (void) close(iter->socket); 403258945Sroberto 404258945Sroberto socket_failure: 405258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 406258945Sroberto if (iter->buf6 != NULL) 407258945Sroberto isc_mem_put(mctx, iter->buf6, iter->bufsize6); 408258945Sroberto ioctl6_failure: 409258945Sroberto if (iter->socket6 != -1) 410258945Sroberto (void) close(iter->socket6); 411258945Sroberto socket6_failure: 412258945Sroberto#endif 413258945Sroberto 414258945Sroberto isc_mem_put(mctx, iter, sizeof(*iter)); 415258945Sroberto return (result); 416258945Sroberto} 417258945Sroberto 418258945Sroberto#ifdef HAVE_TRUCLUSTER 419258945Srobertostatic void 420258945Srobertoget_inaddr(isc_netaddr_t *dst, struct in_addr *src) { 421258945Sroberto dst->family = AF_INET; 422258945Sroberto memcpy(&dst->type.in, src, sizeof(struct in_addr)); 423258945Sroberto} 424258945Sroberto 425258945Srobertostatic isc_result_t 426258945Srobertointernal_current_clusteralias(isc_interfaceiter_t *iter) { 427258945Sroberto struct clua_info ci; 428258945Sroberto if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS) 429258945Sroberto return (ISC_R_IGNORE); 430258945Sroberto memset(&iter->current, 0, sizeof(iter->current)); 431258945Sroberto iter->current.af = iter->clua_sa.sa_family; 432258945Sroberto memset(iter->current.name, 0, sizeof(iter->current.name)); 433258945Sroberto sprintf(iter->current.name, "clua%d", ci.aliasid); 434258945Sroberto iter->current.flags = INTERFACE_F_UP; 435258945Sroberto get_inaddr(&iter->current.address, &ci.addr); 436258945Sroberto get_inaddr(&iter->current.netmask, &ci.netmask); 437258945Sroberto return (ISC_R_SUCCESS); 438258945Sroberto} 439258945Sroberto#endif 440258945Sroberto 441258945Sroberto/* 442258945Sroberto * Get information about the current interface to iter->current. 443258945Sroberto * If successful, return ISC_R_SUCCESS. 444258945Sroberto * If the interface has an unsupported address family, or if 445258945Sroberto * some operation on it fails, return ISC_R_IGNORE to make 446258945Sroberto * the higher-level iterator code ignore it. 447258945Sroberto */ 448258945Sroberto 449258945Srobertostatic isc_result_t 450258945Srobertointernal_current4(isc_interfaceiter_t *iter) { 451258945Sroberto struct ifreq *ifrp; 452258945Sroberto struct ifreq ifreq; 453258945Sroberto int family; 454258945Sroberto char strbuf[ISC_STRERRORSIZE]; 455258945Sroberto#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) 456258945Sroberto struct lifreq lifreq; 457258945Sroberto#else 458258945Sroberto char sabuf[256]; 459258945Sroberto#endif 460258945Sroberto int i, bits, prefixlen; 461258945Sroberto 462258945Sroberto REQUIRE(VALID_IFITER(iter)); 463258945Sroberto 464258945Sroberto if (iter->ifc.ifc_len == 0 || 465258945Sroberto iter->pos == (unsigned int)iter->ifc.ifc_len) { 466258945Sroberto#ifdef __linux 467258945Sroberto return (linux_if_inet6_current(iter)); 468258945Sroberto#else 469258945Sroberto return (ISC_R_NOMORE); 470258945Sroberto#endif 471258945Sroberto } 472258945Sroberto 473258945Sroberto INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len); 474258945Sroberto 475280849Scy ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos); 476258945Sroberto 477258945Sroberto memset(&ifreq, 0, sizeof(ifreq)); 478258945Sroberto memcpy(&ifreq, ifrp, sizeof(ifreq)); 479258945Sroberto 480258945Sroberto family = ifreq.ifr_addr.sa_family; 481258945Sroberto#if defined(ISC_PLATFORM_HAVEIPV6) 482258945Sroberto if (family != AF_INET && family != AF_INET6) 483258945Sroberto#else 484258945Sroberto if (family != AF_INET) 485258945Sroberto#endif 486258945Sroberto return (ISC_R_IGNORE); 487258945Sroberto 488258945Sroberto memset(&iter->current, 0, sizeof(iter->current)); 489258945Sroberto iter->current.af = family; 490258945Sroberto 491258945Sroberto INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); 492258945Sroberto memset(iter->current.name, 0, sizeof(iter->current.name)); 493258945Sroberto memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name)); 494258945Sroberto 495258945Sroberto get_addr(family, &iter->current.address, 496258945Sroberto (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name); 497258945Sroberto 498258945Sroberto /* 499258945Sroberto * If the interface does not have a address ignore it. 500258945Sroberto */ 501258945Sroberto switch (family) { 502258945Sroberto case AF_INET: 503258945Sroberto if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) 504258945Sroberto return (ISC_R_IGNORE); 505258945Sroberto break; 506258945Sroberto case AF_INET6: 507258945Sroberto if (memcmp(&iter->current.address.type.in6, &in6addr_any, 508258945Sroberto sizeof(in6addr_any)) == 0) 509258945Sroberto return (ISC_R_IGNORE); 510258945Sroberto break; 511258945Sroberto } 512258945Sroberto 513258945Sroberto /* 514258945Sroberto * Get interface flags. 515258945Sroberto */ 516258945Sroberto 517258945Sroberto iter->current.flags = 0; 518258945Sroberto 519258945Sroberto /* 520258945Sroberto * Ignore the HP/UX warning about "integer overflow during 521258945Sroberto * conversion. It comes from its own macro definition, 522258945Sroberto * and is really hard to shut up. 523258945Sroberto */ 524280849Scy if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { 525258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 526258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 527258945Sroberto "%s: getting interface flags: %s", 528258945Sroberto ifreq.ifr_name, strbuf); 529258945Sroberto return (ISC_R_IGNORE); 530258945Sroberto } 531258945Sroberto 532258945Sroberto if ((ifreq.ifr_flags & IFF_UP) != 0) 533258945Sroberto iter->current.flags |= INTERFACE_F_UP; 534258945Sroberto 535258945Sroberto#ifdef IFF_POINTOPOINT 536258945Sroberto if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) 537258945Sroberto iter->current.flags |= INTERFACE_F_POINTTOPOINT; 538258945Sroberto#endif 539258945Sroberto 540258945Sroberto if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) 541258945Sroberto iter->current.flags |= INTERFACE_F_LOOPBACK; 542258945Sroberto 543258945Sroberto if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) 544258945Sroberto iter->current.flags |= INTERFACE_F_BROADCAST; 545258945Sroberto 546258945Sroberto#ifdef IFF_MULTICAST 547258945Sroberto if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) 548258945Sroberto iter->current.flags |= INTERFACE_F_MULTICAST; 549258945Sroberto#endif 550258945Sroberto 551258945Sroberto if (family == AF_INET) 552258945Sroberto goto inet; 553258945Sroberto 554258945Sroberto#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) 555258945Sroberto memset(&lifreq, 0, sizeof(lifreq)); 556258945Sroberto memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name)); 557258945Sroberto memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6, 558258945Sroberto sizeof(iter->current.address.type.in6)); 559258945Sroberto 560280849Scy if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) { 561258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 562258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 563258945Sroberto "%s: getting interface address: %s", 564258945Sroberto ifreq.ifr_name, strbuf); 565258945Sroberto return (ISC_R_IGNORE); 566258945Sroberto } 567258945Sroberto prefixlen = lifreq.lifr_addrlen; 568258945Sroberto#else 569258945Sroberto isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf)); 570258945Sroberto isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 571258945Sroberto ISC_LOGMODULE_INTERFACE, 572258945Sroberto ISC_LOG_INFO, 573258945Sroberto isc_msgcat_get(isc_msgcat, 574258945Sroberto ISC_MSGSET_IFITERIOCTL, 575258945Sroberto ISC_MSG_GETIFCONFIG, 576258945Sroberto "prefix length for %s is unknown " 577258945Sroberto "(assume 128)"), sabuf); 578258945Sroberto prefixlen = 128; 579258945Sroberto#endif 580258945Sroberto 581258945Sroberto /* 582258945Sroberto * Netmask already zeroed. 583258945Sroberto */ 584258945Sroberto iter->current.netmask.family = family; 585258945Sroberto for (i = 0; i < 16; i++) { 586258945Sroberto if (prefixlen > 8) { 587258945Sroberto bits = 0; 588258945Sroberto prefixlen -= 8; 589258945Sroberto } else { 590258945Sroberto bits = 8 - prefixlen; 591258945Sroberto prefixlen = 0; 592258945Sroberto } 593258945Sroberto iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff; 594258945Sroberto } 595282408Scy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 596282408Scy iter->current.ifindex = if_nametoindex(iter->current.name); 597282408Scy#endif 598258945Sroberto return (ISC_R_SUCCESS); 599258945Sroberto 600258945Sroberto inet: 601258945Sroberto if (family != AF_INET) 602258945Sroberto return (ISC_R_IGNORE); 603258945Sroberto#ifdef IFF_POINTOPOINT 604258945Sroberto /* 605258945Sroberto * If the interface is point-to-point, get the destination address. 606258945Sroberto */ 607258945Sroberto if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { 608258945Sroberto /* 609258945Sroberto * Ignore the HP/UX warning about "integer overflow during 610258945Sroberto * conversion. It comes from its own macro definition, 611258945Sroberto * and is really hard to shut up. 612258945Sroberto */ 613280849Scy if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq) 614258945Sroberto < 0) { 615258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 616258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 617258945Sroberto isc_msgcat_get(isc_msgcat, 618258945Sroberto ISC_MSGSET_IFITERIOCTL, 619258945Sroberto ISC_MSG_GETDESTADDR, 620258945Sroberto "%s: getting " 621258945Sroberto "destination address: %s"), 622258945Sroberto ifreq.ifr_name, strbuf); 623258945Sroberto return (ISC_R_IGNORE); 624258945Sroberto } 625258945Sroberto get_addr(family, &iter->current.dstaddress, 626258945Sroberto (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name); 627258945Sroberto } 628258945Sroberto#endif 629258945Sroberto 630258945Sroberto if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { 631258945Sroberto /* 632258945Sroberto * Ignore the HP/UX warning about "integer overflow during 633258945Sroberto * conversion. It comes from its own macro definition, 634258945Sroberto * and is really hard to shut up. 635258945Sroberto */ 636280849Scy if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq) 637258945Sroberto < 0) { 638258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 639258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 640258945Sroberto isc_msgcat_get(isc_msgcat, 641258945Sroberto ISC_MSGSET_IFITERIOCTL, 642258945Sroberto ISC_MSG_GETBCSTADDR, 643258945Sroberto "%s: getting " 644258945Sroberto "broadcast address: %s"), 645258945Sroberto ifreq.ifr_name, strbuf); 646258945Sroberto return (ISC_R_IGNORE); 647258945Sroberto } 648258945Sroberto get_addr(family, &iter->current.broadcast, 649258945Sroberto (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name); 650258945Sroberto } 651258945Sroberto 652258945Sroberto /* 653258945Sroberto * Get the network mask. 654258945Sroberto */ 655258945Sroberto memset(&ifreq, 0, sizeof(ifreq)); 656258945Sroberto memcpy(&ifreq, ifrp, sizeof(ifreq)); 657258945Sroberto /* 658258945Sroberto * Ignore the HP/UX warning about "integer overflow during 659258945Sroberto * conversion. It comes from its own macro definition, 660258945Sroberto * and is really hard to shut up. 661258945Sroberto */ 662280849Scy if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) { 663258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 664258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 665258945Sroberto isc_msgcat_get(isc_msgcat, 666258945Sroberto ISC_MSGSET_IFITERIOCTL, 667258945Sroberto ISC_MSG_GETNETMASK, 668258945Sroberto "%s: getting netmask: %s"), 669258945Sroberto ifreq.ifr_name, strbuf); 670258945Sroberto return (ISC_R_IGNORE); 671258945Sroberto } 672258945Sroberto get_addr(family, &iter->current.netmask, 673258945Sroberto (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name); 674282408Scy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 675282408Scy iter->current.ifindex = if_nametoindex(iter->current.name); 676282408Scy#endif 677258945Sroberto return (ISC_R_SUCCESS); 678258945Sroberto} 679258945Sroberto 680258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 681258945Srobertostatic isc_result_t 682258945Srobertointernal_current6(isc_interfaceiter_t *iter) { 683258945Sroberto struct LIFREQ *ifrp; 684258945Sroberto struct LIFREQ lifreq; 685258945Sroberto int family; 686258945Sroberto char strbuf[ISC_STRERRORSIZE]; 687258945Sroberto int fd; 688258945Sroberto 689258945Sroberto REQUIRE(VALID_IFITER(iter)); 690258945Sroberto if (iter->result6 != ISC_R_SUCCESS) 691258945Sroberto return (iter->result6); 692258945Sroberto REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); 693258945Sroberto 694280849Scy ifrp = (void *)((char *)iter->lifc.lifc_req + iter->pos6); 695258945Sroberto 696258945Sroberto memset(&lifreq, 0, sizeof(lifreq)); 697258945Sroberto memcpy(&lifreq, ifrp, sizeof(lifreq)); 698258945Sroberto 699258945Sroberto family = lifreq.lifr_addr.ss_family; 700258945Sroberto#ifdef ISC_PLATFORM_HAVEIPV6 701258945Sroberto if (family != AF_INET && family != AF_INET6) 702258945Sroberto#else 703258945Sroberto if (family != AF_INET) 704258945Sroberto#endif 705258945Sroberto return (ISC_R_IGNORE); 706258945Sroberto 707258945Sroberto memset(&iter->current, 0, sizeof(iter->current)); 708258945Sroberto iter->current.af = family; 709258945Sroberto 710258945Sroberto INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name)); 711258945Sroberto memset(iter->current.name, 0, sizeof(iter->current.name)); 712258945Sroberto memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name)); 713258945Sroberto 714258945Sroberto get_addr(family, &iter->current.address, 715258945Sroberto (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); 716258945Sroberto 717258945Sroberto if (isc_netaddr_islinklocal(&iter->current.address)) 718258945Sroberto isc_netaddr_setzone(&iter->current.address, 719258945Sroberto (isc_uint32_t)lifreq.lifr_index); 720258945Sroberto 721258945Sroberto /* 722258945Sroberto * If the interface does not have a address ignore it. 723258945Sroberto */ 724258945Sroberto switch (family) { 725258945Sroberto case AF_INET: 726258945Sroberto if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) 727258945Sroberto return (ISC_R_IGNORE); 728258945Sroberto break; 729258945Sroberto case AF_INET6: 730258945Sroberto if (memcmp(&iter->current.address.type.in6, &in6addr_any, 731258945Sroberto sizeof(in6addr_any)) == 0) 732258945Sroberto return (ISC_R_IGNORE); 733258945Sroberto break; 734258945Sroberto } 735258945Sroberto 736258945Sroberto /* 737258945Sroberto * Get interface flags. 738258945Sroberto */ 739258945Sroberto 740258945Sroberto iter->current.flags = 0; 741258945Sroberto 742258945Sroberto if (family == AF_INET6) 743258945Sroberto fd = iter->socket6; 744258945Sroberto else 745258945Sroberto fd = iter->socket; 746258945Sroberto 747258945Sroberto /* 748258945Sroberto * Ignore the HP/UX warning about "integer overflow during 749258945Sroberto * conversion. It comes from its own macro definition, 750258945Sroberto * and is really hard to shut up. 751258945Sroberto */ 752280849Scy if (isc_ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) { 753258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 754258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 755258945Sroberto "%s: getting interface flags: %s", 756258945Sroberto lifreq.lifr_name, strbuf); 757258945Sroberto return (ISC_R_IGNORE); 758258945Sroberto } 759258945Sroberto 760258945Sroberto if ((lifreq.lifr_flags & IFF_UP) != 0) 761258945Sroberto iter->current.flags |= INTERFACE_F_UP; 762258945Sroberto 763258945Sroberto#ifdef IFF_POINTOPOINT 764258945Sroberto if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0) 765258945Sroberto iter->current.flags |= INTERFACE_F_POINTTOPOINT; 766258945Sroberto#endif 767258945Sroberto 768258945Sroberto if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0) 769258945Sroberto iter->current.flags |= INTERFACE_F_LOOPBACK; 770258945Sroberto 771258945Sroberto if ((lifreq.lifr_flags & IFF_BROADCAST) != 0) { 772258945Sroberto iter->current.flags |= INTERFACE_F_BROADCAST; 773258945Sroberto } 774258945Sroberto 775258945Sroberto#ifdef IFF_MULTICAST 776258945Sroberto if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) { 777258945Sroberto iter->current.flags |= INTERFACE_F_MULTICAST; 778258945Sroberto } 779258945Sroberto#endif 780258945Sroberto 781258945Sroberto#ifdef IFF_POINTOPOINT 782258945Sroberto /* 783258945Sroberto * If the interface is point-to-point, get the destination address. 784258945Sroberto */ 785258945Sroberto if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { 786258945Sroberto /* 787258945Sroberto * Ignore the HP/UX warning about "integer overflow during 788258945Sroberto * conversion. It comes from its own macro definition, 789258945Sroberto * and is really hard to shut up. 790258945Sroberto */ 791280849Scy if (isc_ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq) 792258945Sroberto < 0) { 793258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 794258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 795258945Sroberto isc_msgcat_get(isc_msgcat, 796258945Sroberto ISC_MSGSET_IFITERIOCTL, 797258945Sroberto ISC_MSG_GETDESTADDR, 798258945Sroberto "%s: getting " 799258945Sroberto "destination address: %s"), 800258945Sroberto lifreq.lifr_name, strbuf); 801258945Sroberto return (ISC_R_IGNORE); 802258945Sroberto } 803258945Sroberto get_addr(family, &iter->current.dstaddress, 804258945Sroberto (struct sockaddr *)&lifreq.lifr_dstaddr, 805258945Sroberto lifreq.lifr_name); 806258945Sroberto } 807258945Sroberto#endif 808258945Sroberto 809258945Sroberto#ifdef SIOCGLIFBRDADDR 810258945Sroberto if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { 811258945Sroberto /* 812258945Sroberto * Ignore the HP/UX warning about "integer overflow during 813258945Sroberto * conversion. It comes from its own macro definition, 814258945Sroberto * and is really hard to shut up. 815258945Sroberto */ 816280849Scy if (isc_ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq) 817258945Sroberto < 0) { 818258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 819258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 820258945Sroberto isc_msgcat_get(isc_msgcat, 821258945Sroberto ISC_MSGSET_IFITERIOCTL, 822258945Sroberto ISC_MSG_GETBCSTADDR, 823258945Sroberto "%s: getting " 824258945Sroberto "broadcast address: %s"), 825258945Sroberto lifreq.lifr_name, strbuf); 826258945Sroberto return (ISC_R_IGNORE); 827258945Sroberto } 828258945Sroberto get_addr(family, &iter->current.broadcast, 829258945Sroberto (struct sockaddr *)&lifreq.lifr_broadaddr, 830258945Sroberto lifreq.lifr_name); 831258945Sroberto } 832258945Sroberto#endif /* SIOCGLIFBRDADDR */ 833258945Sroberto 834258945Sroberto /* 835258945Sroberto * Get the network mask. Netmask already zeroed. 836258945Sroberto */ 837258945Sroberto memset(&lifreq, 0, sizeof(lifreq)); 838258945Sroberto memcpy(&lifreq, ifrp, sizeof(lifreq)); 839258945Sroberto 840258945Sroberto#ifdef lifr_addrlen 841258945Sroberto /* 842258945Sroberto * Special case: if the system provides lifr_addrlen member, the 843258945Sroberto * netmask of an IPv6 address can be derived from the length, since 844258945Sroberto * an IPv6 address always has a contiguous mask. 845258945Sroberto */ 846258945Sroberto if (family == AF_INET6) { 847258945Sroberto int i, bits; 848258945Sroberto 849258945Sroberto iter->current.netmask.family = family; 850258945Sroberto for (i = 0; i < lifreq.lifr_addrlen; i += 8) { 851258945Sroberto bits = lifreq.lifr_addrlen - i; 852258945Sroberto bits = (bits < 8) ? (8 - bits) : 0; 853258945Sroberto iter->current.netmask.type.in6.s6_addr[i / 8] = 854258945Sroberto (~0 << bits) & 0xff; 855258945Sroberto } 856282408Scy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 857282408Scy iter->current.ifindex = if_nametoindex(iter->current.name); 858282408Scy#endif 859258945Sroberto return (ISC_R_SUCCESS); 860258945Sroberto } 861258945Sroberto#endif 862258945Sroberto 863258945Sroberto /* 864258945Sroberto * Ignore the HP/UX warning about "integer overflow during 865258945Sroberto * conversion. It comes from its own macro definition, 866258945Sroberto * and is really hard to shut up. 867258945Sroberto */ 868280849Scy if (isc_ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) { 869258945Sroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 870258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 871258945Sroberto isc_msgcat_get(isc_msgcat, 872258945Sroberto ISC_MSGSET_IFITERIOCTL, 873258945Sroberto ISC_MSG_GETNETMASK, 874258945Sroberto "%s: getting netmask: %s"), 875258945Sroberto lifreq.lifr_name, strbuf); 876258945Sroberto return (ISC_R_IGNORE); 877258945Sroberto } 878258945Sroberto get_addr(family, &iter->current.netmask, 879258945Sroberto (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); 880258945Sroberto 881282408Scy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 882282408Scy iter->current.ifindex = if_nametoindex(iter->current.name); 883282408Scy#endif 884258945Sroberto return (ISC_R_SUCCESS); 885258945Sroberto} 886258945Sroberto#endif 887258945Sroberto 888258945Srobertostatic isc_result_t 889258945Srobertointernal_current(isc_interfaceiter_t *iter) { 890258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 891258945Sroberto if (iter->mode == 6) { 892258945Sroberto iter->result6 = internal_current6(iter); 893258945Sroberto if (iter->result6 != ISC_R_NOMORE) 894258945Sroberto return (iter->result6); 895258945Sroberto } 896258945Sroberto#endif 897258945Sroberto#ifdef HAVE_TRUCLUSTER 898258945Sroberto if (!iter->clua_done) 899258945Sroberto return(internal_current_clusteralias(iter)); 900258945Sroberto#endif 901258945Sroberto return (internal_current4(iter)); 902258945Sroberto} 903258945Sroberto 904258945Sroberto/* 905258945Sroberto * Step the iterator to the next interface. Unlike 906258945Sroberto * isc_interfaceiter_next(), this may leave the iterator 907258945Sroberto * positioned on an interface that will ultimately 908258945Sroberto * be ignored. Return ISC_R_NOMORE if there are no more 909258945Sroberto * interfaces, otherwise ISC_R_SUCCESS. 910258945Sroberto */ 911258945Srobertostatic isc_result_t 912258945Srobertointernal_next4(isc_interfaceiter_t *iter) { 913258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 914258945Sroberto struct ifreq *ifrp; 915258945Sroberto#endif 916258945Sroberto 917258945Sroberto if (iter->pos < (unsigned int) iter->ifc.ifc_len) { 918258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 919258945Sroberto ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); 920258945Sroberto 921258945Sroberto if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) 922258945Sroberto iter->pos += sizeof(ifrp->ifr_name) + 923258945Sroberto ifrp->ifr_addr.sa_len; 924258945Sroberto else 925258945Sroberto#endif 926258945Sroberto iter->pos += sizeof(struct ifreq); 927258945Sroberto 928258945Sroberto } else { 929258945Sroberto INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len); 930258945Sroberto#ifdef __linux 931258945Sroberto return (linux_if_inet6_next(iter)); 932258945Sroberto#else 933258945Sroberto return (ISC_R_NOMORE); 934258945Sroberto#endif 935258945Sroberto } 936258945Sroberto return (ISC_R_SUCCESS); 937258945Sroberto} 938258945Sroberto 939258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 940258945Srobertostatic isc_result_t 941258945Srobertointernal_next6(isc_interfaceiter_t *iter) { 942258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 943258945Sroberto struct LIFREQ *ifrp; 944258945Sroberto#endif 945258945Sroberto 946258945Sroberto if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE) 947258945Sroberto return (iter->result6); 948258945Sroberto 949258945Sroberto REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); 950258945Sroberto 951258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 952258945Sroberto ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6); 953258945Sroberto 954258945Sroberto if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr)) 955258945Sroberto iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len; 956258945Sroberto else 957258945Sroberto#endif 958258945Sroberto iter->pos6 += sizeof(struct LIFREQ); 959258945Sroberto 960258945Sroberto if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len) 961258945Sroberto return (ISC_R_NOMORE); 962258945Sroberto 963258945Sroberto return (ISC_R_SUCCESS); 964258945Sroberto} 965258945Sroberto#endif 966258945Sroberto 967258945Srobertostatic isc_result_t 968258945Srobertointernal_next(isc_interfaceiter_t *iter) { 969258945Sroberto#ifdef HAVE_TRUCLUSTER 970258945Sroberto int clua_result; 971258945Sroberto#endif 972258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 973258945Sroberto if (iter->mode == 6) { 974258945Sroberto iter->result6 = internal_next6(iter); 975258945Sroberto if (iter->result6 != ISC_R_NOMORE) 976258945Sroberto return (iter->result6); 977258945Sroberto if (iter->first6) { 978258945Sroberto iter->first6 = ISC_FALSE; 979258945Sroberto return (ISC_R_SUCCESS); 980258945Sroberto } 981258945Sroberto } 982258945Sroberto#endif 983258945Sroberto#ifdef HAVE_TRUCLUSTER 984258945Sroberto if (!iter->clua_done) { 985258945Sroberto clua_result = clua_getaliasaddress(&iter->clua_sa, 986258945Sroberto &iter->clua_context); 987258945Sroberto if (clua_result != CLUA_SUCCESS) 988258945Sroberto iter->clua_done = ISC_TRUE; 989258945Sroberto return (ISC_R_SUCCESS); 990258945Sroberto } 991258945Sroberto#endif 992258945Sroberto return (internal_next4(iter)); 993258945Sroberto} 994258945Sroberto 995258945Srobertostatic void 996258945Srobertointernal_destroy(isc_interfaceiter_t *iter) { 997258945Sroberto (void) close(iter->socket); 998258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 999258945Sroberto if (iter->socket6 != -1) 1000258945Sroberto (void) close(iter->socket6); 1001258945Sroberto if (iter->buf6 != NULL) { 1002258945Sroberto isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 1003258945Sroberto } 1004258945Sroberto#endif 1005258945Sroberto#ifdef __linux 1006258945Sroberto if (iter->proc != NULL) 1007258945Sroberto fclose(iter->proc); 1008258945Sroberto#endif 1009258945Sroberto} 1010258945Sroberto 1011258945Srobertostatic 1012258945Srobertovoid internal_first(isc_interfaceiter_t *iter) { 1013258945Sroberto#ifdef HAVE_TRUCLUSTER 1014258945Sroberto int clua_result; 1015258945Sroberto#endif 1016258945Sroberto iter->pos = 0; 1017258945Sroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 1018258945Sroberto iter->pos6 = 0; 1019258945Sroberto if (iter->result6 == ISC_R_NOMORE) 1020258945Sroberto iter->result6 = ISC_R_SUCCESS; 1021258945Sroberto iter->first6 = ISC_TRUE; 1022258945Sroberto#endif 1023258945Sroberto#ifdef HAVE_TRUCLUSTER 1024258945Sroberto iter->clua_context = 0; 1025258945Sroberto clua_result = clua_getaliasaddress(&iter->clua_sa, 1026258945Sroberto &iter->clua_context); 1027258945Sroberto iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS); 1028258945Sroberto#endif 1029258945Sroberto#ifdef __linux 1030258945Sroberto linux_if_inet6_first(iter); 1031258945Sroberto#endif 1032258945Sroberto} 1033