Annotation of embedaddon/ntp/lib/isc/unix/ifiter_ioctl.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>