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