Detect FPU by checking CPUID features.
[dragonfly.git] / contrib / bind-9.5.2 / lib / isc / unix / ifiter_ioctl.c
blob1096e3e82b52ae35569964099ade705026580881
1 /*
2 * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
18 /* $Id: ifiter_ioctl.c,v 1.58.90.3 2009/02/16 00:53:58 marka Exp $ */
20 /*! \file
21 * \brief
22 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
23 * See netintro(4).
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
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
50 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
51 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
53 #define ISC_IF_INET6_SZ \
54 sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
56 struct 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. */
91 #ifdef HAVE_TRUCLUSTER
92 #include <clua/clua.h>
93 #include <sys/socket.h>
94 #endif
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.
101 #define IFCONF_BUFSIZE_INITIAL 4096
102 #define IFCONF_BUFSIZE_MAX 1048576
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
114 static isc_result_t
115 getbuf4(isc_interfaceiter_t *iter) {
116 char strbuf[ISC_STRERRORSIZE];
118 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
120 for (;;) {
121 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
122 if (iter->buf == NULL)
123 return (ISC_R_NOMEMORY);
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;
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.
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;
147 * EINVAL. Retry with a bigger buffer.
149 } else {
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.
159 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
160 < iter->bufsize)
161 break;
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;
174 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
176 iter->bufsize *= 2;
178 return (ISC_R_SUCCESS);
180 unexpected:
181 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
182 iter->buf = NULL;
183 return (ISC_R_UNEXPECTED);
186 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
187 static isc_result_t
188 getbuf6(isc_interfaceiter_t *iter) {
189 char strbuf[ISC_STRERRORSIZE];
190 isc_result_t result;
192 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
194 for (;;) {
195 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
196 if (iter->buf6 == NULL)
197 return (ISC_R_NOMEMORY);
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;
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.
213 if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
214 == -1) {
215 #ifdef __hpux
217 * IPv6 interface scanning is not available on all
218 * kernels w/ IPv6 sockets.
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;
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;
248 * EINVAL. Retry with a bigger buffer.
250 } else {
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.
260 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
261 < iter->bufsize6)
262 break;
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;
276 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
278 iter->bufsize6 *= 2;
281 if (iter->lifc.lifc_len != 0)
282 iter->mode = 6;
283 return (ISC_R_SUCCESS);
285 cleanup:
286 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
287 iter->buf6 = NULL;
288 return (result);
290 #endif
292 isc_result_t
293 isc_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];
298 REQUIRE(mctx != NULL);
299 REQUIRE(iterp != NULL);
300 REQUIRE(*iterp == NULL);
302 iter = isc_mem_get(mctx, sizeof(*iter));
303 if (iter == NULL)
304 return (ISC_R_NOMEMORY);
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
319 * Get the interface configuration, allocating more memory if
320 * necessary.
323 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
324 result = isc_net_probeipv6();
325 if (result == ISC_R_SUCCESS) {
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.
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;
343 result = iter->result6 = getbuf6(iter);
344 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
345 goto ioctl6_failure;
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;
360 result = getbuf4(iter);
361 if (result != ISC_R_SUCCESS)
362 goto ioctl_failure;
365 * A newly created iterator has an undefined position
366 * until isc_interfaceiter_first() is called.
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;
379 iter->magic = IFITER_MAGIC;
380 *iterp = iter;
381 return (ISC_R_SUCCESS);
383 ioctl_failure:
384 if (iter->buf != NULL)
385 isc_mem_put(mctx, iter->buf, iter->bufsize);
386 (void) close(iter->socket);
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
398 isc_mem_put(mctx, iter, sizeof(*iter));
399 return (result);
402 #ifdef HAVE_TRUCLUSTER
403 static void
404 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
405 dst->family = AF_INET;
406 memcpy(&dst->type.in, src, sizeof(struct in_addr));
409 static isc_result_t
410 internal_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);
423 #endif
425 #ifdef __linux
426 static isc_result_t
427 linux_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);
436 static void
437 linux_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;
446 static isc_result_t
447 linux_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;
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);
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);
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);
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;
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);
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;
502 isc_netaddr_fromin6(&iter->current.netmask, &addr6);
503 strncpy(iter->current.name, name, sizeof(iter->current.name));
504 return (ISC_R_SUCCESS);
506 #endif
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.
516 static isc_result_t
517 internal_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
532 REQUIRE(VALID_IFITER(iter));
533 REQUIRE(iter->ifc.ifc_len == 0 ||
534 iter->pos < (unsigned int) iter->ifc.ifc_len);
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
543 if (iter->ifc.ifc_len == 0)
544 return (ISC_R_NOMORE);
546 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
548 memset(&ifreq, 0, sizeof(ifreq));
549 memcpy(&ifreq, ifrp, sizeof(ifreq));
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);
559 memset(&iter->current, 0, sizeof(iter->current));
560 iter->current.af = family;
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));
566 get_addr(family, &iter->current.address,
567 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
570 * If the interface does not have a address ignore it.
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;
585 * Get interface flags.
588 iter->current.flags = 0;
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.
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);
603 if ((ifreq.ifr_flags & IFF_UP) != 0)
604 iter->current.flags |= INTERFACE_F_UP;
606 #ifdef IFF_POINTOPOINT
607 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
608 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
609 #endif
611 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
612 iter->current.flags |= INTERFACE_F_LOOPBACK;
614 if (family == AF_INET)
615 goto inet;
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));
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);
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
645 * Netmask already zeroed.
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;
656 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
658 return (ISC_R_SUCCESS);
660 inet:
661 if (family != AF_INET)
662 return (ISC_R_IGNORE);
663 #ifdef IFF_POINTOPOINT
665 * If the interface is point-to-point, get the destination address.
667 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
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.
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);
685 get_addr(family, &iter->current.dstaddress,
686 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
688 #endif
691 * Get the network mask.
693 memset(&ifreq, 0, sizeof(ifreq));
694 memcpy(&ifreq, ifrp, sizeof(ifreq));
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.
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);
710 get_addr(family, &iter->current.netmask,
711 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
712 return (ISC_R_SUCCESS);
715 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
716 static isc_result_t
717 internal_current6(isc_interfaceiter_t *iter) {
718 struct LIFREQ *ifrp;
719 struct LIFREQ lifreq;
720 int family;
721 char strbuf[ISC_STRERRORSIZE];
722 int fd;
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);
729 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
731 memset(&lifreq, 0, sizeof(lifreq));
732 memcpy(&lifreq, ifrp, sizeof(lifreq));
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);
742 memset(&iter->current, 0, sizeof(iter->current));
743 iter->current.af = family;
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));
749 get_addr(family, &iter->current.address,
750 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
753 * If the interface does not have a address ignore it.
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;
768 * Get interface flags.
771 iter->current.flags = 0;
773 if (family == AF_INET6)
774 fd = iter->socket6;
775 else
776 fd = iter->socket;
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.
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);
791 if ((lifreq.lifr_flags & IFF_UP) != 0)
792 iter->current.flags |= INTERFACE_F_UP;
794 #ifdef IFF_POINTOPOINT
795 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
796 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
797 #endif
799 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
800 iter->current.flags |= INTERFACE_F_LOOPBACK;
802 #ifdef IFF_POINTOPOINT
804 * If the interface is point-to-point, get the destination address.
806 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
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.
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);
824 get_addr(family, &iter->current.dstaddress,
825 (struct sockaddr *)&lifreq.lifr_dstaddr,
826 lifreq.lifr_name);
828 #endif
831 * Get the network mask. Netmask already zeroed.
833 memset(&lifreq, 0, sizeof(lifreq));
834 memcpy(&lifreq, ifrp, sizeof(lifreq));
836 #ifdef lifr_addrlen
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.
842 if (family == AF_INET6) {
843 int i, bits;
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;
853 return (ISC_R_SUCCESS);
855 #endif
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.
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);
872 get_addr(family, &iter->current.netmask,
873 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
875 return (ISC_R_SUCCESS);
877 #endif
879 static isc_result_t
880 internal_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);
887 #endif
888 #ifdef HAVE_TRUCLUSTER
889 if (!iter->clua_done)
890 return(internal_current_clusteralias(iter));
891 #endif
892 return (internal_current4(iter));
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.
902 static isc_result_t
903 internal_next4(isc_interfaceiter_t *iter) {
904 #ifdef ISC_PLATFORM_HAVESALEN
905 struct ifreq *ifrp;
906 #endif
908 REQUIRE(iter->ifc.ifc_len == 0 ||
909 iter->pos < (unsigned int) iter->ifc.ifc_len);
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
918 if (iter->ifc.ifc_len == 0)
919 return (ISC_R_NOMORE);
921 #ifdef ISC_PLATFORM_HAVESALEN
922 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
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);
930 if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
931 return (ISC_R_NOMORE);
933 return (ISC_R_SUCCESS);
936 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
937 static isc_result_t
938 internal_next6(isc_interfaceiter_t *iter) {
939 #ifdef ISC_PLATFORM_HAVESALEN
940 struct LIFREQ *ifrp;
941 #endif
943 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
944 return (iter->result6);
946 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
948 #ifdef ISC_PLATFORM_HAVESALEN
949 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
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);
957 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
958 return (ISC_R_NOMORE);
960 return (ISC_R_SUCCESS);
962 #endif
964 static isc_result_t
965 internal_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);
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);
988 #endif
989 return (internal_next4(iter));
992 static void
993 internal_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);
1001 #endif
1002 #ifdef __linux
1003 if (iter->proc != NULL)
1004 fclose(iter->proc);
1005 #endif
1008 static
1009 void 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