ifiter_ioctl.c revision b0196673ab41b4f17e1c45fba160f3ea2623a06f
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson/*
573d78f3d53859bc01ce5d5cebbaac9b8b90bfbaTinderbox User * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1999-2003 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * Permission to use, copy, modify, and distribute this software for any
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
313b4dc3b2e2be29994ce030c42c39c9eef9c46bAutomatic Updater/* $Id: ifiter_ioctl.c,v 1.49 2004/06/22 05:25:49 marka Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * See netintro(4).
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
364a82f7c25b62967678027043425201a5e5171aBob Halley#define lifc_len iflc_len
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define lifc_buf iflc_buf
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define lifc_req iflc_req
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#define LIFCONF if_laddrconf
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#else
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt#define ISC_HAVE_LIFC_FAMILY 1
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#define ISC_HAVE_LIFC_FLAGS 1
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#define LIFCONF lifconf
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#endif
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define lifr_addr iflr_addr
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define lifr_name iflr_name
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define lifr_dstaddr iflr_dstaddr
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define lifr_flags iflr_flags
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#define ss_family sa_family
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define LIFREQ if_laddrreq
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#else
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#define LIFREQ lifreq
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#endif
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#endif
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#define ISC_IF_INET6_SZ \
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntstruct isc_interfaceiter {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson unsigned int magic; /* Magic number. */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_mem_t *mctx;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews int mode;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews int socket;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews struct ifconf ifc;
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews void *buf; /* Buffer for sysctl data. */
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews unsigned int bufsize; /* Bytes allocated. */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt unsigned int pos; /* Current offset in
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews SIOCGIFCONF data */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt int socket6;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt struct LIFCONF lifc;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt void *buf6; /* Buffer for sysctl data. */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews unsigned int bufsize6; /* Bytes allocated. */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson unsigned int pos6; /* Current offset in
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson SIOCGLIFCONF data */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_result_t result6; /* Last result code. */
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews isc_boolean_t first6;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence#endif
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#ifdef HAVE_TRUCLUSTER
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence int clua_context; /* Cluster alias context */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence isc_boolean_t clua_done;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence struct sockaddr clua_sa;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence#endif
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#ifdef __linux
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson FILE * proc;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson char entry[ISC_IF_INET6_SZ];
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_result_t valid;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_boolean_t first;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#endif
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_interface_t current; /* Current interface data. */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_result_t result; /* Last result code. */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson};
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#ifdef HAVE_TRUCLUSTER
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <clua/clua.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <sys/socket.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#endif
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * will have more than a megabyte of interface configuration data.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#define IFCONF_BUFSIZE_INITIAL 4096
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#define IFCONF_BUFSIZE_MAX 1048576
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#ifdef __linux
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#ifndef IF_NAMESIZE
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson# ifdef IFNAMSIZ
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt# define IF_NAMESIZE IFNAMSIZ
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt# else
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson# define IF_NAMESIZE 16
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson# endif
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt#endif
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt#endif
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updaterstatic isc_result_t
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Huntgetbuf4(isc_interfaceiter_t *iter) {
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater char strbuf[ISC_STRERRORSIZE];
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson iter->bufsize = IFCONF_BUFSIZE_INITIAL;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson for (;;) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (iter->buf == NULL)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_R_NOMEMORY);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson iter->ifc.ifc_len = iter->bufsize;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson iter->ifc.ifc_buf = iter->buf;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson /*
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson * Ignore the HP/UX warning about "interger overflow during
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * conversion". It comes from its own macro definition,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * and is really hard to shut up.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson == -1) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson if (errno != EINVAL) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc__strerror(errno, strbuf, sizeof(strbuf));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson UNEXPECTED_ERROR(__FILE__, __LINE__,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_msgcat_get(isc_msgcat,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSGSET_IFITERIOCTL,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSG_GETIFCONFIG,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "get interface "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "configuration: %s"),
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt strbuf);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt goto unexpected;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * EINVAL. Retry with a bigger buffer.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews } else {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * The ioctl succeeded.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Some OS's just return what will fit rather
e80f661db8ec9596eb977d6fc537484aa3662e22Evan Hunt * than set EINVAL if the buffer is too small
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * to fit all the interfaces in. If
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * ifc.lifc_len is too near to the end of the
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * buffer we will grow it just in case and
e80f661db8ec9596eb977d6fc537484aa3662e22Evan Hunt * retry.
106360491ad40eef9669fd792c35710d6af1dab0Evan Hunt */
cdbb3d27740fd052f18067b937097ebf35df356bAutomatic Updater if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
28ad0be64ee756013c0f6a474fc447ee613ee0d1Evan Hunt < iter->bufsize)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt break;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt UNEXPECTED_ERROR(__FILE__, __LINE__,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_msgcat_get(isc_msgcat,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSGSET_IFITERIOCTL,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSG_BUFFERMAX,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "get interface "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "configuration: "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "maximum buffer "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "size exceeded"));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews goto unexpected;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt iter->bufsize *= 2;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_R_SUCCESS);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt unexpected:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt iter->buf = NULL;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_R_UNEXPECTED);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt}
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntstatic isc_result_t
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntgetbuf6(isc_interfaceiter_t *iter) {
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt char strbuf[ISC_STRERRORSIZE];
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_result_t result;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews for (;;) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (iter->buf6 == NULL)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson return (ISC_R_NOMEMORY);
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt memset(&iter->lifc, 0, sizeof(iter->lifc));
175a8bd2b798bbc568cd912b72c8a026cfca8527Mark Andrews#ifdef ISC_HAVE_LIFC_FAMILY
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->lifc.lifc_family = AF_INET6;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#ifdef ISC_HAVE_LIFC_FLAGS
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->lifc.lifc_flags = 0;
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson#endif
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson iter->lifc.lifc_len = iter->bufsize6;
d8d0c5b1bc97ac0f07e35a31b58ced80ce613c55David Lawrence iter->lifc.lifc_buf = iter->buf6;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson /*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Ignore the HP/UX warning about "interger overflow during
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * conversion". It comes from its own macro definition,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * and is really hard to shut up.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt == -1) {
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#ifdef __hpux
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * IPv6 interface scanning is not available on all
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * kernels w/ IPv6 sockets.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
fc7043d7d1294478c9988c10af9a7fb8fd810338Evan Hunt if (errno == ENOENT) {
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_LOGMODULE_INTERFACE,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_LOG_DEBUG(1),
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_msgcat_get(isc_msgcat,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSGSET_IFITERIOCTL,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSG_GETIFCONFIG,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "get interface "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "configuration: %s"),
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt strbuf);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt result = ISC_R_FAILURE;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt goto cleanup;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (errno != EINVAL) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_msgcat_get(isc_msgcat,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ISC_MSGSET_IFITERIOCTL,
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson ISC_MSG_GETIFCONFIG,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson "get interface "
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence "configuration: %s"),
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews strbuf);
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt result = ISC_R_UNEXPECTED;
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt goto cleanup;
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews }
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt /*
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews * EINVAL. Retry with a bigger buffer.
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence */
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence } else {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * The ioctl succeeded.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Some OS's just return what will fit rather
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * than set EINVAL if the buffer is too small
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * to fit all the interfaces in. If
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * ifc.ifc_len is too near to the end of the
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt * buffer we will grow it just in case and
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * retry.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt < iter->bufsize6)
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt break;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson UNEXPECTED_ERROR(__FILE__, __LINE__,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_msgcat_get(isc_msgcat,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSGSET_IFITERIOCTL,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ISC_MSG_BUFFERMAX,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "get interface "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "configuration: "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "maximum buffer "
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt "size exceeded"));
584848087f7463c1f659ce4712dc047d8e7f2b07Francis Dupont result = ISC_R_UNEXPECTED;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt goto cleanup;
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
12e0477d4e132c9122312246ed60aaa646f819b2Mark Andrews iter->bufsize6 *= 2;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter->lifc.lifc_len != 0)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->mode = 6;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_R_SUCCESS);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews cleanup:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->buf6 = NULL;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (result);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews}
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsisc_result_t
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_interfaceiter_t *iter;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_result_t result;
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt char strbuf[ISC_STRERRORSIZE];
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews REQUIRE(mctx != NULL);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews REQUIRE(iterp != NULL);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews REQUIRE(*iterp == NULL);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter = isc_mem_get(mctx, sizeof(*iter));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter == NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_R_NOMEMORY);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->mctx = mctx;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->mode = 4;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->buf = NULL;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->pos = (unsigned int) -1;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->buf6 = NULL;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->pos6 = (unsigned int) -1;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->result6 = ISC_R_NOMORE;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->socket6 = -1;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->first6 = ISC_FALSE;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Get the interface configuration, allocating more memory if
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * necessary.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = isc_net_probeipv6();
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (result == ISC_R_SUCCESS) {
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Create an unbound datagram socket to do the SIOCGLIFCONF
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * ioctl on. HP/UX requires an AF_INET6 socket for
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * SIOCGLIFCONF to get IPv6 addresses.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_msgcat_get(isc_msgcat,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ISC_MSGSET_IFITERIOCTL,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ISC_MSG_MAKESCANSOCKET,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews "making interface "
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews "scan socket: %s"),
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews strbuf);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = ISC_R_UNEXPECTED;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews goto socket6_failure;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->result6 = getbuf6(iter);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter->result6 != ISC_R_NOTIMPLEMENTED &&
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater iter->result6 != ISC_R_SUCCESS)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews goto ioctl6_failure;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_msgcat_get(isc_msgcat,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ISC_MSGSET_IFITERIOCTL,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ISC_MSG_MAKESCANSOCKET,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews "making interface "
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews "scan socket: %s"),
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews strbuf);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = ISC_R_UNEXPECTED;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews goto socket_failure;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = getbuf4(iter);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (result != ISC_R_SUCCESS)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews goto ioctl_failure;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * A newly created iterator has an undefined position
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * until isc_interfaceiter_first() is called.
584848087f7463c1f659ce4712dc047d8e7f2b07Francis Dupont */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#ifdef HAVE_TRUCLUSTER
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt iter->clua_context = -1;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt iter->clua_done = ISC_TRUE;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#endif
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson#ifdef __linux
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews iter->proc = fopen("/proc/net/if_inet6", "r");
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews iter->valid = ISC_R_FAILURE;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews iter->first = ISC_FALSE;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews#endif
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews iter->result = ISC_R_FAILURE;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson iter->magic = IFITER_MAGIC;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson *iterp = iter;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson return (ISC_R_SUCCESS);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ioctl_failure:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter->buf != NULL)
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson isc_mem_put(mctx, iter->buf, iter->bufsize);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt (void) close(iter->socket);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews socket_failure:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt if (iter->buf6 != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_mem_put(mctx, iter->buf6, iter->bufsize6);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews ioctl6_failure:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter->socket6 != -1)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews (void) close(iter->socket6);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews socket6_failure:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_mem_put(mctx, iter, sizeof(*iter));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (result);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews}
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#ifdef HAVE_TRUCLUSTER
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsstatic void
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsget_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dst->family = AF_INET;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews memcpy(&dst->type.in, src, sizeof(struct in_addr));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews}
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Huntstatic isc_result_t
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Huntinternal_current_clusteralias(isc_interfaceiter_t *iter) {
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt struct clua_info ci;
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_R_IGNORE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews memset(&iter->current, 0, sizeof(iter->current));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->current.af = iter->clua_sa.sa_family;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews memset(iter->current.name, 0, sizeof(iter->current.name));
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater sprintf(iter->current.name, "clua%d", ci.aliasid);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->current.flags = INTERFACE_F_UP;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews get_inaddr(&iter->current.address, &ci.addr);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews get_inaddr(&iter->current.netmask, &ci.netmask);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_R_SUCCESS);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews}
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#ifdef __linux
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsstatic isc_result_t
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewslinux_if_inet6_next(isc_interfaceiter_t *iter) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter->proc != NULL &&
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->valid = ISC_R_SUCCESS;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews else
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->valid = ISC_R_NOMORE;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (iter->valid);
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater}
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsstatic void
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewslinux_if_inet6_first(isc_interfaceiter_t *iter) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (iter->proc != NULL) {
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson rewind(iter->proc);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews (void)linux_if_inet6_next(iter);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews } else
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater iter->valid = ISC_R_NOMORE;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson iter->first = ISC_FALSE;
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater}
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonstatic isc_result_t
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelinux_if_inet6_current(isc_interfaceiter_t *iter) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson char address[33];
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt char name[IF_NAMESIZE+1];
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson struct in6_addr addr6;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson int ifindex, prefix, flag3, flag4;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson int res;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson unsigned int i;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence if (iter->valid != ISC_R_SUCCESS)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson return (iter->valid);
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt if (iter->proc == NULL) {
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson "/proc/net/if_inet6:iter->proc == NULL");
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson return (ISC_R_FAILURE);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
12e0477d4e132c9122312246ed60aaa646f819b2Mark Andrews res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
12e0477d4e132c9122312246ed60aaa646f819b2Mark Andrews address, &ifindex, &prefix, &flag3, &flag4, name);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (res != 6) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson res);
ea419adc4eca4c3e44f2c282035b5dce6b795fe2Andreas Gustafsson return (ISC_R_FAILURE);
ea419adc4eca4c3e44f2c282035b5dce6b795fe2Andreas Gustafsson }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (strlen(address) != 32) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson "/proc/net/if_inet6:strlen(%s) != 32", address);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_R_FAILURE);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson for (i = 0; i < 16; i++) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson unsigned char byte;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence static const char hex[] = "0123456789abcdef";
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson byte = ((index(hex, address[i * 2]) - hex) << 4) |
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson (index(hex, address[i * 2 + 1]) - hex);
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt addr6.s6_addr[i] = byte;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt iter->current.af = AF_INET6;
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson iter->current.flags = INTERFACE_F_UP;
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson isc_netaddr_fromin6(&iter->current.address, &addr6);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (isc_netaddr_islinklocal(&iter->current.address)) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_netaddr_setzone(&iter->current.address,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson (isc_uint32_t)ifindex);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews for (i = 0; i < 16; i++) {
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews if (prefix > 8) {
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews addr6.s6_addr[i] = 0xff;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews prefix -= 8;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews } else {
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews prefix = 0;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews }
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_netaddr_fromin6(&iter->current.netmask, &addr6);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt strncpy(iter->current.name, name, sizeof(iter->current.name));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_R_SUCCESS);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt}
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#endif
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt/*
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt * Get information about the current interface to iter->current.
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt * If successful, return ISC_R_SUCCESS.
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt * If the interface has an unsupported address family, or if
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt * some operation on it fails, return ISC_R_IGNORE to make
b0bf1ad5b0b1d29b4cdf5de9789405aec5e0844cEvan Hunt * the higher-level iterator code ignore it.
140a27777d6fba397720770b101967d5cf73f42bAutomatic Updater */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
262c39b2366bf79062f7f86b218947523dd1cbacEvan Huntstatic isc_result_t
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrewsinternal_current4(isc_interfaceiter_t *iter) {
140a27777d6fba397720770b101967d5cf73f42bAutomatic Updater struct ifreq *ifrp;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews struct ifreq ifreq;
140a27777d6fba397720770b101967d5cf73f42bAutomatic Updater int family;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews char strbuf[ISC_STRERRORSIZE];
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews struct lifreq lifreq;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt#else
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt char sabuf[256];
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson int i, bits, prefixlen;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#ifdef __linux
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt isc_result_t result;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews#endif
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews REQUIRE(VALID_IFITER(iter));
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#ifdef __linux
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = linux_if_inet6_current(iter);
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt if (result != ISC_R_NOMORE)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (result);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson iter->first = ISC_TRUE;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson#endif
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater memset(&ifreq, 0, sizeof(ifreq));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt memcpy(&ifreq, ifrp, sizeof(ifreq));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt family = ifreq.ifr_addr.sa_family;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#if defined(ISC_PLATFORM_HAVEIPV6)
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (family != AF_INET && family != AF_INET6)
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews#else
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (family != AF_INET)
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews#endif
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews return (ISC_R_IGNORE);
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews memset(&iter->current, 0, sizeof(iter->current));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt iter->current.af = family;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews memset(iter->current.name, 0, sizeof(iter->current.name));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews get_addr(family, &iter->current.address,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * If the interface does not have a address ignore it.
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt */
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater switch (family) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case AF_INET:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_R_IGNORE);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson break;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson case AF_INET6:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (memcmp(&iter->current.address.type.in6, &in6addr_any,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson sizeof(in6addr_any)) == 0)
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_R_IGNORE);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson break;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson /*
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson * Get interface flags.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews iter->current.flags = 0;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Ignore the HP/UX warning about "interger overflow during
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson * conversion. It comes from its own macro definition,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson * and is really hard to shut up.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc__strerror(errno, strbuf, sizeof(strbuf));
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson UNEXPECTED_ERROR(__FILE__, __LINE__,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson "%s: getting interface flags: %s",
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt ifreq.ifr_name, strbuf);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_R_IGNORE);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if ((ifreq.ifr_flags & IFF_UP) != 0)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt iter->current.flags |= INTERFACE_F_UP;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#ifdef IFF_POINTOPOINT
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence iter->current.flags |= INTERFACE_F_POINTTOPOINT;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#endif
e7220c9b841bbd3d16736726f786a86fec3c0e18Evan Hunt
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson iter->current.flags |= INTERFACE_F_LOOPBACK;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (family == AF_INET)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson goto inet;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson memset(&lifreq, 0, sizeof(lifreq));
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt sizeof(iter->current.address.type.in6));
501941f0b6cce74c2ff75b10aff3f230d5d37e4cEvan Hunt
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc__strerror(errno, strbuf, sizeof(strbuf));
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson UNEXPECTED_ERROR(__FILE__, __LINE__,
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson "%s: getting interface address: %s",
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson ifreq.ifr_name, strbuf);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson return (ISC_R_IGNORE);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson }
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson prefixlen = lifreq.lifr_addrlen;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#else
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson ISC_LOGMODULE_INTERFACE,
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson ISC_LOG_INFO,
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_msgcat_get(isc_msgcat,
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington ISC_MSGSET_IFITERIOCTL,
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson ISC_MSG_GETIFCONFIG,
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson "prefix length for %s is unknown "
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence "(assume 128)"), sabuf);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence prefixlen = 128;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#endif
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson /*
* 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) {
struct ifreq *ifrp;
REQUIRE (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
ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
#ifdef ISC_PLATFORM_HAVESALEN
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(*ifrp);
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) {
struct LIFREQ *ifrp;
if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
return (iter->result6);
REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
#ifdef ISC_PLATFORM_HAVESALEN
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(*ifrp);
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
}