ifiter_ioctl.c revision 91cd0f93ad34d23e8b09dca337120f64fbe8f0a1
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Copyright (C) 1999-2001 Internet Software Consortium.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Permission to use, copy, modify, and distribute this software for any
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * purpose with or without fee is hereby granted, provided that the above
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * copyright notice and this permission notice appear in all copies.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/* $Id: ifiter_ioctl.c,v 1.25 2001/11/27 01:56:14 gson Exp $ */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * See netintro(4).
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews SIOCGLIFCONF data */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_interface_t current; /* Current interface data. */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * will have more than a megabyte of interface configuration data.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Ignore the HP/UX warning about "interger overflow during
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * conversion". It comes from its own macro definition,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * and is really hard to shut up.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "get interface "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "configuration: %s"),
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * EINVAL. Retry with a bigger buffer.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * The ioctl succeeded.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Some OS's just return what will fit rather
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * than set EINVAL if the buffer is too small
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * to fit all the interfaces in. If
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * ifc.lifc_len is too near to the end of the
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * buffer we will grow it just in case and
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "get interface "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "configuration: "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "maximum buffer "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "size exceeded"));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
611a37e72daff14666f7dcc781674775e0c8e5eaMark Andrews isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(&iter->lifc.lifc_len, 0, sizeof(iter->lifc.lifc_len));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Ignore the HP/UX warning about "interger overflow during
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * conversion". It comes from its own macro definition,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * and is really hard to shut up.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->lifc)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "get interface "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "configuration: %s"),
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * EINVAL. Retry with a bigger buffer.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * The ioctl succeeded.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Some OS's just return what will fit rather
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * than set EINVAL if the buffer is too small
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * to fit all the interfaces in. If
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * ifc.ifc_len is too near to the end of the
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * buffer we will grow it just in case and
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "get interface "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "configuration: "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "maximum buffer "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "size exceeded"));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "making interface "
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "scan socket: %s"),
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Get the interface configuration, allocating more memory if
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * necessary.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * A newly created iterator has an undefined position
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * until isc_interfaceiter_first() is called.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Get information about the current interface to iter->current.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * If successful, return ISC_R_SUCCESS.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * If the interface has an unsupported address family, or if
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * some operation on it fails, return ISC_R_IGNORE to make
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * the higher-level iterator code ignore it.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(&iter->current, 0, sizeof(iter->current));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memset(iter->current.name, 0, sizeof(iter->current.name));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Get interface flags.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Ignore the HP/UX warning about "interger overflow during
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * conversion. It comes from its own macro definition,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * and is really hard to shut up.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "%s: getting interface flags: %s",
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews iter->current.flags |= INTERFACE_F_POINTTOPOINT;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * If the interface is point-to-point, get the destination address.
return (ISC_R_IGNORE);
switch (family) {
case AF_INET:
return (ISC_R_IGNORE);
case AF_INET6:
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
int family;
#ifdef ISC_PLATFORM_HAVEIPV6
return (ISC_R_IGNORE);
return (ISC_R_IGNORE);
return (ISC_R_IGNORE);
switch (family) {
case AF_INET:
return (ISC_R_IGNORE);
case AF_INET6: {
#ifdef lifr_addrlen
int i, bits;
return (ISC_R_SUCCESS);
static isc_result_t
static isc_result_t
#ifdef ISC_PLATFORM_HAVESALEN
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
#ifdef ISC_PLATFORM_HAVESALEN
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
static isc_result_t