2 * Copyright (C) 2004 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.14 2004/06/22 04:40:23 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_broadaddr iflr_broadaddr
42 #define lifr_flags iflr_flags
43 #define lifr_index iflr_index
44 #define ss_family sa_family
45 #define LIFREQ if_laddrreq
51 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
52 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
54 #define ISC_IF_INET6_SZ \
55 sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
57 struct isc_interfaceiter
{
58 unsigned int magic
; /* Magic number. */
63 void *buf
; /* Buffer for sysctl data. */
64 unsigned int bufsize
; /* Bytes allocated. */
65 unsigned int pos
; /* Current offset in
67 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
70 void *buf6
; /* Buffer for sysctl data. */
71 unsigned int bufsize6
; /* Bytes allocated. */
72 unsigned int pos6
; /* Current offset in
74 isc_result_t result6
; /* Last result code. */
77 #ifdef HAVE_TRUCLUSTER
78 int clua_context
; /* Cluster alias context */
79 isc_boolean_t clua_done
;
80 struct sockaddr clua_sa
;
84 char entry
[ISC_IF_INET6_SZ
];
88 isc_interface_t current
; /* Current interface data. */
89 isc_result_t result
; /* Last result code. */
92 #ifdef HAVE_TRUCLUSTER
93 #include <clua/clua.h>
94 #include <sys/socket.h>
99 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
100 * will have more than a megabyte of interface configuration data.
102 #define IFCONF_BUFSIZE_INITIAL 4096
103 #define IFCONF_BUFSIZE_MAX 1048576
108 # define IF_NAMESIZE IFNAMSIZ
110 # define IF_NAMESIZE 16
116 getbuf4(isc_interfaceiter_t
*iter
) {
117 char strbuf
[ISC_STRERRORSIZE
];
119 iter
->bufsize
= IFCONF_BUFSIZE_INITIAL
;
122 iter
->buf
= isc_mem_get(iter
->mctx
, iter
->bufsize
);
123 if (iter
->buf
== NULL
)
124 return (ISC_R_NOMEMORY
);
126 memset(&iter
->ifc
.ifc_len
, 0, sizeof(iter
->ifc
.ifc_len
));
127 iter
->ifc
.ifc_len
= iter
->bufsize
;
128 iter
->ifc
.ifc_buf
= iter
->buf
;
130 * Ignore the HP/UX warning about "integer overflow during
131 * conversion". It comes from its own macro definition,
132 * and is really hard to shut up.
134 if (ioctl(iter
->socket
, SIOCGIFCONF
, (char *)&iter
->ifc
)
136 if (errno
!= EINVAL
) {
137 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
138 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
139 isc_msgcat_get(isc_msgcat
,
140 ISC_MSGSET_IFITERIOCTL
,
143 "configuration: %s"),
148 * EINVAL. Retry with a bigger buffer.
152 * The ioctl succeeded.
153 * Some OS's just return what will fit rather
154 * than set EINVAL if the buffer is too small
155 * to fit all the interfaces in. If
156 * ifc.lifc_len is too near to the end of the
157 * buffer we will grow it just in case and
160 if (iter
->ifc
.ifc_len
+ 2 * sizeof(struct ifreq
)
164 if (iter
->bufsize
>= IFCONF_BUFSIZE_MAX
) {
165 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
166 isc_msgcat_get(isc_msgcat
,
167 ISC_MSGSET_IFITERIOCTL
,
175 isc_mem_put(iter
->mctx
, iter
->buf
, iter
->bufsize
);
179 return (ISC_R_SUCCESS
);
182 isc_mem_put(iter
->mctx
, iter
->buf
, iter
->bufsize
);
184 return (ISC_R_UNEXPECTED
);
187 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
189 getbuf6(isc_interfaceiter_t
*iter
) {
190 char strbuf
[ISC_STRERRORSIZE
];
193 iter
->bufsize6
= IFCONF_BUFSIZE_INITIAL
;
196 iter
->buf6
= isc_mem_get(iter
->mctx
, iter
->bufsize6
);
197 if (iter
->buf6
== NULL
)
198 return (ISC_R_NOMEMORY
);
200 memset(&iter
->lifc
, 0, sizeof(iter
->lifc
));
201 #ifdef ISC_HAVE_LIFC_FAMILY
202 iter
->lifc
.lifc_family
= AF_INET6
;
204 #ifdef ISC_HAVE_LIFC_FLAGS
205 iter
->lifc
.lifc_flags
= 0;
207 iter
->lifc
.lifc_len
= iter
->bufsize6
;
208 iter
->lifc
.lifc_buf
= iter
->buf6
;
210 * Ignore the HP/UX warning about "integer overflow during
211 * conversion". It comes from its own macro definition,
212 * and is really hard to shut up.
214 if (ioctl(iter
->socket6
, SIOCGLIFCONF
, (char *)&iter
->lifc
)
218 * IPv6 interface scanning is not available on all
219 * kernels w/ IPv6 sockets.
221 if (errno
== ENOENT
) {
222 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
223 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
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(iterp
!= NULL
);
298 REQUIRE(*iterp
== NULL
);
300 iter
= isc_mem_get(mctx
, sizeof(*iter
));
302 return (ISC_R_NOMEMORY
);
307 iter
->pos
= (unsigned int) -1;
308 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
310 iter
->pos6
= (unsigned int) -1;
311 iter
->result6
= ISC_R_NOMORE
;
313 iter
->first6
= ISC_FALSE
;
317 * Get the interface configuration, allocating more memory if
321 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
322 result
= isc_net_probeipv6();
323 if (result
== ISC_R_SUCCESS
) {
325 * Create an unbound datagram socket to do the SIOCGLIFCONF
326 * ioctl on. HP/UX requires an AF_INET6 socket for
327 * SIOCGLIFCONF to get IPv6 addresses.
329 if ((iter
->socket6
= socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0) {
330 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
331 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
332 isc_msgcat_get(isc_msgcat
,
333 ISC_MSGSET_IFITERIOCTL
,
334 ISC_MSG_MAKESCANSOCKET
,
338 result
= ISC_R_UNEXPECTED
;
339 goto socket6_failure
;
341 iter
->result6
= getbuf6(iter
);
342 if (iter
->result6
!= ISC_R_NOTIMPLEMENTED
&&
343 iter
->result6
!= 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 char strbuf
[ISC_STRERRORSIZE
];
450 struct in6_addr addr6
;
452 int ifindex
, prefix
, scope
, flags
;
456 if (iter
->valid
!= ISC_R_SUCCESS
)
457 return (iter
->valid
);
458 if (iter
->proc
== NULL
) {
459 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
460 "/proc/net/if_inet6:iter->proc == NULL");
461 return (ISC_R_FAILURE
);
465 * Format for /proc/net/if_inet6:
466 * (see iface_proc_info() in net/ipv6/addrconf.c)
467 * <addr6:32> <ifindex:2> <prefix:2> <scope:2> <flags:2> <name:8>
469 res
= sscanf(iter
->entry
, "%32[a-f0-9] %x %x %x %x %16s\n",
470 address
, &ifindex
, &prefix
, &scope
, &flags
, name
);
472 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
473 "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
475 return (ISC_R_FAILURE
);
477 if (strlen(address
) != 32) {
478 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
479 "/proc/net/if_inet6:strlen(%s) != 32", address
);
480 return (ISC_R_FAILURE
);
482 for (i
= 0; i
< 16; i
++) {
484 static const char hex
[] = "0123456789abcdef";
485 byte
= ((index(hex
, address
[i
* 2]) - hex
) << 4) |
486 (index(hex
, address
[i
* 2 + 1]) - hex
);
487 addr6
.s6_addr
[i
] = byte
;
489 iter
->current
.af
= AF_INET6
;
490 /* iter->current.ifindex = ifindex; */
491 iter
->current
.flags
= 0;
493 memset(&ifreq
, 0, sizeof(ifreq
));
494 INSIST(sizeof(ifreq
.ifr_name
) <= sizeof(iter
->current
.name
));
495 strncpy(ifreq
.ifr_name
, name
, sizeof(ifreq
.ifr_name
));
497 if (ioctl(iter
->socket
, SIOCGIFFLAGS
, (char *) &ifreq
) < 0) {
498 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
499 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
500 "%s: getting interface flags: %s",
501 ifreq
.ifr_name
, strbuf
);
502 return (ISC_R_IGNORE
);
505 if ((ifreq
.ifr_flags
& IFF_UP
) != 0)
506 iter
->current
.flags
|= INTERFACE_F_UP
;
507 #ifdef IFF_POINTOPOINT
508 if ((ifreq
.ifr_flags
& IFF_POINTOPOINT
) != 0)
509 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
511 if ((ifreq
.ifr_flags
& IFF_LOOPBACK
) != 0)
512 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
513 if ((ifreq
.ifr_flags
& IFF_BROADCAST
) != 0)
514 iter
->current
.flags
|= INTERFACE_F_BROADCAST
;
516 if ((ifreq
.ifr_flags
& IFF_MULTICAST
) != 0)
517 iter
->current
.flags
|= INTERFACE_F_MULTICAST
;
521 * enable_multicast_if() requires scopeid for setsockopt,
522 * so associate address with their corresponding ifindex.
524 isc_netaddr_fromin6(&iter
->current
.address
, &addr6
);
525 isc_netaddr_setzone(&iter
->current
.address
, (isc_uint32_t
)ifindex
);
527 for (i
= 0; i
< 16; i
++) {
529 addr6
.s6_addr
[i
] = 0xff;
532 addr6
.s6_addr
[i
] = (0xff << (8 - prefix
)) & 0xff;
536 isc_netaddr_fromin6(&iter
->current
.netmask
, &addr6
);
537 strncpy(iter
->current
.name
, name
, sizeof(iter
->current
.name
));
538 return (ISC_R_SUCCESS
);
543 * Get information about the current interface to iter->current.
544 * If successful, return ISC_R_SUCCESS.
545 * If the interface has an unsupported address family, or if
546 * some operation on it fails, return ISC_R_IGNORE to make
547 * the higher-level iterator code ignore it.
551 internal_current4(isc_interfaceiter_t
*iter
) {
555 char strbuf
[ISC_STRERRORSIZE
];
556 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
557 struct lifreq lifreq
;
561 int i
, bits
, prefixlen
;
566 REQUIRE(VALID_IFITER(iter
));
567 REQUIRE (iter
->pos
< (unsigned int) iter
->ifc
.ifc_len
);
570 result
= linux_if_inet6_current(iter
);
571 if (result
!= ISC_R_NOMORE
)
573 iter
->first
= ISC_TRUE
;
576 ifrp
= (struct ifreq
*)((char *) iter
->ifc
.ifc_req
+ iter
->pos
);
578 memset(&ifreq
, 0, sizeof(ifreq
));
579 memcpy(&ifreq
, ifrp
, sizeof(ifreq
));
581 family
= ifreq
.ifr_addr
.sa_family
;
582 #if defined(ISC_PLATFORM_HAVEIPV6)
583 if (family
!= AF_INET
&& family
!= AF_INET6
)
585 if (family
!= AF_INET
)
587 return (ISC_R_IGNORE
);
589 memset(&iter
->current
, 0, sizeof(iter
->current
));
590 iter
->current
.af
= family
;
592 INSIST(sizeof(ifreq
.ifr_name
) <= sizeof(iter
->current
.name
));
593 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
594 memcpy(iter
->current
.name
, ifreq
.ifr_name
, sizeof(ifreq
.ifr_name
));
596 get_addr(family
, &iter
->current
.address
,
597 (struct sockaddr
*)&ifrp
->ifr_addr
, ifreq
.ifr_name
);
600 * If the interface does not have a address ignore it.
604 if (iter
->current
.address
.type
.in
.s_addr
== htonl(INADDR_ANY
))
605 return (ISC_R_IGNORE
);
607 #ifdef ISC_PLATFORM_HAVEIPV6
609 if (memcmp(&iter
->current
.address
.type
.in6
, &in6addr_any
,
610 sizeof(in6addr_any
)) == 0)
611 return (ISC_R_IGNORE
);
617 * Get interface flags.
620 iter
->current
.flags
= 0;
623 * Ignore the HP/UX warning about "integer overflow during
624 * conversion. It comes from its own macro definition,
625 * and is really hard to shut up.
627 if (ioctl(iter
->socket
, SIOCGIFFLAGS
, (char *) &ifreq
) < 0) {
628 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
629 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
630 "%s: getting interface flags: %s",
631 ifreq
.ifr_name
, strbuf
);
632 return (ISC_R_IGNORE
);
635 if ((ifreq
.ifr_flags
& IFF_UP
) != 0)
636 iter
->current
.flags
|= INTERFACE_F_UP
;
638 #ifdef IFF_POINTOPOINT
639 if ((ifreq
.ifr_flags
& IFF_POINTOPOINT
) != 0)
640 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
643 if ((ifreq
.ifr_flags
& IFF_LOOPBACK
) != 0)
644 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
646 if ((ifreq
.ifr_flags
& IFF_BROADCAST
) != 0) {
647 iter
->current
.flags
|= INTERFACE_F_BROADCAST
;
651 if ((ifreq
.ifr_flags
& IFF_MULTICAST
) != 0) {
652 iter
->current
.flags
|= INTERFACE_F_MULTICAST
;
656 if (family
== AF_INET
)
659 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
660 memset(&lifreq
, 0, sizeof(lifreq
));
661 memcpy(lifreq
.lifr_name
, iter
->current
.name
, sizeof(lifreq
.lifr_name
));
662 memcpy(&lifreq
.lifr_addr
, &iter
->current
.address
.type
.in6
,
663 sizeof(iter
->current
.address
.type
.in6
));
665 if (ioctl(iter
->socket
, SIOCGLIFADDR
, &lifreq
) < 0) {
666 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
667 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
668 "%s: getting interface address: %s",
669 ifreq
.ifr_name
, strbuf
);
670 return (ISC_R_IGNORE
);
672 prefixlen
= lifreq
.lifr_addrlen
;
674 isc_netaddr_format(&iter
->current
.address
, sabuf
, sizeof(sabuf
));
675 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
676 isc_msgcat_get(isc_msgcat
,
677 ISC_MSGSET_IFITERIOCTL
,
679 "prefix length for %s is unknown "
680 "(assume 128)"), sabuf
);
685 * Netmask already zeroed.
687 iter
->current
.netmask
.family
= family
;
688 for (i
= 0; i
< 16; i
++) {
693 bits
= 8 - prefixlen
;
696 iter
->current
.netmask
.type
.in6
.s6_addr
[i
] = (~0 << bits
) & 0xff;
698 return (ISC_R_SUCCESS
);
701 if (family
!= AF_INET
)
702 return (ISC_R_IGNORE
);
703 #ifdef IFF_POINTOPOINT
705 * If the interface is point-to-point, get the destination address.
707 if ((iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0) {
709 * Ignore the HP/UX warning about "integer overflow during
710 * conversion. It comes from its own macro definition,
711 * and is really hard to shut up.
713 if (ioctl(iter
->socket
, SIOCGIFDSTADDR
, (char *)&ifreq
)
715 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
716 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
717 isc_msgcat_get(isc_msgcat
,
718 ISC_MSGSET_IFITERIOCTL
,
721 "destination address: %s"),
722 ifreq
.ifr_name
, strbuf
);
723 return (ISC_R_IGNORE
);
725 get_addr(family
, &iter
->current
.dstaddress
,
726 (struct sockaddr
*)&ifreq
.ifr_dstaddr
, ifreq
.ifr_name
);
729 if ((iter
->current
.flags
& INTERFACE_F_BROADCAST
) != 0) {
731 * Ignore the HP/UX warning about "integer overflow during
732 * conversion. It comes from its own macro definition,
733 * and is really hard to shut up.
735 if (ioctl(iter
->socket
, SIOCGIFBRDADDR
, (char *)&ifreq
)
737 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
738 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
739 isc_msgcat_get(isc_msgcat
,
740 ISC_MSGSET_IFITERIOCTL
,
743 "broadcast address: %s"),
744 ifreq
.ifr_name
, strbuf
);
745 return (ISC_R_IGNORE
);
747 get_addr(family
, &iter
->current
.broadcast
,
748 (struct sockaddr
*)&ifreq
.ifr_broadaddr
, ifreq
.ifr_name
);
752 * Get the network mask.
754 memset(&ifreq
, 0, sizeof(ifreq
));
755 memcpy(&ifreq
, ifrp
, sizeof(ifreq
));
757 * Ignore the HP/UX warning about "integer overflow during
758 * conversion. It comes from its own macro definition,
759 * and is really hard to shut up.
761 if (ioctl(iter
->socket
, SIOCGIFNETMASK
, (char *)&ifreq
) < 0) {
762 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
763 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
764 isc_msgcat_get(isc_msgcat
,
765 ISC_MSGSET_IFITERIOCTL
,
767 "%s: getting netmask: %s"),
768 ifreq
.ifr_name
, strbuf
);
769 return (ISC_R_IGNORE
);
771 get_addr(family
, &iter
->current
.netmask
,
772 (struct sockaddr
*)&ifreq
.ifr_addr
, ifreq
.ifr_name
);
773 return (ISC_R_SUCCESS
);
776 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
778 internal_current6(isc_interfaceiter_t
*iter
) {
780 struct LIFREQ lifreq
;
782 char strbuf
[ISC_STRERRORSIZE
];
785 REQUIRE(VALID_IFITER(iter
));
786 if (iter
->result6
!= ISC_R_SUCCESS
)
787 return (iter
->result6
);
788 REQUIRE(iter
->pos6
< (unsigned int) iter
->lifc
.lifc_len
);
790 ifrp
= (struct LIFREQ
*)((char *) iter
->lifc
.lifc_req
+ iter
->pos6
);
792 memset(&lifreq
, 0, sizeof(lifreq
));
793 memcpy(&lifreq
, ifrp
, sizeof(lifreq
));
795 family
= lifreq
.lifr_addr
.ss_family
;
796 #ifdef ISC_PLATFORM_HAVEIPV6
797 if (family
!= AF_INET
&& family
!= AF_INET6
)
799 if (family
!= AF_INET
)
801 return (ISC_R_IGNORE
);
803 memset(&iter
->current
, 0, sizeof(iter
->current
));
804 iter
->current
.af
= family
;
806 INSIST(sizeof(lifreq
.lifr_name
) <= sizeof(iter
->current
.name
));
807 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
808 memcpy(iter
->current
.name
, lifreq
.lifr_name
, sizeof(lifreq
.lifr_name
));
810 get_addr(family
, &iter
->current
.address
,
811 (struct sockaddr
*)&lifreq
.lifr_addr
, lifreq
.lifr_name
);
814 * If the interface does not have a address ignore it.
818 if (iter
->current
.address
.type
.in
.s_addr
== htonl(INADDR_ANY
))
819 return (ISC_R_IGNORE
);
821 #ifdef ISC_PLATFORM_HAVEIPV6
823 if (memcmp(&iter
->current
.address
.type
.in6
, &in6addr_any
,
824 sizeof(in6addr_any
)) == 0)
825 return (ISC_R_IGNORE
);
831 * Get interface flags.
834 iter
->current
.flags
= 0;
836 if (family
== AF_INET6
)
842 * Ignore the HP/UX warning about "integer overflow during
843 * conversion. It comes from its own macro definition,
844 * and is really hard to shut up.
846 if (ioctl(fd
, SIOCGLIFFLAGS
, (char *) &lifreq
) < 0) {
847 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
848 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
849 "%s: getting interface flags: %s",
850 lifreq
.lifr_name
, strbuf
);
851 return (ISC_R_IGNORE
);
854 if ((lifreq
.lifr_flags
& IFF_UP
) != 0)
855 iter
->current
.flags
|= INTERFACE_F_UP
;
857 #ifdef IFF_POINTOPOINT
858 if ((lifreq
.lifr_flags
& IFF_POINTOPOINT
) != 0)
859 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
862 if ((lifreq
.lifr_flags
& IFF_LOOPBACK
) != 0)
863 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
865 if ((lifreq
.lifr_flags
& IFF_BROADCAST
) != 0) {
866 iter
->current
.flags
|= INTERFACE_F_BROADCAST
;
870 if ((lifreq
.lifr_flags
& IFF_MULTICAST
) != 0) {
871 iter
->current
.flags
|= INTERFACE_F_MULTICAST
;
875 #ifdef IFF_POINTOPOINT
877 * If the interface is point-to-point, get the destination address.
879 if ((iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0) {
881 * Ignore the HP/UX warning about "interger overflow during
882 * conversion. It comes from its own macro definition,
883 * and is really hard to shut up.
885 if (ioctl(fd
, SIOCGLIFDSTADDR
, (char *)&lifreq
)
887 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
888 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
889 isc_msgcat_get(isc_msgcat
,
890 ISC_MSGSET_IFITERIOCTL
,
893 "destination address: %s"),
894 lifreq
.lifr_name
, strbuf
);
895 return (ISC_R_IGNORE
);
897 get_addr(family
, &iter
->current
.dstaddress
,
898 (struct sockaddr
*)&lifreq
.lifr_dstaddr
,
903 #ifdef SIOCGLIFBRDADDR
904 if ((iter
->current
.flags
& INTERFACE_F_BROADCAST
) != 0) {
906 * Ignore the HP/UX warning about "integer overflow during
907 * conversion. It comes from its own macro definition,
908 * and is really hard to shut up.
910 if (ioctl(iter
->socket
, SIOCGLIFBRDADDR
, (char *)&lifreq
)
912 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
913 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
914 isc_msgcat_get(isc_msgcat
,
915 ISC_MSGSET_IFITERIOCTL
,
918 "broadcast address: %s"),
919 lifreq
.lifr_name
, strbuf
);
920 return (ISC_R_IGNORE
);
922 get_addr(family
, &iter
->current
.broadcast
,
923 (struct sockaddr
*)&lifreq
.lifr_broadaddr
,
926 #endif /* SIOCGLIFBRDADDR */
929 * Get the network mask. Netmask already zeroed.
931 memset(&lifreq
, 0, sizeof(lifreq
));
932 memcpy(&lifreq
, ifrp
, sizeof(lifreq
));
936 * Special case: if the system provides lifr_addrlen member, the
937 * netmask of an IPv6 address can be derived from the length, since
938 * an IPv6 address always has a contiguous mask.
940 if (family
== AF_INET6
) {
943 iter
->current
.netmask
.family
= family
;
944 for (i
= 0; i
< lifreq
.lifr_addrlen
; i
+= 8) {
945 bits
= lifreq
.lifr_addrlen
- i
;
946 bits
= (bits
< 8) ? (8 - bits
) : 0;
947 iter
->current
.netmask
.type
.in6
.s6_addr
[i
/ 8] =
951 return (ISC_R_SUCCESS
);
956 * Ignore the HP/UX warning about "integer overflow during
957 * conversion. It comes from its own macro definition,
958 * and is really hard to shut up.
960 if (ioctl(fd
, SIOCGLIFNETMASK
, (char *)&lifreq
) < 0) {
961 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
962 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
963 isc_msgcat_get(isc_msgcat
,
964 ISC_MSGSET_IFITERIOCTL
,
966 "%s: getting netmask: %s"),
967 lifreq
.lifr_name
, strbuf
);
968 return (ISC_R_IGNORE
);
970 get_addr(family
, &iter
->current
.netmask
,
971 (struct sockaddr
*)&lifreq
.lifr_addr
, lifreq
.lifr_name
);
973 return (ISC_R_SUCCESS
);
978 internal_current(isc_interfaceiter_t
*iter
) {
979 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
980 if (iter
->mode
== 6) {
981 iter
->result6
= internal_current6(iter
);
982 if (iter
->result6
!= ISC_R_NOMORE
)
983 return (iter
->result6
);
986 #ifdef HAVE_TRUCLUSTER
987 if (!iter
->clua_done
)
988 return(internal_current_clusteralias(iter
));
990 return (internal_current4(iter
));
994 * Step the iterator to the next interface. Unlike
995 * isc_interfaceiter_next(), this may leave the iterator
996 * positioned on an interface that will ultimately
997 * be ignored. Return ISC_R_NOMORE if there are no more
998 * interfaces, otherwise ISC_R_SUCCESS.
1001 internal_next4(isc_interfaceiter_t
*iter
) {
1004 REQUIRE (iter
->pos
< (unsigned int) iter
->ifc
.ifc_len
);
1007 if (linux_if_inet6_next(iter
) == ISC_R_SUCCESS
)
1008 return (ISC_R_SUCCESS
);
1010 return (ISC_R_SUCCESS
);
1012 ifrp
= (struct ifreq
*)((char *) iter
->ifc
.ifc_req
+ iter
->pos
);
1014 #ifdef ISC_PLATFORM_HAVESALEN
1015 if (ifrp
->ifr_addr
.sa_len
> sizeof(struct sockaddr
))
1016 iter
->pos
+= sizeof(ifrp
->ifr_name
) + ifrp
->ifr_addr
.sa_len
;
1019 iter
->pos
+= sizeof(*ifrp
);
1021 if (iter
->pos
>= (unsigned int) iter
->ifc
.ifc_len
)
1022 return (ISC_R_NOMORE
);
1024 return (ISC_R_SUCCESS
);
1027 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1029 internal_next6(isc_interfaceiter_t
*iter
) {
1030 struct LIFREQ
*ifrp
;
1032 if (iter
->result6
!= ISC_R_SUCCESS
&& iter
->result6
!= ISC_R_IGNORE
)
1033 return (iter
->result6
);
1035 REQUIRE(iter
->pos6
< (unsigned int) iter
->lifc
.lifc_len
);
1037 ifrp
= (struct LIFREQ
*)((char *) iter
->lifc
.lifc_req
+ iter
->pos6
);
1039 #ifdef ISC_PLATFORM_HAVESALEN
1040 if (ifrp
->lifr_addr
.sa_len
> sizeof(struct sockaddr
))
1041 iter
->pos6
+= sizeof(ifrp
->lifr_name
) + ifrp
->lifr_addr
.sa_len
;
1044 iter
->pos6
+= sizeof(*ifrp
);
1046 if (iter
->pos6
>= (unsigned int) iter
->lifc
.lifc_len
)
1047 return (ISC_R_NOMORE
);
1049 return (ISC_R_SUCCESS
);
1054 internal_next(isc_interfaceiter_t
*iter
) {
1055 #ifdef HAVE_TRUCLUSTER
1058 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1059 if (iter
->mode
== 6) {
1060 iter
->result6
= internal_next6(iter
);
1061 if (iter
->result6
!= ISC_R_NOMORE
)
1062 return (iter
->result6
);
1064 iter
->first6
= ISC_FALSE
;
1065 return (ISC_R_SUCCESS
);
1069 #ifdef HAVE_TRUCLUSTER
1070 if (!iter
->clua_done
) {
1071 clua_result
= clua_getaliasaddress(&iter
->clua_sa
,
1072 &iter
->clua_context
);
1073 if (clua_result
!= CLUA_SUCCESS
)
1074 iter
->clua_done
= ISC_TRUE
;
1075 return (ISC_R_SUCCESS
);
1078 return (internal_next4(iter
));
1082 internal_destroy(isc_interfaceiter_t
*iter
) {
1083 (void) close(iter
->socket
);
1084 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1085 if (iter
->socket6
!= -1)
1086 (void) close(iter
->socket6
);
1087 if (iter
->buf6
!= NULL
) {
1088 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
1092 if (iter
->proc
!= NULL
)
1098 void internal_first(isc_interfaceiter_t
*iter
) {
1099 #ifdef HAVE_TRUCLUSTER
1103 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1105 if (iter
->result6
== ISC_R_NOMORE
)
1106 iter
->result6
= ISC_R_SUCCESS
;
1107 iter
->first6
= ISC_TRUE
;
1109 #ifdef HAVE_TRUCLUSTER
1110 iter
->clua_context
= 0;
1111 clua_result
= clua_getaliasaddress(&iter
->clua_sa
,
1112 &iter
->clua_context
);
1113 iter
->clua_done
= ISC_TF(clua_result
!= CLUA_SUCCESS
);
1116 linux_if_inet6_first(iter
);