2 * Copyright (C) 2004-2007, 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.58.90.3 2009/02/16 00:53:58 marka Exp $ */
22 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
26 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
27 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
28 #define lifc_len iflc_len
29 #define lifc_buf iflc_buf
30 #define lifc_req iflc_req
31 #define LIFCONF if_laddrconf
33 #define ISC_HAVE_LIFC_FAMILY 1
34 #define ISC_HAVE_LIFC_FLAGS 1
35 #define LIFCONF lifconf
38 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
39 #define lifr_addr iflr_addr
40 #define lifr_name iflr_name
41 #define lifr_dstaddr iflr_dstaddr
42 #define lifr_flags iflr_flags
43 #define ss_family sa_family
44 #define LIFREQ if_laddrreq
50 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
51 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
53 #define ISC_IF_INET6_SZ \
54 sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
56 struct isc_interfaceiter
{
57 unsigned int magic
; /* Magic number. */
62 void *buf
; /* Buffer for sysctl data. */
63 unsigned int bufsize
; /* Bytes allocated. */
64 unsigned int pos
; /* Current offset in
66 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
69 void *buf6
; /* Buffer for sysctl data. */
70 unsigned int bufsize6
; /* Bytes allocated. */
71 unsigned int pos6
; /* Current offset in
73 isc_result_t result6
; /* Last result code. */
76 #ifdef HAVE_TRUCLUSTER
77 int clua_context
; /* Cluster alias context */
78 isc_boolean_t clua_done
;
79 struct sockaddr clua_sa
;
83 char entry
[ISC_IF_INET6_SZ
];
87 isc_interface_t current
; /* Current interface data. */
88 isc_result_t result
; /* Last result code. */
91 #ifdef HAVE_TRUCLUSTER
92 #include <clua/clua.h>
93 #include <sys/socket.h>
98 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
99 * will have more than a megabyte of interface configuration data.
101 #define IFCONF_BUFSIZE_INITIAL 4096
102 #define IFCONF_BUFSIZE_MAX 1048576
107 # define IF_NAMESIZE IFNAMSIZ
109 # define IF_NAMESIZE 16
115 getbuf4(isc_interfaceiter_t
*iter
) {
116 char strbuf
[ISC_STRERRORSIZE
];
118 iter
->bufsize
= IFCONF_BUFSIZE_INITIAL
;
121 iter
->buf
= isc_mem_get(iter
->mctx
, iter
->bufsize
);
122 if (iter
->buf
== NULL
)
123 return (ISC_R_NOMEMORY
);
125 memset(&iter
->ifc
.ifc_len
, 0, sizeof(iter
->ifc
.ifc_len
));
126 iter
->ifc
.ifc_len
= iter
->bufsize
;
127 iter
->ifc
.ifc_buf
= iter
->buf
;
129 * Ignore the HP/UX warning about "integer overflow during
130 * conversion". It comes from its own macro definition,
131 * and is really hard to shut up.
133 if (ioctl(iter
->socket
, SIOCGIFCONF
, (char *)&iter
->ifc
)
135 if (errno
!= EINVAL
) {
136 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
137 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
138 isc_msgcat_get(isc_msgcat
,
139 ISC_MSGSET_IFITERIOCTL
,
142 "configuration: %s"),
147 * EINVAL. Retry with a bigger buffer.
151 * The ioctl succeeded.
152 * Some OS's just return what will fit rather
153 * than set EINVAL if the buffer is too small
154 * to fit all the interfaces in. If
155 * ifc.lifc_len is too near to the end of the
156 * buffer we will grow it just in case and
159 if (iter
->ifc
.ifc_len
+ 2 * sizeof(struct ifreq
)
163 if (iter
->bufsize
>= IFCONF_BUFSIZE_MAX
) {
164 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
165 isc_msgcat_get(isc_msgcat
,
166 ISC_MSGSET_IFITERIOCTL
,
174 isc_mem_put(iter
->mctx
, iter
->buf
, iter
->bufsize
);
178 return (ISC_R_SUCCESS
);
181 isc_mem_put(iter
->mctx
, iter
->buf
, iter
->bufsize
);
183 return (ISC_R_UNEXPECTED
);
186 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
188 getbuf6(isc_interfaceiter_t
*iter
) {
189 char strbuf
[ISC_STRERRORSIZE
];
192 iter
->bufsize6
= IFCONF_BUFSIZE_INITIAL
;
195 iter
->buf6
= isc_mem_get(iter
->mctx
, iter
->bufsize6
);
196 if (iter
->buf6
== NULL
)
197 return (ISC_R_NOMEMORY
);
199 memset(&iter
->lifc
, 0, sizeof(iter
->lifc
));
200 #ifdef ISC_HAVE_LIFC_FAMILY
201 iter
->lifc
.lifc_family
= AF_INET6
;
203 #ifdef ISC_HAVE_LIFC_FLAGS
204 iter
->lifc
.lifc_flags
= 0;
206 iter
->lifc
.lifc_len
= iter
->bufsize6
;
207 iter
->lifc
.lifc_buf
= iter
->buf6
;
209 * Ignore the HP/UX warning about "integer overflow during
210 * conversion". It comes from its own macro definition,
211 * and is really hard to shut up.
213 if (ioctl(iter
->socket6
, SIOCGLIFCONF
, (char *)&iter
->lifc
)
217 * IPv6 interface scanning is not available on all
218 * kernels w/ IPv6 sockets.
220 if (errno
== ENOENT
) {
221 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
222 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
223 ISC_LOGMODULE_INTERFACE
,
225 isc_msgcat_get(isc_msgcat
,
226 ISC_MSGSET_IFITERIOCTL
,
229 "configuration: %s"),
231 result
= ISC_R_FAILURE
;
235 if (errno
!= EINVAL
) {
236 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
237 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
238 isc_msgcat_get(isc_msgcat
,
239 ISC_MSGSET_IFITERIOCTL
,
242 "configuration: %s"),
244 result
= ISC_R_UNEXPECTED
;
248 * EINVAL. Retry with a bigger buffer.
252 * The ioctl succeeded.
253 * Some OS's just return what will fit rather
254 * than set EINVAL if the buffer is too small
255 * to fit all the interfaces in. If
256 * ifc.ifc_len is too near to the end of the
257 * buffer we will grow it just in case and
260 if (iter
->lifc
.lifc_len
+ 2 * sizeof(struct LIFREQ
)
264 if (iter
->bufsize6
>= IFCONF_BUFSIZE_MAX
) {
265 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
266 isc_msgcat_get(isc_msgcat
,
267 ISC_MSGSET_IFITERIOCTL
,
273 result
= ISC_R_UNEXPECTED
;
276 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
281 if (iter
->lifc
.lifc_len
!= 0)
283 return (ISC_R_SUCCESS
);
286 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
293 isc_interfaceiter_create(isc_mem_t
*mctx
, isc_interfaceiter_t
**iterp
) {
294 isc_interfaceiter_t
*iter
;
296 char strbuf
[ISC_STRERRORSIZE
];
298 REQUIRE(mctx
!= NULL
);
299 REQUIRE(iterp
!= NULL
);
300 REQUIRE(*iterp
== NULL
);
302 iter
= isc_mem_get(mctx
, sizeof(*iter
));
304 return (ISC_R_NOMEMORY
);
309 iter
->pos
= (unsigned int) -1;
310 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
312 iter
->pos6
= (unsigned int) -1;
313 iter
->result6
= ISC_R_NOMORE
;
315 iter
->first6
= ISC_FALSE
;
319 * Get the interface configuration, allocating more memory if
323 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
324 result
= isc_net_probeipv6();
325 if (result
== ISC_R_SUCCESS
) {
327 * Create an unbound datagram socket to do the SIOCGLIFCONF
328 * ioctl on. HP/UX requires an AF_INET6 socket for
329 * SIOCGLIFCONF to get IPv6 addresses.
331 if ((iter
->socket6
= socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0) {
332 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
333 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
334 isc_msgcat_get(isc_msgcat
,
335 ISC_MSGSET_IFITERIOCTL
,
336 ISC_MSG_MAKESCANSOCKET
,
340 result
= ISC_R_UNEXPECTED
;
341 goto socket6_failure
;
343 result
= iter
->result6
= getbuf6(iter
);
344 if (result
!= ISC_R_NOTIMPLEMENTED
&& result
!= ISC_R_SUCCESS
)
348 if ((iter
->socket
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
349 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
350 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
351 isc_msgcat_get(isc_msgcat
,
352 ISC_MSGSET_IFITERIOCTL
,
353 ISC_MSG_MAKESCANSOCKET
,
357 result
= ISC_R_UNEXPECTED
;
360 result
= getbuf4(iter
);
361 if (result
!= ISC_R_SUCCESS
)
365 * A newly created iterator has an undefined position
366 * until isc_interfaceiter_first() is called.
368 #ifdef HAVE_TRUCLUSTER
369 iter
->clua_context
= -1;
370 iter
->clua_done
= ISC_TRUE
;
373 iter
->proc
= fopen("/proc/net/if_inet6", "r");
374 iter
->valid
= ISC_R_FAILURE
;
375 iter
->first
= ISC_FALSE
;
377 iter
->result
= ISC_R_FAILURE
;
379 iter
->magic
= IFITER_MAGIC
;
381 return (ISC_R_SUCCESS
);
384 if (iter
->buf
!= NULL
)
385 isc_mem_put(mctx
, iter
->buf
, iter
->bufsize
);
386 (void) close(iter
->socket
);
389 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
390 if (iter
->buf6
!= NULL
)
391 isc_mem_put(mctx
, iter
->buf6
, iter
->bufsize6
);
393 if (iter
->socket6
!= -1)
394 (void) close(iter
->socket6
);
398 isc_mem_put(mctx
, iter
, sizeof(*iter
));
402 #ifdef HAVE_TRUCLUSTER
404 get_inaddr(isc_netaddr_t
*dst
, struct in_addr
*src
) {
405 dst
->family
= AF_INET
;
406 memcpy(&dst
->type
.in
, src
, sizeof(struct in_addr
));
410 internal_current_clusteralias(isc_interfaceiter_t
*iter
) {
412 if (clua_getaliasinfo(&iter
->clua_sa
, &ci
) != CLUA_SUCCESS
)
413 return (ISC_R_IGNORE
);
414 memset(&iter
->current
, 0, sizeof(iter
->current
));
415 iter
->current
.af
= iter
->clua_sa
.sa_family
;
416 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
417 sprintf(iter
->current
.name
, "clua%d", ci
.aliasid
);
418 iter
->current
.flags
= INTERFACE_F_UP
;
419 get_inaddr(&iter
->current
.address
, &ci
.addr
);
420 get_inaddr(&iter
->current
.netmask
, &ci
.netmask
);
421 return (ISC_R_SUCCESS
);
427 linux_if_inet6_next(isc_interfaceiter_t
*iter
) {
428 if (iter
->proc
!= NULL
&&
429 fgets(iter
->entry
, sizeof(iter
->entry
), iter
->proc
) != NULL
)
430 iter
->valid
= ISC_R_SUCCESS
;
432 iter
->valid
= ISC_R_NOMORE
;
433 return (iter
->valid
);
437 linux_if_inet6_first(isc_interfaceiter_t
*iter
) {
438 if (iter
->proc
!= NULL
) {
440 (void)linux_if_inet6_next(iter
);
442 iter
->valid
= ISC_R_NOMORE
;
443 iter
->first
= ISC_FALSE
;
447 linux_if_inet6_current(isc_interfaceiter_t
*iter
) {
449 char name
[IF_NAMESIZE
+1];
450 struct in6_addr addr6
;
451 int ifindex
, prefix
, flag3
, flag4
;
455 if (iter
->valid
!= ISC_R_SUCCESS
)
456 return (iter
->valid
);
457 if (iter
->proc
== NULL
) {
458 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
459 ISC_LOGMODULE_INTERFACE
, ISC_LOG_ERROR
,
460 "/proc/net/if_inet6:iter->proc == NULL");
461 return (ISC_R_FAILURE
);
464 res
= sscanf(iter
->entry
, "%32[a-f0-9] %x %x %x %x %16s\n",
465 address
, &ifindex
, &prefix
, &flag3
, &flag4
, name
);
467 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
468 ISC_LOGMODULE_INTERFACE
, ISC_LOG_ERROR
,
469 "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
471 return (ISC_R_FAILURE
);
473 if (strlen(address
) != 32) {
474 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
475 ISC_LOGMODULE_INTERFACE
, ISC_LOG_ERROR
,
476 "/proc/net/if_inet6:strlen(%s) != 32", address
);
477 return (ISC_R_FAILURE
);
479 for (i
= 0; i
< 16; i
++) {
481 static const char hex
[] = "0123456789abcdef";
482 byte
= ((strchr(hex
, address
[i
* 2]) - hex
) << 4) |
483 (strchr(hex
, address
[i
* 2 + 1]) - hex
);
484 addr6
.s6_addr
[i
] = byte
;
486 iter
->current
.af
= AF_INET6
;
487 iter
->current
.flags
= INTERFACE_F_UP
;
488 isc_netaddr_fromin6(&iter
->current
.address
, &addr6
);
489 if (isc_netaddr_islinklocal(&iter
->current
.address
)) {
490 isc_netaddr_setzone(&iter
->current
.address
,
491 (isc_uint32_t
)ifindex
);
493 for (i
= 0; i
< 16; i
++) {
495 addr6
.s6_addr
[i
] = 0xff;
498 addr6
.s6_addr
[i
] = (0xff << (8 - prefix
)) & 0xff;
502 isc_netaddr_fromin6(&iter
->current
.netmask
, &addr6
);
503 strncpy(iter
->current
.name
, name
, sizeof(iter
->current
.name
));
504 return (ISC_R_SUCCESS
);
509 * Get information about the current interface to iter->current.
510 * If successful, return ISC_R_SUCCESS.
511 * If the interface has an unsupported address family, or if
512 * some operation on it fails, return ISC_R_IGNORE to make
513 * the higher-level iterator code ignore it.
517 internal_current4(isc_interfaceiter_t
*iter
) {
521 char strbuf
[ISC_STRERRORSIZE
];
522 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
523 struct lifreq lifreq
;
527 int i
, bits
, prefixlen
;
532 REQUIRE(VALID_IFITER(iter
));
533 REQUIRE(iter
->ifc
.ifc_len
== 0 ||
534 iter
->pos
< (unsigned int) iter
->ifc
.ifc_len
);
537 result
= linux_if_inet6_current(iter
);
538 if (result
!= ISC_R_NOMORE
)
540 iter
->first
= ISC_TRUE
;
543 if (iter
->ifc
.ifc_len
== 0)
544 return (ISC_R_NOMORE
);
546 ifrp
= (struct ifreq
*)((char *) iter
->ifc
.ifc_req
+ iter
->pos
);
548 memset(&ifreq
, 0, sizeof(ifreq
));
549 memcpy(&ifreq
, ifrp
, sizeof(ifreq
));
551 family
= ifreq
.ifr_addr
.sa_family
;
552 #if defined(ISC_PLATFORM_HAVEIPV6)
553 if (family
!= AF_INET
&& family
!= AF_INET6
)
555 if (family
!= AF_INET
)
557 return (ISC_R_IGNORE
);
559 memset(&iter
->current
, 0, sizeof(iter
->current
));
560 iter
->current
.af
= family
;
562 INSIST(sizeof(ifreq
.ifr_name
) <= sizeof(iter
->current
.name
));
563 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
564 memcpy(iter
->current
.name
, ifreq
.ifr_name
, sizeof(ifreq
.ifr_name
));
566 get_addr(family
, &iter
->current
.address
,
567 (struct sockaddr
*)&ifrp
->ifr_addr
, ifreq
.ifr_name
);
570 * If the interface does not have a address ignore it.
574 if (iter
->current
.address
.type
.in
.s_addr
== htonl(INADDR_ANY
))
575 return (ISC_R_IGNORE
);
578 if (memcmp(&iter
->current
.address
.type
.in6
, &in6addr_any
,
579 sizeof(in6addr_any
)) == 0)
580 return (ISC_R_IGNORE
);
585 * Get interface flags.
588 iter
->current
.flags
= 0;
591 * Ignore the HP/UX warning about "integer overflow during
592 * conversion. It comes from its own macro definition,
593 * and is really hard to shut up.
595 if (ioctl(iter
->socket
, SIOCGIFFLAGS
, (char *) &ifreq
) < 0) {
596 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
597 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
598 "%s: getting interface flags: %s",
599 ifreq
.ifr_name
, strbuf
);
600 return (ISC_R_IGNORE
);
603 if ((ifreq
.ifr_flags
& IFF_UP
) != 0)
604 iter
->current
.flags
|= INTERFACE_F_UP
;
606 #ifdef IFF_POINTOPOINT
607 if ((ifreq
.ifr_flags
& IFF_POINTOPOINT
) != 0)
608 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
611 if ((ifreq
.ifr_flags
& IFF_LOOPBACK
) != 0)
612 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
614 if (family
== AF_INET
)
617 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
618 memset(&lifreq
, 0, sizeof(lifreq
));
619 memcpy(lifreq
.lifr_name
, iter
->current
.name
, sizeof(lifreq
.lifr_name
));
620 memcpy(&lifreq
.lifr_addr
, &iter
->current
.address
.type
.in6
,
621 sizeof(iter
->current
.address
.type
.in6
));
623 if (ioctl(iter
->socket
, SIOCGLIFADDR
, &lifreq
) < 0) {
624 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
625 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
626 "%s: getting interface address: %s",
627 ifreq
.ifr_name
, strbuf
);
628 return (ISC_R_IGNORE
);
630 prefixlen
= lifreq
.lifr_addrlen
;
632 isc_netaddr_format(&iter
->current
.address
, sabuf
, sizeof(sabuf
));
633 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
634 ISC_LOGMODULE_INTERFACE
,
636 isc_msgcat_get(isc_msgcat
,
637 ISC_MSGSET_IFITERIOCTL
,
639 "prefix length for %s is unknown "
640 "(assume 128)"), sabuf
);
645 * Netmask already zeroed.
647 iter
->current
.netmask
.family
= family
;
648 for (i
= 0; i
< 16; i
++) {
653 bits
= 8 - prefixlen
;
656 iter
->current
.netmask
.type
.in6
.s6_addr
[i
] = (~0 << bits
) & 0xff;
658 return (ISC_R_SUCCESS
);
661 if (family
!= AF_INET
)
662 return (ISC_R_IGNORE
);
663 #ifdef IFF_POINTOPOINT
665 * If the interface is point-to-point, get the destination address.
667 if ((iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0) {
669 * Ignore the HP/UX warning about "integer overflow during
670 * conversion. It comes from its own macro definition,
671 * and is really hard to shut up.
673 if (ioctl(iter
->socket
, SIOCGIFDSTADDR
, (char *)&ifreq
)
675 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
676 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
677 isc_msgcat_get(isc_msgcat
,
678 ISC_MSGSET_IFITERIOCTL
,
681 "destination address: %s"),
682 ifreq
.ifr_name
, strbuf
);
683 return (ISC_R_IGNORE
);
685 get_addr(family
, &iter
->current
.dstaddress
,
686 (struct sockaddr
*)&ifreq
.ifr_dstaddr
, ifreq
.ifr_name
);
691 * Get the network mask.
693 memset(&ifreq
, 0, sizeof(ifreq
));
694 memcpy(&ifreq
, ifrp
, sizeof(ifreq
));
696 * Ignore the HP/UX warning about "integer overflow during
697 * conversion. It comes from its own macro definition,
698 * and is really hard to shut up.
700 if (ioctl(iter
->socket
, SIOCGIFNETMASK
, (char *)&ifreq
) < 0) {
701 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
702 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
703 isc_msgcat_get(isc_msgcat
,
704 ISC_MSGSET_IFITERIOCTL
,
706 "%s: getting netmask: %s"),
707 ifreq
.ifr_name
, strbuf
);
708 return (ISC_R_IGNORE
);
710 get_addr(family
, &iter
->current
.netmask
,
711 (struct sockaddr
*)&ifreq
.ifr_addr
, ifreq
.ifr_name
);
712 return (ISC_R_SUCCESS
);
715 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
717 internal_current6(isc_interfaceiter_t
*iter
) {
719 struct LIFREQ lifreq
;
721 char strbuf
[ISC_STRERRORSIZE
];
724 REQUIRE(VALID_IFITER(iter
));
725 if (iter
->result6
!= ISC_R_SUCCESS
)
726 return (iter
->result6
);
727 REQUIRE(iter
->pos6
< (unsigned int) iter
->lifc
.lifc_len
);
729 ifrp
= (struct LIFREQ
*)((char *) iter
->lifc
.lifc_req
+ iter
->pos6
);
731 memset(&lifreq
, 0, sizeof(lifreq
));
732 memcpy(&lifreq
, ifrp
, sizeof(lifreq
));
734 family
= lifreq
.lifr_addr
.ss_family
;
735 #ifdef ISC_PLATFORM_HAVEIPV6
736 if (family
!= AF_INET
&& family
!= AF_INET6
)
738 if (family
!= AF_INET
)
740 return (ISC_R_IGNORE
);
742 memset(&iter
->current
, 0, sizeof(iter
->current
));
743 iter
->current
.af
= family
;
745 INSIST(sizeof(lifreq
.lifr_name
) <= sizeof(iter
->current
.name
));
746 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
747 memcpy(iter
->current
.name
, lifreq
.lifr_name
, sizeof(lifreq
.lifr_name
));
749 get_addr(family
, &iter
->current
.address
,
750 (struct sockaddr
*)&lifreq
.lifr_addr
, lifreq
.lifr_name
);
753 * If the interface does not have a address ignore it.
757 if (iter
->current
.address
.type
.in
.s_addr
== htonl(INADDR_ANY
))
758 return (ISC_R_IGNORE
);
761 if (memcmp(&iter
->current
.address
.type
.in6
, &in6addr_any
,
762 sizeof(in6addr_any
)) == 0)
763 return (ISC_R_IGNORE
);
768 * Get interface flags.
771 iter
->current
.flags
= 0;
773 if (family
== AF_INET6
)
779 * Ignore the HP/UX warning about "integer overflow during
780 * conversion. It comes from its own macro definition,
781 * and is really hard to shut up.
783 if (ioctl(fd
, SIOCGLIFFLAGS
, (char *) &lifreq
) < 0) {
784 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
785 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
786 "%s: getting interface flags: %s",
787 lifreq
.lifr_name
, strbuf
);
788 return (ISC_R_IGNORE
);
791 if ((lifreq
.lifr_flags
& IFF_UP
) != 0)
792 iter
->current
.flags
|= INTERFACE_F_UP
;
794 #ifdef IFF_POINTOPOINT
795 if ((lifreq
.lifr_flags
& IFF_POINTOPOINT
) != 0)
796 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
799 if ((lifreq
.lifr_flags
& IFF_LOOPBACK
) != 0)
800 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
802 #ifdef IFF_POINTOPOINT
804 * If the interface is point-to-point, get the destination address.
806 if ((iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0) {
808 * Ignore the HP/UX warning about "integer overflow during
809 * conversion. It comes from its own macro definition,
810 * and is really hard to shut up.
812 if (ioctl(fd
, SIOCGLIFDSTADDR
, (char *)&lifreq
)
814 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
815 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
816 isc_msgcat_get(isc_msgcat
,
817 ISC_MSGSET_IFITERIOCTL
,
820 "destination address: %s"),
821 lifreq
.lifr_name
, strbuf
);
822 return (ISC_R_IGNORE
);
824 get_addr(family
, &iter
->current
.dstaddress
,
825 (struct sockaddr
*)&lifreq
.lifr_dstaddr
,
831 * Get the network mask. Netmask already zeroed.
833 memset(&lifreq
, 0, sizeof(lifreq
));
834 memcpy(&lifreq
, ifrp
, sizeof(lifreq
));
838 * Special case: if the system provides lifr_addrlen member, the
839 * netmask of an IPv6 address can be derived from the length, since
840 * an IPv6 address always has a contiguous mask.
842 if (family
== AF_INET6
) {
845 iter
->current
.netmask
.family
= family
;
846 for (i
= 0; i
< lifreq
.lifr_addrlen
; i
+= 8) {
847 bits
= lifreq
.lifr_addrlen
- i
;
848 bits
= (bits
< 8) ? (8 - bits
) : 0;
849 iter
->current
.netmask
.type
.in6
.s6_addr
[i
/ 8] =
853 return (ISC_R_SUCCESS
);
858 * Ignore the HP/UX warning about "integer overflow during
859 * conversion. It comes from its own macro definition,
860 * and is really hard to shut up.
862 if (ioctl(fd
, SIOCGLIFNETMASK
, (char *)&lifreq
) < 0) {
863 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
864 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
865 isc_msgcat_get(isc_msgcat
,
866 ISC_MSGSET_IFITERIOCTL
,
868 "%s: getting netmask: %s"),
869 lifreq
.lifr_name
, strbuf
);
870 return (ISC_R_IGNORE
);
872 get_addr(family
, &iter
->current
.netmask
,
873 (struct sockaddr
*)&lifreq
.lifr_addr
, lifreq
.lifr_name
);
875 return (ISC_R_SUCCESS
);
880 internal_current(isc_interfaceiter_t
*iter
) {
881 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
882 if (iter
->mode
== 6) {
883 iter
->result6
= internal_current6(iter
);
884 if (iter
->result6
!= ISC_R_NOMORE
)
885 return (iter
->result6
);
888 #ifdef HAVE_TRUCLUSTER
889 if (!iter
->clua_done
)
890 return(internal_current_clusteralias(iter
));
892 return (internal_current4(iter
));
896 * Step the iterator to the next interface. Unlike
897 * isc_interfaceiter_next(), this may leave the iterator
898 * positioned on an interface that will ultimately
899 * be ignored. Return ISC_R_NOMORE if there are no more
900 * interfaces, otherwise ISC_R_SUCCESS.
903 internal_next4(isc_interfaceiter_t
*iter
) {
904 #ifdef ISC_PLATFORM_HAVESALEN
908 REQUIRE(iter
->ifc
.ifc_len
== 0 ||
909 iter
->pos
< (unsigned int) iter
->ifc
.ifc_len
);
912 if (linux_if_inet6_next(iter
) == ISC_R_SUCCESS
)
913 return (ISC_R_SUCCESS
);
915 return (ISC_R_SUCCESS
);
918 if (iter
->ifc
.ifc_len
== 0)
919 return (ISC_R_NOMORE
);
921 #ifdef ISC_PLATFORM_HAVESALEN
922 ifrp
= (struct ifreq
*)((char *) iter
->ifc
.ifc_req
+ iter
->pos
);
924 if (ifrp
->ifr_addr
.sa_len
> sizeof(struct sockaddr
))
925 iter
->pos
+= sizeof(ifrp
->ifr_name
) + ifrp
->ifr_addr
.sa_len
;
928 iter
->pos
+= sizeof(struct ifreq
);
930 if (iter
->pos
>= (unsigned int) iter
->ifc
.ifc_len
)
931 return (ISC_R_NOMORE
);
933 return (ISC_R_SUCCESS
);
936 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
938 internal_next6(isc_interfaceiter_t
*iter
) {
939 #ifdef ISC_PLATFORM_HAVESALEN
943 if (iter
->result6
!= ISC_R_SUCCESS
&& iter
->result6
!= ISC_R_IGNORE
)
944 return (iter
->result6
);
946 REQUIRE(iter
->pos6
< (unsigned int) iter
->lifc
.lifc_len
);
948 #ifdef ISC_PLATFORM_HAVESALEN
949 ifrp
= (struct LIFREQ
*)((char *) iter
->lifc
.lifc_req
+ iter
->pos6
);
951 if (ifrp
->lifr_addr
.sa_len
> sizeof(struct sockaddr
))
952 iter
->pos6
+= sizeof(ifrp
->lifr_name
) + ifrp
->lifr_addr
.sa_len
;
955 iter
->pos6
+= sizeof(struct LIFREQ
);
957 if (iter
->pos6
>= (unsigned int) iter
->lifc
.lifc_len
)
958 return (ISC_R_NOMORE
);
960 return (ISC_R_SUCCESS
);
965 internal_next(isc_interfaceiter_t
*iter
) {
966 #ifdef HAVE_TRUCLUSTER
969 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
970 if (iter
->mode
== 6) {
971 iter
->result6
= internal_next6(iter
);
972 if (iter
->result6
!= ISC_R_NOMORE
)
973 return (iter
->result6
);
975 iter
->first6
= ISC_FALSE
;
976 return (ISC_R_SUCCESS
);
980 #ifdef HAVE_TRUCLUSTER
981 if (!iter
->clua_done
) {
982 clua_result
= clua_getaliasaddress(&iter
->clua_sa
,
983 &iter
->clua_context
);
984 if (clua_result
!= CLUA_SUCCESS
)
985 iter
->clua_done
= ISC_TRUE
;
986 return (ISC_R_SUCCESS
);
989 return (internal_next4(iter
));
993 internal_destroy(isc_interfaceiter_t
*iter
) {
994 (void) close(iter
->socket
);
995 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
996 if (iter
->socket6
!= -1)
997 (void) close(iter
->socket6
);
998 if (iter
->buf6
!= NULL
) {
999 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
1003 if (iter
->proc
!= NULL
)
1009 void internal_first(isc_interfaceiter_t
*iter
) {
1010 #ifdef HAVE_TRUCLUSTER
1014 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1016 if (iter
->result6
== ISC_R_NOMORE
)
1017 iter
->result6
= ISC_R_SUCCESS
;
1018 iter
->first6
= ISC_TRUE
;
1020 #ifdef HAVE_TRUCLUSTER
1021 iter
->clua_context
= 0;
1022 clua_result
= clua_getaliasaddress(&iter
->clua_sa
,
1023 &iter
->clua_context
);
1024 iter
->clua_done
= ISC_TF(clua_result
!= CLUA_SUCCESS
);
1027 linux_if_inet6_first(iter
);