2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: ifiter_ioctl.c,v 1.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_broadaddr iflr_broadaddr
43 #define lifr_flags iflr_flags
44 #define lifr_index iflr_index
45 #define ss_family sa_family
46 #define LIFREQ if_laddrreq
52 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
53 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
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];
85 isc_interface_t current; /* Current interface data. */
86 isc_result_t result; /* Last result code. */
89 #ifdef HAVE_TRUCLUSTER
90 #include <clua/clua.h>
91 #include <sys/socket.h>
96 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
97 * will have more than a megabyte of interface configuration data.
99 #define IFCONF_BUFSIZE_INITIAL 4096
100 #define IFCONF_BUFSIZE_MAX 1048576
105 # define IF_NAMESIZE IFNAMSIZ
107 # define IF_NAMESIZE 16
112 /* Silence a warning when this file is #included */
114 isc_ioctl(int fildes, int req, char *arg);
117 isc_ioctl(int fildes, int req, char *arg) {
121 for (trys = 0; trys < 3; trys++) {
122 if ((ret = ioctl(fildes, req, arg)) < 0) {
132 getbuf4(isc_interfaceiter_t *iter) {
133 char strbuf[ISC_STRERRORSIZE];
135 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
138 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
139 if (iter->buf == NULL)
140 return (ISC_R_NOMEMORY);
142 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
143 iter->ifc.ifc_len = iter->bufsize;
144 iter->ifc.ifc_buf = iter->buf;
146 * Ignore the HP/UX warning about "integer overflow during
147 * conversion". It comes from its own macro definition,
148 * and is really hard to shut up.
150 if (isc_ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
152 if (errno != EINVAL) {
153 isc__strerror(errno, strbuf, sizeof(strbuf));
154 UNEXPECTED_ERROR(__FILE__, __LINE__,
155 isc_msgcat_get(isc_msgcat,
156 ISC_MSGSET_IFITERIOCTL,
159 "configuration: %s"),
164 * EINVAL. Retry with a bigger buffer.
168 * The ioctl succeeded.
169 * Some OS's just return what will fit rather
170 * than set EINVAL if the buffer is too small
171 * to fit all the interfaces in. If
172 * ifc.lifc_len is too near to the end of the
173 * buffer we will grow it just in case and
176 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
180 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
181 UNEXPECTED_ERROR(__FILE__, __LINE__,
182 isc_msgcat_get(isc_msgcat,
183 ISC_MSGSET_IFITERIOCTL,
191 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
195 return (ISC_R_SUCCESS);
198 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
200 return (ISC_R_UNEXPECTED);
203 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
205 getbuf6(isc_interfaceiter_t *iter) {
206 char strbuf[ISC_STRERRORSIZE];
209 iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
212 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
213 if (iter->buf6 == NULL)
214 return (ISC_R_NOMEMORY);
216 memset(&iter->lifc, 0, sizeof(iter->lifc));
217 #ifdef ISC_HAVE_LIFC_FAMILY
218 iter->lifc.lifc_family = AF_INET6;
220 #ifdef ISC_HAVE_LIFC_FLAGS
221 iter->lifc.lifc_flags = 0;
223 iter->lifc.lifc_len = iter->bufsize6;
224 iter->lifc.lifc_buf = iter->buf6;
226 * Ignore the HP/UX warning about "integer overflow during
227 * conversion". It comes from its own macro definition,
228 * and is really hard to shut up.
230 if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
234 * IPv6 interface scanning is not available on all
235 * kernels w/ IPv6 sockets.
237 if (errno == ENOENT) {
238 isc__strerror(errno, strbuf, sizeof(strbuf));
239 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
240 ISC_LOGMODULE_INTERFACE,
242 isc_msgcat_get(isc_msgcat,
243 ISC_MSGSET_IFITERIOCTL,
246 "configuration: %s"),
248 result = ISC_R_FAILURE;
252 if (errno != EINVAL) {
253 isc__strerror(errno, strbuf, sizeof(strbuf));
254 UNEXPECTED_ERROR(__FILE__, __LINE__,
255 isc_msgcat_get(isc_msgcat,
256 ISC_MSGSET_IFITERIOCTL,
259 "configuration: %s"),
261 result = ISC_R_UNEXPECTED;
265 * EINVAL. Retry with a bigger buffer.
269 * The ioctl succeeded.
270 * Some OS's just return what will fit rather
271 * than set EINVAL if the buffer is too small
272 * to fit all the interfaces in. If
273 * ifc.ifc_len is too near to the end of the
274 * buffer we will grow it just in case and
277 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
281 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
282 UNEXPECTED_ERROR(__FILE__, __LINE__,
283 isc_msgcat_get(isc_msgcat,
284 ISC_MSGSET_IFITERIOCTL,
290 result = ISC_R_UNEXPECTED;
293 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
298 if (iter->lifc.lifc_len != 0)
300 return (ISC_R_SUCCESS);
303 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
310 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
311 isc_interfaceiter_t *iter;
313 char strbuf[ISC_STRERRORSIZE];
315 REQUIRE(mctx != NULL);
316 REQUIRE(iterp != NULL);
317 REQUIRE(*iterp == NULL);
319 iter = isc_mem_get(mctx, sizeof(*iter));
321 return (ISC_R_NOMEMORY);
326 iter->pos = (unsigned int) -1;
327 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
329 iter->pos6 = (unsigned int) -1;
330 iter->result6 = ISC_R_NOMORE;
332 iter->first6 = ISC_FALSE;
336 * Get the interface configuration, allocating more memory if
340 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
341 result = isc_net_probeipv6();
342 if (result == ISC_R_SUCCESS) {
344 * Create an unbound datagram socket to do the SIOCGLIFCONF
345 * ioctl on. HP/UX requires an AF_INET6 socket for
346 * SIOCGLIFCONF to get IPv6 addresses.
348 if ((iter->socket6 = socket(AF_INET6, 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;
358 goto socket6_failure;
360 result = iter->result6 = getbuf6(iter);
361 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
365 if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
366 isc__strerror(errno, strbuf, sizeof(strbuf));
367 UNEXPECTED_ERROR(__FILE__, __LINE__,
368 isc_msgcat_get(isc_msgcat,
369 ISC_MSGSET_IFITERIOCTL,
370 ISC_MSG_MAKESCANSOCKET,
374 result = ISC_R_UNEXPECTED;
377 result = getbuf4(iter);
378 if (result != ISC_R_SUCCESS)
382 * A newly created iterator has an undefined position
383 * until isc_interfaceiter_first() is called.
385 #ifdef HAVE_TRUCLUSTER
386 iter->clua_context = -1;
387 iter->clua_done = ISC_TRUE;
390 iter->proc = fopen("/proc/net/if_inet6", "r");
391 iter->valid = ISC_R_FAILURE;
393 iter->result = ISC_R_FAILURE;
395 iter->magic = IFITER_MAGIC;
397 return (ISC_R_SUCCESS);
400 if (iter->buf != NULL)
401 isc_mem_put(mctx, iter->buf, iter->bufsize);
402 (void) close(iter->socket);
405 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
406 if (iter->buf6 != NULL)
407 isc_mem_put(mctx, iter->buf6, iter->bufsize6);
409 if (iter->socket6 != -1)
410 (void) close(iter->socket6);
414 isc_mem_put(mctx, iter, sizeof(*iter));
418 #ifdef HAVE_TRUCLUSTER
420 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
421 dst->family = AF_INET;
422 memcpy(&dst->type.in, src, sizeof(struct in_addr));
426 internal_current_clusteralias(isc_interfaceiter_t *iter) {
428 if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
429 return (ISC_R_IGNORE);
430 memset(&iter->current, 0, sizeof(iter->current));
431 iter->current.af = iter->clua_sa.sa_family;
432 memset(iter->current.name, 0, sizeof(iter->current.name));
433 sprintf(iter->current.name, "clua%d", ci.aliasid);
434 iter->current.flags = INTERFACE_F_UP;
435 get_inaddr(&iter->current.address, &ci.addr);
436 get_inaddr(&iter->current.netmask, &ci.netmask);
437 return (ISC_R_SUCCESS);
442 * Get information about the current interface to iter->current.
443 * If successful, return ISC_R_SUCCESS.
444 * If the interface has an unsupported address family, or if
445 * some operation on it fails, return ISC_R_IGNORE to make
446 * the higher-level iterator code ignore it.
450 internal_current4(isc_interfaceiter_t *iter) {
454 char strbuf[ISC_STRERRORSIZE];
455 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
456 struct lifreq lifreq;
460 int i, bits, prefixlen;
462 REQUIRE(VALID_IFITER(iter));
464 if (iter->ifc.ifc_len == 0 ||
465 iter->pos == (unsigned int)iter->ifc.ifc_len) {
467 return (linux_if_inet6_current(iter));
469 return (ISC_R_NOMORE);
473 INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
475 ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos);
477 memset(&ifreq, 0, sizeof(ifreq));
478 memcpy(&ifreq, ifrp, sizeof(ifreq));
480 family = ifreq.ifr_addr.sa_family;
481 #if defined(ISC_PLATFORM_HAVEIPV6)
482 if (family != AF_INET && family != AF_INET6)
484 if (family != AF_INET)
486 return (ISC_R_IGNORE);
488 memset(&iter->current, 0, sizeof(iter->current));
489 iter->current.af = family;
491 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
492 memset(iter->current.name, 0, sizeof(iter->current.name));
493 memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
495 get_addr(family, &iter->current.address,
496 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
499 * If the interface does not have a address ignore it.
503 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
504 return (ISC_R_IGNORE);
507 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
508 sizeof(in6addr_any)) == 0)
509 return (ISC_R_IGNORE);
514 * Get interface flags.
517 iter->current.flags = 0;
520 * Ignore the HP/UX warning about "integer overflow during
521 * conversion. It comes from its own macro definition,
522 * and is really hard to shut up.
524 if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
525 isc__strerror(errno, strbuf, sizeof(strbuf));
526 UNEXPECTED_ERROR(__FILE__, __LINE__,
527 "%s: getting interface flags: %s",
528 ifreq.ifr_name, strbuf);
529 return (ISC_R_IGNORE);
532 if ((ifreq.ifr_flags & IFF_UP) != 0)
533 iter->current.flags |= INTERFACE_F_UP;
535 #ifdef IFF_POINTOPOINT
536 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
537 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
540 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
541 iter->current.flags |= INTERFACE_F_LOOPBACK;
543 if ((ifreq.ifr_flags & IFF_BROADCAST) != 0)
544 iter->current.flags |= INTERFACE_F_BROADCAST;
547 if ((ifreq.ifr_flags & IFF_MULTICAST) != 0)
548 iter->current.flags |= INTERFACE_F_MULTICAST;
551 if (family == AF_INET)
554 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
555 memset(&lifreq, 0, sizeof(lifreq));
556 memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
557 memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
558 sizeof(iter->current.address.type.in6));
560 if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
561 isc__strerror(errno, strbuf, sizeof(strbuf));
562 UNEXPECTED_ERROR(__FILE__, __LINE__,
563 "%s: getting interface address: %s",
564 ifreq.ifr_name, strbuf);
565 return (ISC_R_IGNORE);
567 prefixlen = lifreq.lifr_addrlen;
569 isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
570 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
571 ISC_LOGMODULE_INTERFACE,
573 isc_msgcat_get(isc_msgcat,
574 ISC_MSGSET_IFITERIOCTL,
576 "prefix length for %s is unknown "
577 "(assume 128)"), sabuf);
582 * Netmask already zeroed.
584 iter->current.netmask.family = family;
585 for (i = 0; i < 16; i++) {
590 bits = 8 - prefixlen;
593 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
595 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
596 iter->current.ifindex = if_nametoindex(iter->current.name);
598 return (ISC_R_SUCCESS);
601 if (family != AF_INET)
602 return (ISC_R_IGNORE);
603 #ifdef IFF_POINTOPOINT
605 * If the interface is point-to-point, get the destination address.
607 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
609 * Ignore the HP/UX warning about "integer overflow during
610 * conversion. It comes from its own macro definition,
611 * and is really hard to shut up.
613 if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
615 isc__strerror(errno, strbuf, sizeof(strbuf));
616 UNEXPECTED_ERROR(__FILE__, __LINE__,
617 isc_msgcat_get(isc_msgcat,
618 ISC_MSGSET_IFITERIOCTL,
621 "destination address: %s"),
622 ifreq.ifr_name, strbuf);
623 return (ISC_R_IGNORE);
625 get_addr(family, &iter->current.dstaddress,
626 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
630 if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
632 * Ignore the HP/UX warning about "integer overflow during
633 * conversion. It comes from its own macro definition,
634 * and is really hard to shut up.
636 if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
638 isc__strerror(errno, strbuf, sizeof(strbuf));
639 UNEXPECTED_ERROR(__FILE__, __LINE__,
640 isc_msgcat_get(isc_msgcat,
641 ISC_MSGSET_IFITERIOCTL,
644 "broadcast address: %s"),
645 ifreq.ifr_name, strbuf);
646 return (ISC_R_IGNORE);
648 get_addr(family, &iter->current.broadcast,
649 (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name);
653 * Get the network mask.
655 memset(&ifreq, 0, sizeof(ifreq));
656 memcpy(&ifreq, ifrp, sizeof(ifreq));
658 * Ignore the HP/UX warning about "integer overflow during
659 * conversion. It comes from its own macro definition,
660 * and is really hard to shut up.
662 if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
663 isc__strerror(errno, strbuf, sizeof(strbuf));
664 UNEXPECTED_ERROR(__FILE__, __LINE__,
665 isc_msgcat_get(isc_msgcat,
666 ISC_MSGSET_IFITERIOCTL,
668 "%s: getting netmask: %s"),
669 ifreq.ifr_name, strbuf);
670 return (ISC_R_IGNORE);
672 get_addr(family, &iter->current.netmask,
673 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
674 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
675 iter->current.ifindex = if_nametoindex(iter->current.name);
677 return (ISC_R_SUCCESS);
680 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
682 internal_current6(isc_interfaceiter_t *iter) {
684 struct LIFREQ lifreq;
686 char strbuf[ISC_STRERRORSIZE];
689 REQUIRE(VALID_IFITER(iter));
690 if (iter->result6 != ISC_R_SUCCESS)
691 return (iter->result6);
692 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
694 ifrp = (void *)((char *)iter->lifc.lifc_req + iter->pos6);
696 memset(&lifreq, 0, sizeof(lifreq));
697 memcpy(&lifreq, ifrp, sizeof(lifreq));
699 family = lifreq.lifr_addr.ss_family;
700 #ifdef ISC_PLATFORM_HAVEIPV6
701 if (family != AF_INET && family != AF_INET6)
703 if (family != AF_INET)
705 return (ISC_R_IGNORE);
707 memset(&iter->current, 0, sizeof(iter->current));
708 iter->current.af = family;
710 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
711 memset(iter->current.name, 0, sizeof(iter->current.name));
712 memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
714 get_addr(family, &iter->current.address,
715 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
717 if (isc_netaddr_islinklocal(&iter->current.address))
718 isc_netaddr_setzone(&iter->current.address,
719 (isc_uint32_t)lifreq.lifr_index);
722 * If the interface does not have a address ignore it.
726 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
727 return (ISC_R_IGNORE);
730 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
731 sizeof(in6addr_any)) == 0)
732 return (ISC_R_IGNORE);
737 * Get interface flags.
740 iter->current.flags = 0;
742 if (family == AF_INET6)
748 * Ignore the HP/UX warning about "integer overflow during
749 * conversion. It comes from its own macro definition,
750 * and is really hard to shut up.
752 if (isc_ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
753 isc__strerror(errno, strbuf, sizeof(strbuf));
754 UNEXPECTED_ERROR(__FILE__, __LINE__,
755 "%s: getting interface flags: %s",
756 lifreq.lifr_name, strbuf);
757 return (ISC_R_IGNORE);
760 if ((lifreq.lifr_flags & IFF_UP) != 0)
761 iter->current.flags |= INTERFACE_F_UP;
763 #ifdef IFF_POINTOPOINT
764 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
765 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
768 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
769 iter->current.flags |= INTERFACE_F_LOOPBACK;
771 if ((lifreq.lifr_flags & IFF_BROADCAST) != 0) {
772 iter->current.flags |= INTERFACE_F_BROADCAST;
776 if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) {
777 iter->current.flags |= INTERFACE_F_MULTICAST;
781 #ifdef IFF_POINTOPOINT
783 * If the interface is point-to-point, get the destination address.
785 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
787 * Ignore the HP/UX warning about "integer overflow during
788 * conversion. It comes from its own macro definition,
789 * and is really hard to shut up.
791 if (isc_ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
793 isc__strerror(errno, strbuf, sizeof(strbuf));
794 UNEXPECTED_ERROR(__FILE__, __LINE__,
795 isc_msgcat_get(isc_msgcat,
796 ISC_MSGSET_IFITERIOCTL,
799 "destination address: %s"),
800 lifreq.lifr_name, strbuf);
801 return (ISC_R_IGNORE);
803 get_addr(family, &iter->current.dstaddress,
804 (struct sockaddr *)&lifreq.lifr_dstaddr,
809 #ifdef SIOCGLIFBRDADDR
810 if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
812 * Ignore the HP/UX warning about "integer overflow during
813 * conversion. It comes from its own macro definition,
814 * and is really hard to shut up.
816 if (isc_ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq)
818 isc__strerror(errno, strbuf, sizeof(strbuf));
819 UNEXPECTED_ERROR(__FILE__, __LINE__,
820 isc_msgcat_get(isc_msgcat,
821 ISC_MSGSET_IFITERIOCTL,
824 "broadcast address: %s"),
825 lifreq.lifr_name, strbuf);
826 return (ISC_R_IGNORE);
828 get_addr(family, &iter->current.broadcast,
829 (struct sockaddr *)&lifreq.lifr_broadaddr,
832 #endif /* SIOCGLIFBRDADDR */
835 * Get the network mask. Netmask already zeroed.
837 memset(&lifreq, 0, sizeof(lifreq));
838 memcpy(&lifreq, ifrp, sizeof(lifreq));
842 * Special case: if the system provides lifr_addrlen member, the
843 * netmask of an IPv6 address can be derived from the length, since
844 * an IPv6 address always has a contiguous mask.
846 if (family == AF_INET6) {
849 iter->current.netmask.family = family;
850 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
851 bits = lifreq.lifr_addrlen - i;
852 bits = (bits < 8) ? (8 - bits) : 0;
853 iter->current.netmask.type.in6.s6_addr[i / 8] =
856 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
857 iter->current.ifindex = if_nametoindex(iter->current.name);
859 return (ISC_R_SUCCESS);
864 * Ignore the HP/UX warning about "integer overflow during
865 * conversion. It comes from its own macro definition,
866 * and is really hard to shut up.
868 if (isc_ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
869 isc__strerror(errno, strbuf, sizeof(strbuf));
870 UNEXPECTED_ERROR(__FILE__, __LINE__,
871 isc_msgcat_get(isc_msgcat,
872 ISC_MSGSET_IFITERIOCTL,
874 "%s: getting netmask: %s"),
875 lifreq.lifr_name, strbuf);
876 return (ISC_R_IGNORE);
878 get_addr(family, &iter->current.netmask,
879 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
881 #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
882 iter->current.ifindex = if_nametoindex(iter->current.name);
884 return (ISC_R_SUCCESS);
889 internal_current(isc_interfaceiter_t *iter) {
890 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
891 if (iter->mode == 6) {
892 iter->result6 = internal_current6(iter);
893 if (iter->result6 != ISC_R_NOMORE)
894 return (iter->result6);
897 #ifdef HAVE_TRUCLUSTER
898 if (!iter->clua_done)
899 return(internal_current_clusteralias(iter));
901 return (internal_current4(iter));
905 * Step the iterator to the next interface. Unlike
906 * isc_interfaceiter_next(), this may leave the iterator
907 * positioned on an interface that will ultimately
908 * be ignored. Return ISC_R_NOMORE if there are no more
909 * interfaces, otherwise ISC_R_SUCCESS.
912 internal_next4(isc_interfaceiter_t *iter) {
913 #ifdef ISC_PLATFORM_HAVESALEN
917 if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
918 #ifdef ISC_PLATFORM_HAVESALEN
919 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
921 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
922 iter->pos += sizeof(ifrp->ifr_name) +
923 ifrp->ifr_addr.sa_len;
926 iter->pos += sizeof(struct ifreq);
929 INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
931 return (linux_if_inet6_next(iter));
933 return (ISC_R_NOMORE);
936 return (ISC_R_SUCCESS);
939 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
941 internal_next6(isc_interfaceiter_t *iter) {
942 #ifdef ISC_PLATFORM_HAVESALEN
946 if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
947 return (iter->result6);
949 REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
951 #ifdef ISC_PLATFORM_HAVESALEN
952 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
954 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
955 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
958 iter->pos6 += sizeof(struct LIFREQ);
960 if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
961 return (ISC_R_NOMORE);
963 return (ISC_R_SUCCESS);
968 internal_next(isc_interfaceiter_t *iter) {
969 #ifdef HAVE_TRUCLUSTER
972 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
973 if (iter->mode == 6) {
974 iter->result6 = internal_next6(iter);
975 if (iter->result6 != ISC_R_NOMORE)
976 return (iter->result6);
978 iter->first6 = ISC_FALSE;
979 return (ISC_R_SUCCESS);
983 #ifdef HAVE_TRUCLUSTER
984 if (!iter->clua_done) {
985 clua_result = clua_getaliasaddress(&iter->clua_sa,
986 &iter->clua_context);
987 if (clua_result != CLUA_SUCCESS)
988 iter->clua_done = ISC_TRUE;
989 return (ISC_R_SUCCESS);
992 return (internal_next4(iter));
996 internal_destroy(isc_interfaceiter_t *iter) {
997 (void) close(iter->socket);
998 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
999 if (iter->socket6 != -1)
1000 (void) close(iter->socket6);
1001 if (iter->buf6 != NULL) {
1002 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
1006 if (iter->proc != NULL)
1012 void internal_first(isc_interfaceiter_t *iter) {
1013 #ifdef HAVE_TRUCLUSTER
1017 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1019 if (iter->result6 == ISC_R_NOMORE)
1020 iter->result6 = ISC_R_SUCCESS;
1021 iter->first6 = ISC_TRUE;
1023 #ifdef HAVE_TRUCLUSTER
1024 iter->clua_context = 0;
1025 clua_result = clua_getaliasaddress(&iter->clua_sa,
1026 &iter->clua_context);
1027 iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
1030 linux_if_inet6_first(iter);