4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp */
24 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
28 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
29 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
30 #define lifc_len iflc_len
31 #define lifc_buf iflc_buf
32 #define lifc_req iflc_req
33 #define LIFCONF if_laddrconf
35 #define ISC_HAVE_LIFC_FAMILY 1
36 #define ISC_HAVE_LIFC_FLAGS 1
37 #define LIFCONF lifconf
40 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
41 #define lifr_addr iflr_addr
42 #define lifr_name iflr_name
43 #define lifr_dstaddr iflr_dstaddr
44 #define lifr_flags iflr_flags
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
113 getbuf4(isc_interfaceiter_t
*iter
) {
114 char strbuf
[ISC_STRERRORSIZE
];
116 iter
->bufsize
= IFCONF_BUFSIZE_INITIAL
;
119 iter
->buf
= isc_mem_get(iter
->mctx
, iter
->bufsize
);
120 if (iter
->buf
== NULL
)
121 return (ISC_R_NOMEMORY
);
123 memset(&iter
->ifc
.ifc_len
, 0, sizeof(iter
->ifc
.ifc_len
));
124 iter
->ifc
.ifc_len
= iter
->bufsize
;
125 iter
->ifc
.ifc_buf
= iter
->buf
;
127 * Ignore the HP/UX warning about "integer overflow during
128 * conversion". It comes from its own macro definition,
129 * and is really hard to shut up.
131 if (ioctl(iter
->socket
, SIOCGIFCONF
, (char *)&iter
->ifc
)
133 if (errno
!= EINVAL
) {
134 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
135 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
136 isc_msgcat_get(isc_msgcat
,
137 ISC_MSGSET_IFITERIOCTL
,
140 "configuration: %s"),
145 * EINVAL. Retry with a bigger buffer.
149 * The ioctl succeeded.
150 * Some OS's just return what will fit rather
151 * than set EINVAL if the buffer is too small
152 * to fit all the interfaces in. If
153 * ifc.lifc_len is too near to the end of the
154 * buffer we will grow it just in case and
157 if (iter
->ifc
.ifc_len
+ 2 * sizeof(struct ifreq
)
161 if (iter
->bufsize
>= IFCONF_BUFSIZE_MAX
) {
162 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
163 isc_msgcat_get(isc_msgcat
,
164 ISC_MSGSET_IFITERIOCTL
,
172 isc_mem_put(iter
->mctx
, iter
->buf
, iter
->bufsize
);
176 return (ISC_R_SUCCESS
);
179 isc_mem_put(iter
->mctx
, iter
->buf
, iter
->bufsize
);
181 return (ISC_R_UNEXPECTED
);
184 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
186 getbuf6(isc_interfaceiter_t
*iter
) {
187 char strbuf
[ISC_STRERRORSIZE
];
190 iter
->bufsize6
= IFCONF_BUFSIZE_INITIAL
;
193 iter
->buf6
= isc_mem_get(iter
->mctx
, iter
->bufsize6
);
194 if (iter
->buf6
== NULL
)
195 return (ISC_R_NOMEMORY
);
197 memset(&iter
->lifc
, 0, sizeof(iter
->lifc
));
198 #ifdef ISC_HAVE_LIFC_FAMILY
199 iter
->lifc
.lifc_family
= AF_INET6
;
201 #ifdef ISC_HAVE_LIFC_FLAGS
202 iter
->lifc
.lifc_flags
= 0;
204 iter
->lifc
.lifc_len
= iter
->bufsize6
;
205 iter
->lifc
.lifc_buf
= iter
->buf6
;
207 * Ignore the HP/UX warning about "integer overflow during
208 * conversion". It comes from its own macro definition,
209 * and is really hard to shut up.
211 if (ioctl(iter
->socket6
, SIOCGLIFCONF
, (char *)&iter
->lifc
)
215 * IPv6 interface scanning is not available on all
216 * kernels w/ IPv6 sockets.
218 if (errno
== ENOENT
) {
219 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
220 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
221 ISC_LOGMODULE_INTERFACE
,
223 isc_msgcat_get(isc_msgcat
,
224 ISC_MSGSET_IFITERIOCTL
,
227 "configuration: %s"),
229 result
= ISC_R_FAILURE
;
233 if (errno
!= EINVAL
) {
234 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
235 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
236 isc_msgcat_get(isc_msgcat
,
237 ISC_MSGSET_IFITERIOCTL
,
240 "configuration: %s"),
242 result
= ISC_R_UNEXPECTED
;
246 * EINVAL. Retry with a bigger buffer.
250 * The ioctl succeeded.
251 * Some OS's just return what will fit rather
252 * than set EINVAL if the buffer is too small
253 * to fit all the interfaces in. If
254 * ifc.ifc_len is too near to the end of the
255 * buffer we will grow it just in case and
258 if (iter
->lifc
.lifc_len
+ 2 * sizeof(struct LIFREQ
)
262 if (iter
->bufsize6
>= IFCONF_BUFSIZE_MAX
) {
263 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
264 isc_msgcat_get(isc_msgcat
,
265 ISC_MSGSET_IFITERIOCTL
,
271 result
= ISC_R_UNEXPECTED
;
274 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
279 if (iter
->lifc
.lifc_len
!= 0)
281 return (ISC_R_SUCCESS
);
284 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
291 isc_interfaceiter_create(isc_mem_t
*mctx
, isc_interfaceiter_t
**iterp
) {
292 isc_interfaceiter_t
*iter
;
294 char strbuf
[ISC_STRERRORSIZE
];
296 REQUIRE(mctx
!= NULL
);
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 result
= iter
->result6
= getbuf6(iter
);
342 if (result
!= ISC_R_NOTIMPLEMENTED
&& result
!= ISC_R_SUCCESS
)
346 if ((iter
->socket
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
347 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
348 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
349 isc_msgcat_get(isc_msgcat
,
350 ISC_MSGSET_IFITERIOCTL
,
351 ISC_MSG_MAKESCANSOCKET
,
355 result
= ISC_R_UNEXPECTED
;
358 result
= getbuf4(iter
);
359 if (result
!= ISC_R_SUCCESS
)
363 * A newly created iterator has an undefined position
364 * until isc_interfaceiter_first() is called.
366 #ifdef HAVE_TRUCLUSTER
367 iter
->clua_context
= -1;
368 iter
->clua_done
= ISC_TRUE
;
371 iter
->proc
= fopen("/proc/net/if_inet6", "r");
372 iter
->valid
= ISC_R_FAILURE
;
374 iter
->result
= ISC_R_FAILURE
;
376 iter
->magic
= IFITER_MAGIC
;
378 return (ISC_R_SUCCESS
);
381 if (iter
->buf
!= NULL
)
382 isc_mem_put(mctx
, iter
->buf
, iter
->bufsize
);
383 (void) close(iter
->socket
);
386 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
387 if (iter
->buf6
!= NULL
)
388 isc_mem_put(mctx
, iter
->buf6
, iter
->bufsize6
);
390 if (iter
->socket6
!= -1)
391 (void) close(iter
->socket6
);
395 isc_mem_put(mctx
, iter
, sizeof(*iter
));
399 #ifdef HAVE_TRUCLUSTER
401 get_inaddr(isc_netaddr_t
*dst
, struct in_addr
*src
) {
402 dst
->family
= AF_INET
;
403 memcpy(&dst
->type
.in
, src
, sizeof(struct in_addr
));
407 internal_current_clusteralias(isc_interfaceiter_t
*iter
) {
409 if (clua_getaliasinfo(&iter
->clua_sa
, &ci
) != CLUA_SUCCESS
)
410 return (ISC_R_IGNORE
);
411 memset(&iter
->current
, 0, sizeof(iter
->current
));
412 iter
->current
.af
= iter
->clua_sa
.sa_family
;
413 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
414 sprintf(iter
->current
.name
, "clua%d", ci
.aliasid
);
415 iter
->current
.flags
= INTERFACE_F_UP
;
416 get_inaddr(&iter
->current
.address
, &ci
.addr
);
417 get_inaddr(&iter
->current
.netmask
, &ci
.netmask
);
418 return (ISC_R_SUCCESS
);
423 * Get information about the current interface to iter->current.
424 * If successful, return ISC_R_SUCCESS.
425 * If the interface has an unsupported address family, or if
426 * some operation on it fails, return ISC_R_IGNORE to make
427 * the higher-level iterator code ignore it.
431 internal_current4(isc_interfaceiter_t
*iter
) {
435 char strbuf
[ISC_STRERRORSIZE
];
436 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
437 struct lifreq lifreq
;
441 int i
, bits
, prefixlen
;
443 REQUIRE(VALID_IFITER(iter
));
445 if (iter
->ifc
.ifc_len
== 0 ||
446 iter
->pos
== (unsigned int)iter
->ifc
.ifc_len
) {
448 return (linux_if_inet6_current(iter
));
450 return (ISC_R_NOMORE
);
454 INSIST( iter
->pos
< (unsigned int) iter
->ifc
.ifc_len
);
456 ifrp
= (struct ifreq
*)((char *) iter
->ifc
.ifc_req
+ iter
->pos
);
458 memset(&ifreq
, 0, sizeof(ifreq
));
459 memcpy(&ifreq
, ifrp
, sizeof(ifreq
));
461 family
= ifreq
.ifr_addr
.sa_family
;
462 #if defined(ISC_PLATFORM_HAVEIPV6)
463 if (family
!= AF_INET
&& family
!= AF_INET6
)
465 if (family
!= AF_INET
)
467 return (ISC_R_IGNORE
);
469 memset(&iter
->current
, 0, sizeof(iter
->current
));
470 iter
->current
.af
= family
;
472 INSIST(sizeof(ifreq
.ifr_name
) <= sizeof(iter
->current
.name
));
473 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
474 memcpy(iter
->current
.name
, ifreq
.ifr_name
, sizeof(ifreq
.ifr_name
));
476 get_addr(family
, &iter
->current
.address
,
477 (struct sockaddr
*)&ifrp
->ifr_addr
, ifreq
.ifr_name
);
480 * If the interface does not have a address ignore it.
484 if (iter
->current
.address
.type
.in
.s_addr
== htonl(INADDR_ANY
))
485 return (ISC_R_IGNORE
);
488 if (memcmp(&iter
->current
.address
.type
.in6
, &in6addr_any
,
489 sizeof(in6addr_any
)) == 0)
490 return (ISC_R_IGNORE
);
495 * Get interface flags.
498 iter
->current
.flags
= 0;
501 * Ignore the HP/UX warning about "integer overflow during
502 * conversion. It comes from its own macro definition,
503 * and is really hard to shut up.
505 if (ioctl(iter
->socket
, SIOCGIFFLAGS
, (char *) &ifreq
) < 0) {
506 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
507 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
508 "%s: getting interface flags: %s",
509 ifreq
.ifr_name
, strbuf
);
510 return (ISC_R_IGNORE
);
513 if ((ifreq
.ifr_flags
& IFF_UP
) != 0)
514 iter
->current
.flags
|= INTERFACE_F_UP
;
516 #ifdef IFF_POINTOPOINT
517 if ((ifreq
.ifr_flags
& IFF_POINTOPOINT
) != 0)
518 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
521 if ((ifreq
.ifr_flags
& IFF_LOOPBACK
) != 0)
522 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
524 if (family
== AF_INET
)
527 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
528 memset(&lifreq
, 0, sizeof(lifreq
));
529 memcpy(lifreq
.lifr_name
, iter
->current
.name
, sizeof(lifreq
.lifr_name
));
530 memcpy(&lifreq
.lifr_addr
, &iter
->current
.address
.type
.in6
,
531 sizeof(iter
->current
.address
.type
.in6
));
533 if (ioctl(iter
->socket
, SIOCGLIFADDR
, &lifreq
) < 0) {
534 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
535 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
536 "%s: getting interface address: %s",
537 ifreq
.ifr_name
, strbuf
);
538 return (ISC_R_IGNORE
);
540 prefixlen
= lifreq
.lifr_addrlen
;
542 isc_netaddr_format(&iter
->current
.address
, sabuf
, sizeof(sabuf
));
543 isc_log_write(isc_lctx
, ISC_LOGCATEGORY_GENERAL
,
544 ISC_LOGMODULE_INTERFACE
,
546 isc_msgcat_get(isc_msgcat
,
547 ISC_MSGSET_IFITERIOCTL
,
549 "prefix length for %s is unknown "
550 "(assume 128)"), sabuf
);
555 * Netmask already zeroed.
557 iter
->current
.netmask
.family
= family
;
558 for (i
= 0; i
< 16; i
++) {
563 bits
= 8 - prefixlen
;
566 iter
->current
.netmask
.type
.in6
.s6_addr
[i
] = (~0 << bits
) & 0xff;
568 return (ISC_R_SUCCESS
);
571 if (family
!= AF_INET
)
572 return (ISC_R_IGNORE
);
573 #ifdef IFF_POINTOPOINT
575 * If the interface is point-to-point, get the destination address.
577 if ((iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0) {
579 * Ignore the HP/UX warning about "integer overflow during
580 * conversion. It comes from its own macro definition,
581 * and is really hard to shut up.
583 if (ioctl(iter
->socket
, SIOCGIFDSTADDR
, (char *)&ifreq
)
585 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
586 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
587 isc_msgcat_get(isc_msgcat
,
588 ISC_MSGSET_IFITERIOCTL
,
591 "destination address: %s"),
592 ifreq
.ifr_name
, strbuf
);
593 return (ISC_R_IGNORE
);
595 get_addr(family
, &iter
->current
.dstaddress
,
596 (struct sockaddr
*)&ifreq
.ifr_dstaddr
, ifreq
.ifr_name
);
601 * Get the network mask.
603 memset(&ifreq
, 0, sizeof(ifreq
));
604 memcpy(&ifreq
, ifrp
, sizeof(ifreq
));
606 * Ignore the HP/UX warning about "integer overflow during
607 * conversion. It comes from its own macro definition,
608 * and is really hard to shut up.
610 if (ioctl(iter
->socket
, SIOCGIFNETMASK
, (char *)&ifreq
) < 0) {
611 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
612 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
613 isc_msgcat_get(isc_msgcat
,
614 ISC_MSGSET_IFITERIOCTL
,
616 "%s: getting netmask: %s"),
617 ifreq
.ifr_name
, strbuf
);
618 return (ISC_R_IGNORE
);
620 get_addr(family
, &iter
->current
.netmask
,
621 (struct sockaddr
*)&ifreq
.ifr_addr
, ifreq
.ifr_name
);
622 return (ISC_R_SUCCESS
);
625 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
627 internal_current6(isc_interfaceiter_t
*iter
) {
629 struct LIFREQ lifreq
;
631 char strbuf
[ISC_STRERRORSIZE
];
634 REQUIRE(VALID_IFITER(iter
));
635 if (iter
->result6
!= ISC_R_SUCCESS
)
636 return (iter
->result6
);
637 REQUIRE(iter
->pos6
< (unsigned int) iter
->lifc
.lifc_len
);
639 ifrp
= (struct LIFREQ
*)((char *) iter
->lifc
.lifc_req
+ iter
->pos6
);
641 memset(&lifreq
, 0, sizeof(lifreq
));
642 memcpy(&lifreq
, ifrp
, sizeof(lifreq
));
644 family
= lifreq
.lifr_addr
.ss_family
;
645 #ifdef ISC_PLATFORM_HAVEIPV6
646 if (family
!= AF_INET
&& family
!= AF_INET6
)
648 if (family
!= AF_INET
)
650 return (ISC_R_IGNORE
);
652 memset(&iter
->current
, 0, sizeof(iter
->current
));
653 iter
->current
.af
= family
;
655 INSIST(sizeof(lifreq
.lifr_name
) <= sizeof(iter
->current
.name
));
656 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
657 memcpy(iter
->current
.name
, lifreq
.lifr_name
, sizeof(lifreq
.lifr_name
));
659 get_addr(family
, &iter
->current
.address
,
660 (struct sockaddr
*)&lifreq
.lifr_addr
, lifreq
.lifr_name
);
663 * If the interface does not have a address ignore it.
667 if (iter
->current
.address
.type
.in
.s_addr
== htonl(INADDR_ANY
))
668 return (ISC_R_IGNORE
);
671 if (memcmp(&iter
->current
.address
.type
.in6
, &in6addr_any
,
672 sizeof(in6addr_any
)) == 0)
673 return (ISC_R_IGNORE
);
678 * Get interface flags.
681 iter
->current
.flags
= 0;
683 if (family
== AF_INET6
)
689 * Ignore the HP/UX warning about "integer overflow during
690 * conversion. It comes from its own macro definition,
691 * and is really hard to shut up.
693 if (ioctl(fd
, SIOCGLIFFLAGS
, (char *) &lifreq
) < 0) {
694 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
695 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
696 "%s: getting interface flags: %s",
697 lifreq
.lifr_name
, strbuf
);
698 return (ISC_R_IGNORE
);
701 if ((lifreq
.lifr_flags
& IFF_UP
) != 0)
702 iter
->current
.flags
|= INTERFACE_F_UP
;
704 #ifdef IFF_POINTOPOINT
705 if ((lifreq
.lifr_flags
& IFF_POINTOPOINT
) != 0)
706 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
709 if ((lifreq
.lifr_flags
& IFF_LOOPBACK
) != 0)
710 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
712 #ifdef IFF_POINTOPOINT
714 * If the interface is point-to-point, get the destination address.
716 if ((iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0) {
718 * Ignore the HP/UX warning about "integer overflow during
719 * conversion. It comes from its own macro definition,
720 * and is really hard to shut up.
722 if (ioctl(fd
, SIOCGLIFDSTADDR
, (char *)&lifreq
)
724 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
725 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
726 isc_msgcat_get(isc_msgcat
,
727 ISC_MSGSET_IFITERIOCTL
,
730 "destination address: %s"),
731 lifreq
.lifr_name
, strbuf
);
732 return (ISC_R_IGNORE
);
734 get_addr(family
, &iter
->current
.dstaddress
,
735 (struct sockaddr
*)&lifreq
.lifr_dstaddr
,
741 * Get the network mask. Netmask already zeroed.
743 memset(&lifreq
, 0, sizeof(lifreq
));
744 memcpy(&lifreq
, ifrp
, sizeof(lifreq
));
748 * Special case: if the system provides lifr_addrlen member, the
749 * netmask of an IPv6 address can be derived from the length, since
750 * an IPv6 address always has a contiguous mask.
752 if (family
== AF_INET6
) {
755 iter
->current
.netmask
.family
= family
;
756 for (i
= 0; i
< lifreq
.lifr_addrlen
; i
+= 8) {
757 bits
= lifreq
.lifr_addrlen
- i
;
758 bits
= (bits
< 8) ? (8 - bits
) : 0;
759 iter
->current
.netmask
.type
.in6
.s6_addr
[i
/ 8] =
763 return (ISC_R_SUCCESS
);
768 * Ignore the HP/UX warning about "integer overflow during
769 * conversion. It comes from its own macro definition,
770 * and is really hard to shut up.
772 if (ioctl(fd
, SIOCGLIFNETMASK
, (char *)&lifreq
) < 0) {
773 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
774 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
775 isc_msgcat_get(isc_msgcat
,
776 ISC_MSGSET_IFITERIOCTL
,
778 "%s: getting netmask: %s"),
779 lifreq
.lifr_name
, strbuf
);
780 return (ISC_R_IGNORE
);
782 get_addr(family
, &iter
->current
.netmask
,
783 (struct sockaddr
*)&lifreq
.lifr_addr
, lifreq
.lifr_name
);
785 return (ISC_R_SUCCESS
);
790 internal_current(isc_interfaceiter_t
*iter
) {
791 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
792 if (iter
->mode
== 6) {
793 iter
->result6
= internal_current6(iter
);
794 if (iter
->result6
!= ISC_R_NOMORE
)
795 return (iter
->result6
);
798 #ifdef HAVE_TRUCLUSTER
799 if (!iter
->clua_done
)
800 return(internal_current_clusteralias(iter
));
802 return (internal_current4(iter
));
806 * Step the iterator to the next interface. Unlike
807 * isc_interfaceiter_next(), this may leave the iterator
808 * positioned on an interface that will ultimately
809 * be ignored. Return ISC_R_NOMORE if there are no more
810 * interfaces, otherwise ISC_R_SUCCESS.
813 internal_next4(isc_interfaceiter_t
*iter
) {
814 #ifdef ISC_PLATFORM_HAVESALEN
818 if (iter
->pos
< (unsigned int) iter
->ifc
.ifc_len
) {
819 #ifdef ISC_PLATFORM_HAVESALEN
820 ifrp
= (struct ifreq
*)((char *) iter
->ifc
.ifc_req
+ iter
->pos
);
822 if (ifrp
->ifr_addr
.sa_len
> sizeof(struct sockaddr
))
823 iter
->pos
+= sizeof(ifrp
->ifr_name
) +
824 ifrp
->ifr_addr
.sa_len
;
827 iter
->pos
+= sizeof(struct ifreq
);
830 INSIST(iter
->pos
== (unsigned int) iter
->ifc
.ifc_len
);
832 return (linux_if_inet6_next(iter
));
834 return (ISC_R_NOMORE
);
837 return (ISC_R_SUCCESS
);
840 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
842 internal_next6(isc_interfaceiter_t
*iter
) {
843 #ifdef ISC_PLATFORM_HAVESALEN
847 if (iter
->result6
!= ISC_R_SUCCESS
&& iter
->result6
!= ISC_R_IGNORE
)
848 return (iter
->result6
);
850 REQUIRE(iter
->pos6
< (unsigned int) iter
->lifc
.lifc_len
);
852 #ifdef ISC_PLATFORM_HAVESALEN
853 ifrp
= (struct LIFREQ
*)((char *) iter
->lifc
.lifc_req
+ iter
->pos6
);
855 if (ifrp
->lifr_addr
.sa_len
> sizeof(struct sockaddr
))
856 iter
->pos6
+= sizeof(ifrp
->lifr_name
) + ifrp
->lifr_addr
.sa_len
;
859 iter
->pos6
+= sizeof(struct LIFREQ
);
861 if (iter
->pos6
>= (unsigned int) iter
->lifc
.lifc_len
)
862 return (ISC_R_NOMORE
);
864 return (ISC_R_SUCCESS
);
869 internal_next(isc_interfaceiter_t
*iter
) {
870 #ifdef HAVE_TRUCLUSTER
873 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
874 if (iter
->mode
== 6) {
875 iter
->result6
= internal_next6(iter
);
876 if (iter
->result6
!= ISC_R_NOMORE
)
877 return (iter
->result6
);
879 iter
->first6
= ISC_FALSE
;
880 return (ISC_R_SUCCESS
);
884 #ifdef HAVE_TRUCLUSTER
885 if (!iter
->clua_done
) {
886 clua_result
= clua_getaliasaddress(&iter
->clua_sa
,
887 &iter
->clua_context
);
888 if (clua_result
!= CLUA_SUCCESS
)
889 iter
->clua_done
= ISC_TRUE
;
890 return (ISC_R_SUCCESS
);
893 return (internal_next4(iter
));
897 internal_destroy(isc_interfaceiter_t
*iter
) {
898 (void) close(iter
->socket
);
899 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
900 if (iter
->socket6
!= -1)
901 (void) close(iter
->socket6
);
902 if (iter
->buf6
!= NULL
) {
903 isc_mem_put(iter
->mctx
, iter
->buf6
, iter
->bufsize6
);
907 if (iter
->proc
!= NULL
)
913 void internal_first(isc_interfaceiter_t
*iter
) {
914 #ifdef HAVE_TRUCLUSTER
918 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
920 if (iter
->result6
== ISC_R_NOMORE
)
921 iter
->result6
= ISC_R_SUCCESS
;
922 iter
->first6
= ISC_TRUE
;
924 #ifdef HAVE_TRUCLUSTER
925 iter
->clua_context
= 0;
926 clua_result
= clua_getaliasaddress(&iter
->clua_sa
,
927 &iter
->clua_context
);
928 iter
->clua_done
= ISC_TF(clua_result
!= CLUA_SUCCESS
);
931 linux_if_inet6_first(iter
);