2 * Copyright (C) 2004, 2005 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.17 2005/10/14 02:13:07 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->pos < (unsigned int) iter->ifc.ifc_len);
535 result = linux_if_inet6_current(iter);
536 if (result != ISC_R_NOMORE)
538 iter->first = ISC_TRUE;
541 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
543 memset(&ifreq, 0, sizeof(ifreq));
544 memcpy(&ifreq, ifrp, sizeof(ifreq));
546 family = ifreq.ifr_addr.sa_family;
547 #if defined(ISC_PLATFORM_HAVEIPV6)
548 if (family != AF_INET && family != AF_INET6)
550 if (family != AF_INET)
552 return (ISC_R_IGNORE);
554 memset(&iter->current, 0, sizeof(iter->current));
555 iter->current.af = family;
557 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
558 memset(iter->current.name, 0, sizeof(iter->current.name));
559 memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
561 get_addr(family, &iter->current.address,
562 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
565 * If the interface does not have a address ignore it.
569 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
570 return (ISC_R_IGNORE);
573 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
574 sizeof(in6addr_any)) == 0)
575 return (ISC_R_IGNORE);
580 * Get interface flags.
583 iter->current.flags = 0;
586 * Ignore the HP/UX warning about "interger overflow during
587 * conversion. It comes from its own macro definition,
588 * and is really hard to shut up.
590 if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
591 isc__strerror(errno, strbuf, sizeof(strbuf));
592 UNEXPECTED_ERROR(__FILE__, __LINE__,
593 "%s: getting interface flags: %s",
594 ifreq.ifr_name, strbuf);
595 return (ISC_R_IGNORE);
598 if ((ifreq.ifr_flags & IFF_UP) != 0)
599 iter->current.flags |= INTERFACE_F_UP;
601 #ifdef IFF_POINTOPOINT
602 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
603 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
606 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
607 iter->current.flags |= INTERFACE_F_LOOPBACK;
609 if (family == AF_INET)
612 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
613 memset(&lifreq, 0, sizeof(lifreq));
614 memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
615 memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
616 sizeof(iter->current.address.type.in6));
618 if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
619 isc__strerror(errno, strbuf, sizeof(strbuf));
620 UNEXPECTED_ERROR(__FILE__, __LINE__,
621 "%s: getting interface address: %s",
622 ifreq.ifr_name, strbuf);
623 return (ISC_R_IGNORE);
625 prefixlen = lifreq.lifr_addrlen;
627 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
628 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
629 ISC_LOGMODULE_INTERFACE,
631 isc_msgcat_get(isc_msgcat,
632 ISC_MSGSET_IFITERIOCTL,
634 "prefix length for %s is unknown "
635 "(assume 128)"), sabuf);
640 * Netmask already zeroed.
642 iter->current.netmask.family = family;
643 for (i = 0; i < 16; i++) {
648 bits = 8 - prefixlen;
651 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
653 return (ISC_R_SUCCESS);
656 if (family != AF_INET)
657 return (ISC_R_IGNORE);
658 #ifdef IFF_POINTOPOINT
660 * If the interface is point-to-point, get the destination address.
662 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
664 * Ignore the HP/UX warning about "interger overflow during
665 * conversion. It comes from its own macro definition,
666 * and is really hard to shut up.
668 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
670 isc__strerror(errno, strbuf, sizeof(strbuf));
671 UNEXPECTED_ERROR(__FILE__, __LINE__,
672 isc_msgcat_get(isc_msgcat,
673 ISC_MSGSET_IFITERIOCTL,
676 "destination address: %s"),
677 ifreq.ifr_name, strbuf);
678 return (ISC_R_IGNORE);
680 get_addr(family, &iter->current.dstaddress,
681 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
686 * Get the network mask.
688 memset(&ifreq, 0, sizeof(ifreq));
689 memcpy(&ifreq, ifrp, sizeof(ifreq));
691 * Ignore the HP/UX warning about "interger overflow during
692 * conversion. It comes from its own macro definition,
693 * and is really hard to shut up.
695 if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
696 isc__strerror(errno, strbuf, sizeof(strbuf));
697 UNEXPECTED_ERROR(__FILE__, __LINE__,
698 isc_msgcat_get(isc_msgcat,
699 ISC_MSGSET_IFITERIOCTL,
701 "%s: getting netmask: %s"),
702 ifreq.ifr_name, strbuf);
703 return (ISC_R_IGNORE);
705 get_addr(family, &iter->current.netmask,
706 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
707 return (ISC_R_SUCCESS);
710 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
712 internal_current6(isc_interfaceiter_t *iter) {
714 struct LIFREQ lifreq;
716 char strbuf[ISC_STRERRORSIZE];
719 REQUIRE(VALID_IFITER(iter));
720 if (iter->result6 != ISC_R_SUCCESS)
721 return (iter->result6);
722 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
724 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
726 memset(&lifreq, 0, sizeof(lifreq));
727 memcpy(&lifreq, ifrp, sizeof(lifreq));
729 family = lifreq.lifr_addr.ss_family;
730 #ifdef ISC_PLATFORM_HAVEIPV6
731 if (family != AF_INET && family != AF_INET6)
733 if (family != AF_INET)
735 return (ISC_R_IGNORE);
737 memset(&iter->current, 0, sizeof(iter->current));
738 iter->current.af = family;
740 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
741 memset(iter->current.name, 0, sizeof(iter->current.name));
742 memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
744 get_addr(family, &iter->current.address,
745 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
748 * If the interface does not have a address ignore it.
752 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
753 return (ISC_R_IGNORE);
756 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
757 sizeof(in6addr_any)) == 0)
758 return (ISC_R_IGNORE);
763 * Get interface flags.
766 iter->current.flags = 0;
768 if (family == AF_INET6)
774 * Ignore the HP/UX warning about "interger overflow during
775 * conversion. It comes from its own macro definition,
776 * and is really hard to shut up.
778 if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
779 isc__strerror(errno, strbuf, sizeof(strbuf));
780 UNEXPECTED_ERROR(__FILE__, __LINE__,
781 "%s: getting interface flags: %s",
782 lifreq.lifr_name, strbuf);
783 return (ISC_R_IGNORE);
786 if ((lifreq.lifr_flags & IFF_UP) != 0)
787 iter->current.flags |= INTERFACE_F_UP;
789 #ifdef IFF_POINTOPOINT
790 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
791 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
794 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
795 iter->current.flags |= INTERFACE_F_LOOPBACK;
797 #ifdef IFF_POINTOPOINT
799 * If the interface is point-to-point, get the destination address.
801 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
803 * Ignore the HP/UX warning about "interger overflow during
804 * conversion. It comes from its own macro definition,
805 * and is really hard to shut up.
807 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
809 isc__strerror(errno, strbuf, sizeof(strbuf));
810 UNEXPECTED_ERROR(__FILE__, __LINE__,
811 isc_msgcat_get(isc_msgcat,
812 ISC_MSGSET_IFITERIOCTL,
815 "destination address: %s"),
816 lifreq.lifr_name, strbuf);
817 return (ISC_R_IGNORE);
819 get_addr(family, &iter->current.dstaddress,
820 (struct sockaddr *)&lifreq.lifr_dstaddr,
826 * Get the network mask. Netmask already zeroed.
828 memset(&lifreq, 0, sizeof(lifreq));
829 memcpy(&lifreq, ifrp, sizeof(lifreq));
833 * Special case: if the system provides lifr_addrlen member, the
834 * netmask of an IPv6 address can be derived from the length, since
835 * an IPv6 address always has a contiguous mask.
837 if (family == AF_INET6) {
840 iter->current.netmask.family = family;
841 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
842 bits = lifreq.lifr_addrlen - i;
843 bits = (bits < 8) ? (8 - bits) : 0;
844 iter->current.netmask.type.in6.s6_addr[i / 8] =
848 return (ISC_R_SUCCESS);
853 * Ignore the HP/UX warning about "interger overflow during
854 * conversion. It comes from its own macro definition,
855 * and is really hard to shut up.
857 if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
858 isc__strerror(errno, strbuf, sizeof(strbuf));
859 UNEXPECTED_ERROR(__FILE__, __LINE__,
860 isc_msgcat_get(isc_msgcat,
861 ISC_MSGSET_IFITERIOCTL,
863 "%s: getting netmask: %s"),
864 lifreq.lifr_name, strbuf);
865 return (ISC_R_IGNORE);
867 get_addr(family, &iter->current.netmask,
868 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
870 return (ISC_R_SUCCESS);
875 internal_current(isc_interfaceiter_t *iter) {
876 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
877 if (iter->mode == 6) {
878 iter->result6 = internal_current6(iter);
879 if (iter->result6 != ISC_R_NOMORE)
880 return (iter->result6);
883 #ifdef HAVE_TRUCLUSTER
884 if (!iter->clua_done)
885 return(internal_current_clusteralias(iter));
887 return (internal_current4(iter));
891 * Step the iterator to the next interface. Unlike
892 * isc_interfaceiter_next(), this may leave the iterator
893 * positioned on an interface that will ultimately
894 * be ignored. Return ISC_R_NOMORE if there are no more
895 * interfaces, otherwise ISC_R_SUCCESS.
898 internal_next4(isc_interfaceiter_t *iter) {
899 #ifdef ISC_PLATFORM_HAVESALEN
903 REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
906 if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
907 return (ISC_R_SUCCESS);
909 return (ISC_R_SUCCESS);
911 #ifdef ISC_PLATFORM_HAVESALEN
912 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
914 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
915 iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
918 iter->pos += sizeof(struct ifreq);
920 if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
921 return (ISC_R_NOMORE);
923 return (ISC_R_SUCCESS);
926 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
928 internal_next6(isc_interfaceiter_t *iter) {
929 #ifdef ISC_PLATFORM_HAVESALEN
933 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
934 return (iter->result6);
936 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
938 #ifdef ISC_PLATFORM_HAVESALEN
939 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
941 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
942 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
945 iter->pos6 += sizeof(struct LIFREQ);
947 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
948 return (ISC_R_NOMORE);
950 return (ISC_R_SUCCESS);
955 internal_next(isc_interfaceiter_t *iter) {
956 #ifdef HAVE_TRUCLUSTER
959 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
960 if (iter->mode == 6) {
961 iter->result6 = internal_next6(iter);
962 if (iter->result6 != ISC_R_NOMORE)
963 return (iter->result6);
965 iter->first6 = ISC_FALSE;
966 return (ISC_R_SUCCESS);
970 #ifdef HAVE_TRUCLUSTER
971 if (!iter->clua_done) {
972 clua_result = clua_getaliasaddress(&iter->clua_sa,
973 &iter->clua_context);
974 if (clua_result != CLUA_SUCCESS)
975 iter->clua_done = ISC_TRUE;
976 return (ISC_R_SUCCESS);
979 return (internal_next4(iter));
983 internal_destroy(isc_interfaceiter_t *iter) {
984 (void) close(iter->socket);
985 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
986 if (iter->socket6 != -1)
987 (void) close(iter->socket6);
988 if (iter->buf6 != NULL) {
989 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
993 if (iter->proc != NULL)
999 void internal_first(isc_interfaceiter_t *iter) {
1000 #ifdef HAVE_TRUCLUSTER
1004 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1006 if (iter->result6 == ISC_R_NOMORE)
1007 iter->result6 = ISC_R_SUCCESS;
1008 iter->first6 = ISC_TRUE;
1010 #ifdef HAVE_TRUCLUSTER
1011 iter->clua_context = 0;
1012 clua_result = clua_getaliasaddress(&iter->clua_sa,
1013 &iter->clua_context);
1014 iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
1017 linux_if_inet6_first(iter);