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