2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.19.2.5.2.19 2006/02/03 23:51:37 marka Exp $ */
21 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
25 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
26 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
27 #define lifc_len iflc_len
28 #define lifc_buf iflc_buf
29 #define lifc_req iflc_req
30 #define LIFCONF if_laddrconf
32 #define ISC_HAVE_LIFC_FAMILY 1
33 #define ISC_HAVE_LIFC_FLAGS 1
34 #define LIFCONF lifconf
37 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
38 #define lifr_addr iflr_addr
39 #define lifr_name iflr_name
40 #define lifr_dstaddr iflr_dstaddr
41 #define lifr_flags iflr_flags
42 #define ss_family sa_family
43 #define LIFREQ if_laddrreq
49 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
50 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
52 #define ISC_IF_INET6_SZ \
53 sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
55 struct isc_interfaceiter {
56 unsigned int magic; /* Magic number. */
61 void *buf; /* Buffer for sysctl data. */
62 unsigned int bufsize; /* Bytes allocated. */
63 unsigned int pos; /* Current offset in
65 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
68 void *buf6; /* Buffer for sysctl data. */
69 unsigned int bufsize6; /* Bytes allocated. */
70 unsigned int pos6; /* Current offset in
72 isc_result_t result6; /* Last result code. */
75 #ifdef HAVE_TRUCLUSTER
76 int clua_context; /* Cluster alias context */
77 isc_boolean_t clua_done;
78 struct sockaddr clua_sa;
82 char entry[ISC_IF_INET6_SZ];
86 isc_interface_t current; /* Current interface data. */
87 isc_result_t result; /* Last result code. */
90 #ifdef HAVE_TRUCLUSTER
91 #include <clua/clua.h>
92 #include <sys/socket.h>
97 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
98 * will have more than a megabyte of interface configuration data.
100 #define IFCONF_BUFSIZE_INITIAL 4096
101 #define IFCONF_BUFSIZE_MAX 1048576
106 # define IF_NAMESIZE IFNAMSIZ
108 # define IF_NAMESIZE 16
114 getbuf4(isc_interfaceiter_t *iter) {
115 char strbuf[ISC_STRERRORSIZE];
117 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
120 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
121 if (iter->buf == NULL)
122 return (ISC_R_NOMEMORY);
124 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
125 iter->ifc.ifc_len = iter->bufsize;
126 iter->ifc.ifc_buf = iter->buf;
128 * Ignore the HP/UX warning about "interger overflow during
129 * conversion". It comes from its own macro definition,
130 * and is really hard to shut up.
132 if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
134 if (errno != EINVAL) {
135 isc__strerror(errno, strbuf, sizeof(strbuf));
136 UNEXPECTED_ERROR(__FILE__, __LINE__,
137 isc_msgcat_get(isc_msgcat,
138 ISC_MSGSET_IFITERIOCTL,
141 "configuration: %s"),
146 * EINVAL. Retry with a bigger buffer.
150 * The ioctl succeeded.
151 * Some OS's just return what will fit rather
152 * than set EINVAL if the buffer is too small
153 * to fit all the interfaces in. If
154 * ifc.lifc_len is too near to the end of the
155 * buffer we will grow it just in case and
158 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
162 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
163 UNEXPECTED_ERROR(__FILE__, __LINE__,
164 isc_msgcat_get(isc_msgcat,
165 ISC_MSGSET_IFITERIOCTL,
173 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
177 return (ISC_R_SUCCESS);
180 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
182 return (ISC_R_UNEXPECTED);
185 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
187 getbuf6(isc_interfaceiter_t *iter) {
188 char strbuf[ISC_STRERRORSIZE];
191 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
194 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
195 if (iter->buf6 == NULL)
196 return (ISC_R_NOMEMORY);
198 memset(&iter->lifc, 0, sizeof(iter->lifc));
199 #ifdef ISC_HAVE_LIFC_FAMILY
200 iter->lifc.lifc_family = AF_INET6;
202 #ifdef ISC_HAVE_LIFC_FLAGS
203 iter->lifc.lifc_flags = 0;
205 iter->lifc.lifc_len = iter->bufsize6;
206 iter->lifc.lifc_buf = iter->buf6;
208 * Ignore the HP/UX warning about "interger overflow during
209 * conversion". It comes from its own macro definition,
210 * and is really hard to shut up.
212 if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
216 * IPv6 interface scanning is not available on all
217 * kernels w/ IPv6 sockets.
219 if (errno == ENOENT) {
220 isc__strerror(errno, strbuf, sizeof(strbuf));
221 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
222 ISC_LOGMODULE_INTERFACE,
224 isc_msgcat_get(isc_msgcat,
225 ISC_MSGSET_IFITERIOCTL,
228 "configuration: %s"),
230 result = ISC_R_FAILURE;
234 if (errno != EINVAL) {
235 isc__strerror(errno, strbuf, sizeof(strbuf));
236 UNEXPECTED_ERROR(__FILE__, __LINE__,
237 isc_msgcat_get(isc_msgcat,
238 ISC_MSGSET_IFITERIOCTL,
241 "configuration: %s"),
243 result = ISC_R_UNEXPECTED;
247 * EINVAL. Retry with a bigger buffer.
251 * The ioctl succeeded.
252 * Some OS's just return what will fit rather
253 * than set EINVAL if the buffer is too small
254 * to fit all the interfaces in. If
255 * ifc.ifc_len is too near to the end of the
256 * buffer we will grow it just in case and
259 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
263 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
264 UNEXPECTED_ERROR(__FILE__, __LINE__,
265 isc_msgcat_get(isc_msgcat,
266 ISC_MSGSET_IFITERIOCTL,
272 result = ISC_R_UNEXPECTED;
275 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
280 if (iter->lifc.lifc_len != 0)
282 return (ISC_R_SUCCESS);
285 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
292 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
293 isc_interfaceiter_t *iter;
295 char strbuf[ISC_STRERRORSIZE];
297 REQUIRE(mctx != NULL);
298 REQUIRE(iterp != NULL);
299 REQUIRE(*iterp == NULL);
301 iter = isc_mem_get(mctx, sizeof(*iter));
303 return (ISC_R_NOMEMORY);
308 iter->pos = (unsigned int) -1;
309 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
311 iter->pos6 = (unsigned int) -1;
312 iter->result6 = ISC_R_NOMORE;
314 iter->first6 = ISC_FALSE;
318 * Get the interface configuration, allocating more memory if
322 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
323 result = isc_net_probeipv6();
324 if (result == ISC_R_SUCCESS) {
326 * Create an unbound datagram socket to do the SIOCGLIFCONF
327 * ioctl on. HP/UX requires an AF_INET6 socket for
328 * SIOCGLIFCONF to get IPv6 addresses.
330 if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
331 isc__strerror(errno, strbuf, sizeof(strbuf));
332 UNEXPECTED_ERROR(__FILE__, __LINE__,
333 isc_msgcat_get(isc_msgcat,
334 ISC_MSGSET_IFITERIOCTL,
335 ISC_MSG_MAKESCANSOCKET,
339 result = ISC_R_UNEXPECTED;
340 goto socket6_failure;
342 result = iter->result6 = getbuf6(iter);
343 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
347 if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
348 isc__strerror(errno, strbuf, sizeof(strbuf));
349 UNEXPECTED_ERROR(__FILE__, __LINE__,
350 isc_msgcat_get(isc_msgcat,
351 ISC_MSGSET_IFITERIOCTL,
352 ISC_MSG_MAKESCANSOCKET,
356 result = ISC_R_UNEXPECTED;
359 result = getbuf4(iter);
360 if (result != ISC_R_SUCCESS)
364 * A newly created iterator has an undefined position
365 * until isc_interfaceiter_first() is called.
367 #ifdef HAVE_TRUCLUSTER
368 iter->clua_context = -1;
369 iter->clua_done = ISC_TRUE;
372 iter->proc = fopen("/proc/net/if_inet6", "r");
373 iter->valid = ISC_R_FAILURE;
374 iter->first = ISC_FALSE;
376 iter->result = ISC_R_FAILURE;
378 iter->magic = IFITER_MAGIC;
380 return (ISC_R_SUCCESS);
383 if (iter->buf != NULL)
384 isc_mem_put(mctx, iter->buf, iter->bufsize);
385 (void) close(iter->socket);
388 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
389 if (iter->buf6 != NULL)
390 isc_mem_put(mctx, iter->buf6, iter->bufsize6);
392 if (iter->socket6 != -1)
393 (void) close(iter->socket6);
397 isc_mem_put(mctx, iter, sizeof(*iter));
401 #ifdef HAVE_TRUCLUSTER
403 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
404 dst->family = AF_INET;
405 memcpy(&dst->type.in, src, sizeof(struct in_addr));
409 internal_current_clusteralias(isc_interfaceiter_t *iter) {
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);
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;
431 iter->valid = ISC_R_NOMORE;
432 return (iter->valid);
436 linux_if_inet6_first(isc_interfaceiter_t *iter) {
437 if (iter->proc != NULL) {
439 (void)linux_if_inet6_next(iter);
441 iter->valid = ISC_R_NOMORE;
442 iter->first = ISC_FALSE;
446 linux_if_inet6_current(isc_interfaceiter_t *iter) {
448 char name[IF_NAMESIZE+1];
449 struct in6_addr addr6;
450 int ifindex, prefix, flag3, flag4;
454 if (iter->valid != ISC_R_SUCCESS)
455 return (iter->valid);
456 if (iter->proc == NULL) {
457 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
458 ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
459 "/proc/net/if_inet6:iter->proc == NULL");
460 return (ISC_R_FAILURE);
463 res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
464 address, &ifindex, &prefix, &flag3, &flag4, name);
466 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
467 ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
468 "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
470 return (ISC_R_FAILURE);
472 if (strlen(address) != 32) {
473 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
474 ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
475 "/proc/net/if_inet6:strlen(%s) != 32", address);
476 return (ISC_R_FAILURE);
478 for (i = 0; i < 16; i++) {
480 static const char hex[] = "0123456789abcdef";
481 byte = ((index(hex, address[i * 2]) - hex) << 4) |
482 (index(hex, address[i * 2 + 1]) - hex);
483 addr6.s6_addr[i] = byte;
485 iter->current.af = AF_INET6;
486 iter->current.flags = INTERFACE_F_UP;
487 isc_netaddr_fromin6(&iter->current.address, &addr6);
488 if (isc_netaddr_islinklocal(&iter->current.address)) {
489 isc_netaddr_setzone(&iter->current.address,
490 (isc_uint32_t)ifindex);
492 for (i = 0; i < 16; i++) {
494 addr6.s6_addr[i] = 0xff;
497 addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
501 isc_netaddr_fromin6(&iter->current.netmask, &addr6);
502 strncpy(iter->current.name, name, sizeof(iter->current.name));
503 return (ISC_R_SUCCESS);
508 * Get information about the current interface to iter->current.
509 * If successful, return ISC_R_SUCCESS.
510 * If the interface has an unsupported address family, or if
511 * some operation on it fails, return ISC_R_IGNORE to make
512 * the higher-level iterator code ignore it.
516 internal_current4(isc_interfaceiter_t *iter) {
520 char strbuf[ISC_STRERRORSIZE];
521 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
522 struct lifreq lifreq;
526 int i, bits, prefixlen;
531 REQUIRE(VALID_IFITER(iter));
532 REQUIRE(iter->ifc.ifc_len == 0 ||
533 iter->pos < (unsigned int) iter->ifc.ifc_len);
536 result = linux_if_inet6_current(iter);
537 if (result != ISC_R_NOMORE)
539 iter->first = ISC_TRUE;
542 if (iter->ifc.ifc_len == 0)
543 return (ISC_R_NOMORE);
545 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
547 memset(&ifreq, 0, sizeof(ifreq));
548 memcpy(&ifreq, ifrp, sizeof(ifreq));
550 family = ifreq.ifr_addr.sa_family;
551 #if defined(ISC_PLATFORM_HAVEIPV6)
552 if (family != AF_INET && family != AF_INET6)
554 if (family != AF_INET)
556 return (ISC_R_IGNORE);
558 memset(&iter->current, 0, sizeof(iter->current));
559 iter->current.af = family;
561 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
562 memset(iter->current.name, 0, sizeof(iter->current.name));
563 memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
565 get_addr(family, &iter->current.address,
566 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
569 * If the interface does not have a address ignore it.
573 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
574 return (ISC_R_IGNORE);
577 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
578 sizeof(in6addr_any)) == 0)
579 return (ISC_R_IGNORE);
584 * Get interface flags.
587 iter->current.flags = 0;
590 * Ignore the HP/UX warning about "interger overflow during
591 * conversion. It comes from its own macro definition,
592 * and is really hard to shut up.
594 if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
595 isc__strerror(errno, strbuf, sizeof(strbuf));
596 UNEXPECTED_ERROR(__FILE__, __LINE__,
597 "%s: getting interface flags: %s",
598 ifreq.ifr_name, strbuf);
599 return (ISC_R_IGNORE);
602 if ((ifreq.ifr_flags & IFF_UP) != 0)
603 iter->current.flags |= INTERFACE_F_UP;
605 #ifdef IFF_POINTOPOINT
606 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
607 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
610 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
611 iter->current.flags |= INTERFACE_F_LOOPBACK;
613 if (family == AF_INET)
616 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
617 memset(&lifreq, 0, sizeof(lifreq));
618 memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
619 memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
620 sizeof(iter->current.address.type.in6));
622 if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
623 isc__strerror(errno, strbuf, sizeof(strbuf));
624 UNEXPECTED_ERROR(__FILE__, __LINE__,
625 "%s: getting interface address: %s",
626 ifreq.ifr_name, strbuf);
627 return (ISC_R_IGNORE);
629 prefixlen = lifreq.lifr_addrlen;
631 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
632 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
633 ISC_LOGMODULE_INTERFACE,
635 isc_msgcat_get(isc_msgcat,
636 ISC_MSGSET_IFITERIOCTL,
638 "prefix length for %s is unknown "
639 "(assume 128)"), sabuf);
644 * Netmask already zeroed.
646 iter->current.netmask.family = family;
647 for (i = 0; i < 16; i++) {
652 bits = 8 - prefixlen;
655 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
657 return (ISC_R_SUCCESS);
660 if (family != AF_INET)
661 return (ISC_R_IGNORE);
662 #ifdef IFF_POINTOPOINT
664 * If the interface is point-to-point, get the destination address.
666 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
668 * Ignore the HP/UX warning about "interger overflow during
669 * conversion. It comes from its own macro definition,
670 * and is really hard to shut up.
672 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
674 isc__strerror(errno, strbuf, sizeof(strbuf));
675 UNEXPECTED_ERROR(__FILE__, __LINE__,
676 isc_msgcat_get(isc_msgcat,
677 ISC_MSGSET_IFITERIOCTL,
680 "destination address: %s"),
681 ifreq.ifr_name, strbuf);
682 return (ISC_R_IGNORE);
684 get_addr(family, &iter->current.dstaddress,
685 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
690 * Get the network mask.
692 memset(&ifreq, 0, sizeof(ifreq));
693 memcpy(&ifreq, ifrp, sizeof(ifreq));
695 * Ignore the HP/UX warning about "interger overflow during
696 * conversion. It comes from its own macro definition,
697 * and is really hard to shut up.
699 if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
700 isc__strerror(errno, strbuf, sizeof(strbuf));
701 UNEXPECTED_ERROR(__FILE__, __LINE__,
702 isc_msgcat_get(isc_msgcat,
703 ISC_MSGSET_IFITERIOCTL,
705 "%s: getting netmask: %s"),
706 ifreq.ifr_name, strbuf);
707 return (ISC_R_IGNORE);
709 get_addr(family, &iter->current.netmask,
710 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
711 return (ISC_R_SUCCESS);
714 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
716 internal_current6(isc_interfaceiter_t *iter) {
718 struct LIFREQ lifreq;
720 char strbuf[ISC_STRERRORSIZE];
723 REQUIRE(VALID_IFITER(iter));
724 if (iter->result6 != ISC_R_SUCCESS)
725 return (iter->result6);
726 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
728 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
730 memset(&lifreq, 0, sizeof(lifreq));
731 memcpy(&lifreq, ifrp, sizeof(lifreq));
733 family = lifreq.lifr_addr.ss_family;
734 #ifdef ISC_PLATFORM_HAVEIPV6
735 if (family != AF_INET && family != AF_INET6)
737 if (family != AF_INET)
739 return (ISC_R_IGNORE);
741 memset(&iter->current, 0, sizeof(iter->current));
742 iter->current.af = family;
744 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
745 memset(iter->current.name, 0, sizeof(iter->current.name));
746 memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
748 get_addr(family, &iter->current.address,
749 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
752 * If the interface does not have a address ignore it.
756 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
757 return (ISC_R_IGNORE);
760 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
761 sizeof(in6addr_any)) == 0)
762 return (ISC_R_IGNORE);
767 * Get interface flags.
770 iter->current.flags = 0;
772 if (family == AF_INET6)
778 * Ignore the HP/UX warning about "interger overflow during
779 * conversion. It comes from its own macro definition,
780 * and is really hard to shut up.
782 if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
783 isc__strerror(errno, strbuf, sizeof(strbuf));
784 UNEXPECTED_ERROR(__FILE__, __LINE__,
785 "%s: getting interface flags: %s",
786 lifreq.lifr_name, strbuf);
787 return (ISC_R_IGNORE);
790 if ((lifreq.lifr_flags & IFF_UP) != 0)
791 iter->current.flags |= INTERFACE_F_UP;
793 #ifdef IFF_POINTOPOINT
794 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
795 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
798 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
799 iter->current.flags |= INTERFACE_F_LOOPBACK;
801 #ifdef IFF_POINTOPOINT
803 * If the interface is point-to-point, get the destination address.
805 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
807 * Ignore the HP/UX warning about "interger overflow during
808 * conversion. It comes from its own macro definition,
809 * and is really hard to shut up.
811 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
813 isc__strerror(errno, strbuf, sizeof(strbuf));
814 UNEXPECTED_ERROR(__FILE__, __LINE__,
815 isc_msgcat_get(isc_msgcat,
816 ISC_MSGSET_IFITERIOCTL,
819 "destination address: %s"),
820 lifreq.lifr_name, strbuf);
821 return (ISC_R_IGNORE);
823 get_addr(family, &iter->current.dstaddress,
824 (struct sockaddr *)&lifreq.lifr_dstaddr,
830 * Get the network mask. Netmask already zeroed.
832 memset(&lifreq, 0, sizeof(lifreq));
833 memcpy(&lifreq, ifrp, sizeof(lifreq));
837 * Special case: if the system provides lifr_addrlen member, the
838 * netmask of an IPv6 address can be derived from the length, since
839 * an IPv6 address always has a contiguous mask.
841 if (family == AF_INET6) {
844 iter->current.netmask.family = family;
845 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
846 bits = lifreq.lifr_addrlen - i;
847 bits = (bits < 8) ? (8 - bits) : 0;
848 iter->current.netmask.type.in6.s6_addr[i / 8] =
852 return (ISC_R_SUCCESS);
857 * Ignore the HP/UX warning about "interger overflow during
858 * conversion. It comes from its own macro definition,
859 * and is really hard to shut up.
861 if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
862 isc__strerror(errno, strbuf, sizeof(strbuf));
863 UNEXPECTED_ERROR(__FILE__, __LINE__,
864 isc_msgcat_get(isc_msgcat,
865 ISC_MSGSET_IFITERIOCTL,
867 "%s: getting netmask: %s"),
868 lifreq.lifr_name, strbuf);
869 return (ISC_R_IGNORE);
871 get_addr(family, &iter->current.netmask,
872 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
874 return (ISC_R_SUCCESS);
879 internal_current(isc_interfaceiter_t *iter) {
880 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
881 if (iter->mode == 6) {
882 iter->result6 = internal_current6(iter);
883 if (iter->result6 != ISC_R_NOMORE)
884 return (iter->result6);
887 #ifdef HAVE_TRUCLUSTER
888 if (!iter->clua_done)
889 return(internal_current_clusteralias(iter));
891 return (internal_current4(iter));
895 * Step the iterator to the next interface. Unlike
896 * isc_interfaceiter_next(), this may leave the iterator
897 * positioned on an interface that will ultimately
898 * be ignored. Return ISC_R_NOMORE if there are no more
899 * interfaces, otherwise ISC_R_SUCCESS.
902 internal_next4(isc_interfaceiter_t *iter) {
903 #ifdef ISC_PLATFORM_HAVESALEN
907 REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
910 if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
911 return (ISC_R_SUCCESS);
913 return (ISC_R_SUCCESS);
915 #ifdef ISC_PLATFORM_HAVESALEN
916 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
918 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
919 iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
922 iter->pos += sizeof(struct ifreq);
924 if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
925 return (ISC_R_NOMORE);
927 return (ISC_R_SUCCESS);
930 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
932 internal_next6(isc_interfaceiter_t *iter) {
933 #ifdef ISC_PLATFORM_HAVESALEN
937 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
938 return (iter->result6);
940 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
942 #ifdef ISC_PLATFORM_HAVESALEN
943 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
945 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
946 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
949 iter->pos6 += sizeof(struct LIFREQ);
951 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
952 return (ISC_R_NOMORE);
954 return (ISC_R_SUCCESS);
959 internal_next(isc_interfaceiter_t *iter) {
960 #ifdef HAVE_TRUCLUSTER
963 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
964 if (iter->mode == 6) {
965 iter->result6 = internal_next6(iter);
966 if (iter->result6 != ISC_R_NOMORE)
967 return (iter->result6);
969 iter->first6 = ISC_FALSE;
970 return (ISC_R_SUCCESS);
974 #ifdef HAVE_TRUCLUSTER
975 if (!iter->clua_done) {
976 clua_result = clua_getaliasaddress(&iter->clua_sa,
977 &iter->clua_context);
978 if (clua_result != CLUA_SUCCESS)
979 iter->clua_done = ISC_TRUE;
980 return (ISC_R_SUCCESS);
983 return (internal_next4(iter));
987 internal_destroy(isc_interfaceiter_t *iter) {
988 (void) close(iter->socket);
989 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
990 if (iter->socket6 != -1)
991 (void) close(iter->socket6);
992 if (iter->buf6 != NULL) {
993 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
997 if (iter->proc != NULL)
1003 void internal_first(isc_interfaceiter_t *iter) {
1004 #ifdef HAVE_TRUCLUSTER
1008 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1010 if (iter->result6 == ISC_R_NOMORE)
1011 iter->result6 = ISC_R_SUCCESS;
1012 iter->first6 = ISC_TRUE;
1014 #ifdef HAVE_TRUCLUSTER
1015 iter->clua_context = 0;
1016 clua_result = clua_getaliasaddress(&iter->clua_sa,
1017 &iter->clua_context);
1018 iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
1021 linux_if_inet6_first(iter);