2 * Copyright (C) 2004-2009, 2014 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.62 2009/01/18 23:48:14 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 struct isc_interfaceiter {
54 unsigned int magic; /* Magic number. */
59 void *buf; /* Buffer for sysctl data. */
60 unsigned int bufsize; /* Bytes allocated. */
61 unsigned int pos; /* Current offset in
63 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
66 void *buf6; /* Buffer for sysctl data. */
67 unsigned int bufsize6; /* Bytes allocated. */
68 unsigned int pos6; /* Current offset in
70 isc_result_t result6; /* Last result code. */
73 #ifdef HAVE_TRUCLUSTER
74 int clua_context; /* Cluster alias context */
75 isc_boolean_t clua_done;
76 struct sockaddr clua_sa;
80 char entry[ISC_IF_INET6_SZ];
83 isc_interface_t current; /* Current interface data. */
84 isc_result_t result; /* Last result code. */
87 #ifdef HAVE_TRUCLUSTER
88 #include <clua/clua.h>
89 #include <sys/socket.h>
94 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
95 * will have more than a megabyte of interface configuration data.
97 #define IFCONF_BUFSIZE_INITIAL 4096
98 #define IFCONF_BUFSIZE_MAX 1048576
103 # define IF_NAMESIZE IFNAMSIZ
105 # define IF_NAMESIZE 16
111 getbuf4(isc_interfaceiter_t *iter) {
112 char strbuf[ISC_STRERRORSIZE];
114 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
117 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
118 if (iter->buf == NULL)
119 return (ISC_R_NOMEMORY);
121 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
122 iter->ifc.ifc_len = iter->bufsize;
123 iter->ifc.ifc_buf = iter->buf;
125 * Ignore the HP/UX warning about "integer overflow during
126 * conversion". It comes from its own macro definition,
127 * and is really hard to shut up.
129 if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
131 if (errno != EINVAL) {
132 isc__strerror(errno, strbuf, sizeof(strbuf));
133 UNEXPECTED_ERROR(__FILE__, __LINE__,
134 isc_msgcat_get(isc_msgcat,
135 ISC_MSGSET_IFITERIOCTL,
138 "configuration: %s"),
143 * EINVAL. Retry with a bigger buffer.
147 * The ioctl succeeded.
148 * Some OS's just return what will fit rather
149 * than set EINVAL if the buffer is too small
150 * to fit all the interfaces in. If
151 * ifc.lifc_len is too near to the end of the
152 * buffer we will grow it just in case and
155 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
159 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
160 UNEXPECTED_ERROR(__FILE__, __LINE__,
161 isc_msgcat_get(isc_msgcat,
162 ISC_MSGSET_IFITERIOCTL,
170 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
174 return (ISC_R_SUCCESS);
177 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
179 return (ISC_R_UNEXPECTED);
182 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
184 getbuf6(isc_interfaceiter_t *iter) {
185 char strbuf[ISC_STRERRORSIZE];
188 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
191 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
192 if (iter->buf6 == NULL)
193 return (ISC_R_NOMEMORY);
195 memset(&iter->lifc, 0, sizeof(iter->lifc));
196 #ifdef ISC_HAVE_LIFC_FAMILY
197 iter->lifc.lifc_family = AF_INET6;
199 #ifdef ISC_HAVE_LIFC_FLAGS
200 iter->lifc.lifc_flags = 0;
202 iter->lifc.lifc_len = iter->bufsize6;
203 iter->lifc.lifc_buf = iter->buf6;
205 * Ignore the HP/UX warning about "integer overflow during
206 * conversion". It comes from its own macro definition,
207 * and is really hard to shut up.
209 if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
213 * IPv6 interface scanning is not available on all
214 * kernels w/ IPv6 sockets.
216 if (errno == ENOENT) {
217 isc__strerror(errno, strbuf, sizeof(strbuf));
218 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
219 ISC_LOGMODULE_INTERFACE,
221 isc_msgcat_get(isc_msgcat,
222 ISC_MSGSET_IFITERIOCTL,
225 "configuration: %s"),
227 result = ISC_R_FAILURE;
231 if (errno != EINVAL) {
232 isc__strerror(errno, strbuf, sizeof(strbuf));
233 UNEXPECTED_ERROR(__FILE__, __LINE__,
234 isc_msgcat_get(isc_msgcat,
235 ISC_MSGSET_IFITERIOCTL,
238 "configuration: %s"),
240 result = ISC_R_UNEXPECTED;
244 * EINVAL. Retry with a bigger buffer.
248 * The ioctl succeeded.
249 * Some OS's just return what will fit rather
250 * than set EINVAL if the buffer is too small
251 * to fit all the interfaces in. If
252 * ifc.ifc_len is too near to the end of the
253 * buffer we will grow it just in case and
256 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
260 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
261 UNEXPECTED_ERROR(__FILE__, __LINE__,
262 isc_msgcat_get(isc_msgcat,
263 ISC_MSGSET_IFITERIOCTL,
269 result = ISC_R_UNEXPECTED;
272 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
277 if (iter->lifc.lifc_len != 0)
279 return (ISC_R_SUCCESS);
282 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
289 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
290 isc_interfaceiter_t *iter;
292 char strbuf[ISC_STRERRORSIZE];
294 REQUIRE(mctx != NULL);
295 REQUIRE(iterp != NULL);
296 REQUIRE(*iterp == NULL);
298 iter = isc_mem_get(mctx, sizeof(*iter));
300 return (ISC_R_NOMEMORY);
305 iter->pos = (unsigned int) -1;
306 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
308 iter->pos6 = (unsigned int) -1;
309 iter->result6 = ISC_R_NOMORE;
311 iter->first6 = ISC_FALSE;
315 * Get the interface configuration, allocating more memory if
319 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
320 result = isc_net_probeipv6();
321 if (result == ISC_R_SUCCESS) {
323 * Create an unbound datagram socket to do the SIOCGLIFCONF
324 * ioctl on. HP/UX requires an AF_INET6 socket for
325 * SIOCGLIFCONF to get IPv6 addresses.
327 if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
328 isc__strerror(errno, strbuf, sizeof(strbuf));
329 UNEXPECTED_ERROR(__FILE__, __LINE__,
330 isc_msgcat_get(isc_msgcat,
331 ISC_MSGSET_IFITERIOCTL,
332 ISC_MSG_MAKESCANSOCKET,
336 result = ISC_R_UNEXPECTED;
337 goto socket6_failure;
339 result = iter->result6 = getbuf6(iter);
340 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
344 if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
345 isc__strerror(errno, strbuf, sizeof(strbuf));
346 UNEXPECTED_ERROR(__FILE__, __LINE__,
347 isc_msgcat_get(isc_msgcat,
348 ISC_MSGSET_IFITERIOCTL,
349 ISC_MSG_MAKESCANSOCKET,
353 result = ISC_R_UNEXPECTED;
356 result = getbuf4(iter);
357 if (result != ISC_R_SUCCESS)
361 * A newly created iterator has an undefined position
362 * until isc_interfaceiter_first() is called.
364 #ifdef HAVE_TRUCLUSTER
365 iter->clua_context = -1;
366 iter->clua_done = ISC_TRUE;
369 iter->proc = fopen("/proc/net/if_inet6", "r");
370 iter->valid = ISC_R_FAILURE;
372 iter->result = ISC_R_FAILURE;
374 iter->magic = IFITER_MAGIC;
376 return (ISC_R_SUCCESS);
379 if (iter->buf != NULL)
380 isc_mem_put(mctx, iter->buf, iter->bufsize);
381 (void) close(iter->socket);
384 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
385 if (iter->buf6 != NULL)
386 isc_mem_put(mctx, iter->buf6, iter->bufsize6);
388 if (iter->socket6 != -1)
389 (void) close(iter->socket6);
393 isc_mem_put(mctx, iter, sizeof(*iter));
397 #ifdef HAVE_TRUCLUSTER
399 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
400 dst->family = AF_INET;
401 memmove(&dst->type.in, src, sizeof(struct in_addr));
405 internal_current_clusteralias(isc_interfaceiter_t *iter) {
407 if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
408 return (ISC_R_IGNORE);
409 memset(&iter->current, 0, sizeof(iter->current));
410 iter->current.af = iter->clua_sa.sa_family;
411 memset(iter->current.name, 0, sizeof(iter->current.name));
412 sprintf(iter->current.name, "clua%d", ci.aliasid);
413 iter->current.flags = INTERFACE_F_UP;
414 get_inaddr(&iter->current.address, &ci.addr);
415 get_inaddr(&iter->current.netmask, &ci.netmask);
416 return (ISC_R_SUCCESS);
421 * Get information about the current interface to iter->current.
422 * If successful, return ISC_R_SUCCESS.
423 * If the interface has an unsupported address family, or if
424 * some operation on it fails, return ISC_R_IGNORE to make
425 * the higher-level iterator code ignore it.
429 internal_current4(isc_interfaceiter_t *iter) {
433 char strbuf[ISC_STRERRORSIZE];
434 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
435 struct lifreq lifreq;
439 int i, bits, prefixlen;
441 REQUIRE(VALID_IFITER(iter));
443 if (iter->ifc.ifc_len == 0 ||
444 iter->pos == (unsigned int)iter->ifc.ifc_len) {
446 return (linux_if_inet6_current(iter));
448 return (ISC_R_NOMORE);
452 INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
454 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
456 memset(&ifreq, 0, sizeof(ifreq));
457 memmove(&ifreq, ifrp, sizeof(ifreq));
459 family = ifreq.ifr_addr.sa_family;
460 #if defined(ISC_PLATFORM_HAVEIPV6)
461 if (family != AF_INET && family != AF_INET6)
463 if (family != AF_INET)
465 return (ISC_R_IGNORE);
467 memset(&iter->current, 0, sizeof(iter->current));
468 iter->current.af = family;
470 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
471 memset(iter->current.name, 0, sizeof(iter->current.name));
472 memmove(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
474 get_addr(family, &iter->current.address,
475 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
478 * If the interface does not have a address ignore it.
482 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
483 return (ISC_R_IGNORE);
486 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
487 sizeof(in6addr_any)) == 0)
488 return (ISC_R_IGNORE);
493 * Get interface flags.
496 iter->current.flags = 0;
499 * Ignore the HP/UX warning about "integer overflow during
500 * conversion. It comes from its own macro definition,
501 * and is really hard to shut up.
503 if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
504 isc__strerror(errno, strbuf, sizeof(strbuf));
505 UNEXPECTED_ERROR(__FILE__, __LINE__,
506 "%s: getting interface flags: %s",
507 ifreq.ifr_name, strbuf);
508 return (ISC_R_IGNORE);
511 if ((ifreq.ifr_flags & IFF_UP) != 0)
512 iter->current.flags |= INTERFACE_F_UP;
514 #ifdef IFF_POINTOPOINT
515 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
516 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
519 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
520 iter->current.flags |= INTERFACE_F_LOOPBACK;
522 if (family == AF_INET)
525 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
526 memset(&lifreq, 0, sizeof(lifreq));
527 memmove(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
528 memmove(&lifreq.lifr_addr, &iter->current.address.type.in6,
529 sizeof(iter->current.address.type.in6));
531 if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
532 isc__strerror(errno, strbuf, sizeof(strbuf));
533 UNEXPECTED_ERROR(__FILE__, __LINE__,
534 "%s: getting interface address: %s",
535 ifreq.ifr_name, strbuf);
536 return (ISC_R_IGNORE);
538 prefixlen = lifreq.lifr_addrlen;
540 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
541 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
542 ISC_LOGMODULE_INTERFACE,
544 isc_msgcat_get(isc_msgcat,
545 ISC_MSGSET_IFITERIOCTL,
547 "prefix length for %s is unknown "
548 "(assume 128)"), sabuf);
553 * Netmask already zeroed.
555 iter->current.netmask.family = family;
556 for (i = 0; i < 16; i++) {
561 bits = 8 - prefixlen;
564 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
566 return (ISC_R_SUCCESS);
569 if (family != AF_INET)
570 return (ISC_R_IGNORE);
571 #ifdef IFF_POINTOPOINT
573 * If the interface is point-to-point, get the destination address.
575 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
577 * Ignore the HP/UX warning about "integer overflow during
578 * conversion. It comes from its own macro definition,
579 * and is really hard to shut up.
581 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
583 isc__strerror(errno, strbuf, sizeof(strbuf));
584 UNEXPECTED_ERROR(__FILE__, __LINE__,
585 isc_msgcat_get(isc_msgcat,
586 ISC_MSGSET_IFITERIOCTL,
589 "destination address: %s"),
590 ifreq.ifr_name, strbuf);
591 return (ISC_R_IGNORE);
593 get_addr(family, &iter->current.dstaddress,
594 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
599 * Get the network mask.
601 memset(&ifreq, 0, sizeof(ifreq));
602 memmove(&ifreq, ifrp, sizeof(ifreq));
604 * Ignore the HP/UX warning about "integer overflow during
605 * conversion. It comes from its own macro definition,
606 * and is really hard to shut up.
608 if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
609 isc__strerror(errno, strbuf, sizeof(strbuf));
610 UNEXPECTED_ERROR(__FILE__, __LINE__,
611 isc_msgcat_get(isc_msgcat,
612 ISC_MSGSET_IFITERIOCTL,
614 "%s: getting netmask: %s"),
615 ifreq.ifr_name, strbuf);
616 return (ISC_R_IGNORE);
618 get_addr(family, &iter->current.netmask,
619 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
620 return (ISC_R_SUCCESS);
623 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
625 internal_current6(isc_interfaceiter_t *iter) {
627 struct LIFREQ lifreq;
629 char strbuf[ISC_STRERRORSIZE];
632 REQUIRE(VALID_IFITER(iter));
633 if (iter->result6 != ISC_R_SUCCESS)
634 return (iter->result6);
635 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
637 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
639 memset(&lifreq, 0, sizeof(lifreq));
640 memmove(&lifreq, ifrp, sizeof(lifreq));
642 family = lifreq.lifr_addr.ss_family;
643 #ifdef ISC_PLATFORM_HAVEIPV6
644 if (family != AF_INET && family != AF_INET6)
646 if (family != AF_INET)
648 return (ISC_R_IGNORE);
650 memset(&iter->current, 0, sizeof(iter->current));
651 iter->current.af = family;
653 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
654 memset(iter->current.name, 0, sizeof(iter->current.name));
655 memmove(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
657 get_addr(family, &iter->current.address,
658 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
661 * If the interface does not have a address ignore it.
665 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
666 return (ISC_R_IGNORE);
669 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
670 sizeof(in6addr_any)) == 0)
671 return (ISC_R_IGNORE);
676 * Get interface flags.
679 iter->current.flags = 0;
681 if (family == AF_INET6)
687 * Ignore the HP/UX warning about "integer overflow during
688 * conversion. It comes from its own macro definition,
689 * and is really hard to shut up.
691 if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
692 isc__strerror(errno, strbuf, sizeof(strbuf));
693 UNEXPECTED_ERROR(__FILE__, __LINE__,
694 "%s: getting interface flags: %s",
695 lifreq.lifr_name, strbuf);
696 return (ISC_R_IGNORE);
699 if ((lifreq.lifr_flags & IFF_UP) != 0)
700 iter->current.flags |= INTERFACE_F_UP;
702 #ifdef IFF_POINTOPOINT
703 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
704 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
707 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
708 iter->current.flags |= INTERFACE_F_LOOPBACK;
710 #ifdef IFF_POINTOPOINT
712 * If the interface is point-to-point, get the destination address.
714 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
716 * Ignore the HP/UX warning about "integer overflow during
717 * conversion. It comes from its own macro definition,
718 * and is really hard to shut up.
720 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
722 isc__strerror(errno, strbuf, sizeof(strbuf));
723 UNEXPECTED_ERROR(__FILE__, __LINE__,
724 isc_msgcat_get(isc_msgcat,
725 ISC_MSGSET_IFITERIOCTL,
728 "destination address: %s"),
729 lifreq.lifr_name, strbuf);
730 return (ISC_R_IGNORE);
732 get_addr(family, &iter->current.dstaddress,
733 (struct sockaddr *)&lifreq.lifr_dstaddr,
739 * Get the network mask. Netmask already zeroed.
741 memset(&lifreq, 0, sizeof(lifreq));
742 memmove(&lifreq, ifrp, sizeof(lifreq));
746 * Special case: if the system provides lifr_addrlen member, the
747 * netmask of an IPv6 address can be derived from the length, since
748 * an IPv6 address always has a contiguous mask.
750 if (family == AF_INET6) {
753 iter->current.netmask.family = family;
754 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
755 bits = lifreq.lifr_addrlen - i;
756 bits = (bits < 8) ? (8 - bits) : 0;
757 iter->current.netmask.type.in6.s6_addr[i / 8] =
761 return (ISC_R_SUCCESS);
766 * Ignore the HP/UX warning about "integer overflow during
767 * conversion. It comes from its own macro definition,
768 * and is really hard to shut up.
770 if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
771 isc__strerror(errno, strbuf, sizeof(strbuf));
772 UNEXPECTED_ERROR(__FILE__, __LINE__,
773 isc_msgcat_get(isc_msgcat,
774 ISC_MSGSET_IFITERIOCTL,
776 "%s: getting netmask: %s"),
777 lifreq.lifr_name, strbuf);
778 return (ISC_R_IGNORE);
780 get_addr(family, &iter->current.netmask,
781 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
783 return (ISC_R_SUCCESS);
788 internal_current(isc_interfaceiter_t *iter) {
789 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
790 if (iter->mode == 6) {
791 iter->result6 = internal_current6(iter);
792 if (iter->result6 != ISC_R_NOMORE)
793 return (iter->result6);
796 #ifdef HAVE_TRUCLUSTER
797 if (!iter->clua_done)
798 return(internal_current_clusteralias(iter));
800 return (internal_current4(iter));
804 * Step the iterator to the next interface. Unlike
805 * isc_interfaceiter_next(), this may leave the iterator
806 * positioned on an interface that will ultimately
807 * be ignored. Return ISC_R_NOMORE if there are no more
808 * interfaces, otherwise ISC_R_SUCCESS.
811 internal_next4(isc_interfaceiter_t *iter) {
812 #ifdef ISC_PLATFORM_HAVESALEN
816 if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
817 #ifdef ISC_PLATFORM_HAVESALEN
818 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
820 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
821 iter->pos += sizeof(ifrp->ifr_name) +
822 ifrp->ifr_addr.sa_len;
825 iter->pos += sizeof(struct ifreq);
828 INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
830 return (linux_if_inet6_next(iter));
832 return (ISC_R_NOMORE);
835 return (ISC_R_SUCCESS);
838 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
840 internal_next6(isc_interfaceiter_t *iter) {
841 #ifdef ISC_PLATFORM_HAVESALEN
845 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
846 return (iter->result6);
848 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
850 #ifdef ISC_PLATFORM_HAVESALEN
851 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
853 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
854 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
857 iter->pos6 += sizeof(struct LIFREQ);
859 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
860 return (ISC_R_NOMORE);
862 return (ISC_R_SUCCESS);
867 internal_next(isc_interfaceiter_t *iter) {
868 #ifdef HAVE_TRUCLUSTER
871 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
872 if (iter->mode == 6) {
873 iter->result6 = internal_next6(iter);
874 if (iter->result6 != ISC_R_NOMORE)
875 return (iter->result6);
877 iter->first6 = ISC_FALSE;
878 return (ISC_R_SUCCESS);
882 #ifdef HAVE_TRUCLUSTER
883 if (!iter->clua_done) {
884 clua_result = clua_getaliasaddress(&iter->clua_sa,
885 &iter->clua_context);
886 if (clua_result != CLUA_SUCCESS)
887 iter->clua_done = ISC_TRUE;
888 return (ISC_R_SUCCESS);
891 return (internal_next4(iter));
895 internal_destroy(isc_interfaceiter_t *iter) {
896 (void) close(iter->socket);
897 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
898 if (iter->socket6 != -1)
899 (void) close(iter->socket6);
900 if (iter->buf6 != NULL) {
901 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
905 if (iter->proc != NULL)
911 void internal_first(isc_interfaceiter_t *iter) {
912 #ifdef HAVE_TRUCLUSTER
916 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
918 if (iter->result6 == ISC_R_NOMORE)
919 iter->result6 = ISC_R_SUCCESS;
920 iter->first6 = ISC_TRUE;
922 #ifdef HAVE_TRUCLUSTER
923 iter->clua_context = 0;
924 clua_result = clua_getaliasaddress(&iter->clua_sa,
925 &iter->clua_context);
926 iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
929 linux_if_inet6_first(iter);