Annotation of embedaddon/ntp/lib/isc/win32/interfaceiter.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
                      3:  * Copyright (C) 1999-2001  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: interfaceiter.c,v 1.13.110.2 2009/01/18 23:47:41 tbox Exp $ */
                     19: 
                     20: #include <config.h>
                     21: #include <winsock2.h>
                     22: #include <ws2tcpip.h>
                     23: #include <iphlpapi.h>
                     24: #include <sys/types.h>
                     25: 
                     26: #include <stdio.h>
                     27: #include <stdlib.h>
                     28: #include <errno.h>
                     29: 
                     30: #include <isc/interfaceiter.h>
                     31: #include <isc/mem.h>
                     32: #include <isc/result.h>
                     33: #include <isc/string.h>
                     34: #include <isc/strerror.h>
                     35: #include <isc/types.h>
                     36: #include <isc/util.h>
                     37: #include <isc/win32os.h>
                     38: 
                     39: void InitSockets(void);
                     40: 
                     41: 
                     42: #define IFITER_MAGIC           0x49464954U     /* IFIT. */
                     43: #define VALID_IFITER(t)                ((t) != NULL && (t)->magic == IFITER_MAGIC)
                     44: 
                     45: struct isc_interfaceiter {
                     46:        unsigned int            magic;          /* Magic number. */
                     47:        /* common fields */
                     48:        isc_mem_t               *mctx;
                     49:        isc_interface_t         current;        /* Current interface data. */
                     50:        isc_result_t            result;         /* Last result code. */
                     51:        /* fields used if GetAdaptersAddresses is available at runtime */
                     52:        IP_ADAPTER_ADDRESSES *  ipaa;           /* GAA() result buffer */
                     53:        ULONG                   ipaasize;       /* Bytes allocated */
                     54:        IP_ADAPTER_ADDRESSES *  ipaaCur;        /* enumeration position */
                     55:        IP_ADAPTER_UNICAST_ADDRESS *ipuaCur;    /* enumeration subposition */
                     56:        /* fields used for the older address enumeration ioctls */
                     57:        int                     socket;
                     58:        INTERFACE_INFO          IFData;         /* Current Interface Info */
                     59:        int                     numIF;          /* Current Interface count */
                     60:        int                     v4IF;           /* Number of IPv4 Interfaces */
                     61:        INTERFACE_INFO          *buf4;          /* Buffer for WSAIoctl data. */
                     62:        unsigned int            buf4size;       /* Bytes allocated. */
                     63:        INTERFACE_INFO          *pos4;          /* Current offset in IF List */
                     64:        SOCKET_ADDRESS_LIST     *buf6;
                     65:        unsigned int            buf6size;       /* Bytes allocated. */
                     66:        unsigned int            pos6;           /* buf6 index, counts down */
                     67:        struct in6_addr         loop__1;        /* ::1 node-scope localhost */
                     68:        struct in6_addr         loopfe80__1;    /* fe80::1 link-scope localhost */
                     69: };
                     70: 
                     71: typedef ULONG (WINAPI *PGETADAPTERSADDRESSES)(
                     72:     ULONG Family,
                     73:     ULONG Flags,
                     74:     PVOID Reserved,
                     75:     PIP_ADAPTER_ADDRESSES AdapterAddresses,
                     76:     PULONG SizePointer
                     77: );
                     78: 
                     79: static isc_boolean_t           use_GAA;
                     80: static isc_boolean_t           use_GAA_determined;
                     81: static HMODULE                 hmod_iphlpapi;
                     82: static PGETADAPTERSADDRESSES   pGAA;
                     83: 
                     84: 
                     85: /*
                     86:  * Size of buffer for SIO_GET_INTERFACE_LIST, in number of interfaces.
                     87:  * We assume no sane system will have more than than 1K of IP addresses on
                     88:  * all of its adapters.
                     89:  */
                     90: #define IFCONF_SIZE_INITIAL      16
                     91: #define IFCONF_SIZE_INCREMENT    64
                     92: #define IFCONF_SIZE_MAX                1040
                     93: 
                     94: 
                     95: /* Common utility functions */
                     96: 
                     97: /*
                     98:  * Windows always provides 255.255.255.255 as the the broadcast
                     99:  * address.  ntpd needs to know the broadcast address which will target
                    100:  * only that network interface, not all.  Reconstruct it from the
                    101:  * address and mask.
                    102:  */
                    103: static void
                    104: get_broadcastaddr(isc_netaddr_t *bcastaddr, isc_netaddr_t *addr, isc_netaddr_t *netmask) {
                    105: 
                    106:        isc_uint32_t *  b;
                    107:        isc_uint32_t    a, n;
                    108: 
                    109:        b = (isc_uint32_t *)&bcastaddr->type.in;
                    110:        a = *(isc_uint32_t *)&addr->type.in;
                    111:        n = *(isc_uint32_t *)&netmask->type.in;
                    112: 
                    113:        *b = a | ~n;
                    114: }
                    115: 
                    116: isc_result_t
                    117: isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
                    118:        char strbuf[ISC_STRERRORSIZE];
                    119:        isc_interfaceiter_t *iter;
                    120:        isc_result_t result;
                    121:        unsigned int major;
                    122:        unsigned int minor;
                    123:        unsigned int spmajor;
                    124:        ULONG err;
                    125:        int tries;
                    126:        int error;
                    127:        unsigned long bytesReturned = 0;
                    128: 
                    129:        REQUIRE(mctx != NULL);
                    130:        REQUIRE(iterp != NULL);
                    131:        REQUIRE(*iterp == NULL);
                    132: 
                    133:        iter = isc_mem_get(mctx, sizeof(*iter));
                    134:        if (iter == NULL)
                    135:                return (ISC_R_NOMEMORY);
                    136: 
                    137:        InitSockets();
                    138: 
                    139:        iter->mctx = mctx;
                    140:        iter->ipaa = NULL;
                    141:        iter->buf4 = NULL;
                    142:        iter->buf6 = NULL;
                    143:        iter->pos4 = NULL;
                    144:        iter->ipaaCur = NULL;
                    145:        iter->ipuaCur = NULL;
                    146:        iter->ipaasize = 0;
                    147:        iter->pos6 = 0;
                    148:        iter->buf6size = 0;
                    149:        iter->buf4size = 0;
                    150:        iter->result = ISC_R_FAILURE;
                    151:        iter->numIF = 0;
                    152:        iter->v4IF = 0;
                    153: 
                    154:        /*
                    155:         * Use GetAdaptersAddresses in preference to ioctls when running
                    156:         * on Windows XP SP1 or later.  Earlier GetAdaptersAddresses do
                    157:         * not appear to provide enough information to associate unicast
                    158:         * addresses with their prefixes.
                    159:         */
                    160:        if (!use_GAA_determined) {
                    161:                major = isc_win32os_majorversion();
                    162:                minor = isc_win32os_minorversion();
                    163:                spmajor = isc_win32os_servicepackmajor();
                    164:                if (major > 5 || (5 == major &&
                    165:                    (minor > 1 || (1 == minor && spmajor >= 1)))) {
                    166:                        if (NULL == hmod_iphlpapi)
                    167:                                hmod_iphlpapi = LoadLibrary("iphlpapi");
                    168:                        if (NULL != hmod_iphlpapi)
                    169:                                pGAA = (PGETADAPTERSADDRESSES)
                    170:                                    GetProcAddress(
                    171:                                        hmod_iphlpapi,
                    172:                                        "GetAdaptersAddresses");
                    173:                        if (NULL != pGAA)
                    174:                                use_GAA = ISC_TRUE;
                    175:                }
                    176:                use_GAA_determined = ISC_TRUE;
                    177:        }
                    178: 
                    179:        if (!use_GAA)
                    180:                goto use_ioctls;
                    181: 
                    182:        iter->ipaasize = 16 * 1024;
                    183: 
                    184:        for (tries = 0; tries < 5; tries++) {
                    185:                iter->ipaa = isc_mem_reallocate(mctx, iter->ipaa,
                    186:                                                 iter->ipaasize);
                    187:                if (NULL == iter->ipaa) {
                    188:                        result = ISC_R_NOMEMORY;
                    189:                        goto put_iter;
                    190:                }
                    191:                err = (*pGAA)(
                    192:                        AF_UNSPEC,
                    193:                        GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST,
                    194:                        NULL,
                    195:                        iter->ipaa,
                    196:                        &iter->ipaasize);
                    197:                if (NO_ERROR == err || ERROR_BUFFER_OVERFLOW != err)
                    198:                        break;
                    199:        }
                    200: 
                    201:        if (NO_ERROR != err) {
                    202:                isc__strerror(err, strbuf, sizeof(strbuf));
                    203:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                    204:                                "GetAdaptersAddresses: %s",
                    205:                                strbuf);
                    206:                result = ISC_R_UNEXPECTED;
                    207:                goto gaa_failure;
                    208:        }
                    209:        
                    210:        iter->ipaaCur = iter->ipaa;
                    211:        goto success;
                    212: 
                    213:  use_ioctls:
                    214:        /*
                    215:         * Create an unbound datagram socket to do the
                    216:         * SIO_GET_INTERFACE_LIST WSAIoctl on.
                    217:         */
                    218:        if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                    219:                error = WSAGetLastError();
                    220:                if (error == WSAEAFNOSUPPORT)
                    221:                        goto inet6_only;
                    222:                isc__strerror(error, strbuf, sizeof(strbuf));
                    223:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                    224:                                "making interface scan socket: %s",
                    225:                                strbuf);
                    226:                result = ISC_R_UNEXPECTED;
                    227:                goto put_iter;
                    228:        }
                    229: 
                    230:        /*
                    231:         * Get the interface configuration, allocating more memory if
                    232:         * necessary.
                    233:         */
                    234:        iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO);
                    235: 
                    236:        for (;;) {
                    237:                iter->buf4 = isc_mem_get(mctx, iter->buf4size);
                    238:                if (iter->buf4 == NULL) {
                    239:                        result = ISC_R_NOMEMORY;
                    240:                        goto alloc_failure;
                    241:                }
                    242: 
                    243:                if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST,
                    244:                             0, 0, iter->buf4, iter->buf4size,
                    245:                             &bytesReturned, 0, 0) == SOCKET_ERROR)
                    246:                {
                    247:                        error = WSAGetLastError();
                    248:                        if (error != WSAEFAULT && error != WSAENOBUFS) {
                    249:                                errno = error;
                    250:                                isc__strerror(error, strbuf, sizeof(strbuf));
                    251:                                UNEXPECTED_ERROR(__FILE__, __LINE__,
                    252:                                                "get interface configuration: %s",
                    253:                                                strbuf);
                    254:                                result = ISC_R_UNEXPECTED;
                    255:                                goto ioctl_failure;
                    256:                        }
                    257:                        /*
                    258:                         * EINVAL.  Retry with a bigger buffer.
                    259:                         */
                    260:                } else {
                    261:                        /*
                    262:                         * The WSAIoctl succeeded.
                    263:                         * If the number of the returned bytes is the same
                    264:                         * as the buffer size, we will grow it just in
                    265:                         * case and retry.
                    266:                         */
                    267:                        if (bytesReturned > 0 &&
                    268:                            (bytesReturned < iter->buf4size))
                    269:                                break;
                    270:                }
                    271:                if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) {
                    272:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                    273:                                         "get interface configuration: "
                    274:                                         "maximum buffer size exceeded");
                    275:                        result = ISC_R_UNEXPECTED;
                    276:                        goto ioctl_failure;
                    277:                }
                    278:                isc_mem_put(mctx, iter->buf4, iter->buf4size);
                    279: 
                    280:                iter->buf4size += IFCONF_SIZE_INCREMENT *
                    281:                        sizeof(INTERFACE_INFO);
                    282:        }
                    283: 
                    284:        /*
                    285:         * A newly created iterator has an undefined position
                    286:         * until isc_interfaceiter_first() is called.
                    287:         */
                    288:        iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO);
                    289: 
                    290:        /* We don't need the socket any more, so close it */
                    291:        closesocket(iter->socket);
                    292: 
                    293:  inet6_only:
                    294:        /*
                    295:         * Create an unbound datagram socket to do the
                    296:         * SIO_ADDRESS_LIST_QUERY WSAIoctl on.
                    297:         */
                    298:        if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                    299:                error = WSAGetLastError();
                    300:                if (error == WSAEAFNOSUPPORT)
                    301:                        goto success;
                    302:                isc__strerror(error, strbuf, sizeof(strbuf));
                    303:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                    304:                                "making interface scan socket: %s",
                    305:                                strbuf);
                    306:                result = ISC_R_UNEXPECTED;
                    307:                goto put_iter;
                    308:        }
                    309: 
                    310:        /*
                    311:         * Get the interface configuration, allocating more memory if
                    312:         * necessary.
                    313:         */
                    314:        iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) +
                    315:                         IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS);
                    316: 
                    317:        for (;;) {
                    318:                iter->buf6 = isc_mem_get(mctx, iter->buf6size);
                    319:                if (iter->buf6 == NULL) {
                    320:                        result = ISC_R_NOMEMORY;
                    321:                        goto ioctl_failure;
                    322:                }
                    323: 
                    324:                if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY,
                    325:                             0, 0, iter->buf6, iter->buf6size,
                    326:                             &bytesReturned, 0, 0) == SOCKET_ERROR)
                    327:                {
                    328:                        error = WSAGetLastError();
                    329:                        if (error != WSAEFAULT && error != WSAENOBUFS) {
                    330:                                errno = error;
                    331:                                isc__strerror(error, strbuf, sizeof(strbuf));
                    332:                                UNEXPECTED_ERROR(__FILE__, __LINE__,
                    333:                                                 "sio address list query: %s",
                    334:                                                 strbuf);
                    335:                                result = ISC_R_UNEXPECTED;
                    336:                                goto ioctl6_failure;
                    337:                        }
                    338:                        /*
                    339:                         * EINVAL.  Retry with a bigger buffer.
                    340:                         */
                    341:                } else
                    342:                        break;
                    343: 
                    344:                if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) {
                    345:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                    346:                                         "get interface configuration: "
                    347:                                         "maximum buffer size exceeded");
                    348:                        result = ISC_R_UNEXPECTED;
                    349:                        goto ioctl6_failure;
                    350:                }
                    351:                isc_mem_put(mctx, iter->buf6, iter->buf6size);
                    352: 
                    353:                iter->buf6size += IFCONF_SIZE_INCREMENT *
                    354:                        sizeof(SOCKET_ADDRESS);
                    355:        }
                    356: 
                    357:        /*
                    358:         * initialize loop__1 to [::1] and loopfe80__1 to [fe80::1].
                    359:         * used by internal_current6().
                    360:         */
                    361:        memset(&iter->loop__1, 0, sizeof(iter->loop__1));
                    362:        memset(&iter->loopfe80__1, 0, sizeof(iter->loopfe80__1));
                    363:        iter->loop__1.s6_addr[15] = 1;
                    364:        iter->loopfe80__1.s6_addr[15] = 1;
                    365:        iter->loopfe80__1.s6_addr[0] = 0xfe;
                    366:        iter->loopfe80__1.s6_addr[1] = 0x80;
                    367: 
                    368:        closesocket(iter->socket);
                    369: 
                    370:  success:
                    371:        iter->magic = IFITER_MAGIC;
                    372:        *iterp = iter;
                    373:        return (ISC_R_SUCCESS);
                    374: 
                    375:  gaa_failure:
                    376:        isc_mem_put(mctx, iter->ipaa, iter->ipaasize);
                    377:        goto put_iter;
                    378: 
                    379:  ioctl6_failure:
                    380:        isc_mem_put(mctx, iter->buf6, iter->buf6size);
                    381: 
                    382:  ioctl_failure:
                    383:        if (iter->buf4 != NULL)
                    384:                isc_mem_put(mctx, iter->buf4, iter->buf4size);
                    385: 
                    386:  alloc_failure:
                    387:        if (iter->socket >= 0)
                    388:                (void) closesocket(iter->socket);
                    389: 
                    390:  put_iter:
                    391:        isc_mem_put(mctx, iter, sizeof(*iter));
                    392:        return (result);
                    393: }
                    394: 
                    395: static unsigned char
                    396: GAA_find_prefix(isc_interfaceiter_t *iter) {
                    397:        IP_ADAPTER_PREFIX *     ipap;
                    398:        IP_ADAPTER_PREFIX *     ipap_match;
                    399:        int                     match_len;
                    400:        int                     max_len;
                    401:        isc_netaddr_t           target;
                    402:        u_short                 af;
                    403:        isc_netaddr_t           pfx;
                    404:        int                     pfx_len;
                    405:        size_t                  nbytes;
                    406:        unsigned char           nbits;
                    407:        unsigned char *         pbits;
                    408:        unsigned int            octets;
                    409: 
                    410:        match_len = 0;
                    411:        ipap_match = NULL;
                    412:        isc_netaddr_fromsockaddr(&target,
                    413:            (isc_sockaddr_t *)iter->ipuaCur->Address.lpSockaddr);
                    414:        af = (u_short)target.family;
                    415:        INSIST(AF_INET == af || AF_INET6 == af);
                    416:        max_len = (AF_INET6 == af) ? 128 : 32;
                    417:        iter->current.netmask.family = af;
                    418:        for (ipap = iter->ipaaCur->FirstPrefix;
                    419:             ipap != NULL;
                    420:             ipap = ipap->Next) {
                    421:                if (ipap->Address.lpSockaddr->sa_family != af)
                    422:                        continue;
                    423:                isc_netaddr_fromsockaddr(&pfx,
                    424:                    (isc_sockaddr_t *)ipap->Address.lpSockaddr);
                    425:                pfx_len = ipap->PrefixLength;
                    426:                INSIST(0 <= pfx_len && pfx_len <= max_len);
                    427:                if (pfx_len > match_len && pfx_len < max_len &&
                    428:                    isc_netaddr_eqprefix(&target, &pfx, pfx_len)) {
                    429:                        ipap_match = ipap;
                    430:                        match_len = pfx_len;
                    431:                }
                    432:        }
                    433:        if (NULL == ipap_match) {
                    434:                /* presume all-ones mask */
                    435:                if (AF_INET6 == af)
                    436:                        octets = sizeof(iter->current.netmask.type.in6);
                    437:                else
                    438:                        octets = sizeof(iter->current.netmask.type.in);
                    439:                memset(&iter->current.netmask.type, 0xFF, octets);
                    440:                return (8 * (unsigned char)octets);
                    441:        }
                    442:        nbytes = match_len / 8;
                    443:        nbits = match_len % 8;
                    444:        memset(&iter->current.netmask.type.in6, 0xFF, nbytes);
                    445:        pbits = (void *)&iter->current.netmask.type.in6;
                    446:        pbits += nbytes;
                    447:        *pbits |= 0xFF << (8 - nbits);
                    448:        return ((unsigned char)match_len);
                    449: }
                    450: 
                    451: static isc_result_t
                    452: internal_current_GAA(isc_interfaceiter_t *iter) {
                    453:        IP_ADAPTER_ADDRESSES *adap;
                    454:        IP_ADAPTER_UNICAST_ADDRESS *addr;
                    455:        unsigned char prefix_len;
                    456: 
                    457:        REQUIRE(iter->ipaaCur != NULL);
                    458:        REQUIRE(iter->ipuaCur != NULL);
                    459:        adap = iter->ipaaCur;
                    460:        addr = iter->ipuaCur;
                    461:        if (IpDadStatePreferred != addr->DadState)
                    462:                return (ISC_R_IGNORE);
                    463:        memset(&iter->current, 0, sizeof(iter->current));
                    464:        iter->current.af = addr->Address.lpSockaddr->sa_family;
                    465:        isc_netaddr_fromsockaddr(&iter->current.address,
                    466:            (isc_sockaddr_t *)addr->Address.lpSockaddr);
                    467:        if (AF_INET6 == iter->current.af)
                    468:                iter->current.ifindex = adap->Ipv6IfIndex;
                    469:        iter->current.name[0] = '\0';
                    470:        WideCharToMultiByte(
                    471:                CP_ACP, 
                    472:                0, 
                    473:                adap->FriendlyName,
                    474:                -1,
                    475:                iter->current.name,
                    476:                sizeof(iter->current.name),
                    477:                NULL,
                    478:                NULL);
                    479:        iter->current.name[sizeof(iter->current.name) - 1] = '\0';
                    480:        if (IfOperStatusUp == adap->OperStatus)
                    481:                iter->current.flags |= INTERFACE_F_UP;
                    482:        if (IF_TYPE_PPP == adap->IfType)
                    483:                iter->current.flags |= INTERFACE_F_POINTTOPOINT;
                    484:        else if (IF_TYPE_SOFTWARE_LOOPBACK == adap->IfType)
                    485:                iter->current.flags |= INTERFACE_F_LOOPBACK;
                    486:        if ((IP_ADAPTER_NO_MULTICAST & adap->Flags) == 0)
                    487:                iter->current.flags |= INTERFACE_F_MULTICAST;
                    488:        if (IpSuffixOriginRandom == addr->SuffixOrigin)
                    489:                iter->current.flags |= INTERFACE_F_PRIVACY;
                    490: 
                    491:        prefix_len = GAA_find_prefix(iter);
                    492:        /* I'm failing to see a broadcast flag via GAA */
                    493:        if (AF_INET == iter->current.af && prefix_len < 32 &&
                    494:            (INTERFACE_F_LOOPBACK & iter->current.flags) == 0) {
                    495:                iter->current.flags |= INTERFACE_F_BROADCAST;
                    496:                get_broadcastaddr(&iter->current.broadcast,
                    497:                                  &iter->current.address,
                    498:                                  &iter->current.netmask);
                    499:        }
                    500:        return (ISC_R_SUCCESS);
                    501: }
                    502: 
                    503: /*
                    504:  * Get information about the current interface to iter->current.
                    505:  * If successful, return ISC_R_SUCCESS.
                    506:  * If the interface has an unsupported address family, or if
                    507:  * some operation on it fails, return ISC_R_IGNORE to make
                    508:  * the higher-level iterator code ignore it.
                    509:  */
                    510: 
                    511: static isc_result_t
                    512: internal_current(isc_interfaceiter_t *iter) {
                    513:        BOOL ifNamed = FALSE;
                    514:        unsigned long flags;
                    515: 
                    516:        REQUIRE(VALID_IFITER(iter));
                    517:        REQUIRE(iter->numIF >= 0);
                    518: 
                    519:        memset(&iter->current, 0, sizeof(iter->current));
                    520:        iter->current.af = AF_INET;
                    521: 
                    522:        isc_netaddr_fromsockaddr(&iter->current.address,
                    523:            (isc_sockaddr_t *)&(iter->IFData.iiAddress));
                    524: 
                    525:        /*
                    526:         * Get interface flags.
                    527:         */
                    528: 
                    529:        iter->current.flags = 0;
                    530:        flags = iter->IFData.iiFlags;
                    531: 
                    532:        if ((flags & IFF_UP) != 0)
                    533:                iter->current.flags |= INTERFACE_F_UP;
                    534: 
                    535:        if ((flags & IFF_BROADCAST) != 0)
                    536:                iter->current.flags |= INTERFACE_F_BROADCAST;
                    537: 
                    538:        if ((flags & IFF_MULTICAST) != 0)
                    539:                iter->current.flags |= INTERFACE_F_MULTICAST;
                    540: 
                    541:        if ((flags & IFF_POINTTOPOINT) != 0) {
                    542:                iter->current.flags |= INTERFACE_F_POINTTOPOINT;
                    543:                snprintf(iter->current.name, sizeof(iter->current.name),
                    544:                         "PPP %d", iter->numIF);
                    545:                ifNamed = TRUE;
                    546:        }
                    547: 
                    548:        if ((flags & IFF_LOOPBACK) != 0) {
                    549:                iter->current.flags |= INTERFACE_F_LOOPBACK;
                    550:                snprintf(iter->current.name, sizeof(iter->current.name),
                    551:                        "v4loop %d", iter->numIF);
                    552:                ifNamed = TRUE;
                    553:        }
                    554: 
                    555:        /*
                    556:         * If the interface is point-to-point, get the destination address.
                    557:         */
                    558:        if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
                    559:                isc_netaddr_fromsockaddr(&iter->current.dstaddress,
                    560:                    (isc_sockaddr_t *)&(iter->IFData.iiBroadcastAddress));
                    561: 
                    562:        /*
                    563:         * Get the network mask.
                    564:         */
                    565:        isc_netaddr_fromsockaddr(&iter->current.netmask,
                    566:            (isc_sockaddr_t *)&(iter->IFData.iiNetmask));
                    567: 
                    568:        /*
                    569:         * If the interface is broadcast, get the broadcast address,
                    570:         * based on the unicast address and network mask.
                    571:         */
                    572:        if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0)
                    573:                get_broadcastaddr(&iter->current.broadcast,
                    574:                                  &iter->current.address,
                    575:                                  &iter->current.netmask);
                    576: 
                    577:        if (ifNamed == FALSE)
                    578:                snprintf(iter->current.name, sizeof(iter->current.name),
                    579:                        "IPv4 %d", iter->numIF);
                    580: 
                    581:        return (ISC_R_SUCCESS);
                    582: }
                    583: 
                    584: static isc_result_t
                    585: internal_current6(isc_interfaceiter_t *iter) {
                    586:        BOOL ifNamed = FALSE;
                    587:        struct sockaddr_in6 *psa6;
                    588:        BOOL localhostSeen;
                    589:        int i;
                    590: 
                    591:        REQUIRE(VALID_IFITER(iter));
                    592:        REQUIRE(iter->pos6 >= 0);
                    593:        REQUIRE(iter->buf6 != 0);
                    594: 
                    595:        memset(&iter->current, 0, sizeof(iter->current));
                    596:        iter->current.af = AF_INET6;
                    597: 
                    598:        /*
                    599:         * synthesize localhost ::1 before returning the rest, if ::1
                    600:         * is not on the list.
                    601:         */
                    602:        if (iter->pos6 >= (unsigned)iter->buf6->iAddressCount) {
                    603:                localhostSeen = FALSE;
                    604:                for (i = 0; i < iter->buf6->iAddressCount; i++) {
                    605:                        psa6 = (struct sockaddr_in6 *)
                    606:                               iter->buf6->Address[i].lpSockaddr;
                    607:                        if (!memcmp(&iter->loop__1, &psa6->sin6_addr,
                    608:                                    sizeof(iter->loop__1))) {
                    609:                                localhostSeen = TRUE;
                    610:                                break;
                    611:                        }
                    612:                }
                    613:                if (localhostSeen)
                    614:                        iter->pos6 = iter->buf6->iAddressCount - 1;
                    615:        }
                    616: 
                    617:        if (iter->pos6 < (unsigned)iter->buf6->iAddressCount) {
                    618:                isc_netaddr_fromsockaddr(&iter->current.address,
                    619:                    (isc_sockaddr_t *)iter->buf6->Address[iter->pos6].lpSockaddr);
                    620:        } else {
                    621:                iter->current.address.family = AF_INET6;
                    622:                memcpy(&iter->current.address.type.in6, &iter->loop__1,
                    623:                       sizeof(iter->current.address.type.in6));
                    624:        }
                    625: 
                    626:        /*
                    627:         * Get interface flags.
                    628:         */
                    629: 
                    630:        iter->current.flags = INTERFACE_F_UP | INTERFACE_F_MULTICAST;
                    631: 
                    632:        if (!memcmp(&iter->current.address.type.in6, &iter->loop__1,
                    633:                    sizeof(iter->current.address.type.in6)) ||
                    634:            !memcmp(&iter->current.address.type.in6, &iter->loopfe80__1,
                    635:                    sizeof(iter->current.address.type.in6))) {
                    636: 
                    637:                iter->current.flags |= INTERFACE_F_LOOPBACK;
                    638:                snprintf(iter->current.name, sizeof(iter->current.name),
                    639:                         "v6loop %d",
                    640:                         iter->buf6->iAddressCount - iter->pos6);
                    641:                ifNamed = TRUE;
                    642:        }
                    643: 
                    644:        if (ifNamed == FALSE)
                    645:                snprintf(iter->current.name, sizeof(iter->current.name),
                    646:                         "IPv6 %d",
                    647:                         iter->buf6->iAddressCount - iter->pos6);
                    648: 
                    649:        memset(iter->current.netmask.type.in6.s6_addr, 0xff,
                    650:               sizeof(iter->current.netmask.type.in6.s6_addr));
                    651:        iter->current.netmask.family = AF_INET6;
                    652:        return (ISC_R_SUCCESS);
                    653: }
                    654: 
                    655: static isc_result_t
                    656: internal_next_GAA(isc_interfaceiter_t *iter) {
                    657:        REQUIRE(use_GAA);
                    658:        if (NULL == iter->ipaaCur)
                    659:                return (ISC_R_NOMORE);
                    660:        if (NULL == iter->ipuaCur)
                    661:                iter->ipuaCur = iter->ipaaCur->FirstUnicastAddress;
                    662:        else
                    663:                iter->ipuaCur = iter->ipuaCur->Next;
                    664:        while (NULL == iter->ipuaCur) {
                    665:                iter->ipaaCur = iter->ipaaCur->Next;
                    666:                if (NULL == iter->ipaaCur)
                    667:                        return (ISC_R_NOMORE);
                    668:                iter->ipuaCur = iter->ipaaCur->FirstUnicastAddress;
                    669:        }
                    670:        return (ISC_R_SUCCESS);
                    671: }
                    672: 
                    673: /*
                    674:  * Step the iterator to the next interface.  Unlike
                    675:  * isc_interfaceiter_next(), this may leave the iterator
                    676:  * positioned on an interface that will ultimately
                    677:  * be ignored.  Return ISC_R_NOMORE if there are no more
                    678:  * interfaces, otherwise ISC_R_SUCCESS.
                    679:  */
                    680: static isc_result_t
                    681: internal_next(isc_interfaceiter_t *iter) {
                    682:        if (iter->numIF >= iter->v4IF)
                    683:                return (ISC_R_NOMORE);
                    684: 
                    685:        /*
                    686:         * The first one needs to be set up to point to the last
                    687:         * Element of the array.  Go to the end and back up
                    688:         * Microsoft's implementation is peculiar for returning
                    689:         * the list in reverse order
                    690:         */
                    691: 
                    692:        if (iter->numIF == 0)
                    693:                iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF));
                    694: 
                    695:        iter->pos4--;
                    696:        if (&(iter->pos4) < &(iter->buf4))
                    697:                return (ISC_R_NOMORE);
                    698: 
                    699:        memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO));
                    700:        memcpy(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO));
                    701:        iter->numIF++;
                    702: 
                    703:        return (ISC_R_SUCCESS);
                    704: }
                    705: 
                    706: static isc_result_t
                    707: internal_next6(isc_interfaceiter_t *iter) {
                    708:        if (iter->pos6 == 0)
                    709:                return (ISC_R_NOMORE);
                    710:        iter->pos6--;
                    711:        return (ISC_R_SUCCESS);
                    712: }
                    713: 
                    714: isc_result_t
                    715: isc_interfaceiter_current(isc_interfaceiter_t *iter,
                    716:                          isc_interface_t *ifdata) {
                    717:        REQUIRE(iter->result == ISC_R_SUCCESS);
                    718:        memcpy(ifdata, &iter->current, sizeof(*ifdata));
                    719:        return (ISC_R_SUCCESS);
                    720: }
                    721: 
                    722: isc_result_t
                    723: isc_interfaceiter_first(isc_interfaceiter_t *iter) {
                    724:        REQUIRE(VALID_IFITER(iter));
                    725:        REQUIRE(use_GAA_determined);
                    726:        /*
                    727:         * SIO_ADDRESS_LIST_QUERY (used to query IPv6 addresses)
                    728:         * intentionally omits localhost addresses [::1] and [::fe80] in
                    729:         * some cases.  ntpd depends on enumerating [::1] to listen on
                    730:         * it, and ntpq and ntpdc default to "localhost" as the target,
                    731:         * so they will attempt to talk to [::1]:123 and fail. This
                    732:         * means we need to synthesize ::1, which we will do first,
                    733:         * hence iAddressCount + 1.  internal_next6() will decrement
                    734:         * it before the first use as an index, and internal_current6()
                    735:         * will treat pos6 == iAddressCount as a sign to synthesize
                    736:         * [::1] if needed.
                    737:         */
                    738:        if (!use_GAA && iter->buf6 != NULL)
                    739:                iter->pos6 = iter->buf6->iAddressCount + 1;
                    740:        iter->result = ISC_R_SUCCESS;
                    741:        return (isc_interfaceiter_next(iter));
                    742: }
                    743: 
                    744: isc_result_t
                    745: isc_interfaceiter_next(isc_interfaceiter_t *iter) {
                    746:        isc_result_t result;
                    747: 
                    748:        REQUIRE(VALID_IFITER(iter));
                    749:        REQUIRE(iter->result == ISC_R_SUCCESS);
                    750:        REQUIRE(use_GAA_determined);
                    751: 
                    752:        if (use_GAA) {
                    753:                do {
                    754:                        result = internal_next_GAA(iter);
                    755:                        if (ISC_R_NOMORE == result)
                    756:                                goto set_result;
                    757:                        result = internal_current_GAA(iter);
                    758:                } while (ISC_R_IGNORE == result);
                    759:                goto set_result;
                    760:        }
                    761: 
                    762:        for (;;) {
                    763:                result = internal_next(iter);
                    764:                if (result == ISC_R_NOMORE) {
                    765:                        result = internal_next6(iter);
                    766:                        if (result != ISC_R_SUCCESS)
                    767:                                break;
                    768:                        result = internal_current6(iter);
                    769:                        if (result != ISC_R_IGNORE)
                    770:                                break;
                    771:                } else if (result != ISC_R_SUCCESS)
                    772:                        break;
                    773:                result = internal_current(iter);
                    774:                if (result != ISC_R_IGNORE)
                    775:                        break;
                    776:        }
                    777:  set_result:
                    778:        iter->result = result;
                    779:        return (result);
                    780: }
                    781: 
                    782: void
                    783: isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
                    784:        isc_interfaceiter_t *iter;
                    785: 
                    786:        REQUIRE(iterp != NULL);
                    787:        iter = *iterp;
                    788:        REQUIRE(VALID_IFITER(iter));
                    789:        REQUIRE(use_GAA_determined);
                    790: 
                    791:        if (use_GAA) {
                    792:                REQUIRE(NULL == iter->buf4);
                    793:                REQUIRE(NULL == iter->buf4);
                    794:                if (iter->ipaa != NULL)
                    795:                        isc_mem_put(iter->mctx, iter->ipaa, iter->ipaasize);
                    796:        } else {
                    797:                REQUIRE(NULL == iter->ipaa);
                    798:                if (iter->buf4 != NULL)
                    799:                        isc_mem_put(iter->mctx, iter->buf4, iter->buf4size);
                    800:                if (iter->buf6 != NULL)
                    801:                        isc_mem_put(iter->mctx, iter->buf6, iter->buf6size);
                    802:        }
                    803: 
                    804:        iter->magic = 0;
                    805:        isc_mem_put(iter->mctx, iter, sizeof(*iter));
                    806:        *iterp = NULL;
                    807: }

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