1*00b67f09SDavid van Moolenbroek /* $NetBSD: ifiter_ioctl.c,v 1.5 2014/12/10 04:38:01 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004-2009, 2014 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2003 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /* Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp */
21*00b67f09SDavid van Moolenbroek
22*00b67f09SDavid van Moolenbroek /*! \file
23*00b67f09SDavid van Moolenbroek * \brief
24*00b67f09SDavid van Moolenbroek * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
25*00b67f09SDavid van Moolenbroek * See netintro(4).
26*00b67f09SDavid van Moolenbroek */
27*00b67f09SDavid van Moolenbroek
28*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
29*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
30*00b67f09SDavid van Moolenbroek #define lifc_len iflc_len
31*00b67f09SDavid van Moolenbroek #define lifc_buf iflc_buf
32*00b67f09SDavid van Moolenbroek #define lifc_req iflc_req
33*00b67f09SDavid van Moolenbroek #define LIFCONF if_laddrconf
34*00b67f09SDavid van Moolenbroek #else
35*00b67f09SDavid van Moolenbroek #define ISC_HAVE_LIFC_FAMILY 1
36*00b67f09SDavid van Moolenbroek #define ISC_HAVE_LIFC_FLAGS 1
37*00b67f09SDavid van Moolenbroek #define LIFCONF lifconf
38*00b67f09SDavid van Moolenbroek #endif
39*00b67f09SDavid van Moolenbroek
40*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
41*00b67f09SDavid van Moolenbroek #define lifr_addr iflr_addr
42*00b67f09SDavid van Moolenbroek #define lifr_name iflr_name
43*00b67f09SDavid van Moolenbroek #define lifr_dstaddr iflr_dstaddr
44*00b67f09SDavid van Moolenbroek #define lifr_flags iflr_flags
45*00b67f09SDavid van Moolenbroek #define ss_family sa_family
46*00b67f09SDavid van Moolenbroek #define LIFREQ if_laddrreq
47*00b67f09SDavid van Moolenbroek #else
48*00b67f09SDavid van Moolenbroek #define LIFREQ lifreq
49*00b67f09SDavid van Moolenbroek #endif
50*00b67f09SDavid van Moolenbroek #endif
51*00b67f09SDavid van Moolenbroek
52*00b67f09SDavid van Moolenbroek #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
53*00b67f09SDavid van Moolenbroek #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
54*00b67f09SDavid van Moolenbroek
55*00b67f09SDavid van Moolenbroek struct isc_interfaceiter {
56*00b67f09SDavid van Moolenbroek unsigned int magic; /* Magic number. */
57*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
58*00b67f09SDavid van Moolenbroek int mode;
59*00b67f09SDavid van Moolenbroek int socket;
60*00b67f09SDavid van Moolenbroek struct ifconf ifc;
61*00b67f09SDavid van Moolenbroek void *buf; /* Buffer for sysctl data. */
62*00b67f09SDavid van Moolenbroek unsigned int bufsize; /* Bytes allocated. */
63*00b67f09SDavid van Moolenbroek unsigned int pos; /* Current offset in
64*00b67f09SDavid van Moolenbroek SIOCGIFCONF data */
65*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
66*00b67f09SDavid van Moolenbroek int socket6;
67*00b67f09SDavid van Moolenbroek struct LIFCONF lifc;
68*00b67f09SDavid van Moolenbroek void *buf6; /* Buffer for sysctl data. */
69*00b67f09SDavid van Moolenbroek unsigned int bufsize6; /* Bytes allocated. */
70*00b67f09SDavid van Moolenbroek unsigned int pos6; /* Current offset in
71*00b67f09SDavid van Moolenbroek SIOCGLIFCONF data */
72*00b67f09SDavid van Moolenbroek isc_result_t result6; /* Last result code. */
73*00b67f09SDavid van Moolenbroek isc_boolean_t first6;
74*00b67f09SDavid van Moolenbroek #endif
75*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
76*00b67f09SDavid van Moolenbroek int clua_context; /* Cluster alias context */
77*00b67f09SDavid van Moolenbroek isc_boolean_t clua_done;
78*00b67f09SDavid van Moolenbroek struct sockaddr clua_sa;
79*00b67f09SDavid van Moolenbroek #endif
80*00b67f09SDavid van Moolenbroek #ifdef __linux
81*00b67f09SDavid van Moolenbroek FILE * proc;
82*00b67f09SDavid van Moolenbroek char entry[ISC_IF_INET6_SZ];
83*00b67f09SDavid van Moolenbroek isc_result_t valid;
84*00b67f09SDavid van Moolenbroek #endif
85*00b67f09SDavid van Moolenbroek isc_interface_t current; /* Current interface data. */
86*00b67f09SDavid van Moolenbroek isc_result_t result; /* Last result code. */
87*00b67f09SDavid van Moolenbroek };
88*00b67f09SDavid van Moolenbroek
89*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
90*00b67f09SDavid van Moolenbroek #include <clua/clua.h>
91*00b67f09SDavid van Moolenbroek #include <sys/socket.h>
92*00b67f09SDavid van Moolenbroek #endif
93*00b67f09SDavid van Moolenbroek
94*00b67f09SDavid van Moolenbroek
95*00b67f09SDavid van Moolenbroek /*%
96*00b67f09SDavid van Moolenbroek * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
97*00b67f09SDavid van Moolenbroek * will have more than a megabyte of interface configuration data.
98*00b67f09SDavid van Moolenbroek */
99*00b67f09SDavid van Moolenbroek #define IFCONF_BUFSIZE_INITIAL 4096
100*00b67f09SDavid van Moolenbroek #define IFCONF_BUFSIZE_MAX 1048576
101*00b67f09SDavid van Moolenbroek
102*00b67f09SDavid van Moolenbroek #ifdef __linux
103*00b67f09SDavid van Moolenbroek #ifndef IF_NAMESIZE
104*00b67f09SDavid van Moolenbroek # ifdef IFNAMSIZ
105*00b67f09SDavid van Moolenbroek # define IF_NAMESIZE IFNAMSIZ
106*00b67f09SDavid van Moolenbroek # else
107*00b67f09SDavid van Moolenbroek # define IF_NAMESIZE 16
108*00b67f09SDavid van Moolenbroek # endif
109*00b67f09SDavid van Moolenbroek #endif
110*00b67f09SDavid van Moolenbroek #endif
111*00b67f09SDavid van Moolenbroek
112*00b67f09SDavid van Moolenbroek static isc_result_t
getbuf4(isc_interfaceiter_t * iter)113*00b67f09SDavid van Moolenbroek getbuf4(isc_interfaceiter_t *iter) {
114*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
115*00b67f09SDavid van Moolenbroek
116*00b67f09SDavid van Moolenbroek iter->bufsize = IFCONF_BUFSIZE_INITIAL;
117*00b67f09SDavid van Moolenbroek
118*00b67f09SDavid van Moolenbroek for (;;) {
119*00b67f09SDavid van Moolenbroek iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
120*00b67f09SDavid van Moolenbroek if (iter->buf == NULL)
121*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
122*00b67f09SDavid van Moolenbroek
123*00b67f09SDavid van Moolenbroek memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
124*00b67f09SDavid van Moolenbroek iter->ifc.ifc_len = iter->bufsize;
125*00b67f09SDavid van Moolenbroek iter->ifc.ifc_buf = iter->buf;
126*00b67f09SDavid van Moolenbroek /*
127*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
128*00b67f09SDavid van Moolenbroek * conversion". It comes from its own macro definition,
129*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
130*00b67f09SDavid van Moolenbroek */
131*00b67f09SDavid van Moolenbroek if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
132*00b67f09SDavid van Moolenbroek == -1) {
133*00b67f09SDavid van Moolenbroek if (errno != EINVAL) {
134*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
135*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
136*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
137*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
138*00b67f09SDavid van Moolenbroek ISC_MSG_GETIFCONFIG,
139*00b67f09SDavid van Moolenbroek "get interface "
140*00b67f09SDavid van Moolenbroek "configuration: %s"),
141*00b67f09SDavid van Moolenbroek strbuf);
142*00b67f09SDavid van Moolenbroek goto unexpected;
143*00b67f09SDavid van Moolenbroek }
144*00b67f09SDavid van Moolenbroek /*
145*00b67f09SDavid van Moolenbroek * EINVAL. Retry with a bigger buffer.
146*00b67f09SDavid van Moolenbroek */
147*00b67f09SDavid van Moolenbroek } else {
148*00b67f09SDavid van Moolenbroek /*
149*00b67f09SDavid van Moolenbroek * The ioctl succeeded.
150*00b67f09SDavid van Moolenbroek * Some OS's just return what will fit rather
151*00b67f09SDavid van Moolenbroek * than set EINVAL if the buffer is too small
152*00b67f09SDavid van Moolenbroek * to fit all the interfaces in. If
153*00b67f09SDavid van Moolenbroek * ifc.lifc_len is too near to the end of the
154*00b67f09SDavid van Moolenbroek * buffer we will grow it just in case and
155*00b67f09SDavid van Moolenbroek * retry.
156*00b67f09SDavid van Moolenbroek */
157*00b67f09SDavid van Moolenbroek if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
158*00b67f09SDavid van Moolenbroek < iter->bufsize)
159*00b67f09SDavid van Moolenbroek break;
160*00b67f09SDavid van Moolenbroek }
161*00b67f09SDavid van Moolenbroek if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
162*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
163*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
164*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
165*00b67f09SDavid van Moolenbroek ISC_MSG_BUFFERMAX,
166*00b67f09SDavid van Moolenbroek "get interface "
167*00b67f09SDavid van Moolenbroek "configuration: "
168*00b67f09SDavid van Moolenbroek "maximum buffer "
169*00b67f09SDavid van Moolenbroek "size exceeded"));
170*00b67f09SDavid van Moolenbroek goto unexpected;
171*00b67f09SDavid van Moolenbroek }
172*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
173*00b67f09SDavid van Moolenbroek
174*00b67f09SDavid van Moolenbroek iter->bufsize *= 2;
175*00b67f09SDavid van Moolenbroek }
176*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
177*00b67f09SDavid van Moolenbroek
178*00b67f09SDavid van Moolenbroek unexpected:
179*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
180*00b67f09SDavid van Moolenbroek iter->buf = NULL;
181*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
182*00b67f09SDavid van Moolenbroek }
183*00b67f09SDavid van Moolenbroek
184*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
185*00b67f09SDavid van Moolenbroek static isc_result_t
getbuf6(isc_interfaceiter_t * iter)186*00b67f09SDavid van Moolenbroek getbuf6(isc_interfaceiter_t *iter) {
187*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
188*00b67f09SDavid van Moolenbroek isc_result_t result;
189*00b67f09SDavid van Moolenbroek
190*00b67f09SDavid van Moolenbroek iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
191*00b67f09SDavid van Moolenbroek
192*00b67f09SDavid van Moolenbroek for (;;) {
193*00b67f09SDavid van Moolenbroek iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
194*00b67f09SDavid van Moolenbroek if (iter->buf6 == NULL)
195*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
196*00b67f09SDavid van Moolenbroek
197*00b67f09SDavid van Moolenbroek memset(&iter->lifc, 0, sizeof(iter->lifc));
198*00b67f09SDavid van Moolenbroek #ifdef ISC_HAVE_LIFC_FAMILY
199*00b67f09SDavid van Moolenbroek iter->lifc.lifc_family = AF_INET6;
200*00b67f09SDavid van Moolenbroek #endif
201*00b67f09SDavid van Moolenbroek #ifdef ISC_HAVE_LIFC_FLAGS
202*00b67f09SDavid van Moolenbroek iter->lifc.lifc_flags = 0;
203*00b67f09SDavid van Moolenbroek #endif
204*00b67f09SDavid van Moolenbroek iter->lifc.lifc_len = iter->bufsize6;
205*00b67f09SDavid van Moolenbroek iter->lifc.lifc_buf = iter->buf6;
206*00b67f09SDavid van Moolenbroek /*
207*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
208*00b67f09SDavid van Moolenbroek * conversion". It comes from its own macro definition,
209*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
210*00b67f09SDavid van Moolenbroek */
211*00b67f09SDavid van Moolenbroek if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
212*00b67f09SDavid van Moolenbroek == -1) {
213*00b67f09SDavid van Moolenbroek #ifdef __hpux
214*00b67f09SDavid van Moolenbroek /*
215*00b67f09SDavid van Moolenbroek * IPv6 interface scanning is not available on all
216*00b67f09SDavid van Moolenbroek * kernels w/ IPv6 sockets.
217*00b67f09SDavid van Moolenbroek */
218*00b67f09SDavid van Moolenbroek if (errno == ENOENT) {
219*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
220*00b67f09SDavid van Moolenbroek isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
221*00b67f09SDavid van Moolenbroek ISC_LOGMODULE_INTERFACE,
222*00b67f09SDavid van Moolenbroek ISC_LOG_DEBUG(1),
223*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
224*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
225*00b67f09SDavid van Moolenbroek ISC_MSG_GETIFCONFIG,
226*00b67f09SDavid van Moolenbroek "get interface "
227*00b67f09SDavid van Moolenbroek "configuration: %s"),
228*00b67f09SDavid van Moolenbroek strbuf);
229*00b67f09SDavid van Moolenbroek result = ISC_R_FAILURE;
230*00b67f09SDavid van Moolenbroek goto cleanup;
231*00b67f09SDavid van Moolenbroek }
232*00b67f09SDavid van Moolenbroek #endif
233*00b67f09SDavid van Moolenbroek if (errno != EINVAL) {
234*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
235*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
236*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
237*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
238*00b67f09SDavid van Moolenbroek ISC_MSG_GETIFCONFIG,
239*00b67f09SDavid van Moolenbroek "get interface "
240*00b67f09SDavid van Moolenbroek "configuration: %s"),
241*00b67f09SDavid van Moolenbroek strbuf);
242*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
243*00b67f09SDavid van Moolenbroek goto cleanup;
244*00b67f09SDavid van Moolenbroek }
245*00b67f09SDavid van Moolenbroek /*
246*00b67f09SDavid van Moolenbroek * EINVAL. Retry with a bigger buffer.
247*00b67f09SDavid van Moolenbroek */
248*00b67f09SDavid van Moolenbroek } else {
249*00b67f09SDavid van Moolenbroek /*
250*00b67f09SDavid van Moolenbroek * The ioctl succeeded.
251*00b67f09SDavid van Moolenbroek * Some OS's just return what will fit rather
252*00b67f09SDavid van Moolenbroek * than set EINVAL if the buffer is too small
253*00b67f09SDavid van Moolenbroek * to fit all the interfaces in. If
254*00b67f09SDavid van Moolenbroek * ifc.ifc_len is too near to the end of the
255*00b67f09SDavid van Moolenbroek * buffer we will grow it just in case and
256*00b67f09SDavid van Moolenbroek * retry.
257*00b67f09SDavid van Moolenbroek */
258*00b67f09SDavid van Moolenbroek if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
259*00b67f09SDavid van Moolenbroek < iter->bufsize6)
260*00b67f09SDavid van Moolenbroek break;
261*00b67f09SDavid van Moolenbroek }
262*00b67f09SDavid van Moolenbroek if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
263*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
264*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
265*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
266*00b67f09SDavid van Moolenbroek ISC_MSG_BUFFERMAX,
267*00b67f09SDavid van Moolenbroek "get interface "
268*00b67f09SDavid van Moolenbroek "configuration: "
269*00b67f09SDavid van Moolenbroek "maximum buffer "
270*00b67f09SDavid van Moolenbroek "size exceeded"));
271*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
272*00b67f09SDavid van Moolenbroek goto cleanup;
273*00b67f09SDavid van Moolenbroek }
274*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
275*00b67f09SDavid van Moolenbroek
276*00b67f09SDavid van Moolenbroek iter->bufsize6 *= 2;
277*00b67f09SDavid van Moolenbroek }
278*00b67f09SDavid van Moolenbroek
279*00b67f09SDavid van Moolenbroek if (iter->lifc.lifc_len != 0)
280*00b67f09SDavid van Moolenbroek iter->mode = 6;
281*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
282*00b67f09SDavid van Moolenbroek
283*00b67f09SDavid van Moolenbroek cleanup:
284*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
285*00b67f09SDavid van Moolenbroek iter->buf6 = NULL;
286*00b67f09SDavid van Moolenbroek return (result);
287*00b67f09SDavid van Moolenbroek }
288*00b67f09SDavid van Moolenbroek #endif
289*00b67f09SDavid van Moolenbroek
290*00b67f09SDavid van Moolenbroek isc_result_t
isc_interfaceiter_create(isc_mem_t * mctx,isc_interfaceiter_t ** iterp)291*00b67f09SDavid van Moolenbroek isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
292*00b67f09SDavid van Moolenbroek isc_interfaceiter_t *iter;
293*00b67f09SDavid van Moolenbroek isc_result_t result;
294*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
295*00b67f09SDavid van Moolenbroek
296*00b67f09SDavid van Moolenbroek REQUIRE(mctx != NULL);
297*00b67f09SDavid van Moolenbroek REQUIRE(iterp != NULL);
298*00b67f09SDavid van Moolenbroek REQUIRE(*iterp == NULL);
299*00b67f09SDavid van Moolenbroek
300*00b67f09SDavid van Moolenbroek iter = isc_mem_get(mctx, sizeof(*iter));
301*00b67f09SDavid van Moolenbroek if (iter == NULL)
302*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
303*00b67f09SDavid van Moolenbroek
304*00b67f09SDavid van Moolenbroek iter->mctx = mctx;
305*00b67f09SDavid van Moolenbroek iter->mode = 4;
306*00b67f09SDavid van Moolenbroek iter->buf = NULL;
307*00b67f09SDavid van Moolenbroek iter->pos = (unsigned int) -1;
308*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
309*00b67f09SDavid van Moolenbroek iter->buf6 = NULL;
310*00b67f09SDavid van Moolenbroek iter->pos6 = (unsigned int) -1;
311*00b67f09SDavid van Moolenbroek iter->result6 = ISC_R_NOMORE;
312*00b67f09SDavid van Moolenbroek iter->socket6 = -1;
313*00b67f09SDavid van Moolenbroek iter->first6 = ISC_FALSE;
314*00b67f09SDavid van Moolenbroek #endif
315*00b67f09SDavid van Moolenbroek
316*00b67f09SDavid van Moolenbroek /*
317*00b67f09SDavid van Moolenbroek * Get the interface configuration, allocating more memory if
318*00b67f09SDavid van Moolenbroek * necessary.
319*00b67f09SDavid van Moolenbroek */
320*00b67f09SDavid van Moolenbroek
321*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
322*00b67f09SDavid van Moolenbroek result = isc_net_probeipv6();
323*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
324*00b67f09SDavid van Moolenbroek /*
325*00b67f09SDavid van Moolenbroek * Create an unbound datagram socket to do the SIOCGLIFCONF
326*00b67f09SDavid van Moolenbroek * ioctl on. HP/UX requires an AF_INET6 socket for
327*00b67f09SDavid van Moolenbroek * SIOCGLIFCONF to get IPv6 addresses.
328*00b67f09SDavid van Moolenbroek */
329*00b67f09SDavid van Moolenbroek if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
330*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
331*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
332*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
333*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
334*00b67f09SDavid van Moolenbroek ISC_MSG_MAKESCANSOCKET,
335*00b67f09SDavid van Moolenbroek "making interface "
336*00b67f09SDavid van Moolenbroek "scan socket: %s"),
337*00b67f09SDavid van Moolenbroek strbuf);
338*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
339*00b67f09SDavid van Moolenbroek goto socket6_failure;
340*00b67f09SDavid van Moolenbroek }
341*00b67f09SDavid van Moolenbroek result = iter->result6 = getbuf6(iter);
342*00b67f09SDavid van Moolenbroek if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
343*00b67f09SDavid van Moolenbroek goto ioctl6_failure;
344*00b67f09SDavid van Moolenbroek }
345*00b67f09SDavid van Moolenbroek #endif
346*00b67f09SDavid van Moolenbroek if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
347*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
348*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
349*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
350*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
351*00b67f09SDavid van Moolenbroek ISC_MSG_MAKESCANSOCKET,
352*00b67f09SDavid van Moolenbroek "making interface "
353*00b67f09SDavid van Moolenbroek "scan socket: %s"),
354*00b67f09SDavid van Moolenbroek strbuf);
355*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
356*00b67f09SDavid van Moolenbroek goto socket_failure;
357*00b67f09SDavid van Moolenbroek }
358*00b67f09SDavid van Moolenbroek result = getbuf4(iter);
359*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
360*00b67f09SDavid van Moolenbroek goto ioctl_failure;
361*00b67f09SDavid van Moolenbroek
362*00b67f09SDavid van Moolenbroek /*
363*00b67f09SDavid van Moolenbroek * A newly created iterator has an undefined position
364*00b67f09SDavid van Moolenbroek * until isc_interfaceiter_first() is called.
365*00b67f09SDavid van Moolenbroek */
366*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
367*00b67f09SDavid van Moolenbroek iter->clua_context = -1;
368*00b67f09SDavid van Moolenbroek iter->clua_done = ISC_TRUE;
369*00b67f09SDavid van Moolenbroek #endif
370*00b67f09SDavid van Moolenbroek #ifdef __linux
371*00b67f09SDavid van Moolenbroek iter->proc = fopen("/proc/net/if_inet6", "r");
372*00b67f09SDavid van Moolenbroek iter->valid = ISC_R_FAILURE;
373*00b67f09SDavid van Moolenbroek #endif
374*00b67f09SDavid van Moolenbroek iter->result = ISC_R_FAILURE;
375*00b67f09SDavid van Moolenbroek
376*00b67f09SDavid van Moolenbroek iter->magic = IFITER_MAGIC;
377*00b67f09SDavid van Moolenbroek *iterp = iter;
378*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
379*00b67f09SDavid van Moolenbroek
380*00b67f09SDavid van Moolenbroek ioctl_failure:
381*00b67f09SDavid van Moolenbroek if (iter->buf != NULL)
382*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter->buf, iter->bufsize);
383*00b67f09SDavid van Moolenbroek (void) close(iter->socket);
384*00b67f09SDavid van Moolenbroek
385*00b67f09SDavid van Moolenbroek socket_failure:
386*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
387*00b67f09SDavid van Moolenbroek if (iter->buf6 != NULL)
388*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter->buf6, iter->bufsize6);
389*00b67f09SDavid van Moolenbroek ioctl6_failure:
390*00b67f09SDavid van Moolenbroek if (iter->socket6 != -1)
391*00b67f09SDavid van Moolenbroek (void) close(iter->socket6);
392*00b67f09SDavid van Moolenbroek socket6_failure:
393*00b67f09SDavid van Moolenbroek #endif
394*00b67f09SDavid van Moolenbroek
395*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter, sizeof(*iter));
396*00b67f09SDavid van Moolenbroek return (result);
397*00b67f09SDavid van Moolenbroek }
398*00b67f09SDavid van Moolenbroek
399*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
400*00b67f09SDavid van Moolenbroek static void
get_inaddr(isc_netaddr_t * dst,struct in_addr * src)401*00b67f09SDavid van Moolenbroek get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
402*00b67f09SDavid van Moolenbroek dst->family = AF_INET;
403*00b67f09SDavid van Moolenbroek memmove(&dst->type.in, src, sizeof(struct in_addr));
404*00b67f09SDavid van Moolenbroek }
405*00b67f09SDavid van Moolenbroek
406*00b67f09SDavid van Moolenbroek static isc_result_t
internal_current_clusteralias(isc_interfaceiter_t * iter)407*00b67f09SDavid van Moolenbroek internal_current_clusteralias(isc_interfaceiter_t *iter) {
408*00b67f09SDavid van Moolenbroek struct clua_info ci;
409*00b67f09SDavid van Moolenbroek if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
410*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
411*00b67f09SDavid van Moolenbroek memset(&iter->current, 0, sizeof(iter->current));
412*00b67f09SDavid van Moolenbroek iter->current.af = iter->clua_sa.sa_family;
413*00b67f09SDavid van Moolenbroek memset(iter->current.name, 0, sizeof(iter->current.name));
414*00b67f09SDavid van Moolenbroek sprintf(iter->current.name, "clua%d", ci.aliasid);
415*00b67f09SDavid van Moolenbroek iter->current.flags = INTERFACE_F_UP;
416*00b67f09SDavid van Moolenbroek get_inaddr(&iter->current.address, &ci.addr);
417*00b67f09SDavid van Moolenbroek get_inaddr(&iter->current.netmask, &ci.netmask);
418*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
419*00b67f09SDavid van Moolenbroek }
420*00b67f09SDavid van Moolenbroek #endif
421*00b67f09SDavid van Moolenbroek
422*00b67f09SDavid van Moolenbroek /*
423*00b67f09SDavid van Moolenbroek * Get information about the current interface to iter->current.
424*00b67f09SDavid van Moolenbroek * If successful, return ISC_R_SUCCESS.
425*00b67f09SDavid van Moolenbroek * If the interface has an unsupported address family, or if
426*00b67f09SDavid van Moolenbroek * some operation on it fails, return ISC_R_IGNORE to make
427*00b67f09SDavid van Moolenbroek * the higher-level iterator code ignore it.
428*00b67f09SDavid van Moolenbroek */
429*00b67f09SDavid van Moolenbroek
430*00b67f09SDavid van Moolenbroek static isc_result_t
internal_current4(isc_interfaceiter_t * iter)431*00b67f09SDavid van Moolenbroek internal_current4(isc_interfaceiter_t *iter) {
432*00b67f09SDavid van Moolenbroek struct ifreq *ifrp;
433*00b67f09SDavid van Moolenbroek struct ifreq ifreq;
434*00b67f09SDavid van Moolenbroek int family;
435*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
436*00b67f09SDavid van Moolenbroek #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
437*00b67f09SDavid van Moolenbroek struct lifreq lifreq;
438*00b67f09SDavid van Moolenbroek #else
439*00b67f09SDavid van Moolenbroek char sabuf[256];
440*00b67f09SDavid van Moolenbroek #endif
441*00b67f09SDavid van Moolenbroek int i, bits, prefixlen;
442*00b67f09SDavid van Moolenbroek
443*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
444*00b67f09SDavid van Moolenbroek
445*00b67f09SDavid van Moolenbroek if (iter->ifc.ifc_len == 0 ||
446*00b67f09SDavid van Moolenbroek iter->pos == (unsigned int)iter->ifc.ifc_len) {
447*00b67f09SDavid van Moolenbroek #ifdef __linux
448*00b67f09SDavid van Moolenbroek return (linux_if_inet6_current(iter));
449*00b67f09SDavid van Moolenbroek #else
450*00b67f09SDavid van Moolenbroek return (ISC_R_NOMORE);
451*00b67f09SDavid van Moolenbroek #endif
452*00b67f09SDavid van Moolenbroek }
453*00b67f09SDavid van Moolenbroek
454*00b67f09SDavid van Moolenbroek INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
455*00b67f09SDavid van Moolenbroek
456*00b67f09SDavid van Moolenbroek ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
457*00b67f09SDavid van Moolenbroek
458*00b67f09SDavid van Moolenbroek memset(&ifreq, 0, sizeof(ifreq));
459*00b67f09SDavid van Moolenbroek memmove(&ifreq, ifrp, sizeof(ifreq));
460*00b67f09SDavid van Moolenbroek
461*00b67f09SDavid van Moolenbroek family = ifreq.ifr_addr.sa_family;
462*00b67f09SDavid van Moolenbroek #if defined(ISC_PLATFORM_HAVEIPV6)
463*00b67f09SDavid van Moolenbroek if (family != AF_INET && family != AF_INET6)
464*00b67f09SDavid van Moolenbroek #else
465*00b67f09SDavid van Moolenbroek if (family != AF_INET)
466*00b67f09SDavid van Moolenbroek #endif
467*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
468*00b67f09SDavid van Moolenbroek
469*00b67f09SDavid van Moolenbroek memset(&iter->current, 0, sizeof(iter->current));
470*00b67f09SDavid van Moolenbroek iter->current.af = family;
471*00b67f09SDavid van Moolenbroek
472*00b67f09SDavid van Moolenbroek INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
473*00b67f09SDavid van Moolenbroek memset(iter->current.name, 0, sizeof(iter->current.name));
474*00b67f09SDavid van Moolenbroek memmove(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
475*00b67f09SDavid van Moolenbroek
476*00b67f09SDavid van Moolenbroek get_addr(family, &iter->current.address,
477*00b67f09SDavid van Moolenbroek (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
478*00b67f09SDavid van Moolenbroek
479*00b67f09SDavid van Moolenbroek /*
480*00b67f09SDavid van Moolenbroek * If the interface does not have a address ignore it.
481*00b67f09SDavid van Moolenbroek */
482*00b67f09SDavid van Moolenbroek switch (family) {
483*00b67f09SDavid van Moolenbroek case AF_INET:
484*00b67f09SDavid van Moolenbroek if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
485*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
486*00b67f09SDavid van Moolenbroek break;
487*00b67f09SDavid van Moolenbroek case AF_INET6:
488*00b67f09SDavid van Moolenbroek if (memcmp(&iter->current.address.type.in6, &in6addr_any,
489*00b67f09SDavid van Moolenbroek sizeof(in6addr_any)) == 0)
490*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
491*00b67f09SDavid van Moolenbroek break;
492*00b67f09SDavid van Moolenbroek }
493*00b67f09SDavid van Moolenbroek
494*00b67f09SDavid van Moolenbroek /*
495*00b67f09SDavid van Moolenbroek * Get interface flags.
496*00b67f09SDavid van Moolenbroek */
497*00b67f09SDavid van Moolenbroek
498*00b67f09SDavid van Moolenbroek iter->current.flags = 0;
499*00b67f09SDavid van Moolenbroek
500*00b67f09SDavid van Moolenbroek /*
501*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
502*00b67f09SDavid van Moolenbroek * conversion. It comes from its own macro definition,
503*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
504*00b67f09SDavid van Moolenbroek */
505*00b67f09SDavid van Moolenbroek if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
506*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
507*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
508*00b67f09SDavid van Moolenbroek "%s: getting interface flags: %s",
509*00b67f09SDavid van Moolenbroek ifreq.ifr_name, strbuf);
510*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
511*00b67f09SDavid van Moolenbroek }
512*00b67f09SDavid van Moolenbroek
513*00b67f09SDavid van Moolenbroek if ((ifreq.ifr_flags & IFF_UP) != 0)
514*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_UP;
515*00b67f09SDavid van Moolenbroek
516*00b67f09SDavid van Moolenbroek #ifdef IFF_POINTOPOINT
517*00b67f09SDavid van Moolenbroek if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
518*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_POINTTOPOINT;
519*00b67f09SDavid van Moolenbroek #endif
520*00b67f09SDavid van Moolenbroek
521*00b67f09SDavid van Moolenbroek if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
522*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_LOOPBACK;
523*00b67f09SDavid van Moolenbroek
524*00b67f09SDavid van Moolenbroek if (family == AF_INET)
525*00b67f09SDavid van Moolenbroek goto inet;
526*00b67f09SDavid van Moolenbroek
527*00b67f09SDavid van Moolenbroek #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
528*00b67f09SDavid van Moolenbroek memset(&lifreq, 0, sizeof(lifreq));
529*00b67f09SDavid van Moolenbroek memmove(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
530*00b67f09SDavid van Moolenbroek memmove(&lifreq.lifr_addr, &iter->current.address.type.in6,
531*00b67f09SDavid van Moolenbroek sizeof(iter->current.address.type.in6));
532*00b67f09SDavid van Moolenbroek
533*00b67f09SDavid van Moolenbroek if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
534*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
535*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
536*00b67f09SDavid van Moolenbroek "%s: getting interface address: %s",
537*00b67f09SDavid van Moolenbroek ifreq.ifr_name, strbuf);
538*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
539*00b67f09SDavid van Moolenbroek }
540*00b67f09SDavid van Moolenbroek prefixlen = lifreq.lifr_addrlen;
541*00b67f09SDavid van Moolenbroek #else
542*00b67f09SDavid van Moolenbroek isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
543*00b67f09SDavid van Moolenbroek isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
544*00b67f09SDavid van Moolenbroek ISC_LOGMODULE_INTERFACE,
545*00b67f09SDavid van Moolenbroek ISC_LOG_INFO,
546*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
547*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
548*00b67f09SDavid van Moolenbroek ISC_MSG_GETIFCONFIG,
549*00b67f09SDavid van Moolenbroek "prefix length for %s is unknown "
550*00b67f09SDavid van Moolenbroek "(assume 128)"), sabuf);
551*00b67f09SDavid van Moolenbroek prefixlen = 128;
552*00b67f09SDavid van Moolenbroek #endif
553*00b67f09SDavid van Moolenbroek
554*00b67f09SDavid van Moolenbroek /*
555*00b67f09SDavid van Moolenbroek * Netmask already zeroed.
556*00b67f09SDavid van Moolenbroek */
557*00b67f09SDavid van Moolenbroek iter->current.netmask.family = family;
558*00b67f09SDavid van Moolenbroek for (i = 0; i < 16; i++) {
559*00b67f09SDavid van Moolenbroek if (prefixlen > 8) {
560*00b67f09SDavid van Moolenbroek bits = 0;
561*00b67f09SDavid van Moolenbroek prefixlen -= 8;
562*00b67f09SDavid van Moolenbroek } else {
563*00b67f09SDavid van Moolenbroek bits = 8 - prefixlen;
564*00b67f09SDavid van Moolenbroek prefixlen = 0;
565*00b67f09SDavid van Moolenbroek }
566*00b67f09SDavid van Moolenbroek iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
567*00b67f09SDavid van Moolenbroek }
568*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
569*00b67f09SDavid van Moolenbroek
570*00b67f09SDavid van Moolenbroek inet:
571*00b67f09SDavid van Moolenbroek if (family != AF_INET)
572*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
573*00b67f09SDavid van Moolenbroek #ifdef IFF_POINTOPOINT
574*00b67f09SDavid van Moolenbroek /*
575*00b67f09SDavid van Moolenbroek * If the interface is point-to-point, get the destination address.
576*00b67f09SDavid van Moolenbroek */
577*00b67f09SDavid van Moolenbroek if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
578*00b67f09SDavid van Moolenbroek /*
579*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
580*00b67f09SDavid van Moolenbroek * conversion. It comes from its own macro definition,
581*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
582*00b67f09SDavid van Moolenbroek */
583*00b67f09SDavid van Moolenbroek if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
584*00b67f09SDavid van Moolenbroek < 0) {
585*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
586*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
587*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
588*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
589*00b67f09SDavid van Moolenbroek ISC_MSG_GETDESTADDR,
590*00b67f09SDavid van Moolenbroek "%s: getting "
591*00b67f09SDavid van Moolenbroek "destination address: %s"),
592*00b67f09SDavid van Moolenbroek ifreq.ifr_name, strbuf);
593*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
594*00b67f09SDavid van Moolenbroek }
595*00b67f09SDavid van Moolenbroek get_addr(family, &iter->current.dstaddress,
596*00b67f09SDavid van Moolenbroek (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
597*00b67f09SDavid van Moolenbroek }
598*00b67f09SDavid van Moolenbroek #endif
599*00b67f09SDavid van Moolenbroek
600*00b67f09SDavid van Moolenbroek /*
601*00b67f09SDavid van Moolenbroek * Get the network mask.
602*00b67f09SDavid van Moolenbroek */
603*00b67f09SDavid van Moolenbroek memset(&ifreq, 0, sizeof(ifreq));
604*00b67f09SDavid van Moolenbroek memmove(&ifreq, ifrp, sizeof(ifreq));
605*00b67f09SDavid van Moolenbroek /*
606*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
607*00b67f09SDavid van Moolenbroek * conversion. It comes from its own macro definition,
608*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
609*00b67f09SDavid van Moolenbroek */
610*00b67f09SDavid van Moolenbroek if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
611*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
612*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
613*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
614*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
615*00b67f09SDavid van Moolenbroek ISC_MSG_GETNETMASK,
616*00b67f09SDavid van Moolenbroek "%s: getting netmask: %s"),
617*00b67f09SDavid van Moolenbroek ifreq.ifr_name, strbuf);
618*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
619*00b67f09SDavid van Moolenbroek }
620*00b67f09SDavid van Moolenbroek get_addr(family, &iter->current.netmask,
621*00b67f09SDavid van Moolenbroek (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
622*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
623*00b67f09SDavid van Moolenbroek }
624*00b67f09SDavid van Moolenbroek
625*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
626*00b67f09SDavid van Moolenbroek static isc_result_t
internal_current6(isc_interfaceiter_t * iter)627*00b67f09SDavid van Moolenbroek internal_current6(isc_interfaceiter_t *iter) {
628*00b67f09SDavid van Moolenbroek struct LIFREQ *ifrp;
629*00b67f09SDavid van Moolenbroek struct LIFREQ lifreq;
630*00b67f09SDavid van Moolenbroek int family;
631*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
632*00b67f09SDavid van Moolenbroek int fd;
633*00b67f09SDavid van Moolenbroek
634*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
635*00b67f09SDavid van Moolenbroek if (iter->result6 != ISC_R_SUCCESS)
636*00b67f09SDavid van Moolenbroek return (iter->result6);
637*00b67f09SDavid van Moolenbroek REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
638*00b67f09SDavid van Moolenbroek
639*00b67f09SDavid van Moolenbroek ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
640*00b67f09SDavid van Moolenbroek
641*00b67f09SDavid van Moolenbroek memset(&lifreq, 0, sizeof(lifreq));
642*00b67f09SDavid van Moolenbroek memmove(&lifreq, ifrp, sizeof(lifreq));
643*00b67f09SDavid van Moolenbroek
644*00b67f09SDavid van Moolenbroek family = lifreq.lifr_addr.ss_family;
645*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVEIPV6
646*00b67f09SDavid van Moolenbroek if (family != AF_INET && family != AF_INET6)
647*00b67f09SDavid van Moolenbroek #else
648*00b67f09SDavid van Moolenbroek if (family != AF_INET)
649*00b67f09SDavid van Moolenbroek #endif
650*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
651*00b67f09SDavid van Moolenbroek
652*00b67f09SDavid van Moolenbroek memset(&iter->current, 0, sizeof(iter->current));
653*00b67f09SDavid van Moolenbroek iter->current.af = family;
654*00b67f09SDavid van Moolenbroek
655*00b67f09SDavid van Moolenbroek INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
656*00b67f09SDavid van Moolenbroek memset(iter->current.name, 0, sizeof(iter->current.name));
657*00b67f09SDavid van Moolenbroek memmove(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
658*00b67f09SDavid van Moolenbroek
659*00b67f09SDavid van Moolenbroek get_addr(family, &iter->current.address,
660*00b67f09SDavid van Moolenbroek (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
661*00b67f09SDavid van Moolenbroek
662*00b67f09SDavid van Moolenbroek /*
663*00b67f09SDavid van Moolenbroek * If the interface does not have a address ignore it.
664*00b67f09SDavid van Moolenbroek */
665*00b67f09SDavid van Moolenbroek switch (family) {
666*00b67f09SDavid van Moolenbroek case AF_INET:
667*00b67f09SDavid van Moolenbroek if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
668*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
669*00b67f09SDavid van Moolenbroek break;
670*00b67f09SDavid van Moolenbroek case AF_INET6:
671*00b67f09SDavid van Moolenbroek if (memcmp(&iter->current.address.type.in6, &in6addr_any,
672*00b67f09SDavid van Moolenbroek sizeof(in6addr_any)) == 0)
673*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
674*00b67f09SDavid van Moolenbroek break;
675*00b67f09SDavid van Moolenbroek }
676*00b67f09SDavid van Moolenbroek
677*00b67f09SDavid van Moolenbroek /*
678*00b67f09SDavid van Moolenbroek * Get interface flags.
679*00b67f09SDavid van Moolenbroek */
680*00b67f09SDavid van Moolenbroek
681*00b67f09SDavid van Moolenbroek iter->current.flags = 0;
682*00b67f09SDavid van Moolenbroek
683*00b67f09SDavid van Moolenbroek if (family == AF_INET6)
684*00b67f09SDavid van Moolenbroek fd = iter->socket6;
685*00b67f09SDavid van Moolenbroek else
686*00b67f09SDavid van Moolenbroek fd = iter->socket;
687*00b67f09SDavid van Moolenbroek
688*00b67f09SDavid van Moolenbroek /*
689*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
690*00b67f09SDavid van Moolenbroek * conversion. It comes from its own macro definition,
691*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
692*00b67f09SDavid van Moolenbroek */
693*00b67f09SDavid van Moolenbroek if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
694*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
695*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
696*00b67f09SDavid van Moolenbroek "%s: getting interface flags: %s",
697*00b67f09SDavid van Moolenbroek lifreq.lifr_name, strbuf);
698*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
699*00b67f09SDavid van Moolenbroek }
700*00b67f09SDavid van Moolenbroek
701*00b67f09SDavid van Moolenbroek if ((lifreq.lifr_flags & IFF_UP) != 0)
702*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_UP;
703*00b67f09SDavid van Moolenbroek
704*00b67f09SDavid van Moolenbroek #ifdef IFF_POINTOPOINT
705*00b67f09SDavid van Moolenbroek if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
706*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_POINTTOPOINT;
707*00b67f09SDavid van Moolenbroek #endif
708*00b67f09SDavid van Moolenbroek
709*00b67f09SDavid van Moolenbroek if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
710*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_LOOPBACK;
711*00b67f09SDavid van Moolenbroek
712*00b67f09SDavid van Moolenbroek #ifdef IFF_POINTOPOINT
713*00b67f09SDavid van Moolenbroek /*
714*00b67f09SDavid van Moolenbroek * If the interface is point-to-point, get the destination address.
715*00b67f09SDavid van Moolenbroek */
716*00b67f09SDavid van Moolenbroek if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
717*00b67f09SDavid van Moolenbroek /*
718*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
719*00b67f09SDavid van Moolenbroek * conversion. It comes from its own macro definition,
720*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
721*00b67f09SDavid van Moolenbroek */
722*00b67f09SDavid van Moolenbroek if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
723*00b67f09SDavid van Moolenbroek < 0) {
724*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
725*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
726*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
727*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
728*00b67f09SDavid van Moolenbroek ISC_MSG_GETDESTADDR,
729*00b67f09SDavid van Moolenbroek "%s: getting "
730*00b67f09SDavid van Moolenbroek "destination address: %s"),
731*00b67f09SDavid van Moolenbroek lifreq.lifr_name, strbuf);
732*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
733*00b67f09SDavid van Moolenbroek }
734*00b67f09SDavid van Moolenbroek get_addr(family, &iter->current.dstaddress,
735*00b67f09SDavid van Moolenbroek (struct sockaddr *)&lifreq.lifr_dstaddr,
736*00b67f09SDavid van Moolenbroek lifreq.lifr_name);
737*00b67f09SDavid van Moolenbroek }
738*00b67f09SDavid van Moolenbroek #endif
739*00b67f09SDavid van Moolenbroek
740*00b67f09SDavid van Moolenbroek /*
741*00b67f09SDavid van Moolenbroek * Get the network mask. Netmask already zeroed.
742*00b67f09SDavid van Moolenbroek */
743*00b67f09SDavid van Moolenbroek memset(&lifreq, 0, sizeof(lifreq));
744*00b67f09SDavid van Moolenbroek memmove(&lifreq, ifrp, sizeof(lifreq));
745*00b67f09SDavid van Moolenbroek
746*00b67f09SDavid van Moolenbroek #ifdef lifr_addrlen
747*00b67f09SDavid van Moolenbroek /*
748*00b67f09SDavid van Moolenbroek * Special case: if the system provides lifr_addrlen member, the
749*00b67f09SDavid van Moolenbroek * netmask of an IPv6 address can be derived from the length, since
750*00b67f09SDavid van Moolenbroek * an IPv6 address always has a contiguous mask.
751*00b67f09SDavid van Moolenbroek */
752*00b67f09SDavid van Moolenbroek if (family == AF_INET6) {
753*00b67f09SDavid van Moolenbroek int i, bits;
754*00b67f09SDavid van Moolenbroek
755*00b67f09SDavid van Moolenbroek iter->current.netmask.family = family;
756*00b67f09SDavid van Moolenbroek for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
757*00b67f09SDavid van Moolenbroek bits = lifreq.lifr_addrlen - i;
758*00b67f09SDavid van Moolenbroek bits = (bits < 8) ? (8 - bits) : 0;
759*00b67f09SDavid van Moolenbroek iter->current.netmask.type.in6.s6_addr[i / 8] =
760*00b67f09SDavid van Moolenbroek (~0 << bits) & 0xff;
761*00b67f09SDavid van Moolenbroek }
762*00b67f09SDavid van Moolenbroek
763*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
764*00b67f09SDavid van Moolenbroek }
765*00b67f09SDavid van Moolenbroek #endif
766*00b67f09SDavid van Moolenbroek
767*00b67f09SDavid van Moolenbroek /*
768*00b67f09SDavid van Moolenbroek * Ignore the HP/UX warning about "integer overflow during
769*00b67f09SDavid van Moolenbroek * conversion. It comes from its own macro definition,
770*00b67f09SDavid van Moolenbroek * and is really hard to shut up.
771*00b67f09SDavid van Moolenbroek */
772*00b67f09SDavid van Moolenbroek if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
773*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
774*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
775*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat,
776*00b67f09SDavid van Moolenbroek ISC_MSGSET_IFITERIOCTL,
777*00b67f09SDavid van Moolenbroek ISC_MSG_GETNETMASK,
778*00b67f09SDavid van Moolenbroek "%s: getting netmask: %s"),
779*00b67f09SDavid van Moolenbroek lifreq.lifr_name, strbuf);
780*00b67f09SDavid van Moolenbroek return (ISC_R_IGNORE);
781*00b67f09SDavid van Moolenbroek }
782*00b67f09SDavid van Moolenbroek get_addr(family, &iter->current.netmask,
783*00b67f09SDavid van Moolenbroek (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
784*00b67f09SDavid van Moolenbroek
785*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
786*00b67f09SDavid van Moolenbroek }
787*00b67f09SDavid van Moolenbroek #endif
788*00b67f09SDavid van Moolenbroek
789*00b67f09SDavid van Moolenbroek static isc_result_t
internal_current(isc_interfaceiter_t * iter)790*00b67f09SDavid van Moolenbroek internal_current(isc_interfaceiter_t *iter) {
791*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
792*00b67f09SDavid van Moolenbroek if (iter->mode == 6) {
793*00b67f09SDavid van Moolenbroek iter->result6 = internal_current6(iter);
794*00b67f09SDavid van Moolenbroek if (iter->result6 != ISC_R_NOMORE)
795*00b67f09SDavid van Moolenbroek return (iter->result6);
796*00b67f09SDavid van Moolenbroek }
797*00b67f09SDavid van Moolenbroek #endif
798*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
799*00b67f09SDavid van Moolenbroek if (!iter->clua_done)
800*00b67f09SDavid van Moolenbroek return(internal_current_clusteralias(iter));
801*00b67f09SDavid van Moolenbroek #endif
802*00b67f09SDavid van Moolenbroek return (internal_current4(iter));
803*00b67f09SDavid van Moolenbroek }
804*00b67f09SDavid van Moolenbroek
805*00b67f09SDavid van Moolenbroek /*
806*00b67f09SDavid van Moolenbroek * Step the iterator to the next interface. Unlike
807*00b67f09SDavid van Moolenbroek * isc_interfaceiter_next(), this may leave the iterator
808*00b67f09SDavid van Moolenbroek * positioned on an interface that will ultimately
809*00b67f09SDavid van Moolenbroek * be ignored. Return ISC_R_NOMORE if there are no more
810*00b67f09SDavid van Moolenbroek * interfaces, otherwise ISC_R_SUCCESS.
811*00b67f09SDavid van Moolenbroek */
812*00b67f09SDavid van Moolenbroek static isc_result_t
internal_next4(isc_interfaceiter_t * iter)813*00b67f09SDavid van Moolenbroek internal_next4(isc_interfaceiter_t *iter) {
814*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESALEN
815*00b67f09SDavid van Moolenbroek struct ifreq *ifrp;
816*00b67f09SDavid van Moolenbroek #endif
817*00b67f09SDavid van Moolenbroek
818*00b67f09SDavid van Moolenbroek if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
819*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESALEN
820*00b67f09SDavid van Moolenbroek ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
821*00b67f09SDavid van Moolenbroek
822*00b67f09SDavid van Moolenbroek if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
823*00b67f09SDavid van Moolenbroek iter->pos += sizeof(ifrp->ifr_name) +
824*00b67f09SDavid van Moolenbroek ifrp->ifr_addr.sa_len;
825*00b67f09SDavid van Moolenbroek else
826*00b67f09SDavid van Moolenbroek #endif
827*00b67f09SDavid van Moolenbroek iter->pos += sizeof(struct ifreq);
828*00b67f09SDavid van Moolenbroek
829*00b67f09SDavid van Moolenbroek } else {
830*00b67f09SDavid van Moolenbroek INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
831*00b67f09SDavid van Moolenbroek #ifdef __linux
832*00b67f09SDavid van Moolenbroek return (linux_if_inet6_next(iter));
833*00b67f09SDavid van Moolenbroek #else
834*00b67f09SDavid van Moolenbroek return (ISC_R_NOMORE);
835*00b67f09SDavid van Moolenbroek #endif
836*00b67f09SDavid van Moolenbroek }
837*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
838*00b67f09SDavid van Moolenbroek }
839*00b67f09SDavid van Moolenbroek
840*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
841*00b67f09SDavid van Moolenbroek static isc_result_t
internal_next6(isc_interfaceiter_t * iter)842*00b67f09SDavid van Moolenbroek internal_next6(isc_interfaceiter_t *iter) {
843*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESALEN
844*00b67f09SDavid van Moolenbroek struct LIFREQ *ifrp;
845*00b67f09SDavid van Moolenbroek #endif
846*00b67f09SDavid van Moolenbroek
847*00b67f09SDavid van Moolenbroek if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
848*00b67f09SDavid van Moolenbroek return (iter->result6);
849*00b67f09SDavid van Moolenbroek
850*00b67f09SDavid van Moolenbroek REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
851*00b67f09SDavid van Moolenbroek
852*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESALEN
853*00b67f09SDavid van Moolenbroek ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
854*00b67f09SDavid van Moolenbroek
855*00b67f09SDavid van Moolenbroek if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
856*00b67f09SDavid van Moolenbroek iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
857*00b67f09SDavid van Moolenbroek else
858*00b67f09SDavid van Moolenbroek #endif
859*00b67f09SDavid van Moolenbroek iter->pos6 += sizeof(struct LIFREQ);
860*00b67f09SDavid van Moolenbroek
861*00b67f09SDavid van Moolenbroek if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
862*00b67f09SDavid van Moolenbroek return (ISC_R_NOMORE);
863*00b67f09SDavid van Moolenbroek
864*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
865*00b67f09SDavid van Moolenbroek }
866*00b67f09SDavid van Moolenbroek #endif
867*00b67f09SDavid van Moolenbroek
868*00b67f09SDavid van Moolenbroek static isc_result_t
internal_next(isc_interfaceiter_t * iter)869*00b67f09SDavid van Moolenbroek internal_next(isc_interfaceiter_t *iter) {
870*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
871*00b67f09SDavid van Moolenbroek int clua_result;
872*00b67f09SDavid van Moolenbroek #endif
873*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
874*00b67f09SDavid van Moolenbroek if (iter->mode == 6) {
875*00b67f09SDavid van Moolenbroek iter->result6 = internal_next6(iter);
876*00b67f09SDavid van Moolenbroek if (iter->result6 != ISC_R_NOMORE)
877*00b67f09SDavid van Moolenbroek return (iter->result6);
878*00b67f09SDavid van Moolenbroek if (iter->first6) {
879*00b67f09SDavid van Moolenbroek iter->first6 = ISC_FALSE;
880*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
881*00b67f09SDavid van Moolenbroek }
882*00b67f09SDavid van Moolenbroek }
883*00b67f09SDavid van Moolenbroek #endif
884*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
885*00b67f09SDavid van Moolenbroek if (!iter->clua_done) {
886*00b67f09SDavid van Moolenbroek clua_result = clua_getaliasaddress(&iter->clua_sa,
887*00b67f09SDavid van Moolenbroek &iter->clua_context);
888*00b67f09SDavid van Moolenbroek if (clua_result != CLUA_SUCCESS)
889*00b67f09SDavid van Moolenbroek iter->clua_done = ISC_TRUE;
890*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
891*00b67f09SDavid van Moolenbroek }
892*00b67f09SDavid van Moolenbroek #endif
893*00b67f09SDavid van Moolenbroek return (internal_next4(iter));
894*00b67f09SDavid van Moolenbroek }
895*00b67f09SDavid van Moolenbroek
896*00b67f09SDavid van Moolenbroek static void
internal_destroy(isc_interfaceiter_t * iter)897*00b67f09SDavid van Moolenbroek internal_destroy(isc_interfaceiter_t *iter) {
898*00b67f09SDavid van Moolenbroek (void) close(iter->socket);
899*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
900*00b67f09SDavid van Moolenbroek if (iter->socket6 != -1)
901*00b67f09SDavid van Moolenbroek (void) close(iter->socket6);
902*00b67f09SDavid van Moolenbroek if (iter->buf6 != NULL) {
903*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
904*00b67f09SDavid van Moolenbroek }
905*00b67f09SDavid van Moolenbroek #endif
906*00b67f09SDavid van Moolenbroek #ifdef __linux
907*00b67f09SDavid van Moolenbroek if (iter->proc != NULL)
908*00b67f09SDavid van Moolenbroek fclose(iter->proc);
909*00b67f09SDavid van Moolenbroek #endif
910*00b67f09SDavid van Moolenbroek }
911*00b67f09SDavid van Moolenbroek
912*00b67f09SDavid van Moolenbroek static
internal_first(isc_interfaceiter_t * iter)913*00b67f09SDavid van Moolenbroek void internal_first(isc_interfaceiter_t *iter) {
914*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
915*00b67f09SDavid van Moolenbroek int clua_result;
916*00b67f09SDavid van Moolenbroek #endif
917*00b67f09SDavid van Moolenbroek iter->pos = 0;
918*00b67f09SDavid van Moolenbroek #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
919*00b67f09SDavid van Moolenbroek iter->pos6 = 0;
920*00b67f09SDavid van Moolenbroek if (iter->result6 == ISC_R_NOMORE)
921*00b67f09SDavid van Moolenbroek iter->result6 = ISC_R_SUCCESS;
922*00b67f09SDavid van Moolenbroek iter->first6 = ISC_TRUE;
923*00b67f09SDavid van Moolenbroek #endif
924*00b67f09SDavid van Moolenbroek #ifdef HAVE_TRUCLUSTER
925*00b67f09SDavid van Moolenbroek iter->clua_context = 0;
926*00b67f09SDavid van Moolenbroek clua_result = clua_getaliasaddress(&iter->clua_sa,
927*00b67f09SDavid van Moolenbroek &iter->clua_context);
928*00b67f09SDavid van Moolenbroek iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
929*00b67f09SDavid van Moolenbroek #endif
930*00b67f09SDavid van Moolenbroek #ifdef __linux
931*00b67f09SDavid van Moolenbroek linux_if_inet6_first(iter);
932*00b67f09SDavid van Moolenbroek #endif
933*00b67f09SDavid van Moolenbroek }
934