summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/isc/unix/ifiter_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/isc/unix/ifiter_ioctl.c')
-rw-r--r--contrib/bind9/lib/isc/unix/ifiter_ioctl.c1029
1 files changed, 0 insertions, 1029 deletions
diff --git a/contrib/bind9/lib/isc/unix/ifiter_ioctl.c b/contrib/bind9/lib/isc/unix/ifiter_ioctl.c
deleted file mode 100644
index ce63de7..0000000
--- a/contrib/bind9/lib/isc/unix/ifiter_ioctl.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 1999-2003 Internet Software Consortium.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* $Id: ifiter_ioctl.c,v 1.44.18.13 2007/08/31 23:46:25 tbox Exp $ */
-
-/*! \file
- * \brief
- * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
- * See netintro(4).
- */
-
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
-#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
-#define lifc_len iflc_len
-#define lifc_buf iflc_buf
-#define lifc_req iflc_req
-#define LIFCONF if_laddrconf
-#else
-#define ISC_HAVE_LIFC_FAMILY 1
-#define ISC_HAVE_LIFC_FLAGS 1
-#define LIFCONF lifconf
-#endif
-
-#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
-#define lifr_addr iflr_addr
-#define lifr_name iflr_name
-#define lifr_dstaddr iflr_dstaddr
-#define lifr_flags iflr_flags
-#define ss_family sa_family
-#define LIFREQ if_laddrreq
-#else
-#define LIFREQ lifreq
-#endif
-#endif
-
-#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
-#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
-
-#define ISC_IF_INET6_SZ \
- sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
-
-struct isc_interfaceiter {
- unsigned int magic; /* Magic number. */
- isc_mem_t *mctx;
- int mode;
- int socket;
- struct ifconf ifc;
- void *buf; /* Buffer for sysctl data. */
- unsigned int bufsize; /* Bytes allocated. */
- unsigned int pos; /* Current offset in
- SIOCGIFCONF data */
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- int socket6;
- struct LIFCONF lifc;
- void *buf6; /* Buffer for sysctl data. */
- unsigned int bufsize6; /* Bytes allocated. */
- unsigned int pos6; /* Current offset in
- SIOCGLIFCONF data */
- isc_result_t result6; /* Last result code. */
- isc_boolean_t first6;
-#endif
-#ifdef HAVE_TRUCLUSTER
- int clua_context; /* Cluster alias context */
- isc_boolean_t clua_done;
- struct sockaddr clua_sa;
-#endif
-#ifdef __linux
- FILE * proc;
- char entry[ISC_IF_INET6_SZ];
- isc_result_t valid;
- isc_boolean_t first;
-#endif
- isc_interface_t current; /* Current interface data. */
- isc_result_t result; /* Last result code. */
-};
-
-#ifdef HAVE_TRUCLUSTER
-#include <clua/clua.h>
-#include <sys/socket.h>
-#endif
-
-
-/*%
- * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
- * will have more than a megabyte of interface configuration data.
- */
-#define IFCONF_BUFSIZE_INITIAL 4096
-#define IFCONF_BUFSIZE_MAX 1048576
-
-#ifdef __linux
-#ifndef IF_NAMESIZE
-# ifdef IFNAMSIZ
-# define IF_NAMESIZE IFNAMSIZ
-# else
-# define IF_NAMESIZE 16
-# endif
-#endif
-#endif
-
-static isc_result_t
-getbuf4(isc_interfaceiter_t *iter) {
- char strbuf[ISC_STRERRORSIZE];
-
- iter->bufsize = IFCONF_BUFSIZE_INITIAL;
-
- for (;;) {
- iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
- if (iter->buf == NULL)
- return (ISC_R_NOMEMORY);
-
- memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
- iter->ifc.ifc_len = iter->bufsize;
- iter->ifc.ifc_buf = iter->buf;
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion". It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
- == -1) {
- if (errno != EINVAL) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETIFCONFIG,
- "get interface "
- "configuration: %s"),
- strbuf);
- goto unexpected;
- }
- /*
- * EINVAL. Retry with a bigger buffer.
- */
- } else {
- /*
- * The ioctl succeeded.
- * Some OS's just return what will fit rather
- * than set EINVAL if the buffer is too small
- * to fit all the interfaces in. If
- * ifc.lifc_len is too near to the end of the
- * buffer we will grow it just in case and
- * retry.
- */
- if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
- < iter->bufsize)
- break;
- }
- if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_BUFFERMAX,
- "get interface "
- "configuration: "
- "maximum buffer "
- "size exceeded"));
- goto unexpected;
- }
- isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
-
- iter->bufsize *= 2;
- }
- return (ISC_R_SUCCESS);
-
- unexpected:
- isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
- iter->buf = NULL;
- return (ISC_R_UNEXPECTED);
-}
-
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
-static isc_result_t
-getbuf6(isc_interfaceiter_t *iter) {
- char strbuf[ISC_STRERRORSIZE];
- isc_result_t result;
-
- iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
-
- for (;;) {
- iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
- if (iter->buf6 == NULL)
- return (ISC_R_NOMEMORY);
-
- memset(&iter->lifc, 0, sizeof(iter->lifc));
-#ifdef ISC_HAVE_LIFC_FAMILY
- iter->lifc.lifc_family = AF_INET6;
-#endif
-#ifdef ISC_HAVE_LIFC_FLAGS
- iter->lifc.lifc_flags = 0;
-#endif
- iter->lifc.lifc_len = iter->bufsize6;
- iter->lifc.lifc_buf = iter->buf6;
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion". It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
- == -1) {
-#ifdef __hpux
- /*
- * IPv6 interface scanning is not available on all
- * kernels w/ IPv6 sockets.
- */
- if (errno == ENOENT) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_INTERFACE,
- ISC_LOG_DEBUG(1),
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETIFCONFIG,
- "get interface "
- "configuration: %s"),
- strbuf);
- result = ISC_R_FAILURE;
- goto cleanup;
- }
-#endif
- if (errno != EINVAL) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETIFCONFIG,
- "get interface "
- "configuration: %s"),
- strbuf);
- result = ISC_R_UNEXPECTED;
- goto cleanup;
- }
- /*
- * EINVAL. Retry with a bigger buffer.
- */
- } else {
- /*
- * The ioctl succeeded.
- * Some OS's just return what will fit rather
- * than set EINVAL if the buffer is too small
- * to fit all the interfaces in. If
- * ifc.ifc_len is too near to the end of the
- * buffer we will grow it just in case and
- * retry.
- */
- if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
- < iter->bufsize6)
- break;
- }
- if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_BUFFERMAX,
- "get interface "
- "configuration: "
- "maximum buffer "
- "size exceeded"));
- result = ISC_R_UNEXPECTED;
- goto cleanup;
- }
- isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
-
- iter->bufsize6 *= 2;
- }
-
- if (iter->lifc.lifc_len != 0)
- iter->mode = 6;
- return (ISC_R_SUCCESS);
-
- cleanup:
- isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
- iter->buf6 = NULL;
- return (result);
-}
-#endif
-
-isc_result_t
-isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
- isc_interfaceiter_t *iter;
- isc_result_t result;
- char strbuf[ISC_STRERRORSIZE];
-
- REQUIRE(mctx != NULL);
- REQUIRE(iterp != NULL);
- REQUIRE(*iterp == NULL);
-
- iter = isc_mem_get(mctx, sizeof(*iter));
- if (iter == NULL)
- return (ISC_R_NOMEMORY);
-
- iter->mctx = mctx;
- iter->mode = 4;
- iter->buf = NULL;
- iter->pos = (unsigned int) -1;
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- iter->buf6 = NULL;
- iter->pos6 = (unsigned int) -1;
- iter->result6 = ISC_R_NOMORE;
- iter->socket6 = -1;
- iter->first6 = ISC_FALSE;
-#endif
-
- /*
- * Get the interface configuration, allocating more memory if
- * necessary.
- */
-
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- result = isc_net_probeipv6();
- if (result == ISC_R_SUCCESS) {
- /*
- * Create an unbound datagram socket to do the SIOCGLIFCONF
- * ioctl on. HP/UX requires an AF_INET6 socket for
- * SIOCGLIFCONF to get IPv6 addresses.
- */
- if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_MAKESCANSOCKET,
- "making interface "
- "scan socket: %s"),
- strbuf);
- result = ISC_R_UNEXPECTED;
- goto socket6_failure;
- }
- result = iter->result6 = getbuf6(iter);
- if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
- goto ioctl6_failure;
- }
-#endif
- if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_MAKESCANSOCKET,
- "making interface "
- "scan socket: %s"),
- strbuf);
- result = ISC_R_UNEXPECTED;
- goto socket_failure;
- }
- result = getbuf4(iter);
- if (result != ISC_R_SUCCESS)
- goto ioctl_failure;
-
- /*
- * A newly created iterator has an undefined position
- * until isc_interfaceiter_first() is called.
- */
-#ifdef HAVE_TRUCLUSTER
- iter->clua_context = -1;
- iter->clua_done = ISC_TRUE;
-#endif
-#ifdef __linux
- iter->proc = fopen("/proc/net/if_inet6", "r");
- iter->valid = ISC_R_FAILURE;
- iter->first = ISC_FALSE;
-#endif
- iter->result = ISC_R_FAILURE;
-
- iter->magic = IFITER_MAGIC;
- *iterp = iter;
- return (ISC_R_SUCCESS);
-
- ioctl_failure:
- if (iter->buf != NULL)
- isc_mem_put(mctx, iter->buf, iter->bufsize);
- (void) close(iter->socket);
-
- socket_failure:
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- if (iter->buf6 != NULL)
- isc_mem_put(mctx, iter->buf6, iter->bufsize6);
- ioctl6_failure:
- if (iter->socket6 != -1)
- (void) close(iter->socket6);
- socket6_failure:
-#endif
-
- isc_mem_put(mctx, iter, sizeof(*iter));
- return (result);
-}
-
-#ifdef HAVE_TRUCLUSTER
-static void
-get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
- dst->family = AF_INET;
- memcpy(&dst->type.in, src, sizeof(struct in_addr));
-}
-
-static isc_result_t
-internal_current_clusteralias(isc_interfaceiter_t *iter) {
- struct clua_info ci;
- if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
- return (ISC_R_IGNORE);
- memset(&iter->current, 0, sizeof(iter->current));
- iter->current.af = iter->clua_sa.sa_family;
- memset(iter->current.name, 0, sizeof(iter->current.name));
- sprintf(iter->current.name, "clua%d", ci.aliasid);
- iter->current.flags = INTERFACE_F_UP;
- get_inaddr(&iter->current.address, &ci.addr);
- get_inaddr(&iter->current.netmask, &ci.netmask);
- return (ISC_R_SUCCESS);
-}
-#endif
-
-#ifdef __linux
-static isc_result_t
-linux_if_inet6_next(isc_interfaceiter_t *iter) {
- if (iter->proc != NULL &&
- fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
- iter->valid = ISC_R_SUCCESS;
- else
- iter->valid = ISC_R_NOMORE;
- return (iter->valid);
-}
-
-static void
-linux_if_inet6_first(isc_interfaceiter_t *iter) {
- if (iter->proc != NULL) {
- rewind(iter->proc);
- (void)linux_if_inet6_next(iter);
- } else
- iter->valid = ISC_R_NOMORE;
- iter->first = ISC_FALSE;
-}
-
-static isc_result_t
-linux_if_inet6_current(isc_interfaceiter_t *iter) {
- char address[33];
- char name[IF_NAMESIZE+1];
- struct in6_addr addr6;
- int ifindex, prefix, flag3, flag4;
- int res;
- unsigned int i;
-
- if (iter->valid != ISC_R_SUCCESS)
- return (iter->valid);
- if (iter->proc == NULL) {
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
- "/proc/net/if_inet6:iter->proc == NULL");
- return (ISC_R_FAILURE);
- }
-
- res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
- address, &ifindex, &prefix, &flag3, &flag4, name);
- if (res != 6) {
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
- "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
- res);
- return (ISC_R_FAILURE);
- }
- if (strlen(address) != 32) {
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
- "/proc/net/if_inet6:strlen(%s) != 32", address);
- return (ISC_R_FAILURE);
- }
- for (i = 0; i < 16; i++) {
- unsigned char byte;
- static const char hex[] = "0123456789abcdef";
- byte = ((index(hex, address[i * 2]) - hex) << 4) |
- (index(hex, address[i * 2 + 1]) - hex);
- addr6.s6_addr[i] = byte;
- }
- iter->current.af = AF_INET6;
- iter->current.flags = INTERFACE_F_UP;
- isc_netaddr_fromin6(&iter->current.address, &addr6);
- if (isc_netaddr_islinklocal(&iter->current.address)) {
- isc_netaddr_setzone(&iter->current.address,
- (isc_uint32_t)ifindex);
- }
- for (i = 0; i < 16; i++) {
- if (prefix > 8) {
- addr6.s6_addr[i] = 0xff;
- prefix -= 8;
- } else {
- addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
- prefix = 0;
- }
- }
- isc_netaddr_fromin6(&iter->current.netmask, &addr6);
- strncpy(iter->current.name, name, sizeof(iter->current.name));
- return (ISC_R_SUCCESS);
-}
-#endif
-
-/*
- * Get information about the current interface to iter->current.
- * If successful, return ISC_R_SUCCESS.
- * If the interface has an unsupported address family, or if
- * some operation on it fails, return ISC_R_IGNORE to make
- * the higher-level iterator code ignore it.
- */
-
-static isc_result_t
-internal_current4(isc_interfaceiter_t *iter) {
- struct ifreq *ifrp;
- struct ifreq ifreq;
- int family;
- char strbuf[ISC_STRERRORSIZE];
-#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
- struct lifreq lifreq;
-#else
- char sabuf[256];
-#endif
- int i, bits, prefixlen;
-#ifdef __linux
- isc_result_t result;
-#endif
-
- REQUIRE(VALID_IFITER(iter));
- REQUIRE(iter->ifc.ifc_len == 0 ||
- iter->pos < (unsigned int) iter->ifc.ifc_len);
-
-#ifdef __linux
- result = linux_if_inet6_current(iter);
- if (result != ISC_R_NOMORE)
- return (result);
- iter->first = ISC_TRUE;
-#endif
-
- if (iter->ifc.ifc_len == 0)
- return (ISC_R_NOMORE);
-
- ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
-
- memset(&ifreq, 0, sizeof(ifreq));
- memcpy(&ifreq, ifrp, sizeof(ifreq));
-
- family = ifreq.ifr_addr.sa_family;
-#if defined(ISC_PLATFORM_HAVEIPV6)
- if (family != AF_INET && family != AF_INET6)
-#else
- if (family != AF_INET)
-#endif
- return (ISC_R_IGNORE);
-
- memset(&iter->current, 0, sizeof(iter->current));
- iter->current.af = family;
-
- INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
- memset(iter->current.name, 0, sizeof(iter->current.name));
- memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
-
- get_addr(family, &iter->current.address,
- (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
-
- /*
- * If the interface does not have a address ignore it.
- */
- switch (family) {
- case AF_INET:
- if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
- return (ISC_R_IGNORE);
- break;
- case AF_INET6:
- if (memcmp(&iter->current.address.type.in6, &in6addr_any,
- sizeof(in6addr_any)) == 0)
- return (ISC_R_IGNORE);
- break;
- }
-
- /*
- * Get interface flags.
- */
-
- iter->current.flags = 0;
-
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion. It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "%s: getting interface flags: %s",
- ifreq.ifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
-
- if ((ifreq.ifr_flags & IFF_UP) != 0)
- iter->current.flags |= INTERFACE_F_UP;
-
-#ifdef IFF_POINTOPOINT
- if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
- iter->current.flags |= INTERFACE_F_POINTTOPOINT;
-#endif
-
- if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
- iter->current.flags |= INTERFACE_F_LOOPBACK;
-
- if (family == AF_INET)
- goto inet;
-
-#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
- memset(&lifreq, 0, sizeof(lifreq));
- memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
- memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
- sizeof(iter->current.address.type.in6));
-
- if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "%s: getting interface address: %s",
- ifreq.ifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
- prefixlen = lifreq.lifr_addrlen;
-#else
- isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_INTERFACE,
- ISC_LOG_INFO,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETIFCONFIG,
- "prefix length for %s is unknown "
- "(assume 128)"), sabuf);
- prefixlen = 128;
-#endif
-
- /*
- * Netmask already zeroed.
- */
- iter->current.netmask.family = family;
- for (i = 0; i < 16; i++) {
- if (prefixlen > 8) {
- bits = 0;
- prefixlen -= 8;
- } else {
- bits = 8 - prefixlen;
- prefixlen = 0;
- }
- iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
- }
- return (ISC_R_SUCCESS);
-
- inet:
- if (family != AF_INET)
- return (ISC_R_IGNORE);
-#ifdef IFF_POINTOPOINT
- /*
- * If the interface is point-to-point, get the destination address.
- */
- if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion. It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
- < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETDESTADDR,
- "%s: getting "
- "destination address: %s"),
- ifreq.ifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
- get_addr(family, &iter->current.dstaddress,
- (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
- }
-#endif
-
- /*
- * Get the network mask.
- */
- memset(&ifreq, 0, sizeof(ifreq));
- memcpy(&ifreq, ifrp, sizeof(ifreq));
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion. It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETNETMASK,
- "%s: getting netmask: %s"),
- ifreq.ifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
- get_addr(family, &iter->current.netmask,
- (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
- return (ISC_R_SUCCESS);
-}
-
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
-static isc_result_t
-internal_current6(isc_interfaceiter_t *iter) {
- struct LIFREQ *ifrp;
- struct LIFREQ lifreq;
- int family;
- char strbuf[ISC_STRERRORSIZE];
- int fd;
-
- REQUIRE(VALID_IFITER(iter));
- if (iter->result6 != ISC_R_SUCCESS)
- return (iter->result6);
- REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
-
- ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
-
- memset(&lifreq, 0, sizeof(lifreq));
- memcpy(&lifreq, ifrp, sizeof(lifreq));
-
- family = lifreq.lifr_addr.ss_family;
-#ifdef ISC_PLATFORM_HAVEIPV6
- if (family != AF_INET && family != AF_INET6)
-#else
- if (family != AF_INET)
-#endif
- return (ISC_R_IGNORE);
-
- memset(&iter->current, 0, sizeof(iter->current));
- iter->current.af = family;
-
- INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
- memset(iter->current.name, 0, sizeof(iter->current.name));
- memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
-
- get_addr(family, &iter->current.address,
- (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
-
- /*
- * If the interface does not have a address ignore it.
- */
- switch (family) {
- case AF_INET:
- if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
- return (ISC_R_IGNORE);
- break;
- case AF_INET6:
- if (memcmp(&iter->current.address.type.in6, &in6addr_any,
- sizeof(in6addr_any)) == 0)
- return (ISC_R_IGNORE);
- break;
- }
-
- /*
- * Get interface flags.
- */
-
- iter->current.flags = 0;
-
- if (family == AF_INET6)
- fd = iter->socket6;
- else
- fd = iter->socket;
-
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion. It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "%s: getting interface flags: %s",
- lifreq.lifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
-
- if ((lifreq.lifr_flags & IFF_UP) != 0)
- iter->current.flags |= INTERFACE_F_UP;
-
-#ifdef IFF_POINTOPOINT
- if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
- iter->current.flags |= INTERFACE_F_POINTTOPOINT;
-#endif
-
- if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
- iter->current.flags |= INTERFACE_F_LOOPBACK;
-
-#ifdef IFF_POINTOPOINT
- /*
- * If the interface is point-to-point, get the destination address.
- */
- if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion. It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
- < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETDESTADDR,
- "%s: getting "
- "destination address: %s"),
- lifreq.lifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
- get_addr(family, &iter->current.dstaddress,
- (struct sockaddr *)&lifreq.lifr_dstaddr,
- lifreq.lifr_name);
- }
-#endif
-
- /*
- * Get the network mask. Netmask already zeroed.
- */
- memset(&lifreq, 0, sizeof(lifreq));
- memcpy(&lifreq, ifrp, sizeof(lifreq));
-
-#ifdef lifr_addrlen
- /*
- * Special case: if the system provides lifr_addrlen member, the
- * netmask of an IPv6 address can be derived from the length, since
- * an IPv6 address always has a contiguous mask.
- */
- if (family == AF_INET6) {
- int i, bits;
-
- iter->current.netmask.family = family;
- for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
- bits = lifreq.lifr_addrlen - i;
- bits = (bits < 8) ? (8 - bits) : 0;
- iter->current.netmask.type.in6.s6_addr[i / 8] =
- (~0 << bits) & 0xff;
- }
-
- return (ISC_R_SUCCESS);
- }
-#endif
-
- /*
- * Ignore the HP/UX warning about "interger overflow during
- * conversion. It comes from its own macro definition,
- * and is really hard to shut up.
- */
- if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERIOCTL,
- ISC_MSG_GETNETMASK,
- "%s: getting netmask: %s"),
- lifreq.lifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
- get_addr(family, &iter->current.netmask,
- (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
-
- return (ISC_R_SUCCESS);
-}
-#endif
-
-static isc_result_t
-internal_current(isc_interfaceiter_t *iter) {
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- if (iter->mode == 6) {
- iter->result6 = internal_current6(iter);
- if (iter->result6 != ISC_R_NOMORE)
- return (iter->result6);
- }
-#endif
-#ifdef HAVE_TRUCLUSTER
- if (!iter->clua_done)
- return(internal_current_clusteralias(iter));
-#endif
- return (internal_current4(iter));
-}
-
-/*
- * Step the iterator to the next interface. Unlike
- * isc_interfaceiter_next(), this may leave the iterator
- * positioned on an interface that will ultimately
- * be ignored. Return ISC_R_NOMORE if there are no more
- * interfaces, otherwise ISC_R_SUCCESS.
- */
-static isc_result_t
-internal_next4(isc_interfaceiter_t *iter) {
-#ifdef ISC_PLATFORM_HAVESALEN
- struct ifreq *ifrp;
-#endif
-
- REQUIRE(iter->ifc.ifc_len == 0 ||
- iter->pos < (unsigned int) iter->ifc.ifc_len);
-
-#ifdef __linux
- if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
- return (ISC_R_SUCCESS);
- if (!iter->first)
- return (ISC_R_SUCCESS);
-#endif
-
- if (iter->ifc.ifc_len == 0)
- return (ISC_R_NOMORE);
-
-#ifdef ISC_PLATFORM_HAVESALEN
- ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
-
- if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
- iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
- else
-#endif
- iter->pos += sizeof(struct ifreq);
-
- if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
- return (ISC_R_NOMORE);
-
- return (ISC_R_SUCCESS);
-}
-
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
-static isc_result_t
-internal_next6(isc_interfaceiter_t *iter) {
-#ifdef ISC_PLATFORM_HAVESALEN
- struct LIFREQ *ifrp;
-#endif
-
- if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
- return (iter->result6);
-
- REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
-
-#ifdef ISC_PLATFORM_HAVESALEN
- ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
-
- if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
- iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
- else
-#endif
- iter->pos6 += sizeof(struct LIFREQ);
-
- if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
- return (ISC_R_NOMORE);
-
- return (ISC_R_SUCCESS);
-}
-#endif
-
-static isc_result_t
-internal_next(isc_interfaceiter_t *iter) {
-#ifdef HAVE_TRUCLUSTER
- int clua_result;
-#endif
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- if (iter->mode == 6) {
- iter->result6 = internal_next6(iter);
- if (iter->result6 != ISC_R_NOMORE)
- return (iter->result6);
- if (iter->first6) {
- iter->first6 = ISC_FALSE;
- return (ISC_R_SUCCESS);
- }
- }
-#endif
-#ifdef HAVE_TRUCLUSTER
- if (!iter->clua_done) {
- clua_result = clua_getaliasaddress(&iter->clua_sa,
- &iter->clua_context);
- if (clua_result != CLUA_SUCCESS)
- iter->clua_done = ISC_TRUE;
- return (ISC_R_SUCCESS);
- }
-#endif
- return (internal_next4(iter));
-}
-
-static void
-internal_destroy(isc_interfaceiter_t *iter) {
- (void) close(iter->socket);
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- if (iter->socket6 != -1)
- (void) close(iter->socket6);
- if (iter->buf6 != NULL) {
- isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
- }
-#endif
-#ifdef __linux
- if (iter->proc != NULL)
- fclose(iter->proc);
-#endif
-}
-
-static
-void internal_first(isc_interfaceiter_t *iter) {
-#ifdef HAVE_TRUCLUSTER
- int clua_result;
-#endif
- iter->pos = 0;
-#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
- iter->pos6 = 0;
- if (iter->result6 == ISC_R_NOMORE)
- iter->result6 = ISC_R_SUCCESS;
- iter->first6 = ISC_TRUE;
-#endif
-#ifdef HAVE_TRUCLUSTER
- iter->clua_context = 0;
- clua_result = clua_getaliasaddress(&iter->clua_sa,
- &iter->clua_context);
- iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
-#endif
-#ifdef __linux
- linux_if_inet6_first(iter);
-#endif
-}
OpenPOWER on IntegriCloud