1118e757roberto/* 2d54cfbdroberto * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 37a6072eroberto * Copyright (C) 1999-2003 Internet Software Consortium. 4118e757roberto * 5d54cfbdroberto * Permission to use, copy, modify, and/or distribute this software for any 6118e757roberto * purpose with or without fee is hereby granted, provided that the above 7118e757roberto * copyright notice and this permission notice appear in all copies. 8118e757roberto * 97a6072eroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 107a6072eroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 117a6072eroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 127a6072eroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 137a6072eroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 147a6072eroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 157a6072eroberto * PERFORMANCE OF THIS SOFTWARE. 16118e757roberto */ 17118e757roberto 18047f369cy/* $Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp $ */ 19118e757roberto 20d54cfbdroberto/*! \file 21d54cfbdroberto * \brief 22118e757roberto * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. 23118e757roberto * See netintro(4). 24118e757roberto */ 25118e757roberto 26118e757roberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 27118e757roberto#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF 28118e757roberto#define lifc_len iflc_len 29118e757roberto#define lifc_buf iflc_buf 30118e757roberto#define lifc_req iflc_req 31118e757roberto#define LIFCONF if_laddrconf 32118e757roberto#else 33118e757roberto#define ISC_HAVE_LIFC_FAMILY 1 34118e757roberto#define ISC_HAVE_LIFC_FLAGS 1 35118e757roberto#define LIFCONF lifconf 36118e757roberto#endif 37118e757roberto 38118e757roberto#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ 39118e757roberto#define lifr_addr iflr_addr 40118e757roberto#define lifr_name iflr_name 41118e757roberto#define lifr_dstaddr iflr_dstaddr 42118e757roberto#define lifr_broadaddr iflr_broadaddr 43118e757roberto#define lifr_flags iflr_flags 447a6072eroberto#define lifr_index iflr_index 45118e757roberto#define ss_family sa_family 46118e757roberto#define LIFREQ if_laddrreq 47118e757roberto#else 48118e757roberto#define LIFREQ lifreq 49118e757roberto#endif 50118e757roberto#endif 51118e757roberto 52118e757roberto#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') 53118e757roberto#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) 54118e757roberto 55118e757robertostruct isc_interfaceiter { 56118e757roberto unsigned int magic; /* Magic number. */ 57118e757roberto isc_mem_t *mctx; 58118e757roberto int mode; 597a6072eroberto int socket; 60118e757roberto struct ifconf ifc; 617a6072eroberto void *buf; /* Buffer for sysctl data. */ 627a6072eroberto unsigned int bufsize; /* Bytes allocated. */ 637a6072eroberto unsigned int pos; /* Current offset in 647a6072eroberto SIOCGIFCONF data */ 65118e757roberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 667a6072eroberto int socket6; 67118e757roberto struct LIFCONF lifc; 687a6072eroberto void *buf6; /* Buffer for sysctl data. */ 697a6072eroberto unsigned int bufsize6; /* Bytes allocated. */ 707a6072eroberto unsigned int pos6; /* Current offset in 717a6072eroberto SIOCGLIFCONF data */ 727a6072eroberto isc_result_t result6; /* Last result code. */ 737a6072eroberto isc_boolean_t first6; 74118e757roberto#endif 75118e757roberto#ifdef HAVE_TRUCLUSTER 76118e757roberto int clua_context; /* Cluster alias context */ 777a6072eroberto isc_boolean_t clua_done; 787a6072eroberto struct sockaddr clua_sa; 797a6072eroberto#endif 807a6072eroberto#ifdef __linux 817a6072eroberto FILE * proc; 827a6072eroberto char entry[ISC_IF_INET6_SZ]; 837a6072eroberto isc_result_t valid; 84118e757roberto#endif 85118e757roberto isc_interface_t current; /* Current interface data. */ 86118e757roberto isc_result_t result; /* Last result code. */ 87118e757roberto}; 88118e757roberto 89118e757roberto#ifdef HAVE_TRUCLUSTER 90118e757roberto#include <clua/clua.h> 91118e757roberto#include <sys/socket.h> 92118e757roberto#endif 93118e757roberto 94118e757roberto 95d54cfbdroberto/*% 96118e757roberto * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system 97118e757roberto * will have more than a megabyte of interface configuration data. 98118e757roberto */ 99118e757roberto#define IFCONF_BUFSIZE_INITIAL 4096 100118e757roberto#define IFCONF_BUFSIZE_MAX 1048576 101118e757roberto 1027a6072eroberto#ifdef __linux 1037a6072eroberto#ifndef IF_NAMESIZE 1047a6072eroberto# ifdef IFNAMSIZ 105d54cfbdroberto# define IF_NAMESIZE IFNAMSIZ 1067a6072eroberto# else 1077a6072eroberto# define IF_NAMESIZE 16 1087a6072eroberto# endif 1097a6072eroberto#endif 1107a6072eroberto#endif 1117a6072eroberto 112f63afe2cy/* Silence a warning when this file is #included */ 113f63afe2cyint 114f63afe2cyisc_ioctl(int fildes, int req, char *arg); 115f63afe2cy 116047f369cyint 117047f369cyisc_ioctl(int fildes, int req, char *arg) { 118047f369cy int trys; 119047f369cy int ret; 120047f369cy 121047f369cy for (trys = 0; trys < 3; trys++) { 122047f369cy if ((ret = ioctl(fildes, req, arg)) < 0) { 123047f369cy if (errno == EINTR) 124047f369cy continue; 125047f369cy } 126047f369cy break; 127047f369cy } 128047f369cy return (ret); 129047f369cy} 130047f369cy 131118e757robertostatic isc_result_t 132118e757robertogetbuf4(isc_interfaceiter_t *iter) { 133118e757roberto char strbuf[ISC_STRERRORSIZE]; 134118e757roberto 135118e757roberto iter->bufsize = IFCONF_BUFSIZE_INITIAL; 136118e757roberto 137118e757roberto for (;;) { 138118e757roberto iter->buf = isc_mem_get(iter->mctx, iter->bufsize); 139118e757roberto if (iter->buf == NULL) 140118e757roberto return (ISC_R_NOMEMORY); 141118e757roberto 142118e757roberto memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); 143118e757roberto iter->ifc.ifc_len = iter->bufsize; 144118e757roberto iter->ifc.ifc_buf = iter->buf; 145118e757roberto /* 146118e757roberto * Ignore the HP/UX warning about "integer overflow during 147118e757roberto * conversion". It comes from its own macro definition, 148118e757roberto * and is really hard to shut up. 149118e757roberto */ 150047f369cy if (isc_ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) 151118e757roberto == -1) { 152118e757roberto if (errno != EINVAL) { 153118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 154118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 155118e757roberto isc_msgcat_get(isc_msgcat, 156118e757roberto ISC_MSGSET_IFITERIOCTL, 157118e757roberto ISC_MSG_GETIFCONFIG, 158118e757roberto "get interface " 159118e757roberto "configuration: %s"), 160118e757roberto strbuf); 161118e757roberto goto unexpected; 162118e757roberto } 163118e757roberto /* 164118e757roberto * EINVAL. Retry with a bigger buffer. 165118e757roberto */ 166118e757roberto } else { 167118e757roberto /* 168118e757roberto * The ioctl succeeded. 169118e757roberto * Some OS's just return what will fit rather 170118e757roberto * than set EINVAL if the buffer is too small 171118e757roberto * to fit all the interfaces in. If 172118e757roberto * ifc.lifc_len is too near to the end of the 173118e757roberto * buffer we will grow it just in case and 174118e757roberto * retry. 175118e757roberto */ 176118e757roberto if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) 177118e757roberto < iter->bufsize) 178118e757roberto break; 179118e757roberto } 180118e757roberto if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { 181118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 182118e757roberto isc_msgcat_get(isc_msgcat, 183118e757roberto ISC_MSGSET_IFITERIOCTL, 184118e757roberto ISC_MSG_BUFFERMAX, 185118e757roberto "get interface " 186118e757roberto "configuration: " 187118e757roberto "maximum buffer " 188118e757roberto "size exceeded")); 189118e757roberto goto unexpected; 190118e757roberto } 191118e757roberto isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 192118e757roberto 193118e757roberto iter->bufsize *= 2; 194118e757roberto } 195118e757roberto return (ISC_R_SUCCESS); 196118e757roberto 197118e757roberto unexpected: 198118e757roberto isc_mem_put(iter->mctx, iter->buf, iter->bufsize); 199118e757roberto iter->buf = NULL; 200118e757roberto return (ISC_R_UNEXPECTED); 201118e757roberto} 202118e757roberto 2037a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 204118e757robertostatic isc_result_t 205118e757robertogetbuf6(isc_interfaceiter_t *iter) { 206118e757roberto char strbuf[ISC_STRERRORSIZE]; 207118e757roberto isc_result_t result; 208118e757roberto 2097a6072eroberto iter->bufsize6 = IFCONF_BUFSIZE_INITIAL; 210118e757roberto 211118e757roberto for (;;) { 2127a6072eroberto iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6); 2137a6072eroberto if (iter->buf6 == NULL) 214118e757roberto return (ISC_R_NOMEMORY); 215118e757roberto 2167a6072eroberto memset(&iter->lifc, 0, sizeof(iter->lifc)); 217118e757roberto#ifdef ISC_HAVE_LIFC_FAMILY 2187a6072eroberto iter->lifc.lifc_family = AF_INET6; 219118e757roberto#endif 220118e757roberto#ifdef ISC_HAVE_LIFC_FLAGS 221118e757roberto iter->lifc.lifc_flags = 0; 222118e757roberto#endif 2237a6072eroberto iter->lifc.lifc_len = iter->bufsize6; 2247a6072eroberto iter->lifc.lifc_buf = iter->buf6; 225118e757roberto /* 226118e757roberto * Ignore the HP/UX warning about "integer overflow during 227118e757roberto * conversion". It comes from its own macro definition, 228118e757roberto * and is really hard to shut up. 229118e757roberto */ 230047f369cy if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc) 231118e757roberto == -1) { 232118e757roberto#ifdef __hpux 233118e757roberto /* 234118e757roberto * IPv6 interface scanning is not available on all 235118e757roberto * kernels w/ IPv6 sockets. 236118e757roberto */ 237118e757roberto if (errno == ENOENT) { 238118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 239d54cfbdroberto isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 240d54cfbdroberto ISC_LOGMODULE_INTERFACE, 241d54cfbdroberto ISC_LOG_DEBUG(1), 242d54cfbdroberto isc_msgcat_get(isc_msgcat, 243118e757roberto ISC_MSGSET_IFITERIOCTL, 244118e757roberto ISC_MSG_GETIFCONFIG, 245118e757roberto "get interface " 246118e757roberto "configuration: %s"), 247d54cfbdroberto strbuf); 248118e757roberto result = ISC_R_FAILURE; 249118e757roberto goto cleanup; 250118e757roberto } 251118e757roberto#endif 252118e757roberto if (errno != EINVAL) { 253118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 254118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 255118e757roberto isc_msgcat_get(isc_msgcat, 256118e757roberto ISC_MSGSET_IFITERIOCTL, 257118e757roberto ISC_MSG_GETIFCONFIG, 258118e757roberto "get interface " 259118e757roberto "configuration: %s"), 260118e757roberto strbuf); 261118e757roberto result = ISC_R_UNEXPECTED; 262118e757roberto goto cleanup; 263118e757roberto } 264118e757roberto /* 265118e757roberto * EINVAL. Retry with a bigger buffer. 266118e757roberto */ 267118e757roberto } else { 268118e757roberto /* 269118e757roberto * The ioctl succeeded. 270118e757roberto * Some OS's just return what will fit rather 271118e757roberto * than set EINVAL if the buffer is too small 272118e757roberto * to fit all the interfaces in. If 273118e757roberto * ifc.ifc_len is too near to the end of the 274118e757roberto * buffer we will grow it just in case and 275118e757roberto * retry. 276118e757roberto */ 277118e757roberto if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) 2787a6072eroberto < iter->bufsize6) 279118e757roberto break; 280118e757roberto } 2817a6072eroberto if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) { 282118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 283118e757roberto isc_msgcat_get(isc_msgcat, 284118e757roberto ISC_MSGSET_IFITERIOCTL, 285118e757roberto ISC_MSG_BUFFERMAX, 286118e757roberto "get interface " 287118e757roberto "configuration: " 288118e757roberto "maximum buffer " 289118e757roberto "size exceeded")); 290118e757roberto result = ISC_R_UNEXPECTED; 291118e757roberto goto cleanup; 292118e757roberto } 2937a6072eroberto isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 294118e757roberto 2957a6072eroberto iter->bufsize6 *= 2; 296118e757roberto } 297118e757roberto 2987a6072eroberto if (iter->lifc.lifc_len != 0) 2997a6072eroberto iter->mode = 6; 300118e757roberto return (ISC_R_SUCCESS); 301118e757roberto 302118e757roberto cleanup: 3037a6072eroberto isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 3047a6072eroberto iter->buf6 = NULL; 305118e757roberto return (result); 306118e757roberto} 3077a6072eroberto#endif 308118e757roberto 309118e757robertoisc_result_t 310118e757robertoisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { 311118e757roberto isc_interfaceiter_t *iter; 312118e757roberto isc_result_t result; 313118e757roberto char strbuf[ISC_STRERRORSIZE]; 314118e757roberto 315d54cfbdroberto REQUIRE(mctx != NULL); 316118e757roberto REQUIRE(iterp != NULL); 317118e757roberto REQUIRE(*iterp == NULL); 318118e757roberto 319118e757roberto iter = isc_mem_get(mctx, sizeof(*iter)); 320118e757roberto if (iter == NULL) 321118e757roberto return (ISC_R_NOMEMORY); 322118e757roberto 323118e757roberto iter->mctx = mctx; 3247a6072eroberto iter->mode = 4; 325118e757roberto iter->buf = NULL; 3267a6072eroberto iter->pos = (unsigned int) -1; 3277a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 3287a6072eroberto iter->buf6 = NULL; 3297a6072eroberto iter->pos6 = (unsigned int) -1; 3307a6072eroberto iter->result6 = ISC_R_NOMORE; 3317a6072eroberto iter->socket6 = -1; 3327a6072eroberto iter->first6 = ISC_FALSE; 3337a6072eroberto#endif 334118e757roberto 335118e757roberto /* 3367a6072eroberto * Get the interface configuration, allocating more memory if 3377a6072eroberto * necessary. 338118e757roberto */ 3397a6072eroberto 3407a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 3417a6072eroberto result = isc_net_probeipv6(); 3427a6072eroberto if (result == ISC_R_SUCCESS) { 3437a6072eroberto /* 3447a6072eroberto * Create an unbound datagram socket to do the SIOCGLIFCONF 3457a6072eroberto * ioctl on. HP/UX requires an AF_INET6 socket for 3467a6072eroberto * SIOCGLIFCONF to get IPv6 addresses. 3477a6072eroberto */ 3487a6072eroberto if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 3497a6072eroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 3507a6072eroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 3517a6072eroberto isc_msgcat_get(isc_msgcat, 3527a6072eroberto ISC_MSGSET_IFITERIOCTL, 3537a6072eroberto ISC_MSG_MAKESCANSOCKET, 3547a6072eroberto "making interface " 3557a6072eroberto "scan socket: %s"), 3567a6072eroberto strbuf); 3577a6072eroberto result = ISC_R_UNEXPECTED; 3587a6072eroberto goto socket6_failure; 3597a6072eroberto } 360d54cfbdroberto result = iter->result6 = getbuf6(iter); 361d54cfbdroberto if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS) 3627a6072eroberto goto ioctl6_failure; 3637a6072eroberto } 3647a6072eroberto#endif 365118e757roberto if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 366118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 367118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 368118e757roberto isc_msgcat_get(isc_msgcat, 369118e757roberto ISC_MSGSET_IFITERIOCTL, 370118e757roberto ISC_MSG_MAKESCANSOCKET, 371118e757roberto "making interface " 372118e757roberto "scan socket: %s"), 373118e757roberto strbuf); 374118e757roberto result = ISC_R_UNEXPECTED; 375118e757roberto goto socket_failure; 376118e757roberto } 3777a6072eroberto result = getbuf4(iter); 378118e757roberto if (result != ISC_R_SUCCESS) 379118e757roberto goto ioctl_failure; 380118e757roberto 381118e757roberto /* 382118e757roberto * A newly created iterator has an undefined position 383118e757roberto * until isc_interfaceiter_first() is called. 384118e757roberto */ 385118e757roberto#ifdef HAVE_TRUCLUSTER 386118e757roberto iter->clua_context = -1; 3877a6072eroberto iter->clua_done = ISC_TRUE; 3887a6072eroberto#endif 3897a6072eroberto#ifdef __linux 3907a6072eroberto iter->proc = fopen("/proc/net/if_inet6", "r"); 3917a6072eroberto iter->valid = ISC_R_FAILURE; 392118e757roberto#endif 393118e757roberto iter->result = ISC_R_FAILURE; 394118e757roberto 395118e757roberto iter->magic = IFITER_MAGIC; 396118e757roberto *iterp = iter; 397118e757roberto return (ISC_R_SUCCESS); 398118e757roberto 399118e757roberto ioctl_failure: 400118e757roberto if (iter->buf != NULL) 401118e757roberto isc_mem_put(mctx, iter->buf, iter->bufsize); 402118e757roberto (void) close(iter->socket); 403118e757roberto 404118e757roberto socket_failure: 4057a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 4067a6072eroberto if (iter->buf6 != NULL) 4077a6072eroberto isc_mem_put(mctx, iter->buf6, iter->bufsize6); 4087a6072eroberto ioctl6_failure: 4097a6072eroberto if (iter->socket6 != -1) 4107a6072eroberto (void) close(iter->socket6); 4117a6072eroberto socket6_failure: 4127a6072eroberto#endif 413d54cfbdroberto 414118e757roberto isc_mem_put(mctx, iter, sizeof(*iter)); 415118e757roberto return (result); 416118e757roberto} 417118e757roberto 418118e757roberto#ifdef HAVE_TRUCLUSTER 419118e757robertostatic void 420118e757robertoget_inaddr(isc_netaddr_t *dst, struct in_addr *src) { 421118e757roberto dst->family = AF_INET; 422118e757roberto memcpy(&dst->type.in, src, sizeof(struct in_addr)); 423118e757roberto} 424118e757roberto 425118e757robertostatic isc_result_t 426118e757robertointernal_current_clusteralias(isc_interfaceiter_t *iter) { 427118e757roberto struct clua_info ci; 4287a6072eroberto if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS) 4297a6072eroberto return (ISC_R_IGNORE); 4307a6072eroberto memset(&iter->current, 0, sizeof(iter->current)); 4317a6072eroberto iter->current.af = iter->clua_sa.sa_family; 4327a6072eroberto memset(iter->current.name, 0, sizeof(iter->current.name)); 4337a6072eroberto sprintf(iter->current.name, "clua%d", ci.aliasid); 4347a6072eroberto iter->current.flags = INTERFACE_F_UP; 4357a6072eroberto get_inaddr(&iter->current.address, &ci.addr); 4367a6072eroberto get_inaddr(&iter->current.netmask, &ci.netmask); 4377a6072eroberto return (ISC_R_SUCCESS); 4387a6072eroberto} 4397a6072eroberto#endif 4407a6072eroberto 441118e757roberto/* 442118e757roberto * Get information about the current interface to iter->current. 443118e757roberto * If successful, return ISC_R_SUCCESS. 444118e757roberto * If the interface has an unsupported address family, or if 445118e757roberto * some operation on it fails, return ISC_R_IGNORE to make 446118e757roberto * the higher-level iterator code ignore it. 447118e757roberto */ 448118e757roberto 449118e757robertostatic isc_result_t 450118e757robertointernal_current4(isc_interfaceiter_t *iter) { 451118e757roberto struct ifreq *ifrp; 452118e757roberto struct ifreq ifreq; 453118e757roberto int family; 454118e757roberto char strbuf[ISC_STRERRORSIZE]; 4557a6072eroberto#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) 4567a6072eroberto struct lifreq lifreq; 4577a6072eroberto#else 4587a6072eroberto char sabuf[256]; 4597a6072eroberto#endif 4607a6072eroberto int i, bits, prefixlen; 461118e757roberto 462118e757roberto REQUIRE(VALID_IFITER(iter)); 463118e757roberto 464d54cfbdroberto if (iter->ifc.ifc_len == 0 || 465d54cfbdroberto iter->pos == (unsigned int)iter->ifc.ifc_len) { 4667a6072eroberto#ifdef __linux 467d54cfbdroberto return (linux_if_inet6_current(iter)); 468d54cfbdroberto#else 469d54cfbdroberto return (ISC_R_NOMORE); 4707a6072eroberto#endif 471d54cfbdroberto } 472d54cfbdroberto 473d54cfbdroberto INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len); 4747a6072eroberto 475047f369cy ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos); 476118e757roberto 477118e757roberto memset(&ifreq, 0, sizeof(ifreq)); 478118e757roberto memcpy(&ifreq, ifrp, sizeof(ifreq)); 479118e757roberto 480118e757roberto family = ifreq.ifr_addr.sa_family; 4817a6072eroberto#if defined(ISC_PLATFORM_HAVEIPV6) 482118e757roberto if (family != AF_INET && family != AF_INET6) 483118e757roberto#else 484118e757roberto if (family != AF_INET) 485118e757roberto#endif 486118e757roberto return (ISC_R_IGNORE); 487118e757roberto 488118e757roberto memset(&iter->current, 0, sizeof(iter->current)); 489118e757roberto iter->current.af = family; 490118e757roberto 491118e757roberto INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); 492118e757roberto memset(iter->current.name, 0, sizeof(iter->current.name)); 493118e757roberto memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name)); 494118e757roberto 495118e757roberto get_addr(family, &iter->current.address, 4967a6072eroberto (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name); 497118e757roberto 498118e757roberto /* 499118e757roberto * If the interface does not have a address ignore it. 500118e757roberto */ 501118e757roberto switch (family) { 502118e757roberto case AF_INET: 503118e757roberto if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) 504118e757roberto return (ISC_R_IGNORE); 505118e757roberto break; 506118e757roberto case AF_INET6: 507118e757roberto if (memcmp(&iter->current.address.type.in6, &in6addr_any, 508118e757roberto sizeof(in6addr_any)) == 0) 509118e757roberto return (ISC_R_IGNORE); 510118e757roberto break; 511118e757roberto } 512118e757roberto 513118e757roberto /* 514118e757roberto * Get interface flags. 515118e757roberto */ 516118e757roberto 517118e757roberto iter->current.flags = 0; 518118e757roberto 519118e757roberto /* 520118e757roberto * Ignore the HP/UX warning about "integer overflow during 521118e757roberto * conversion. It comes from its own macro definition, 522118e757roberto * and is really hard to shut up. 523118e757roberto */ 524047f369cy if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { 525118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 526118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 527118e757roberto "%s: getting interface flags: %s", 528118e757roberto ifreq.ifr_name, strbuf); 529118e757roberto return (ISC_R_IGNORE); 530118e757roberto } 531118e757roberto 532118e757roberto if ((ifreq.ifr_flags & IFF_UP) != 0) 533118e757roberto iter->current.flags |= INTERFACE_F_UP; 534118e757roberto 5357a6072eroberto#ifdef IFF_POINTOPOINT 536118e757roberto if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) 537118e757roberto iter->current.flags |= INTERFACE_F_POINTTOPOINT; 5387a6072eroberto#endif 539118e757roberto 540118e757roberto if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) 541118e757roberto iter->current.flags |= INTERFACE_F_LOOPBACK; 542118e757roberto 543d54cfbdroberto if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) 544118e757roberto iter->current.flags |= INTERFACE_F_BROADCAST; 545118e757roberto 546118e757roberto#ifdef IFF_MULTICAST 547d54cfbdroberto if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) 548118e757roberto iter->current.flags |= INTERFACE_F_MULTICAST; 549118e757roberto#endif 550118e757roberto 5517a6072eroberto if (family == AF_INET) 552118e757roberto goto inet; 553118e757roberto 5547a6072eroberto#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) 5557a6072eroberto memset(&lifreq, 0, sizeof(lifreq)); 5567a6072eroberto memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name)); 5577a6072eroberto memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6, 558118e757roberto sizeof(iter->current.address.type.in6)); 559118e757roberto 560047f369cy if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) { 561118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 562118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 563118e757roberto "%s: getting interface address: %s", 564118e757roberto ifreq.ifr_name, strbuf); 565118e757roberto return (ISC_R_IGNORE); 566118e757roberto } 5677a6072eroberto prefixlen = lifreq.lifr_addrlen; 5687a6072eroberto#else 5697a6072eroberto isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf)); 570d54cfbdroberto isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 571d54cfbdroberto ISC_LOGMODULE_INTERFACE, 572d54cfbdroberto ISC_LOG_INFO, 5737a6072eroberto isc_msgcat_get(isc_msgcat, 5747a6072eroberto ISC_MSGSET_IFITERIOCTL, 5757a6072eroberto ISC_MSG_GETIFCONFIG, 5767a6072eroberto "prefix length for %s is unknown " 5777a6072eroberto "(assume 128)"), sabuf); 5787a6072eroberto prefixlen = 128; 5797a6072eroberto#endif 580118e757roberto 581118e757roberto /* 582118e757roberto * Netmask already zeroed. 583118e757roberto */ 584118e757roberto iter->current.netmask.family = family; 585118e757roberto for (i = 0; i < 16; i++) { 5867a6072eroberto if (prefixlen > 8) { 587118e757roberto bits = 0; 5887a6072eroberto prefixlen -= 8; 589118e757roberto } else { 5907a6072eroberto bits = 8 - prefixlen; 5917a6072eroberto prefixlen = 0; 592118e757roberto } 593118e757roberto iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff; 594118e757roberto } 595f63afe2cy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 596f63afe2cy iter->current.ifindex = if_nametoindex(iter->current.name); 597f63afe2cy#endif 598118e757roberto return (ISC_R_SUCCESS); 599118e757roberto 600118e757roberto inet: 601118e757roberto if (family != AF_INET) 602118e757roberto return (ISC_R_IGNORE); 6037a6072eroberto#ifdef IFF_POINTOPOINT 604118e757roberto /* 605118e757roberto * If the interface is point-to-point, get the destination address. 606118e757roberto */ 607118e757roberto if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { 608118e757roberto /* 609118e757roberto * Ignore the HP/UX warning about "integer overflow during 610118e757roberto * conversion. It comes from its own macro definition, 611118e757roberto * and is really hard to shut up. 612118e757roberto */ 613047f369cy if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq) 614118e757roberto < 0) { 615118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 616118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 617118e757roberto isc_msgcat_get(isc_msgcat, 618118e757roberto ISC_MSGSET_IFITERIOCTL, 619118e757roberto ISC_MSG_GETDESTADDR, 620118e757roberto "%s: getting " 621118e757roberto "destination address: %s"), 622118e757roberto ifreq.ifr_name, strbuf); 623118e757roberto return (ISC_R_IGNORE); 624118e757roberto } 625118e757roberto get_addr(family, &iter->current.dstaddress, 6267a6072eroberto (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name); 627118e757roberto } 6287a6072eroberto#endif 629d54cfbdroberto 630118e757roberto if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { 631118e757roberto /* 632118e757roberto * Ignore the HP/UX warning about "integer overflow during 633118e757roberto * conversion. It comes from its own macro definition, 634118e757roberto * and is really hard to shut up. 635118e757roberto */ 636047f369cy if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq) 637118e757roberto < 0) { 638118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 639118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 640118e757roberto isc_msgcat_get(isc_msgcat, 641118e757roberto ISC_MSGSET_IFITERIOCTL, 642d54cfbdroberto ISC_MSG_GETBCSTADDR, 643118e757roberto "%s: getting " 644118e757roberto "broadcast address: %s"), 645118e757roberto ifreq.ifr_name, strbuf); 646118e757roberto return (ISC_R_IGNORE); 647118e757roberto } 648118e757roberto get_addr(family, &iter->current.broadcast, 6497a6072eroberto (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name); 650118e757roberto } 6517a6072eroberto 652118e757roberto /* 653118e757roberto * Get the network mask. 654118e757roberto */ 655118e757roberto memset(&ifreq, 0, sizeof(ifreq)); 656118e757roberto memcpy(&ifreq, ifrp, sizeof(ifreq)); 657118e757roberto /* 658118e757roberto * Ignore the HP/UX warning about "integer overflow during 659118e757roberto * conversion. It comes from its own macro definition, 660118e757roberto * and is really hard to shut up. 661118e757roberto */ 662047f369cy if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) { 663118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 664118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 665118e757roberto isc_msgcat_get(isc_msgcat, 666118e757roberto ISC_MSGSET_IFITERIOCTL, 667118e757roberto ISC_MSG_GETNETMASK, 668118e757roberto "%s: getting netmask: %s"), 669118e757roberto ifreq.ifr_name, strbuf); 670118e757roberto return (ISC_R_IGNORE); 671118e757roberto } 672118e757roberto get_addr(family, &iter->current.netmask, 6737a6072eroberto (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name); 674f63afe2cy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 675f63afe2cy iter->current.ifindex = if_nametoindex(iter->current.name); 676f63afe2cy#endif 677118e757roberto return (ISC_R_SUCCESS); 678118e757roberto} 679118e757roberto 6807a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 681118e757robertostatic isc_result_t 682118e757robertointernal_current6(isc_interfaceiter_t *iter) { 683118e757roberto struct LIFREQ *ifrp; 684118e757roberto struct LIFREQ lifreq; 685118e757roberto int family; 686118e757roberto char strbuf[ISC_STRERRORSIZE]; 6877a6072eroberto int fd; 688118e757roberto 689118e757roberto REQUIRE(VALID_IFITER(iter)); 6907a6072eroberto if (iter->result6 != ISC_R_SUCCESS) 6917a6072eroberto return (iter->result6); 6927a6072eroberto REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); 693118e757roberto 694047f369cy ifrp = (void *)((char *)iter->lifc.lifc_req + iter->pos6); 695118e757roberto 696118e757roberto memset(&lifreq, 0, sizeof(lifreq)); 697118e757roberto memcpy(&lifreq, ifrp, sizeof(lifreq)); 698118e757roberto 699118e757roberto family = lifreq.lifr_addr.ss_family; 700118e757roberto#ifdef ISC_PLATFORM_HAVEIPV6 701118e757roberto if (family != AF_INET && family != AF_INET6) 702118e757roberto#else 703118e757roberto if (family != AF_INET) 704118e757roberto#endif 705118e757roberto return (ISC_R_IGNORE); 706118e757roberto 707118e757roberto memset(&iter->current, 0, sizeof(iter->current)); 708118e757roberto iter->current.af = family; 709118e757roberto 710118e757roberto INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name)); 711118e757roberto memset(iter->current.name, 0, sizeof(iter->current.name)); 712118e757roberto memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name)); 713118e757roberto 714118e757roberto get_addr(family, &iter->current.address, 7157a6072eroberto (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); 716118e757roberto 717d54cfbdroberto if (isc_netaddr_islinklocal(&iter->current.address)) 718d54cfbdroberto isc_netaddr_setzone(&iter->current.address, 719d54cfbdroberto (isc_uint32_t)lifreq.lifr_index); 720d54cfbdroberto 721118e757roberto /* 722118e757roberto * If the interface does not have a address ignore it. 723118e757roberto */ 724118e757roberto switch (family) { 725118e757roberto case AF_INET: 726118e757roberto if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) 727118e757roberto return (ISC_R_IGNORE); 728118e757roberto break; 729118e757roberto case AF_INET6: 730118e757roberto if (memcmp(&iter->current.address.type.in6, &in6addr_any, 731118e757roberto sizeof(in6addr_any)) == 0) 732118e757roberto return (ISC_R_IGNORE); 733118e757roberto break; 734118e757roberto } 735118e757roberto 736118e757roberto /* 737118e757roberto * Get interface flags. 738118e757roberto */ 739118e757roberto 740118e757roberto iter->current.flags = 0; 741118e757roberto 7427a6072eroberto if (family == AF_INET6) 7437a6072eroberto fd = iter->socket6; 7447a6072eroberto else 7457a6072eroberto fd = iter->socket; 7467a6072eroberto 747118e757roberto /* 748118e757roberto * Ignore the HP/UX warning about "integer overflow during 749118e757roberto * conversion. It comes from its own macro definition, 750118e757roberto * and is really hard to shut up. 751118e757roberto */ 752047f369cy if (isc_ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) { 7537a6072eroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 7547a6072eroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 755118e757roberto "%s: getting interface flags: %s", 756118e757roberto lifreq.lifr_name, strbuf); 7577a6072eroberto return (ISC_R_IGNORE); 758118e757roberto } 759118e757roberto 760118e757roberto if ((lifreq.lifr_flags & IFF_UP) != 0) 761118e757roberto iter->current.flags |= INTERFACE_F_UP; 762118e757roberto 7637a6072eroberto#ifdef IFF_POINTOPOINT 764118e757roberto if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0) 765118e757roberto iter->current.flags |= INTERFACE_F_POINTTOPOINT; 7667a6072eroberto#endif 767118e757roberto 768118e757roberto if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0) 769118e757roberto iter->current.flags |= INTERFACE_F_LOOPBACK; 770118e757roberto 7717a6072eroberto if ((lifreq.lifr_flags & IFF_BROADCAST) != 0) { 7727a6072eroberto iter->current.flags |= INTERFACE_F_BROADCAST; 7737a6072eroberto } 774118e757roberto 775118e757roberto#ifdef IFF_MULTICAST 776118e757roberto if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) { 777118e757roberto iter->current.flags |= INTERFACE_F_MULTICAST; 778118e757roberto } 779118e757roberto#endif 780118e757roberto 7817a6072eroberto#ifdef IFF_POINTOPOINT 782118e757roberto /* 783118e757roberto * If the interface is point-to-point, get the destination address. 784118e757roberto */ 785118e757roberto if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { 786118e757roberto /* 787d54cfbdroberto * Ignore the HP/UX warning about "integer overflow during 788118e757roberto * conversion. It comes from its own macro definition, 789118e757roberto * and is really hard to shut up. 790118e757roberto */ 791047f369cy if (isc_ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq) 792118e757roberto < 0) { 793118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 794118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 795118e757roberto isc_msgcat_get(isc_msgcat, 796118e757roberto ISC_MSGSET_IFITERIOCTL, 797118e757roberto ISC_MSG_GETDESTADDR, 798118e757roberto "%s: getting " 799118e757roberto "destination address: %s"), 800118e757roberto lifreq.lifr_name, strbuf); 801118e757roberto return (ISC_R_IGNORE); 802118e757roberto } 803118e757roberto get_addr(family, &iter->current.dstaddress, 8047a6072eroberto (struct sockaddr *)&lifreq.lifr_dstaddr, 8057a6072eroberto lifreq.lifr_name); 806118e757roberto } 8077a6072eroberto#endif 808118e757roberto 8097a6072eroberto#ifdef SIOCGLIFBRDADDR 8107a6072eroberto if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { 811118e757roberto /* 812118e757roberto * Ignore the HP/UX warning about "integer overflow during 813118e757roberto * conversion. It comes from its own macro definition, 814118e757roberto * and is really hard to shut up. 815118e757roberto */ 816047f369cy if (isc_ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq) 817118e757roberto < 0) { 818118e757roberto isc__strerror(errno, strbuf, sizeof(strbuf)); 819118e757roberto UNEXPECTED_ERROR(__FILE__, __LINE__, 820118e757roberto isc_msgcat_get(isc_msgcat, 821118e757roberto ISC_MSGSET_IFITERIOCTL, 822d54cfbdroberto ISC_MSG_GETBCSTADDR, 8237a6072eroberto "%s: getting " 8247a6072eroberto "broadcast address: %s"), 825118e757roberto lifreq.lifr_name, strbuf); 826118e757roberto return (ISC_R_IGNORE); 827118e757roberto } 8287a6072eroberto get_addr(family, &iter->current.broadcast, 8297a6072eroberto (struct sockaddr *)&lifreq.lifr_broadaddr, 8307a6072eroberto lifreq.lifr_name); 8317a6072eroberto } 8327a6072eroberto#endif /* SIOCGLIFBRDADDR */ 8337a6072eroberto 8347a6072eroberto /* 8357a6072eroberto * Get the network mask. Netmask already zeroed. 8367a6072eroberto */ 8377a6072eroberto memset(&lifreq, 0, sizeof(lifreq)); 8387a6072eroberto memcpy(&lifreq, ifrp, sizeof(lifreq)); 8397a6072eroberto 840118e757roberto#ifdef lifr_addrlen 8417a6072eroberto /* 8427a6072eroberto * Special case: if the system provides lifr_addrlen member, the 8437a6072eroberto * netmask of an IPv6 address can be derived from the length, since 8447a6072eroberto * an IPv6 address always has a contiguous mask. 8457a6072eroberto */ 8467a6072eroberto if (family == AF_INET6) { 847118e757roberto int i, bits; 848118e757roberto 849118e757roberto iter->current.netmask.family = family; 850118e757roberto for (i = 0; i < lifreq.lifr_addrlen; i += 8) { 851118e757roberto bits = lifreq.lifr_addrlen - i; 852118e757roberto bits = (bits < 8) ? (8 - bits) : 0; 853118e757roberto iter->current.netmask.type.in6.s6_addr[i / 8] = 854118e757roberto (~0 << bits) & 0xff; 855118e757roberto } 856f63afe2cy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 857f63afe2cy iter->current.ifindex = if_nametoindex(iter->current.name); 858f63afe2cy#endif 8597a6072eroberto return (ISC_R_SUCCESS); 860118e757roberto } 8617a6072eroberto#endif 8627a6072eroberto 8637a6072eroberto /* 8647a6072eroberto * Ignore the HP/UX warning about "integer overflow during 8657a6072eroberto * conversion. It comes from its own macro definition, 8667a6072eroberto * and is really hard to shut up. 8677a6072eroberto */ 868047f369cy if (isc_ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) { 8697a6072eroberto isc__strerror(errno, strbuf, sizeof(strbuf)); 8707a6072eroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 8717a6072eroberto isc_msgcat_get(isc_msgcat, 8727a6072eroberto ISC_MSGSET_IFITERIOCTL, 8737a6072eroberto ISC_MSG_GETNETMASK, 8747a6072eroberto "%s: getting netmask: %s"), 8757a6072eroberto lifreq.lifr_name, strbuf); 8767a6072eroberto return (ISC_R_IGNORE); 877118e757roberto } 8787a6072eroberto get_addr(family, &iter->current.netmask, 8797a6072eroberto (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); 880118e757roberto 881f63afe2cy#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX 882f63afe2cy iter->current.ifindex = if_nametoindex(iter->current.name); 883f63afe2cy#endif 884118e757roberto return (ISC_R_SUCCESS); 885118e757roberto} 8867a6072eroberto#endif 887118e757roberto 888118e757robertostatic isc_result_t 889118e757robertointernal_current(isc_interfaceiter_t *iter) { 8907a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 8917a6072eroberto if (iter->mode == 6) { 8927a6072eroberto iter->result6 = internal_current6(iter); 8937a6072eroberto if (iter->result6 != ISC_R_NOMORE) 8947a6072eroberto return (iter->result6); 8957a6072eroberto } 8967a6072eroberto#endif 8977a6072eroberto#ifdef HAVE_TRUCLUSTER 8987a6072eroberto if (!iter->clua_done) 8997a6072eroberto return(internal_current_clusteralias(iter)); 9007a6072eroberto#endif 901118e757roberto return (internal_current4(iter)); 902118e757roberto} 903118e757roberto 904118e757roberto/* 905118e757roberto * Step the iterator to the next interface. Unlike 906118e757roberto * isc_interfaceiter_next(), this may leave the iterator 907118e757roberto * positioned on an interface that will ultimately 908118e757roberto * be ignored. Return ISC_R_NOMORE if there are no more 909118e757roberto * interfaces, otherwise ISC_R_SUCCESS. 910118e757roberto */ 911118e757robertostatic isc_result_t 912118e757robertointernal_next4(isc_interfaceiter_t *iter) { 913d54cfbdroberto#ifdef ISC_PLATFORM_HAVESALEN 914118e757roberto struct ifreq *ifrp; 915118e757roberto#endif 916118e757roberto 917d54cfbdroberto if (iter->pos < (unsigned int) iter->ifc.ifc_len) { 918118e757roberto#ifdef ISC_PLATFORM_HAVESALEN 919d54cfbdroberto ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); 920d54cfbdroberto 921d54cfbdroberto if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) 922d54cfbdroberto iter->pos += sizeof(ifrp->ifr_name) + 923d54cfbdroberto ifrp->ifr_addr.sa_len; 924d54cfbdroberto else 925118e757roberto#endif 926d54cfbdroberto iter->pos += sizeof(struct ifreq); 927118e757roberto 928d54cfbdroberto } else { 929d54cfbdroberto INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len); 930d54cfbdroberto#ifdef __linux 931d54cfbdroberto return (linux_if_inet6_next(iter)); 932d54cfbdroberto#else 933118e757roberto return (ISC_R_NOMORE); 934d54cfbdroberto#endif 935d54cfbdroberto } 936118e757roberto return (ISC_R_SUCCESS); 937118e757roberto} 938118e757roberto 9397a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 940118e757robertostatic isc_result_t 941118e757robertointernal_next6(isc_interfaceiter_t *iter) { 942d54cfbdroberto#ifdef ISC_PLATFORM_HAVESALEN 943118e757roberto struct LIFREQ *ifrp; 944d54cfbdroberto#endif 945d54cfbdroberto 9467a6072eroberto if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE) 9477a6072eroberto return (iter->result6); 948118e757roberto 9497a6072eroberto REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); 950118e757roberto 951d54cfbdroberto#ifdef ISC_PLATFORM_HAVESALEN 9527a6072eroberto ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6); 953118e757roberto 954118e757roberto if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr)) 9557a6072eroberto iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len; 956118e757roberto else 957118e757roberto#endif 958d54cfbdroberto iter->pos6 += sizeof(struct LIFREQ); 959118e757roberto 9607a6072eroberto if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len) 961118e757roberto return (ISC_R_NOMORE); 962118e757roberto 963118e757roberto return (ISC_R_SUCCESS); 964118e757roberto} 9657a6072eroberto#endif 966118e757roberto 967118e757robertostatic isc_result_t 968118e757robertointernal_next(isc_interfaceiter_t *iter) { 9697a6072eroberto#ifdef HAVE_TRUCLUSTER 9707a6072eroberto int clua_result; 9717a6072eroberto#endif 9727a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 9737a6072eroberto if (iter->mode == 6) { 9747a6072eroberto iter->result6 = internal_next6(iter); 9757a6072eroberto if (iter->result6 != ISC_R_NOMORE) 9767a6072eroberto return (iter->result6); 9777a6072eroberto if (iter->first6) { 9787a6072eroberto iter->first6 = ISC_FALSE; 9797a6072eroberto return (ISC_R_SUCCESS); 9807a6072eroberto } 9817a6072eroberto } 9827a6072eroberto#endif 9837a6072eroberto#ifdef HAVE_TRUCLUSTER 9847a6072eroberto if (!iter->clua_done) { 9857a6072eroberto clua_result = clua_getaliasaddress(&iter->clua_sa, 9867a6072eroberto &iter->clua_context); 9877a6072eroberto if (clua_result != CLUA_SUCCESS) 9887a6072eroberto iter->clua_done = ISC_TRUE; 9897a6072eroberto return (ISC_R_SUCCESS); 9907a6072eroberto } 9917a6072eroberto#endif 992118e757roberto return (internal_next4(iter)); 993118e757roberto} 994118e757roberto 995118e757robertostatic void 996118e757robertointernal_destroy(isc_interfaceiter_t *iter) { 997118e757roberto (void) close(iter->socket); 9987a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 9997a6072eroberto if (iter->socket6 != -1) 10007a6072eroberto (void) close(iter->socket6); 10017a6072eroberto if (iter->buf6 != NULL) { 10027a6072eroberto isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); 10037a6072eroberto } 10047a6072eroberto#endif 10057a6072eroberto#ifdef __linux 10067a6072eroberto if (iter->proc != NULL) 10077a6072eroberto fclose(iter->proc); 10087a6072eroberto#endif 10097a6072eroberto} 10107a6072eroberto 10117a6072erobertostatic 10127a6072erobertovoid internal_first(isc_interfaceiter_t *iter) { 10137a6072eroberto#ifdef HAVE_TRUCLUSTER 10147a6072eroberto int clua_result; 10157a6072eroberto#endif 10167a6072eroberto iter->pos = 0; 10177a6072eroberto#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) 10187a6072eroberto iter->pos6 = 0; 10197a6072eroberto if (iter->result6 == ISC_R_NOMORE) 10207a6072eroberto iter->result6 = ISC_R_SUCCESS; 10217a6072eroberto iter->first6 = ISC_TRUE; 10227a6072eroberto#endif 10237a6072eroberto#ifdef HAVE_TRUCLUSTER 10247a6072eroberto iter->clua_context = 0; 10257a6072eroberto clua_result = clua_getaliasaddress(&iter->clua_sa, 10267a6072eroberto &iter->clua_context); 10277a6072eroberto iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS); 10287a6072eroberto#endif 10297a6072eroberto#ifdef __linux 10307a6072eroberto linux_if_inet6_first(iter); 10317a6072eroberto#endif 1032118e757roberto} 1033