2 * Copyright (C) 2004-2007 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.44.18.13 2007/08/31 23:46:25 tbox Exp $ */
22 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
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
33 #define ISC_HAVE_LIFC_FAMILY 1
34 #define ISC_HAVE_LIFC_FLAGS 1
35 #define LIFCONF lifconf
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
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. */
62 void *buf; /* Buffer for sysctl data. */
63 unsigned int bufsize; /* Bytes allocated. */
64 unsigned int pos; /* Current offset in
66 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
69 void *buf6; /* Buffer for sysctl data. */
70 unsigned int bufsize6; /* Bytes allocated. */
71 unsigned int pos6; /* Current offset in
73 isc_result_t result6; /* Last result code. */
76 #ifdef HAVE_TRUCLUSTER
77 int clua_context; /* Cluster alias context */
78 isc_boolean_t clua_done;
79 struct sockaddr clua_sa;
83 char entry[ISC_IF_INET6_SZ];
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>
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
107 # define IF_NAMESIZE IFNAMSIZ
109 # define IF_NAMESIZE 16
115 getbuf4(isc_interfaceiter_t *iter) {
116 char strbuf[ISC_STRERRORSIZE];
118 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
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 "interger 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)
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,
142 "configuration: %s"),
147 * EINVAL. Retry with a bigger buffer.
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
159 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
163 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
164 UNEXPECTED_ERROR(__FILE__, __LINE__,
165 isc_msgcat_get(isc_msgcat,
166 ISC_MSGSET_IFITERIOCTL,
174 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
178 return (ISC_R_SUCCESS);
181 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
183 return (ISC_R_UNEXPECTED);
186 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
188 getbuf6(isc_interfaceiter_t *iter) {
189 char strbuf[ISC_STRERRORSIZE];
192 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
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;
203 #ifdef ISC_HAVE_LIFC_FLAGS
204 iter->lifc.lifc_flags = 0;
206 iter->lifc.lifc_len = iter->bufsize6;
207 iter->lifc.lifc_buf = iter->buf6;
209 * Ignore the HP/UX warning about "interger 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)
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,
225 isc_msgcat_get(isc_msgcat,
226 ISC_MSGSET_IFITERIOCTL,
229 "configuration: %s"),
231 result = ISC_R_FAILURE;
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,
242 "configuration: %s"),
244 result = ISC_R_UNEXPECTED;
248 * EINVAL. Retry with a bigger buffer.
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
260 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
264 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
265 UNEXPECTED_ERROR(__FILE__, __LINE__,
266 isc_msgcat_get(isc_msgcat,
267 ISC_MSGSET_IFITERIOCTL,
273 result = ISC_R_UNEXPECTED;
276 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
281 if (iter->lifc.lifc_len != 0)
283 return (ISC_R_SUCCESS);
286 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
293 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
294 isc_interfaceiter_t *iter;
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));
304 return (ISC_R_NOMEMORY);
309 iter->pos = (unsigned int) -1;
310 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
312 iter->pos6 = (unsigned int) -1;
313 iter->result6 = ISC_R_NOMORE;
315 iter->first6 = ISC_FALSE;
319 * Get the interface configuration, allocating more memory if
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,
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)
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,
357 result = ISC_R_UNEXPECTED;
360 result = getbuf4(iter);
361 if (result != ISC_R_SUCCESS)
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;
373 iter->proc = fopen("/proc/net/if_inet6", "r");
374 iter->valid = ISC_R_FAILURE;
375 iter->first = ISC_FALSE;
377 iter->result = ISC_R_FAILURE;
379 iter->magic = IFITER_MAGIC;
381 return (ISC_R_SUCCESS);
384 if (iter->buf != NULL)
385 isc_mem_put(mctx, iter->buf, iter->bufsize);
386 (void) close(iter->socket);
389 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
390 if (iter->buf6 != NULL)
391 isc_mem_put(mctx, iter->buf6, iter->bufsize6);
393 if (iter->socket6 != -1)
394 (void) close(iter->socket6);
398 isc_mem_put(mctx, iter, sizeof(*iter));
402 #ifdef HAVE_TRUCLUSTER
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));
410 internal_current_clusteralias(isc_interfaceiter_t *iter) {
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);
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;
432 iter->valid = ISC_R_NOMORE;
433 return (iter->valid);
437 linux_if_inet6_first(isc_interfaceiter_t *iter) {
438 if (iter->proc != NULL) {
440 (void)linux_if_inet6_next(iter);
442 iter->valid = ISC_R_NOMORE;
443 iter->first = ISC_FALSE;
447 linux_if_inet6_current(isc_interfaceiter_t *iter) {
449 char name[IF_NAMESIZE+1];
450 struct in6_addr addr6;
451 int ifindex, prefix, flag3, flag4;
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);
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)",
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++) {
481 static const char hex[] = "0123456789abcdef";
482 byte = ((index(hex, address[i * 2]) - hex) << 4) |
483 (index(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++) {
495 addr6.s6_addr[i] = 0xff;
498 addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
502 isc_netaddr_fromin6(&iter->current.netmask, &addr6);
503 strncpy(iter->current.name, name, sizeof(iter->current.name));
504 return (ISC_R_SUCCESS);
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.
517 internal_current4(isc_interfaceiter_t *iter) {
521 char strbuf[ISC_STRERRORSIZE];
522 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
523 struct lifreq lifreq;
527 int i, bits, prefixlen;
532 REQUIRE(VALID_IFITER(iter));
533 REQUIRE(iter->ifc.ifc_len == 0 ||
534 iter->pos < (unsigned int) iter->ifc.ifc_len);
537 result = linux_if_inet6_current(iter);
538 if (result != ISC_R_NOMORE)
540 iter->first = ISC_TRUE;
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)
555 if (family != AF_INET)
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.
574 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
575 return (ISC_R_IGNORE);
578 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
579 sizeof(in6addr_any)) == 0)
580 return (ISC_R_IGNORE);
585 * Get interface flags.
588 iter->current.flags = 0;
591 * Ignore the HP/UX warning about "interger 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;
611 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
612 iter->current.flags |= INTERFACE_F_LOOPBACK;
614 if (family == AF_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;
632 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
633 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
634 ISC_LOGMODULE_INTERFACE,
636 isc_msgcat_get(isc_msgcat,
637 ISC_MSGSET_IFITERIOCTL,
639 "prefix length for %s is unknown "
640 "(assume 128)"), sabuf);
645 * Netmask already zeroed.
647 iter->current.netmask.family = family;
648 for (i = 0; i < 16; i++) {
653 bits = 8 - prefixlen;
656 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
658 return (ISC_R_SUCCESS);
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 "interger 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)
675 isc__strerror(errno, strbuf, sizeof(strbuf));
676 UNEXPECTED_ERROR(__FILE__, __LINE__,
677 isc_msgcat_get(isc_msgcat,
678 ISC_MSGSET_IFITERIOCTL,
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);
691 * Get the network mask.
693 memset(&ifreq, 0, sizeof(ifreq));
694 memcpy(&ifreq, ifrp, sizeof(ifreq));
696 * Ignore the HP/UX warning about "interger 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,
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)
717 internal_current6(isc_interfaceiter_t *iter) {
719 struct LIFREQ lifreq;
721 char strbuf[ISC_STRERRORSIZE];
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)
738 if (family != AF_INET)
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.
757 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
758 return (ISC_R_IGNORE);
761 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
762 sizeof(in6addr_any)) == 0)
763 return (ISC_R_IGNORE);
768 * Get interface flags.
771 iter->current.flags = 0;
773 if (family == AF_INET6)
779 * Ignore the HP/UX warning about "interger 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;
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 "interger 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)
814 isc__strerror(errno, strbuf, sizeof(strbuf));
815 UNEXPECTED_ERROR(__FILE__, __LINE__,
816 isc_msgcat_get(isc_msgcat,
817 ISC_MSGSET_IFITERIOCTL,
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,
831 * Get the network mask. Netmask already zeroed.
833 memset(&lifreq, 0, sizeof(lifreq));
834 memcpy(&lifreq, ifrp, sizeof(lifreq));
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) {
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] =
853 return (ISC_R_SUCCESS);
858 * Ignore the HP/UX warning about "interger 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,
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);
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);
888 #ifdef HAVE_TRUCLUSTER
889 if (!iter->clua_done)
890 return(internal_current_clusteralias(iter));
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.
903 internal_next4(isc_interfaceiter_t *iter) {
904 #ifdef ISC_PLATFORM_HAVESALEN
908 REQUIRE(iter->ifc.ifc_len == 0 ||
909 iter->pos < (unsigned int) iter->ifc.ifc_len);
912 if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
913 return (ISC_R_SUCCESS);
915 return (ISC_R_SUCCESS);
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;
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)
938 internal_next6(isc_interfaceiter_t *iter) {
939 #ifdef ISC_PLATFORM_HAVESALEN
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;
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);
965 internal_next(isc_interfaceiter_t *iter) {
966 #ifdef HAVE_TRUCLUSTER
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);
975 iter->first6 = ISC_FALSE;
976 return (ISC_R_SUCCESS);
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);
989 return (internal_next4(iter));
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);
1003 if (iter->proc != NULL)
1009 void internal_first(isc_interfaceiter_t *iter) {
1010 #ifdef HAVE_TRUCLUSTER
1014 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1016 if (iter->result6 == ISC_R_NOMORE)
1017 iter->result6 = ISC_R_SUCCESS;
1018 iter->first6 = ISC_TRUE;
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);
1027 linux_if_inet6_first(iter);