"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/isc/unix/ifiter_ioctl.c" (7 Sep 2020, 24347 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ifiter_ioctl.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <config.h>
   13 
   14 #include <stdbool.h>
   15 
   16 #include <isc/print.h>
   17 
   18 /*! \file
   19  * \brief
   20  * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
   21  * See netintro(4).
   22  */
   23 
   24 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
   25 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
   26 #define lifc_len iflc_len
   27 #define lifc_buf iflc_buf
   28 #define lifc_req iflc_req
   29 #define LIFCONF if_laddrconf
   30 #else
   31 #define ISC_HAVE_LIFC_FAMILY 1
   32 #define ISC_HAVE_LIFC_FLAGS 1
   33 #define LIFCONF lifconf
   34 #endif
   35 
   36 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
   37 #define lifr_addr iflr_addr
   38 #define lifr_name iflr_name
   39 #define lifr_dstaddr iflr_dstaddr
   40 #define lifr_flags iflr_flags
   41 #define ss_family sa_family
   42 #define LIFREQ if_laddrreq
   43 #else
   44 #define LIFREQ lifreq
   45 #endif
   46 #endif
   47 
   48 #define IFITER_MAGIC        ISC_MAGIC('I', 'F', 'I', 'T')
   49 #define VALID_IFITER(t)     ISC_MAGIC_VALID(t, IFITER_MAGIC)
   50 
   51 struct isc_interfaceiter {
   52     unsigned int        magic;      /* Magic number. */
   53     isc_mem_t       *mctx;
   54     int         mode;
   55     int         socket;
   56     struct ifconf       ifc;
   57     void            *buf;       /* Buffer for sysctl data. */
   58     unsigned int        bufsize;    /* Bytes allocated. */
   59     unsigned int        pos;        /* Current offset in
   60                            SIOCGIFCONF data */
   61 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
   62     int         socket6;
   63     struct LIFCONF      lifc;
   64     void            *buf6;      /* Buffer for sysctl data. */
   65     unsigned int        bufsize6;   /* Bytes allocated. */
   66     unsigned int        pos6;       /* Current offset in
   67                            SIOCGLIFCONF data */
   68     isc_result_t        result6;    /* Last result code. */
   69     bool        first6;
   70 #endif
   71 #ifdef HAVE_TRUCLUSTER
   72     int         clua_context;   /* Cluster alias context */
   73     bool        clua_done;
   74     struct sockaddr     clua_sa;
   75 #endif
   76 #ifdef  __linux
   77     FILE *          proc;
   78     char            entry[ISC_IF_INET6_SZ];
   79     isc_result_t        valid;
   80 #endif
   81     isc_interface_t     current;    /* Current interface data. */
   82     isc_result_t        result;     /* Last result code. */
   83 };
   84 
   85 #ifdef HAVE_TRUCLUSTER
   86 #include <clua/clua.h>
   87 #include <sys/socket.h>
   88 #endif
   89 
   90 
   91 /*%
   92  * Size of buffer for SIOCGLIFCONF, in bytes.  We assume no sane system
   93  * will have more than a megabyte of interface configuration data.
   94  */
   95 #define IFCONF_BUFSIZE_INITIAL  4096
   96 #define IFCONF_BUFSIZE_MAX  1048576
   97 
   98 #ifdef __linux
   99 #ifndef IF_NAMESIZE
  100 # ifdef IFNAMSIZ
  101 #  define IF_NAMESIZE  IFNAMSIZ
  102 # else
  103 #  define IF_NAMESIZE 16
  104 # endif
  105 #endif
  106 #endif
  107 
  108 static isc_result_t
  109 getbuf4(isc_interfaceiter_t *iter) {
  110     char strbuf[ISC_STRERRORSIZE];
  111 
  112     iter->bufsize = IFCONF_BUFSIZE_INITIAL;
  113 
  114     for (;;) {
  115         iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
  116         if (iter->buf == NULL)
  117             return (ISC_R_NOMEMORY);
  118 
  119         memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
  120         iter->ifc.ifc_len = iter->bufsize;
  121         iter->ifc.ifc_buf = iter->buf;
  122         /*
  123          * Ignore the HP/UX warning about "integer overflow during
  124          * conversion".  It comes from its own macro definition,
  125          * and is really hard to shut up.
  126          */
  127         if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
  128             == -1) {
  129             if (errno != EINVAL) {
  130                 isc__strerror(errno, strbuf, sizeof(strbuf));
  131                 UNEXPECTED_ERROR(__FILE__, __LINE__,
  132                          isc_msgcat_get(isc_msgcat,
  133                             ISC_MSGSET_IFITERIOCTL,
  134                             ISC_MSG_GETIFCONFIG,
  135                             "get interface "
  136                             "configuration: %s"),
  137                          strbuf);
  138                 goto unexpected;
  139             }
  140             /*
  141              * EINVAL.  Retry with a bigger buffer.
  142              */
  143         } else {
  144             /*
  145              * The ioctl succeeded.
  146              * Some OS's just return what will fit rather
  147              * than set EINVAL if the buffer is too small
  148              * to fit all the interfaces in.  If
  149              * ifc.lifc_len is too near to the end of the
  150              * buffer we will grow it just in case and
  151              * retry.
  152              */
  153             if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
  154                 < iter->bufsize)
  155                 break;
  156         }
  157         if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
  158             UNEXPECTED_ERROR(__FILE__, __LINE__,
  159                      isc_msgcat_get(isc_msgcat,
  160                             ISC_MSGSET_IFITERIOCTL,
  161                             ISC_MSG_BUFFERMAX,
  162                             "get interface "
  163                             "configuration: "
  164                             "maximum buffer "
  165                             "size exceeded"));
  166             goto unexpected;
  167         }
  168         isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
  169 
  170         iter->bufsize *= 2;
  171     }
  172     return (ISC_R_SUCCESS);
  173 
  174  unexpected:
  175     isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
  176     iter->buf = NULL;
  177     return (ISC_R_UNEXPECTED);
  178 }
  179 
  180 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  181 static isc_result_t
  182 getbuf6(isc_interfaceiter_t *iter) {
  183     char strbuf[ISC_STRERRORSIZE];
  184     isc_result_t result;
  185 
  186     iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
  187 
  188     for (;;) {
  189         iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
  190         if (iter->buf6 == NULL)
  191             return (ISC_R_NOMEMORY);
  192 
  193         memset(&iter->lifc, 0, sizeof(iter->lifc));
  194 #ifdef ISC_HAVE_LIFC_FAMILY
  195         iter->lifc.lifc_family = AF_INET6;
  196 #endif
  197 #ifdef ISC_HAVE_LIFC_FLAGS
  198         iter->lifc.lifc_flags = 0;
  199 #endif
  200         iter->lifc.lifc_len = iter->bufsize6;
  201         iter->lifc.lifc_buf = iter->buf6;
  202         /*
  203          * Ignore the HP/UX warning about "integer overflow during
  204          * conversion".  It comes from its own macro definition,
  205          * and is really hard to shut up.
  206          */
  207         if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
  208             == -1) {
  209 #ifdef __hpux
  210             /*
  211              * IPv6 interface scanning is not available on all
  212              * kernels w/ IPv6 sockets.
  213              */
  214             if (errno == ENOENT) {
  215                 isc__strerror(errno, strbuf, sizeof(strbuf));
  216                 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
  217                           ISC_LOGMODULE_INTERFACE,
  218                           ISC_LOG_DEBUG(1),
  219                           isc_msgcat_get(isc_msgcat,
  220                             ISC_MSGSET_IFITERIOCTL,
  221                             ISC_MSG_GETIFCONFIG,
  222                             "get interface "
  223                             "configuration: %s"),
  224                            strbuf);
  225                 result = ISC_R_FAILURE;
  226                 goto cleanup;
  227             }
  228 #endif
  229             if (errno != EINVAL) {
  230                 isc__strerror(errno, strbuf, sizeof(strbuf));
  231                 UNEXPECTED_ERROR(__FILE__, __LINE__,
  232                          isc_msgcat_get(isc_msgcat,
  233                             ISC_MSGSET_IFITERIOCTL,
  234                             ISC_MSG_GETIFCONFIG,
  235                             "get interface "
  236                             "configuration: %s"),
  237                          strbuf);
  238                 result = ISC_R_UNEXPECTED;
  239                 goto cleanup;
  240             }
  241             /*
  242              * EINVAL.  Retry with a bigger buffer.
  243              */
  244         } else {
  245             /*
  246              * The ioctl succeeded.
  247              * Some OS's just return what will fit rather
  248              * than set EINVAL if the buffer is too small
  249              * to fit all the interfaces in.  If
  250              * ifc.ifc_len is too near to the end of the
  251              * buffer we will grow it just in case and
  252              * retry.
  253              */
  254             if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
  255                 < iter->bufsize6)
  256                 break;
  257         }
  258         if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
  259             UNEXPECTED_ERROR(__FILE__, __LINE__,
  260                      isc_msgcat_get(isc_msgcat,
  261                             ISC_MSGSET_IFITERIOCTL,
  262                             ISC_MSG_BUFFERMAX,
  263                             "get interface "
  264                             "configuration: "
  265                             "maximum buffer "
  266                             "size exceeded"));
  267             result = ISC_R_UNEXPECTED;
  268             goto cleanup;
  269         }
  270         isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
  271 
  272         iter->bufsize6 *= 2;
  273     }
  274 
  275     if (iter->lifc.lifc_len != 0)
  276         iter->mode = 6;
  277     return (ISC_R_SUCCESS);
  278 
  279  cleanup:
  280     isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
  281     iter->buf6 = NULL;
  282     return (result);
  283 }
  284 #endif
  285 
  286 isc_result_t
  287 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
  288     isc_interfaceiter_t *iter;
  289     isc_result_t result;
  290     char strbuf[ISC_STRERRORSIZE];
  291 
  292     REQUIRE(mctx != NULL);
  293     REQUIRE(iterp != NULL);
  294     REQUIRE(*iterp == NULL);
  295 
  296     iter = isc_mem_get(mctx, sizeof(*iter));
  297     if (iter == NULL)
  298         return (ISC_R_NOMEMORY);
  299 
  300     iter->mctx = mctx;
  301     iter->mode = 4;
  302     iter->buf = NULL;
  303     iter->pos = (unsigned int) -1;
  304 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  305     iter->buf6 = NULL;
  306     iter->pos6 = (unsigned int) -1;
  307     iter->result6 = ISC_R_NOMORE;
  308     iter->socket6 = -1;
  309     iter->first6 = false;
  310 #endif
  311 
  312     /*
  313      * Get the interface configuration, allocating more memory if
  314      * necessary.
  315      */
  316 
  317 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  318     result = isc_net_probeipv6();
  319     if (result == ISC_R_SUCCESS) {
  320         /*
  321          * Create an unbound datagram socket to do the SIOCGLIFCONF
  322          * ioctl on.  HP/UX requires an AF_INET6 socket for
  323          * SIOCGLIFCONF to get IPv6 addresses.
  324          */
  325         if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
  326             isc__strerror(errno, strbuf, sizeof(strbuf));
  327             UNEXPECTED_ERROR(__FILE__, __LINE__,
  328                      isc_msgcat_get(isc_msgcat,
  329                             ISC_MSGSET_IFITERIOCTL,
  330                             ISC_MSG_MAKESCANSOCKET,
  331                             "making interface "
  332                             "scan socket: %s"),
  333                      strbuf);
  334             result = ISC_R_UNEXPECTED;
  335             goto socket6_failure;
  336         }
  337         result = iter->result6 = getbuf6(iter);
  338         if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
  339             goto ioctl6_failure;
  340     }
  341 #endif
  342     if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  343         isc__strerror(errno, strbuf, sizeof(strbuf));
  344         UNEXPECTED_ERROR(__FILE__, __LINE__,
  345                  isc_msgcat_get(isc_msgcat,
  346                         ISC_MSGSET_IFITERIOCTL,
  347                         ISC_MSG_MAKESCANSOCKET,
  348                         "making interface "
  349                         "scan socket: %s"),
  350                  strbuf);
  351         result = ISC_R_UNEXPECTED;
  352         goto socket_failure;
  353     }
  354     result = getbuf4(iter);
  355     if (result != ISC_R_SUCCESS)
  356         goto ioctl_failure;
  357 
  358     /*
  359      * A newly created iterator has an undefined position
  360      * until isc_interfaceiter_first() is called.
  361      */
  362 #ifdef HAVE_TRUCLUSTER
  363     iter->clua_context = -1;
  364     iter->clua_done = true;
  365 #endif
  366 #ifdef __linux
  367     iter->proc = fopen("/proc/net/if_inet6", "r");
  368     iter->valid = ISC_R_FAILURE;
  369 #endif
  370     iter->result = ISC_R_FAILURE;
  371 
  372     iter->magic = IFITER_MAGIC;
  373     *iterp = iter;
  374     return (ISC_R_SUCCESS);
  375 
  376  ioctl_failure:
  377     if (iter->buf != NULL)
  378         isc_mem_put(mctx, iter->buf, iter->bufsize);
  379     (void) close(iter->socket);
  380 
  381  socket_failure:
  382 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  383     if (iter->buf6 != NULL)
  384         isc_mem_put(mctx, iter->buf6, iter->bufsize6);
  385   ioctl6_failure:
  386     if (iter->socket6 != -1)
  387         (void) close(iter->socket6);
  388   socket6_failure:
  389 #endif
  390 
  391     isc_mem_put(mctx, iter, sizeof(*iter));
  392     return (result);
  393 }
  394 
  395 #ifdef HAVE_TRUCLUSTER
  396 static void
  397 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
  398     dst->family = AF_INET;
  399     memmove(&dst->type.in, src, sizeof(struct in_addr));
  400 }
  401 
  402 static isc_result_t
  403 internal_current_clusteralias(isc_interfaceiter_t *iter) {
  404     struct clua_info ci;
  405     if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
  406         return (ISC_R_IGNORE);
  407     memset(&iter->current, 0, sizeof(iter->current));
  408     iter->current.af = iter->clua_sa.sa_family;
  409     memset(iter->current.name, 0, sizeof(iter->current.name));
  410     snprintf(iter->current.name, sizeof(iter->current.name),
  411          "clua%d", ci.aliasid);
  412     iter->current.flags = INTERFACE_F_UP;
  413     get_inaddr(&iter->current.address, &ci.addr);
  414     get_inaddr(&iter->current.netmask, &ci.netmask);
  415     return (ISC_R_SUCCESS);
  416 }
  417 #endif
  418 
  419 /*
  420  * Get information about the current interface to iter->current.
  421  * If successful, return ISC_R_SUCCESS.
  422  * If the interface has an unsupported address family, or if
  423  * some operation on it fails, return ISC_R_IGNORE to make
  424  * the higher-level iterator code ignore it.
  425  */
  426 
  427 static isc_result_t
  428 internal_current4(isc_interfaceiter_t *iter) {
  429     struct ifreq *ifrp;
  430     struct ifreq ifreq;
  431     int family;
  432     char strbuf[ISC_STRERRORSIZE];
  433 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
  434     struct lifreq lifreq;
  435 #else
  436     char sabuf[256];
  437 #endif
  438     int i, bits, prefixlen;
  439 
  440     REQUIRE(VALID_IFITER(iter));
  441 
  442     if (iter->ifc.ifc_len == 0 ||
  443         iter->pos == (unsigned int)iter->ifc.ifc_len) {
  444 #ifdef __linux
  445         return (linux_if_inet6_current(iter));
  446 #else
  447         return (ISC_R_NOMORE);
  448 #endif
  449     }
  450 
  451     INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
  452 
  453     ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
  454 
  455     memset(&ifreq, 0, sizeof(ifreq));
  456     memmove(&ifreq, ifrp, sizeof(ifreq));
  457 
  458     family = ifreq.ifr_addr.sa_family;
  459 #if defined(ISC_PLATFORM_HAVEIPV6)
  460     if (family != AF_INET && family != AF_INET6)
  461 #else
  462     if (family != AF_INET)
  463 #endif
  464         return (ISC_R_IGNORE);
  465 
  466     memset(&iter->current, 0, sizeof(iter->current));
  467     iter->current.af = family;
  468 
  469     INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
  470     memset(iter->current.name, 0, sizeof(iter->current.name));
  471     memmove(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
  472 
  473     get_addr(family, &iter->current.address,
  474          (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
  475 
  476     /*
  477      * If the interface does not have a address ignore it.
  478      */
  479     switch (family) {
  480     case AF_INET:
  481         if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
  482             return (ISC_R_IGNORE);
  483         break;
  484     case AF_INET6:
  485         if (memcmp(&iter->current.address.type.in6, &in6addr_any,
  486                sizeof(in6addr_any)) == 0)
  487             return (ISC_R_IGNORE);
  488         break;
  489     }
  490 
  491     /*
  492      * Get interface flags.
  493      */
  494 
  495     iter->current.flags = 0;
  496 
  497     /*
  498      * Ignore the HP/UX warning about "integer overflow during
  499      * conversion.  It comes from its own macro definition,
  500      * and is really hard to shut up.
  501      */
  502     if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
  503         isc__strerror(errno, strbuf, sizeof(strbuf));
  504         UNEXPECTED_ERROR(__FILE__, __LINE__,
  505                  "%s: getting interface flags: %s",
  506                  ifreq.ifr_name, strbuf);
  507         return (ISC_R_IGNORE);
  508     }
  509 
  510     if ((ifreq.ifr_flags & IFF_UP) != 0)
  511         iter->current.flags |= INTERFACE_F_UP;
  512 
  513 #ifdef IFF_POINTOPOINT
  514     if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
  515         iter->current.flags |= INTERFACE_F_POINTTOPOINT;
  516 #endif
  517 
  518     if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
  519         iter->current.flags |= INTERFACE_F_LOOPBACK;
  520 
  521     if (family == AF_INET)
  522         goto inet;
  523 
  524 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
  525     memset(&lifreq, 0, sizeof(lifreq));
  526     memmove(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
  527     memmove(&lifreq.lifr_addr, &iter->current.address.type.in6,
  528            sizeof(iter->current.address.type.in6));
  529 
  530     if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
  531         isc__strerror(errno, strbuf, sizeof(strbuf));
  532         UNEXPECTED_ERROR(__FILE__, __LINE__,
  533                  "%s: getting interface address: %s",
  534                  ifreq.ifr_name, strbuf);
  535         return (ISC_R_IGNORE);
  536     }
  537     prefixlen = lifreq.lifr_addrlen;
  538 #else
  539     isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
  540     isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
  541               ISC_LOGMODULE_INTERFACE,
  542               ISC_LOG_INFO,
  543               isc_msgcat_get(isc_msgcat,
  544                      ISC_MSGSET_IFITERIOCTL,
  545                      ISC_MSG_GETIFCONFIG,
  546                      "prefix length for %s is unknown "
  547                      "(assume 128)"), sabuf);
  548     prefixlen = 128;
  549 #endif
  550 
  551     /*
  552      * Netmask already zeroed.
  553      */
  554     iter->current.netmask.family = family;
  555     for (i = 0; i < 16; i++) {
  556         if (prefixlen > 8) {
  557             bits = 0;
  558             prefixlen -= 8;
  559         } else {
  560             bits = 8 - prefixlen;
  561             prefixlen = 0;
  562         }
  563         iter->current.netmask.type.in6.s6_addr[i] =
  564             (~0U << bits) & 0xff;
  565     }
  566     return (ISC_R_SUCCESS);
  567 
  568  inet:
  569     if (family != AF_INET)
  570         return (ISC_R_IGNORE);
  571 #ifdef IFF_POINTOPOINT
  572     /*
  573      * If the interface is point-to-point, get the destination address.
  574      */
  575     if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
  576         /*
  577          * Ignore the HP/UX warning about "integer overflow during
  578          * conversion.  It comes from its own macro definition,
  579          * and is really hard to shut up.
  580          */
  581         if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
  582             < 0) {
  583             isc__strerror(errno, strbuf, sizeof(strbuf));
  584             UNEXPECTED_ERROR(__FILE__, __LINE__,
  585                 isc_msgcat_get(isc_msgcat,
  586                            ISC_MSGSET_IFITERIOCTL,
  587                            ISC_MSG_GETDESTADDR,
  588                            "%s: getting "
  589                            "destination address: %s"),
  590                      ifreq.ifr_name, strbuf);
  591             return (ISC_R_IGNORE);
  592         }
  593         get_addr(family, &iter->current.dstaddress,
  594              (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
  595     }
  596 #endif
  597 
  598     /*
  599      * Get the network mask.
  600      */
  601     memset(&ifreq, 0, sizeof(ifreq));
  602     memmove(&ifreq, ifrp, sizeof(ifreq));
  603     /*
  604      * Ignore the HP/UX warning about "integer overflow during
  605      * conversion.  It comes from its own macro definition,
  606      * and is really hard to shut up.
  607      */
  608     if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
  609         isc__strerror(errno, strbuf, sizeof(strbuf));
  610         UNEXPECTED_ERROR(__FILE__, __LINE__,
  611             isc_msgcat_get(isc_msgcat,
  612                        ISC_MSGSET_IFITERIOCTL,
  613                        ISC_MSG_GETNETMASK,
  614                        "%s: getting netmask: %s"),
  615                        ifreq.ifr_name, strbuf);
  616         return (ISC_R_IGNORE);
  617     }
  618     get_addr(family, &iter->current.netmask,
  619          (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
  620     return (ISC_R_SUCCESS);
  621 }
  622 
  623 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  624 static isc_result_t
  625 internal_current6(isc_interfaceiter_t *iter) {
  626     struct LIFREQ *ifrp;
  627     struct LIFREQ lifreq;
  628     int family;
  629     char strbuf[ISC_STRERRORSIZE];
  630     int fd;
  631 
  632     REQUIRE(VALID_IFITER(iter));
  633     if (iter->result6 != ISC_R_SUCCESS)
  634         return (iter->result6);
  635     REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
  636 
  637     ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
  638 
  639     memset(&lifreq, 0, sizeof(lifreq));
  640     memmove(&lifreq, ifrp, sizeof(lifreq));
  641 
  642     family = lifreq.lifr_addr.ss_family;
  643 #ifdef ISC_PLATFORM_HAVEIPV6
  644     if (family != AF_INET && family != AF_INET6)
  645 #else
  646     if (family != AF_INET)
  647 #endif
  648         return (ISC_R_IGNORE);
  649 
  650     memset(&iter->current, 0, sizeof(iter->current));
  651     iter->current.af = family;
  652 
  653     INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
  654     memset(iter->current.name, 0, sizeof(iter->current.name));
  655     memmove(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
  656 
  657     get_addr(family, &iter->current.address,
  658          (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
  659 
  660     /*
  661      * If the interface does not have a address ignore it.
  662      */
  663     switch (family) {
  664     case AF_INET:
  665         if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
  666             return (ISC_R_IGNORE);
  667         break;
  668     case AF_INET6:
  669         if (memcmp(&iter->current.address.type.in6, &in6addr_any,
  670                sizeof(in6addr_any)) == 0)
  671             return (ISC_R_IGNORE);
  672         break;
  673     }
  674 
  675     /*
  676      * Get interface flags.
  677      */
  678 
  679     iter->current.flags = 0;
  680 
  681     if (family == AF_INET6)
  682         fd = iter->socket6;
  683     else
  684         fd = iter->socket;
  685 
  686     /*
  687      * Ignore the HP/UX warning about "integer overflow during
  688      * conversion.  It comes from its own macro definition,
  689      * and is really hard to shut up.
  690      */
  691     if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
  692         isc__strerror(errno, strbuf, sizeof(strbuf));
  693         UNEXPECTED_ERROR(__FILE__, __LINE__,
  694                  "%s: getting interface flags: %s",
  695                  lifreq.lifr_name, strbuf);
  696         return (ISC_R_IGNORE);
  697     }
  698 
  699     if ((lifreq.lifr_flags & IFF_UP) != 0)
  700         iter->current.flags |= INTERFACE_F_UP;
  701 
  702 #ifdef IFF_POINTOPOINT
  703     if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
  704         iter->current.flags |= INTERFACE_F_POINTTOPOINT;
  705 #endif
  706 
  707     if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
  708         iter->current.flags |= INTERFACE_F_LOOPBACK;
  709 
  710 #ifdef IFF_POINTOPOINT
  711     /*
  712      * If the interface is point-to-point, get the destination address.
  713      */
  714     if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
  715         /*
  716          * Ignore the HP/UX warning about "integer overflow during
  717          * conversion.  It comes from its own macro definition,
  718          * and is really hard to shut up.
  719          */
  720         if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
  721             < 0) {
  722             isc__strerror(errno, strbuf, sizeof(strbuf));
  723             UNEXPECTED_ERROR(__FILE__, __LINE__,
  724                 isc_msgcat_get(isc_msgcat,
  725                            ISC_MSGSET_IFITERIOCTL,
  726                            ISC_MSG_GETDESTADDR,
  727                            "%s: getting "
  728                            "destination address: %s"),
  729                      lifreq.lifr_name, strbuf);
  730             return (ISC_R_IGNORE);
  731         }
  732         get_addr(family, &iter->current.dstaddress,
  733              (struct sockaddr *)&lifreq.lifr_dstaddr,
  734              lifreq.lifr_name);
  735     }
  736 #endif
  737 
  738     /*
  739      * Get the network mask.  Netmask already zeroed.
  740      */
  741     memset(&lifreq, 0, sizeof(lifreq));
  742     memmove(&lifreq, ifrp, sizeof(lifreq));
  743 
  744 #ifdef lifr_addrlen
  745     /*
  746      * Special case: if the system provides lifr_addrlen member, the
  747      * netmask of an IPv6 address can be derived from the length, since
  748      * an IPv6 address always has a contiguous mask.
  749      */
  750     if (family == AF_INET6) {
  751         int i, bits;
  752 
  753         iter->current.netmask.family = family;
  754         for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
  755             bits = lifreq.lifr_addrlen - i;
  756             bits = (bits < 8) ? (8 - bits) : 0;
  757             iter->current.netmask.type.in6.s6_addr[i / 8] =
  758                 (~0U << bits) & 0xff;
  759         }
  760 
  761         return (ISC_R_SUCCESS);
  762     }
  763 #endif
  764 
  765     /*
  766      * Ignore the HP/UX warning about "integer overflow during
  767      * conversion.  It comes from its own macro definition,
  768      * and is really hard to shut up.
  769      */
  770     if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
  771         isc__strerror(errno, strbuf, sizeof(strbuf));
  772         UNEXPECTED_ERROR(__FILE__, __LINE__,
  773                  isc_msgcat_get(isc_msgcat,
  774                         ISC_MSGSET_IFITERIOCTL,
  775                         ISC_MSG_GETNETMASK,
  776                         "%s: getting netmask: %s"),
  777                  lifreq.lifr_name, strbuf);
  778         return (ISC_R_IGNORE);
  779     }
  780     get_addr(family, &iter->current.netmask,
  781          (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
  782 
  783     return (ISC_R_SUCCESS);
  784 }
  785 #endif
  786 
  787 static isc_result_t
  788 internal_current(isc_interfaceiter_t *iter) {
  789 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  790     if (iter->mode == 6) {
  791         iter->result6 = internal_current6(iter);
  792         if (iter->result6 != ISC_R_NOMORE)
  793             return (iter->result6);
  794     }
  795 #endif
  796 #ifdef HAVE_TRUCLUSTER
  797     if (!iter->clua_done)
  798         return(internal_current_clusteralias(iter));
  799 #endif
  800     return (internal_current4(iter));
  801 }
  802 
  803 /*
  804  * Step the iterator to the next interface.  Unlike
  805  * isc_interfaceiter_next(), this may leave the iterator
  806  * positioned on an interface that will ultimately
  807  * be ignored.  Return ISC_R_NOMORE if there are no more
  808  * interfaces, otherwise ISC_R_SUCCESS.
  809  */
  810 static isc_result_t
  811 internal_next4(isc_interfaceiter_t *iter) {
  812 #ifdef ISC_PLATFORM_HAVESALEN
  813     struct ifreq *ifrp;
  814 #endif
  815 
  816     if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
  817 #ifdef ISC_PLATFORM_HAVESALEN
  818         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
  819 
  820         if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
  821             iter->pos += sizeof(ifrp->ifr_name) +
  822                      ifrp->ifr_addr.sa_len;
  823         else
  824 #endif
  825             iter->pos += sizeof(struct ifreq);
  826 
  827     } else {
  828         INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
  829 #ifdef __linux
  830         return (linux_if_inet6_next(iter));
  831 #else
  832         return (ISC_R_NOMORE);
  833 #endif
  834     }
  835     return (ISC_R_SUCCESS);
  836 }
  837 
  838 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  839 static isc_result_t
  840 internal_next6(isc_interfaceiter_t *iter) {
  841 #ifdef ISC_PLATFORM_HAVESALEN
  842     struct LIFREQ *ifrp;
  843 #endif
  844 
  845     if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
  846         return (iter->result6);
  847 
  848     REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
  849 
  850 #ifdef ISC_PLATFORM_HAVESALEN
  851     ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
  852 
  853     if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
  854         iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
  855     else
  856 #endif
  857         iter->pos6 += sizeof(struct LIFREQ);
  858 
  859     if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
  860         return (ISC_R_NOMORE);
  861 
  862     return (ISC_R_SUCCESS);
  863 }
  864 #endif
  865 
  866 static isc_result_t
  867 internal_next(isc_interfaceiter_t *iter) {
  868 #ifdef HAVE_TRUCLUSTER
  869     int clua_result;
  870 #endif
  871 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  872     if (iter->mode == 6) {
  873         iter->result6 = internal_next6(iter);
  874         if (iter->result6 != ISC_R_NOMORE)
  875             return (iter->result6);
  876         if (iter->first6) {
  877             iter->first6 = false;
  878             return (ISC_R_SUCCESS);
  879         }
  880     }
  881 #endif
  882 #ifdef HAVE_TRUCLUSTER
  883     if (!iter->clua_done) {
  884         clua_result = clua_getaliasaddress(&iter->clua_sa,
  885                            &iter->clua_context);
  886         if (clua_result != CLUA_SUCCESS)
  887             iter->clua_done = true;
  888         return (ISC_R_SUCCESS);
  889     }
  890 #endif
  891     return (internal_next4(iter));
  892 }
  893 
  894 static void
  895 internal_destroy(isc_interfaceiter_t *iter) {
  896     (void) close(iter->socket);
  897 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  898     if (iter->socket6 != -1)
  899         (void) close(iter->socket6);
  900     if (iter->buf6 != NULL) {
  901         isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
  902     }
  903 #endif
  904 #ifdef __linux
  905     if (iter->proc != NULL)
  906         fclose(iter->proc);
  907 #endif
  908 }
  909 
  910 static
  911 void internal_first(isc_interfaceiter_t *iter) {
  912 #ifdef HAVE_TRUCLUSTER
  913     int clua_result;
  914 #endif
  915     iter->pos = 0;
  916 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
  917     iter->pos6 = 0;
  918     if (iter->result6 == ISC_R_NOMORE)
  919         iter->result6 = ISC_R_SUCCESS;
  920     iter->first6 = true;
  921 #endif
  922 #ifdef HAVE_TRUCLUSTER
  923     iter->clua_context = 0;
  924     clua_result = clua_getaliasaddress(&iter->clua_sa,
  925                        &iter->clua_context);
  926     iter->clua_done = (clua_result != CLUA_SUCCESS);
  927 #endif
  928 #ifdef __linux
  929     linux_if_inet6_first(iter);
  930 #endif
  931 }