~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to libisc/ifiter_ioctl.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-01-05 21:10:03 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090105211003-mh6zc3um4k1uhsj7
Tags: 1:4.2.4p4+dfsg-8
It did not properly check the return value of EVP_VerifyFinal
which results in an malformed DSA signature being treated as
a good signature rather than as an error.  (CVE-2009-0021)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 1999-2001  Internet Software Consortium.
 
2
 * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
 
3
 * Copyright (C) 1999-2003  Internet Software Consortium.
3
4
 *
4
5
 * Permission to use, copy, modify, and distribute this software for any
5
6
 * purpose with or without fee is hereby granted, provided that the above
6
7
 * copyright notice and this permission notice appear in all copies.
7
8
 *
8
 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
9
 
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
10
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
11
 
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
12
 
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
13
 
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
14
 
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15
 
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
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
16
 */
17
17
 
18
 
/* $Id: ifiter_ioctl.c,v 1.34 2002/08/16 00:05:57 marka Exp $ */
 
18
/* $Id: ifiter_ioctl.c,v 1.19.2.5.2.14 2004/06/22 04:40:23 marka Exp $ */
19
19
 
20
20
/*
21
21
 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
51
51
#define IFITER_MAGIC            ISC_MAGIC('I', 'F', 'I', 'T')
52
52
#define VALID_IFITER(t)         ISC_MAGIC_VALID(t, IFITER_MAGIC)
53
53
 
 
54
#define ISC_IF_INET6_SZ \
 
55
    sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
 
56
 
54
57
struct isc_interfaceiter {
55
58
        unsigned int            magic;          /* Magic number. */
56
59
        isc_mem_t               *mctx;
 
60
        int                     mode;
57
61
        int                     socket;
58
 
        int                     mode;
59
62
        struct ifconf           ifc;
60
 
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
61
 
        struct LIFCONF          lifc;
62
 
#endif
63
63
        void                    *buf;           /* Buffer for sysctl data. */
64
64
        unsigned int            bufsize;        /* Bytes allocated. */
65
 
#ifdef HAVE_TRUCLUSTER
66
 
        int                     clua_context;   /* Cluster alias context */
67
 
#endif
68
65
        unsigned int            pos;            /* Current offset in
 
66
                                                   SIOCGIFCONF data */
 
67
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
 
68
        int                     socket6;
 
69
        struct LIFCONF          lifc;
 
70
        void                    *buf6;          /* Buffer for sysctl data. */
 
71
        unsigned int            bufsize6;       /* Bytes allocated. */
 
72
        unsigned int            pos6;           /* Current offset in
69
73
                                                   SIOCGLIFCONF data */
 
74
        isc_result_t            result6;        /* Last result code. */
 
75
        isc_boolean_t           first6;
 
76
#endif
 
77
#ifdef HAVE_TRUCLUSTER
 
78
        int                     clua_context;   /* Cluster alias context */
 
79
        isc_boolean_t           clua_done;
 
80
        struct sockaddr         clua_sa;
 
81
#endif
 
82
#ifdef  __linux
 
83
        FILE *                  proc;
 
84
        char                    entry[ISC_IF_INET6_SZ];
 
85
        isc_result_t            valid;
 
86
        isc_boolean_t           first;
 
87
#endif
70
88
        isc_interface_t         current;        /* Current interface data. */
71
89
        isc_result_t            result;         /* Last result code. */
72
90
};
84
102
#define IFCONF_BUFSIZE_INITIAL  4096
85
103
#define IFCONF_BUFSIZE_MAX      1048576
86
104
 
 
105
#ifdef __linux
 
106
#ifndef IF_NAMESIZE
 
107
# ifdef IFNAMSIZ
 
108
#  define IF_NAMESIZE  IFNAMSIZ  
 
109
# else
 
110
#  define IF_NAMESIZE 16
 
111
# endif
 
112
#endif
 
113
#endif
 
114
 
87
115
static isc_result_t
88
116
getbuf4(isc_interfaceiter_t *iter) {
89
117
        char strbuf[ISC_STRERRORSIZE];
148
176
 
149
177
                iter->bufsize *= 2;
150
178
        }
151
 
        iter->mode = 4;
152
179
        return (ISC_R_SUCCESS);
153
180
 
154
181
 unexpected:
157
184
        return (ISC_R_UNEXPECTED);
158
185
}
159
186
 
 
187
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
160
188
static isc_result_t
161
189
getbuf6(isc_interfaceiter_t *iter) {
162
 
#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
163
 
        UNUSED(iter);
164
 
        return (ISC_R_NOTIMPLEMENTED);
165
 
#else
166
190
        char strbuf[ISC_STRERRORSIZE];
167
191
        isc_result_t result;
168
192
 
169
 
        iter->bufsize = IFCONF_BUFSIZE_INITIAL;
 
193
        iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
170
194
 
171
195
        for (;;) {
172
 
                iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
173
 
                if (iter->buf == NULL)
 
196
                iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
 
197
                if (iter->buf6 == NULL)
174
198
                        return (ISC_R_NOMEMORY);
175
199
 
176
 
                memset(&iter->lifc.lifc_len, 0, sizeof(iter->lifc.lifc_len));
 
200
                memset(&iter->lifc, 0, sizeof(iter->lifc));
177
201
#ifdef ISC_HAVE_LIFC_FAMILY
178
 
                iter->lifc.lifc_family = AF_UNSPEC;
 
202
                iter->lifc.lifc_family = AF_INET6;
179
203
#endif
180
204
#ifdef ISC_HAVE_LIFC_FLAGS
181
205
                iter->lifc.lifc_flags = 0;
182
206
#endif
183
 
                iter->lifc.lifc_len = iter->bufsize;
184
 
                iter->lifc.lifc_buf = iter->buf;
 
207
                iter->lifc.lifc_len = iter->bufsize6;
 
208
                iter->lifc.lifc_buf = iter->buf6;
185
209
                /*
186
210
                 * Ignore the HP/UX warning about "integer overflow during
187
211
                 * conversion".  It comes from its own macro definition,
188
212
                 * and is really hard to shut up.
189
213
                 */
190
 
                if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->lifc)
 
214
                if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
191
215
                    == -1) {
192
216
#ifdef __hpux
193
217
                        /*
233
257
                         * retry.
234
258
                         */
235
259
                        if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
236
 
                            < iter->bufsize)
 
260
                            < iter->bufsize6)
237
261
                                break;
238
262
                }
239
 
                if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
 
263
                if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
240
264
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
241
265
                                         isc_msgcat_get(isc_msgcat,
242
266
                                                        ISC_MSGSET_IFITERIOCTL,
248
272
                        result = ISC_R_UNEXPECTED;
249
273
                        goto cleanup;
250
274
                }
251
 
                isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
 
275
                isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
252
276
 
253
 
                iter->bufsize *= 2;
 
277
                iter->bufsize6 *= 2;
254
278
        }
255
279
 
256
 
        iter->mode = 6;
 
280
        if (iter->lifc.lifc_len != 0)
 
281
                iter->mode = 6;
257
282
        return (ISC_R_SUCCESS);
258
283
 
259
284
 cleanup:
260
 
        isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
261
 
        iter->buf = NULL;
 
285
        isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
 
286
        iter->buf6 = NULL;
262
287
        return (result);
 
288
}
263
289
#endif
264
 
}
265
290
 
266
291
isc_result_t
267
292
isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
277
302
                return (ISC_R_NOMEMORY);
278
303
 
279
304
        iter->mctx = mctx;
 
305
        iter->mode = 4;
280
306
        iter->buf = NULL;
281
 
        iter->mode = 0;
 
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
282
315
 
283
316
        /*
284
 
         * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on.
 
317
         * Get the interface configuration, allocating more memory if
 
318
         * necessary.
285
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
                iter->result6 = getbuf6(iter);
 
342
                if (iter->result6 != ISC_R_NOTIMPLEMENTED &&
 
343
                    iter->result6 != ISC_R_SUCCESS)
 
344
                        goto ioctl6_failure;
 
345
        }
 
346
#endif
286
347
        if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
287
348
                isc__strerror(errno, strbuf, sizeof(strbuf));
288
349
                UNEXPECTED_ERROR(__FILE__, __LINE__,
295
356
                result = ISC_R_UNEXPECTED;
296
357
                goto socket_failure;
297
358
        }
298
 
 
299
 
        /*
300
 
         * Get the interface configuration, allocating more memory if
301
 
         * necessary.
302
 
         */
303
 
 
304
 
        result = isc_net_probeipv6();
305
 
        if (result == ISC_R_SUCCESS)
306
 
                result = getbuf6(iter);
307
 
        if (result != ISC_R_SUCCESS)
308
 
                result = getbuf4(iter);
 
359
        result = getbuf4(iter);
309
360
        if (result != ISC_R_SUCCESS)
310
361
                goto ioctl_failure;
311
362
 
315
366
         */
316
367
#ifdef HAVE_TRUCLUSTER
317
368
        iter->clua_context = -1;
318
 
#endif
319
 
        iter->pos = (unsigned int) -1;
 
369
        iter->clua_done = ISC_TRUE;
 
370
#endif
 
371
#ifdef __linux
 
372
        iter->proc = fopen("/proc/net/if_inet6", "r");
 
373
        iter->valid = ISC_R_FAILURE;
 
374
        iter->first = ISC_FALSE;
 
375
#endif
320
376
        iter->result = ISC_R_FAILURE;
321
377
 
322
378
        iter->magic = IFITER_MAGIC;
329
385
        (void) close(iter->socket);
330
386
 
331
387
 socket_failure:
 
388
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
 
389
        if (iter->buf6 != NULL)
 
390
                isc_mem_put(mctx, iter->buf6, iter->bufsize6);
 
391
  ioctl6_failure:
 
392
        if (iter->socket6 != -1)
 
393
                (void) close(iter->socket6);
 
394
  socket6_failure:
 
395
#endif
 
396
 
332
397
        isc_mem_put(mctx, iter, sizeof(*iter));
333
398
        return (result);
334
399
}
342
407
 
343
408
static isc_result_t
344
409
internal_current_clusteralias(isc_interfaceiter_t *iter) {
345
 
        struct sockaddr sa;
346
410
        struct clua_info ci;
347
 
        while (clua_getaliasaddress(&sa, &iter->clua_context) == CLUA_SUCCESS) {
348
 
                if (clua_getaliasinfo(&sa, &ci) != CLUA_SUCCESS)
349
 
                        continue;
350
 
                memset(&iter->current, 0, sizeof(iter->current));
351
 
                iter->current.af = sa.sa_family;
352
 
                memset(iter->current.name, 0, sizeof(iter->current.name));
353
 
                sprintf(iter->current.name, "clua%d", ci.aliasid);
354
 
                iter->current.flags = INTERFACE_F_UP;
355
 
                get_inaddr(&iter->current.address, &ci.addr);
356
 
                get_inaddr(&iter->current.netmask, &ci.netmask);
357
 
                return (ISC_R_SUCCESS);
358
 
        }
359
 
        return (ISC_R_NOMORE);
 
411
        if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
 
412
                return (ISC_R_IGNORE);
 
413
        memset(&iter->current, 0, sizeof(iter->current));
 
414
        iter->current.af = iter->clua_sa.sa_family;
 
415
        memset(iter->current.name, 0, sizeof(iter->current.name));
 
416
        sprintf(iter->current.name, "clua%d", ci.aliasid);
 
417
        iter->current.flags = INTERFACE_F_UP;
 
418
        get_inaddr(&iter->current.address, &ci.addr);
 
419
        get_inaddr(&iter->current.netmask, &ci.netmask);
 
420
        return (ISC_R_SUCCESS);
 
421
}
 
422
#endif
 
423
 
 
424
#ifdef __linux
 
425
static isc_result_t
 
426
linux_if_inet6_next(isc_interfaceiter_t *iter) {
 
427
        if (iter->proc != NULL &&
 
428
            fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
 
429
                iter->valid = ISC_R_SUCCESS;
 
430
        else
 
431
                iter->valid = ISC_R_NOMORE;
 
432
        return (iter->valid);
 
433
}
 
434
 
 
435
static void
 
436
linux_if_inet6_first(isc_interfaceiter_t *iter) {
 
437
        if (iter->proc != NULL) {
 
438
                rewind(iter->proc);
 
439
                (void)linux_if_inet6_next(iter);
 
440
        } else
 
441
                iter->valid = ISC_R_NOMORE;
 
442
        iter->first = ISC_FALSE;
 
443
}
 
444
 
 
445
static isc_result_t
 
446
linux_if_inet6_current(isc_interfaceiter_t *iter) {
 
447
        char address[33];
 
448
        char name[IF_NAMESIZE+1];
 
449
        char strbuf[ISC_STRERRORSIZE];
 
450
        struct in6_addr addr6;
 
451
        struct ifreq ifreq;
 
452
        int ifindex, prefix, scope, flags;
 
453
        int res;
 
454
        unsigned int i;
 
455
 
 
456
        if (iter->valid != ISC_R_SUCCESS)
 
457
                return (iter->valid);
 
458
        if (iter->proc == NULL) {
 
459
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
460
                              "/proc/net/if_inet6:iter->proc == NULL");
 
461
                return (ISC_R_FAILURE);
 
462
        }
 
463
 
 
464
        /*
 
465
         * Format for /proc/net/if_inet6:
 
466
         * (see iface_proc_info() in net/ipv6/addrconf.c)
 
467
         * <addr6:32> <ifindex:2> <prefix:2> <scope:2> <flags:2> <name:8>
 
468
         */
 
469
        res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
 
470
                     address, &ifindex, &prefix, &scope, &flags, name);
 
471
        if (res != 6) {
 
472
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
473
                              "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
 
474
                              res);
 
475
                return (ISC_R_FAILURE);
 
476
        }
 
477
        if (strlen(address) != 32) {
 
478
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
479
                              "/proc/net/if_inet6:strlen(%s) != 32", address);
 
480
                return (ISC_R_FAILURE);
 
481
        }
 
482
        for (i = 0; i < 16; i++) {
 
483
                unsigned char byte;
 
484
                static const char hex[] = "0123456789abcdef";
 
485
                byte = ((index(hex, address[i * 2]) - hex) << 4) |
 
486
                       (index(hex, address[i * 2 + 1]) - hex);
 
487
                addr6.s6_addr[i] = byte;
 
488
        }
 
489
        iter->current.af = AF_INET6;
 
490
        /* iter->current.ifindex = ifindex; */
 
491
        iter->current.flags = 0;
 
492
 
 
493
        memset(&ifreq, 0, sizeof(ifreq));
 
494
        INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
 
495
        strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
 
496
 
 
497
        if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
 
498
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
499
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
500
                                 "%s: getting interface flags: %s",
 
501
                                 ifreq.ifr_name, strbuf);
 
502
                return (ISC_R_IGNORE);
 
503
        }
 
504
 
 
505
        if ((ifreq.ifr_flags & IFF_UP) != 0)
 
506
                iter->current.flags |= INTERFACE_F_UP;
 
507
#ifdef IFF_POINTOPOINT
 
508
        if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) 
 
509
                iter->current.flags |= INTERFACE_F_POINTTOPOINT;
 
510
#endif
 
511
        if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
 
512
                iter->current.flags |= INTERFACE_F_LOOPBACK;
 
513
        if ((ifreq.ifr_flags & IFF_BROADCAST) != 0)
 
514
                iter->current.flags |= INTERFACE_F_BROADCAST;
 
515
#ifdef IFF_MULTICAST
 
516
        if ((ifreq.ifr_flags & IFF_MULTICAST) != 0)
 
517
                iter->current.flags |= INTERFACE_F_MULTICAST;
 
518
#endif
 
519
 
 
520
        /*
 
521
         * enable_multicast_if() requires scopeid for setsockopt,
 
522
         * so associate address with their corresponding ifindex.
 
523
         */
 
524
        isc_netaddr_fromin6(&iter->current.address, &addr6);
 
525
        isc_netaddr_setzone(&iter->current.address, (isc_uint32_t)ifindex);
 
526
 
 
527
        for (i = 0; i < 16; i++) {
 
528
                if (prefix > 8) {
 
529
                        addr6.s6_addr[i] = 0xff;
 
530
                        prefix -= 8;
 
531
                } else {
 
532
                        addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
 
533
                        prefix = 0;
 
534
                }
 
535
        }
 
536
        isc_netaddr_fromin6(&iter->current.netmask, &addr6);
 
537
        strncpy(iter->current.name, name, sizeof(iter->current.name));
 
538
        return (ISC_R_SUCCESS);
360
539
}
361
540
#endif
362
541
 
374
553
        struct ifreq ifreq;
375
554
        int family;
376
555
        char strbuf[ISC_STRERRORSIZE];
377
 
#if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
378
 
        struct if_laddrreq if_laddrreq;
379
 
        int i, bits;
 
556
#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
 
557
        struct lifreq lifreq;
 
558
#else
 
559
        char sabuf[256];
 
560
#endif
 
561
        int i, bits, prefixlen;
 
562
#ifdef __linux
 
563
        isc_result_t result;
380
564
#endif
381
565
 
382
566
        REQUIRE(VALID_IFITER(iter));
383
567
        REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
384
568
 
 
569
#ifdef __linux
 
570
        result = linux_if_inet6_current(iter);
 
571
        if (result != ISC_R_NOMORE)
 
572
                return (result);
 
573
        iter->first = ISC_TRUE;
 
574
#endif
 
575
 
385
576
        ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
386
577
 
387
578
        memset(&ifreq, 0, sizeof(ifreq));
388
579
        memcpy(&ifreq, ifrp, sizeof(ifreq));
389
580
 
390
581
        family = ifreq.ifr_addr.sa_family;
391
 
#if !defined (SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
392
 
    defined(ISC_PLATFORM_HAVEIPV6)
 
582
#if defined(ISC_PLATFORM_HAVEIPV6)
393
583
        if (family != AF_INET && family != AF_INET6)
394
584
#else
395
585
        if (family != AF_INET)
403
593
        memset(iter->current.name, 0, sizeof(iter->current.name));
404
594
        memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
405
595
 
406
 
        /* Some older O/S's don't have the interface index. Since ifr_index is
407
 
         * usually a macro definition into the actual structure we
408
 
         * use that to determine if we should get it.
409
 
         */
410
 
#ifdef ifr_index
411
 
        iter->current.ifindex = ifreq.ifr_index;        /* Save the if index */
412
 
#else
413
 
        iter->current.ifindex = 0;
414
 
#endif
415
 
 
416
596
        get_addr(family, &iter->current.address,
417
 
                 (struct sockaddr *)&ifrp->ifr_addr);
 
597
                 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
418
598
 
419
599
        /*
420
600
         * If the interface does not have a address ignore it.
424
604
                if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
425
605
                        return (ISC_R_IGNORE);
426
606
                break;
 
607
#ifdef ISC_PLATFORM_HAVEIPV6
427
608
        case AF_INET6:
428
609
                if (memcmp(&iter->current.address.type.in6, &in6addr_any,
429
610
                           sizeof(in6addr_any)) == 0)
430
611
                        return (ISC_R_IGNORE);
431
612
                break;
 
613
#endif
432
614
        }
433
615
 
434
616
        /*
453
635
        if ((ifreq.ifr_flags & IFF_UP) != 0)
454
636
                iter->current.flags |= INTERFACE_F_UP;
455
637
 
 
638
#ifdef IFF_POINTOPOINT
456
639
        if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
457
640
                iter->current.flags |= INTERFACE_F_POINTTOPOINT;
 
641
#endif
458
642
 
459
643
        if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
460
644
                iter->current.flags |= INTERFACE_F_LOOPBACK;
469
653
        }
470
654
#endif
471
655
 
472
 
#if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
473
 
        if (family == AF_INET) 
 
656
        if (family == AF_INET)
474
657
                goto inet;
475
658
 
476
 
        memset(&if_laddrreq, 0, sizeof(if_laddrreq));
477
 
        memcpy(if_laddrreq.iflr_name, iter->current.name,
478
 
               sizeof(if_laddrreq.iflr_name));
479
 
        memcpy(&if_laddrreq.addr, &iter->current.address.type.in6,
 
659
#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
 
660
        memset(&lifreq, 0, sizeof(lifreq));
 
661
        memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
 
662
        memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
480
663
               sizeof(iter->current.address.type.in6));
481
664
 
482
 
        if (ioctl(iter->socket, SIOCGLIFADDR, &if_laddrreq) < 0) {
 
665
        if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
483
666
                isc__strerror(errno, strbuf, sizeof(strbuf));
484
667
                UNEXPECTED_ERROR(__FILE__, __LINE__,
485
668
                                 "%s: getting interface address: %s",
486
669
                                 ifreq.ifr_name, strbuf);
487
670
                return (ISC_R_IGNORE);
488
671
        }
 
672
        prefixlen = lifreq.lifr_addrlen;
 
673
#else
 
674
        isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
 
675
        UNEXPECTED_ERROR(__FILE__, __LINE__,
 
676
                      isc_msgcat_get(isc_msgcat,
 
677
                                     ISC_MSGSET_IFITERIOCTL,
 
678
                                     ISC_MSG_GETIFCONFIG,
 
679
                                     "prefix length for %s is unknown "
 
680
                                     "(assume 128)"), sabuf);
 
681
        prefixlen = 128;
 
682
#endif
489
683
 
490
684
        /*
491
685
         * Netmask already zeroed.
492
686
         */
493
687
        iter->current.netmask.family = family;
494
688
        for (i = 0; i < 16; i++) {
495
 
                if (if_laddrreq.prefixlen > 8) {
 
689
                if (prefixlen > 8) {
496
690
                        bits = 0;
497
 
                        if_laddrreq.prefixlen -= 8;
 
691
                        prefixlen -= 8;
498
692
                } else {
499
 
                        bits = 8 - if_laddrreq.prefixlen;
500
 
                        if_laddrreq.prefixlen = 0;
 
693
                        bits = 8 - prefixlen;
 
694
                        prefixlen = 0;
501
695
                }
502
696
                iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
503
697
        }
504
698
        return (ISC_R_SUCCESS);
505
699
 
506
700
 inet:
507
 
#endif
508
701
        if (family != AF_INET)
509
702
                return (ISC_R_IGNORE);
 
703
#ifdef IFF_POINTOPOINT
510
704
        /*
511
705
         * If the interface is point-to-point, get the destination address.
512
706
         */
529
723
                        return (ISC_R_IGNORE);
530
724
                }
531
725
                get_addr(family, &iter->current.dstaddress,
532
 
                         (struct sockaddr *)&ifreq.ifr_dstaddr);
 
726
                         (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
533
727
        }
534
 
 
 
728
#endif
535
729
        if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
536
730
                /*
537
731
                 * Ignore the HP/UX warning about "integer overflow during
551
745
                        return (ISC_R_IGNORE);
552
746
                }
553
747
                get_addr(family, &iter->current.broadcast,
554
 
                         (struct sockaddr *)&ifreq.ifr_broadaddr);
 
748
                         (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name);
555
749
        }
 
750
 
556
751
        /*
557
752
         * Get the network mask.
558
753
         */
563
758
         * conversion.  It comes from its own macro definition,
564
759
         * and is really hard to shut up.
565
760
         */
566
 
        if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq)
567
 
            < 0) {
 
761
        if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
568
762
                isc__strerror(errno, strbuf, sizeof(strbuf));
569
763
                UNEXPECTED_ERROR(__FILE__, __LINE__,
570
764
                        isc_msgcat_get(isc_msgcat,
575
769
                return (ISC_R_IGNORE);
576
770
        }
577
771
        get_addr(family, &iter->current.netmask,
578
 
                 (struct sockaddr *)&ifreq.ifr_addr);
 
772
                 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
579
773
        return (ISC_R_SUCCESS);
580
774
}
581
775
 
 
776
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
582
777
static isc_result_t
583
778
internal_current6(isc_interfaceiter_t *iter) {
584
 
#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
585
 
        UNUSED(iter);
586
 
        return (ISC_R_NOTIMPLEMENTED);
587
 
#else
588
779
        struct LIFREQ *ifrp;
589
780
        struct LIFREQ lifreq;
590
781
        int family;
591
782
        char strbuf[ISC_STRERRORSIZE];
 
783
        int fd;
592
784
 
593
785
        REQUIRE(VALID_IFITER(iter));
594
 
        REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len);
 
786
        if (iter->result6 != ISC_R_SUCCESS)
 
787
                return (iter->result6);
 
788
        REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
595
789
 
596
 
        ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos);
 
790
        ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
597
791
 
598
792
        memset(&lifreq, 0, sizeof(lifreq));
599
793
        memcpy(&lifreq, ifrp, sizeof(lifreq));
612
806
        INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
613
807
        memset(iter->current.name, 0, sizeof(iter->current.name));
614
808
        memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
615
 
        iter->current.ifindex = lifreq.lifr_index;      /* Save the if index */
616
809
 
617
810
        get_addr(family, &iter->current.address,
618
 
                 (struct sockaddr *)&lifreq.lifr_addr);
 
811
                 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
619
812
 
620
 
#ifdef ISC_PLATFORM_HAVEIPV6
621
 
        iter->current.scopeid = get_scopeid(family, (struct sockaddr *)&lifreq.lifr_addr);
622
 
#endif
623
813
        /*
624
814
         * If the interface does not have a address ignore it.
625
815
         */
628
818
                if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
629
819
                        return (ISC_R_IGNORE);
630
820
                break;
 
821
#ifdef ISC_PLATFORM_HAVEIPV6
631
822
        case AF_INET6:
632
823
                if (memcmp(&iter->current.address.type.in6, &in6addr_any,
633
824
                           sizeof(in6addr_any)) == 0)
634
825
                        return (ISC_R_IGNORE);
635
826
                break;
 
827
#endif
636
828
        }
637
829
 
638
830
        /*
641
833
 
642
834
        iter->current.flags = 0;
643
835
 
 
836
        if (family == AF_INET6)
 
837
                fd = iter->socket6;
 
838
        else
 
839
                fd = iter->socket;
 
840
 
644
841
        /*
645
842
         * Ignore the HP/UX warning about "integer overflow during
646
843
         * conversion.  It comes from its own macro definition,
647
844
         * and is really hard to shut up.
648
845
         */
649
 
        if (ioctl(iter->socket, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
650
 
 
651
 
                /*
652
 
                 * XXX This should be looked at further since it looks strange.
653
 
                 * If we get an ENXIO then we ignore the error and not worry
654
 
                 * about the flags.
655
 
                 */
656
 
                if (errno != ENXIO) {
657
 
                        isc__strerror(errno, strbuf, sizeof(strbuf));
658
 
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
 
846
        if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
 
847
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
848
                UNEXPECTED_ERROR(__FILE__, __LINE__,
659
849
                                 "%s: getting interface flags: %s",
660
850
                                 lifreq.lifr_name, strbuf);
661
 
                        return (ISC_R_IGNORE);
662
 
                }
 
851
                return (ISC_R_IGNORE);
663
852
        }
664
853
 
665
854
        if ((lifreq.lifr_flags & IFF_UP) != 0)
666
855
                iter->current.flags |= INTERFACE_F_UP;
667
856
 
 
857
#ifdef IFF_POINTOPOINT
668
858
        if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
669
859
                iter->current.flags |= INTERFACE_F_POINTTOPOINT;
 
860
#endif
670
861
 
671
862
        if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
672
863
                iter->current.flags |= INTERFACE_F_LOOPBACK;
681
872
        }
682
873
#endif
683
874
 
 
875
#ifdef IFF_POINTOPOINT
684
876
        /*
685
877
         * If the interface is point-to-point, get the destination address.
686
878
         */
690
882
                 * conversion.  It comes from its own macro definition,
691
883
                 * and is really hard to shut up.
692
884
                 */
693
 
                if (ioctl(iter->socket, SIOCGLIFDSTADDR, (char *)&lifreq)
 
885
                if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
694
886
                    < 0) {
695
887
                        isc__strerror(errno, strbuf, sizeof(strbuf));
696
888
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
703
895
                        return (ISC_R_IGNORE);
704
896
                }
705
897
                get_addr(family, &iter->current.dstaddress,
706
 
                         (struct sockaddr *)&lifreq.lifr_dstaddr);
 
898
                         (struct sockaddr *)&lifreq.lifr_dstaddr,
 
899
                         lifreq.lifr_name);
707
900
        }
 
901
#endif
 
902
 
708
903
#ifdef SIOCGLIFBRDADDR
709
904
        if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
710
905
                /*
725
920
                        return (ISC_R_IGNORE);
726
921
                }
727
922
                get_addr(family, &iter->current.broadcast,
728
 
                         (struct sockaddr *)&lifreq.lifr_broadaddr);
 
923
                         (struct sockaddr *)&lifreq.lifr_broadaddr,
 
924
                         lifreq.lifr_name);
729
925
        }
730
926
#endif  /* SIOCGLIFBRDADDR */
731
927
 
732
928
        /*
733
 
         * Get the network mask.
 
929
         * Get the network mask.  Netmask already zeroed.
734
930
         */
735
931
        memset(&lifreq, 0, sizeof(lifreq));
736
932
        memcpy(&lifreq, ifrp, sizeof(lifreq));
737
 
        switch (family) {
738
 
        case AF_INET:
739
 
                /*
740
 
                 * Ignore the HP/UX warning about "integer overflow during
741
 
                 * conversion.  It comes from its own macro definition,
742
 
                 * and is really hard to shut up.
743
 
                 */
744
 
                if (ioctl(iter->socket, SIOCGLIFNETMASK, (char *)&lifreq)
745
 
                    < 0) {
746
 
                        isc__strerror(errno, strbuf, sizeof(strbuf));
747
 
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
748
 
                                isc_msgcat_get(isc_msgcat,
749
 
                                               ISC_MSGSET_IFITERIOCTL,
750
 
                                               ISC_MSG_GETNETMASK,
751
 
                                               "%s: getting netmask: %s"),
752
 
                                         lifreq.lifr_name, strbuf);
753
 
                        return (ISC_R_IGNORE);
754
 
                }
755
 
                get_addr(family, &iter->current.netmask,
756
 
                         (struct sockaddr *)&lifreq.lifr_addr);
757
 
                break;
758
 
        case AF_INET6: {
 
933
 
759
934
#ifdef lifr_addrlen
 
935
        /*
 
936
         * Special case: if the system provides lifr_addrlen member, the
 
937
         * netmask of an IPv6 address can be derived from the length, since
 
938
         * an IPv6 address always has a contiguous mask.
 
939
         */
 
940
        if (family == AF_INET6) {
760
941
                int i, bits;
761
942
 
762
 
                /*
763
 
                 * Netmask already zeroed.
764
 
                 */
765
943
                iter->current.netmask.family = family;
766
944
                for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
767
945
                        bits = lifreq.lifr_addrlen - i;
769
947
                        iter->current.netmask.type.in6.s6_addr[i / 8] =
770
948
                                (~0 << bits) & 0xff;
771
949
                }
 
950
 
 
951
                return (ISC_R_SUCCESS);
 
952
        }
772
953
#endif
773
 
                break;
774
 
        }
775
 
        }
 
954
 
 
955
        /*
 
956
         * Ignore the HP/UX warning about "integer overflow during
 
957
         * conversion.  It comes from its own macro definition,
 
958
         * and is really hard to shut up.
 
959
         */
 
960
        if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
 
961
                isc__strerror(errno, strbuf, sizeof(strbuf));
 
962
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
963
                                 isc_msgcat_get(isc_msgcat,
 
964
                                                ISC_MSGSET_IFITERIOCTL,
 
965
                                                ISC_MSG_GETNETMASK,
 
966
                                                "%s: getting netmask: %s"),
 
967
                                 lifreq.lifr_name, strbuf);
 
968
                return (ISC_R_IGNORE);
 
969
        }
 
970
        get_addr(family, &iter->current.netmask,
 
971
                 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
776
972
 
777
973
        return (ISC_R_SUCCESS);
778
 
#endif
779
974
}
 
975
#endif
780
976
 
781
977
static isc_result_t
782
978
internal_current(isc_interfaceiter_t *iter) {
783
 
        if (iter->mode == 6)
784
 
                return (internal_current6(iter));
 
979
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
 
980
        if (iter->mode == 6) {
 
981
                iter->result6 = internal_current6(iter);
 
982
                if (iter->result6 != ISC_R_NOMORE)
 
983
                        return (iter->result6);
 
984
        }
 
985
#endif
 
986
#ifdef HAVE_TRUCLUSTER
 
987
        if (!iter->clua_done)
 
988
                return(internal_current_clusteralias(iter));
 
989
#endif
785
990
        return (internal_current4(iter));
786
991
}
787
992
 
798
1003
 
799
1004
        REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
800
1005
 
801
 
#ifdef HAVE_TRUCLUSTER
802
 
        if (internal_current_clusteralias(iter) == ISC_R_SUCCESS)
 
1006
#ifdef __linux
 
1007
        if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
 
1008
                return (ISC_R_SUCCESS);
 
1009
        if (!iter->first)
803
1010
                return (ISC_R_SUCCESS);
804
1011
#endif
805
1012
        ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
817
1024
        return (ISC_R_SUCCESS);
818
1025
}
819
1026
 
 
1027
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
820
1028
static isc_result_t
821
1029
internal_next6(isc_interfaceiter_t *iter) {
822
 
#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
823
 
        UNUSED(iter);
824
 
        return (ISC_R_NOTIMPLEMENTED);
825
 
#else
826
1030
        struct LIFREQ *ifrp;
827
 
 
828
 
        REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len);
829
 
 
830
 
        ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos);
 
1031
        
 
1032
        if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
 
1033
                return (iter->result6);
 
1034
 
 
1035
        REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
 
1036
 
 
1037
        ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
831
1038
 
832
1039
#ifdef ISC_PLATFORM_HAVESALEN
833
1040
        if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
834
 
                iter->pos += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
 
1041
                iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
835
1042
        else
836
1043
#endif
837
 
                iter->pos += sizeof(*ifrp);
 
1044
                iter->pos6 += sizeof(*ifrp);
838
1045
 
839
 
        if (iter->pos >= (unsigned int) iter->lifc.lifc_len)
 
1046
        if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
840
1047
                return (ISC_R_NOMORE);
841
1048
 
842
1049
        return (ISC_R_SUCCESS);
843
 
#endif
844
1050
}
 
1051
#endif
845
1052
 
846
1053
static isc_result_t
847
1054
internal_next(isc_interfaceiter_t *iter) {
848
 
        if (iter->mode == 6)
849
 
                return (internal_next6(iter));
 
1055
#ifdef HAVE_TRUCLUSTER
 
1056
        int clua_result;
 
1057
#endif
 
1058
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
 
1059
        if (iter->mode == 6) {
 
1060
                iter->result6 = internal_next6(iter);
 
1061
                if (iter->result6 != ISC_R_NOMORE)
 
1062
                        return (iter->result6);
 
1063
                if (iter->first6) {
 
1064
                        iter->first6 = ISC_FALSE;
 
1065
                        return (ISC_R_SUCCESS);
 
1066
                }
 
1067
        }
 
1068
#endif
 
1069
#ifdef HAVE_TRUCLUSTER
 
1070
        if (!iter->clua_done) {
 
1071
                clua_result = clua_getaliasaddress(&iter->clua_sa,
 
1072
                                                   &iter->clua_context);
 
1073
                if (clua_result != CLUA_SUCCESS)
 
1074
                        iter->clua_done = ISC_TRUE;
 
1075
                return (ISC_R_SUCCESS);
 
1076
        }
 
1077
#endif
850
1078
        return (internal_next4(iter));
851
1079
}
852
1080
 
853
1081
static void
854
1082
internal_destroy(isc_interfaceiter_t *iter) {
855
1083
        (void) close(iter->socket);
 
1084
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
 
1085
        if (iter->socket6 != -1)
 
1086
                (void) close(iter->socket6);
 
1087
        if (iter->buf6 != NULL) {
 
1088
                isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
 
1089
        }
 
1090
#endif
 
1091
#ifdef __linux
 
1092
        if (iter->proc != NULL)
 
1093
                fclose(iter->proc);
 
1094
#endif
 
1095
}
 
1096
 
 
1097
static
 
1098
void internal_first(isc_interfaceiter_t *iter) {
 
1099
#ifdef HAVE_TRUCLUSTER
 
1100
        int clua_result;
 
1101
#endif
 
1102
        iter->pos = 0;
 
1103
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
 
1104
        iter->pos6 = 0;
 
1105
        if (iter->result6 == ISC_R_NOMORE)
 
1106
                iter->result6 = ISC_R_SUCCESS;
 
1107
        iter->first6 = ISC_TRUE;
 
1108
#endif
 
1109
#ifdef HAVE_TRUCLUSTER
 
1110
        iter->clua_context = 0;
 
1111
        clua_result = clua_getaliasaddress(&iter->clua_sa,
 
1112
                                           &iter->clua_context);
 
1113
        iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
 
1114
#endif
 
1115
#ifdef __linux
 
1116
        linux_if_inet6_first(iter);
 
1117
#endif
856
1118
}