1*00b67f09SDavid van Moolenbroek /* $NetBSD: interfaceiter.c,v 1.6 2014/12/10 04:38:01 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004, 2007-2009, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2001 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: interfaceiter.c,v 1.15 2009/01/18 23:48:14 tbox Exp */
21*00b67f09SDavid van Moolenbroek
22*00b67f09SDavid van Moolenbroek /*
23*00b67f09SDavid van Moolenbroek * Note that this code will need to be revisited to support IPv6 Interfaces.
24*00b67f09SDavid van Moolenbroek * For now we just iterate through IPv4 interfaces.
25*00b67f09SDavid van Moolenbroek */
26*00b67f09SDavid van Moolenbroek
27*00b67f09SDavid van Moolenbroek #include <config.h>
28*00b67f09SDavid van Moolenbroek #include <winsock2.h>
29*00b67f09SDavid van Moolenbroek #include <ws2tcpip.h>
30*00b67f09SDavid van Moolenbroek #include <sys/types.h>
31*00b67f09SDavid van Moolenbroek
32*00b67f09SDavid van Moolenbroek #include <stdio.h>
33*00b67f09SDavid van Moolenbroek #include <stdlib.h>
34*00b67f09SDavid van Moolenbroek #include <errno.h>
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek #include <isc/interfaceiter.h>
37*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
38*00b67f09SDavid van Moolenbroek #include <isc/result.h>
39*00b67f09SDavid van Moolenbroek #include <isc/string.h>
40*00b67f09SDavid van Moolenbroek #include <isc/strerror.h>
41*00b67f09SDavid van Moolenbroek #include <isc/types.h>
42*00b67f09SDavid van Moolenbroek #include <isc/util.h>
43*00b67f09SDavid van Moolenbroek
44*00b67f09SDavid van Moolenbroek void InitSockets(void);
45*00b67f09SDavid van Moolenbroek
46*00b67f09SDavid van Moolenbroek /* Common utility functions */
47*00b67f09SDavid van Moolenbroek
48*00b67f09SDavid van Moolenbroek /*
49*00b67f09SDavid van Moolenbroek * Extract the network address part from a "struct sockaddr".
50*00b67f09SDavid van Moolenbroek *
51*00b67f09SDavid van Moolenbroek * The address family is given explicitly
52*00b67f09SDavid van Moolenbroek * instead of using src->sa_family, because the latter does not work
53*00b67f09SDavid van Moolenbroek * for copying a network mask obtained by SIOCGIFNETMASK (it does
54*00b67f09SDavid van Moolenbroek * not have a valid address family).
55*00b67f09SDavid van Moolenbroek */
56*00b67f09SDavid van Moolenbroek
57*00b67f09SDavid van Moolenbroek
58*00b67f09SDavid van Moolenbroek #define IFITER_MAGIC 0x49464954U /* IFIT. */
59*00b67f09SDavid van Moolenbroek #define VALID_IFITER(t) ((t) != NULL && (t)->magic == IFITER_MAGIC)
60*00b67f09SDavid van Moolenbroek
61*00b67f09SDavid van Moolenbroek struct isc_interfaceiter {
62*00b67f09SDavid van Moolenbroek unsigned int magic; /* Magic number. */
63*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
64*00b67f09SDavid van Moolenbroek SOCKET socket;
65*00b67f09SDavid van Moolenbroek INTERFACE_INFO IFData; /* Current Interface Info */
66*00b67f09SDavid van Moolenbroek int numIF; /* Current Interface count */
67*00b67f09SDavid van Moolenbroek int v4IF; /* Number of IPv4 Interfaces */
68*00b67f09SDavid van Moolenbroek INTERFACE_INFO *buf4; /* Buffer for WSAIoctl data. */
69*00b67f09SDavid van Moolenbroek unsigned int buf4size; /* Bytes allocated. */
70*00b67f09SDavid van Moolenbroek INTERFACE_INFO *pos4; /* Current offset in IF List */
71*00b67f09SDavid van Moolenbroek SOCKET_ADDRESS_LIST *buf6;
72*00b67f09SDavid van Moolenbroek unsigned int buf6size; /* Bytes allocated. */
73*00b67f09SDavid van Moolenbroek unsigned int pos6;
74*00b67f09SDavid van Moolenbroek isc_interface_t current; /* Current interface data. */
75*00b67f09SDavid van Moolenbroek isc_result_t result; /* Last result code. */
76*00b67f09SDavid van Moolenbroek };
77*00b67f09SDavid van Moolenbroek
78*00b67f09SDavid van Moolenbroek
79*00b67f09SDavid van Moolenbroek /*
80*00b67f09SDavid van Moolenbroek * Size of buffer for SIO_GET_INTERFACE_LIST, in number of interfaces.
81*00b67f09SDavid van Moolenbroek * We assume no sane system will have more than than 1K of IP addresses on
82*00b67f09SDavid van Moolenbroek * all of its adapters.
83*00b67f09SDavid van Moolenbroek */
84*00b67f09SDavid van Moolenbroek #define IFCONF_SIZE_INITIAL 16
85*00b67f09SDavid van Moolenbroek #define IFCONF_SIZE_INCREMENT 64
86*00b67f09SDavid van Moolenbroek #define IFCONF_SIZE_MAX 1040
87*00b67f09SDavid van Moolenbroek
88*00b67f09SDavid van Moolenbroek static void
get_addr(unsigned int family,isc_netaddr_t * dst,struct sockaddr * src)89*00b67f09SDavid van Moolenbroek get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) {
90*00b67f09SDavid van Moolenbroek dst->family = family;
91*00b67f09SDavid van Moolenbroek switch (family) {
92*00b67f09SDavid van Moolenbroek case AF_INET:
93*00b67f09SDavid van Moolenbroek memmove(&dst->type.in,
94*00b67f09SDavid van Moolenbroek &((struct sockaddr_in *) src)->sin_addr,
95*00b67f09SDavid van Moolenbroek sizeof(struct in_addr));
96*00b67f09SDavid van Moolenbroek break;
97*00b67f09SDavid van Moolenbroek case AF_INET6:
98*00b67f09SDavid van Moolenbroek memmove(&dst->type.in6,
99*00b67f09SDavid van Moolenbroek &((struct sockaddr_in6 *) src)->sin6_addr,
100*00b67f09SDavid van Moolenbroek sizeof(struct in6_addr));
101*00b67f09SDavid van Moolenbroek dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id;
102*00b67f09SDavid van Moolenbroek break;
103*00b67f09SDavid van Moolenbroek default:
104*00b67f09SDavid van Moolenbroek INSIST(0);
105*00b67f09SDavid van Moolenbroek break;
106*00b67f09SDavid van Moolenbroek }
107*00b67f09SDavid van Moolenbroek }
108*00b67f09SDavid van Moolenbroek
109*00b67f09SDavid van Moolenbroek isc_result_t
isc_interfaceiter_create(isc_mem_t * mctx,isc_interfaceiter_t ** iterp)110*00b67f09SDavid van Moolenbroek isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
111*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
112*00b67f09SDavid van Moolenbroek isc_interfaceiter_t *iter;
113*00b67f09SDavid van Moolenbroek isc_result_t result;
114*00b67f09SDavid van Moolenbroek int error;
115*00b67f09SDavid van Moolenbroek unsigned long bytesReturned = 0;
116*00b67f09SDavid van Moolenbroek
117*00b67f09SDavid van Moolenbroek REQUIRE(mctx != NULL);
118*00b67f09SDavid van Moolenbroek REQUIRE(iterp != NULL);
119*00b67f09SDavid van Moolenbroek REQUIRE(*iterp == NULL);
120*00b67f09SDavid van Moolenbroek
121*00b67f09SDavid van Moolenbroek iter = isc_mem_get(mctx, sizeof(*iter));
122*00b67f09SDavid van Moolenbroek if (iter == NULL)
123*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
124*00b67f09SDavid van Moolenbroek
125*00b67f09SDavid van Moolenbroek InitSockets();
126*00b67f09SDavid van Moolenbroek
127*00b67f09SDavid van Moolenbroek iter->mctx = mctx;
128*00b67f09SDavid van Moolenbroek iter->buf4 = NULL;
129*00b67f09SDavid van Moolenbroek iter->buf6 = NULL;
130*00b67f09SDavid van Moolenbroek iter->pos4 = NULL;
131*00b67f09SDavid van Moolenbroek iter->pos6 = 0;
132*00b67f09SDavid van Moolenbroek iter->buf6size = 0;
133*00b67f09SDavid van Moolenbroek iter->buf4size = 0;
134*00b67f09SDavid van Moolenbroek iter->result = ISC_R_FAILURE;
135*00b67f09SDavid van Moolenbroek iter->numIF = 0;
136*00b67f09SDavid van Moolenbroek iter->v4IF = 0;
137*00b67f09SDavid van Moolenbroek
138*00b67f09SDavid van Moolenbroek /*
139*00b67f09SDavid van Moolenbroek * Create an unbound datagram socket to do the
140*00b67f09SDavid van Moolenbroek * SIO_GET_INTERFACE_LIST WSAIoctl on.
141*00b67f09SDavid van Moolenbroek */
142*00b67f09SDavid van Moolenbroek iter->socket = socket(AF_INET, SOCK_DGRAM, 0);
143*00b67f09SDavid van Moolenbroek if (iter->socket == INVALID_SOCKET) {
144*00b67f09SDavid van Moolenbroek error = WSAGetLastError();
145*00b67f09SDavid van Moolenbroek if (error == WSAEAFNOSUPPORT)
146*00b67f09SDavid van Moolenbroek goto inet6_only;
147*00b67f09SDavid van Moolenbroek isc__strerror(error, strbuf, sizeof(strbuf));
148*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
149*00b67f09SDavid van Moolenbroek "making interface scan socket: %s",
150*00b67f09SDavid van Moolenbroek strbuf);
151*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
152*00b67f09SDavid van Moolenbroek goto socket_failure;
153*00b67f09SDavid van Moolenbroek }
154*00b67f09SDavid van Moolenbroek
155*00b67f09SDavid van Moolenbroek /*
156*00b67f09SDavid van Moolenbroek * Get the interface configuration, allocating more memory if
157*00b67f09SDavid van Moolenbroek * necessary.
158*00b67f09SDavid van Moolenbroek */
159*00b67f09SDavid van Moolenbroek iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO);
160*00b67f09SDavid van Moolenbroek
161*00b67f09SDavid van Moolenbroek for (;;) {
162*00b67f09SDavid van Moolenbroek iter->buf4 = isc_mem_get(mctx, iter->buf4size);
163*00b67f09SDavid van Moolenbroek if (iter->buf4 == NULL) {
164*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
165*00b67f09SDavid van Moolenbroek goto alloc_failure;
166*00b67f09SDavid van Moolenbroek }
167*00b67f09SDavid van Moolenbroek
168*00b67f09SDavid van Moolenbroek if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST,
169*00b67f09SDavid van Moolenbroek 0, 0, iter->buf4, iter->buf4size,
170*00b67f09SDavid van Moolenbroek &bytesReturned, 0, 0) == SOCKET_ERROR)
171*00b67f09SDavid van Moolenbroek {
172*00b67f09SDavid van Moolenbroek error = WSAGetLastError();
173*00b67f09SDavid van Moolenbroek if (error != WSAEFAULT && error != WSAENOBUFS) {
174*00b67f09SDavid van Moolenbroek errno = error;
175*00b67f09SDavid van Moolenbroek isc__strerror(error, strbuf, sizeof(strbuf));
176*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
177*00b67f09SDavid van Moolenbroek "get interface configuration: %s",
178*00b67f09SDavid van Moolenbroek strbuf);
179*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
180*00b67f09SDavid van Moolenbroek goto ioctl_failure;
181*00b67f09SDavid van Moolenbroek }
182*00b67f09SDavid van Moolenbroek /*
183*00b67f09SDavid van Moolenbroek * EINVAL. Retry with a bigger buffer.
184*00b67f09SDavid van Moolenbroek */
185*00b67f09SDavid van Moolenbroek } else {
186*00b67f09SDavid van Moolenbroek /*
187*00b67f09SDavid van Moolenbroek * The WSAIoctl succeeded.
188*00b67f09SDavid van Moolenbroek * If the number of the returned bytes is the same
189*00b67f09SDavid van Moolenbroek * as the buffer size, we will grow it just in
190*00b67f09SDavid van Moolenbroek * case and retry.
191*00b67f09SDavid van Moolenbroek */
192*00b67f09SDavid van Moolenbroek if (bytesReturned > 0 &&
193*00b67f09SDavid van Moolenbroek (bytesReturned < iter->buf4size))
194*00b67f09SDavid van Moolenbroek break;
195*00b67f09SDavid van Moolenbroek }
196*00b67f09SDavid van Moolenbroek if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) {
197*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
198*00b67f09SDavid van Moolenbroek "get interface configuration: "
199*00b67f09SDavid van Moolenbroek "maximum buffer size exceeded");
200*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
201*00b67f09SDavid van Moolenbroek goto ioctl_failure;
202*00b67f09SDavid van Moolenbroek }
203*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter->buf4, iter->buf4size);
204*00b67f09SDavid van Moolenbroek
205*00b67f09SDavid van Moolenbroek iter->buf4size += IFCONF_SIZE_INCREMENT *
206*00b67f09SDavid van Moolenbroek sizeof(INTERFACE_INFO);
207*00b67f09SDavid van Moolenbroek }
208*00b67f09SDavid van Moolenbroek
209*00b67f09SDavid van Moolenbroek /*
210*00b67f09SDavid van Moolenbroek * A newly created iterator has an undefined position
211*00b67f09SDavid van Moolenbroek * until isc_interfaceiter_first() is called.
212*00b67f09SDavid van Moolenbroek */
213*00b67f09SDavid van Moolenbroek iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO);
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek /* We don't need the socket any more, so close it */
216*00b67f09SDavid van Moolenbroek closesocket(iter->socket);
217*00b67f09SDavid van Moolenbroek
218*00b67f09SDavid van Moolenbroek inet6_only:
219*00b67f09SDavid van Moolenbroek /*
220*00b67f09SDavid van Moolenbroek * Create an unbound datagram socket to do the
221*00b67f09SDavid van Moolenbroek * SIO_ADDRESS_LIST_QUERY WSAIoctl on.
222*00b67f09SDavid van Moolenbroek */
223*00b67f09SDavid van Moolenbroek iter->socket = socket(AF_INET6, SOCK_DGRAM, 0);
224*00b67f09SDavid van Moolenbroek if (iter->socket == INVALID_SOCKET) {
225*00b67f09SDavid van Moolenbroek error = WSAGetLastError();
226*00b67f09SDavid van Moolenbroek if (error == WSAEAFNOSUPPORT)
227*00b67f09SDavid van Moolenbroek goto inet_only;
228*00b67f09SDavid van Moolenbroek isc__strerror(error, strbuf, sizeof(strbuf));
229*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
230*00b67f09SDavid van Moolenbroek "making interface scan socket: %s",
231*00b67f09SDavid van Moolenbroek strbuf);
232*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
233*00b67f09SDavid van Moolenbroek goto ioctl_failure;
234*00b67f09SDavid van Moolenbroek }
235*00b67f09SDavid van Moolenbroek
236*00b67f09SDavid van Moolenbroek /*
237*00b67f09SDavid van Moolenbroek * Get the interface configuration, allocating more memory if
238*00b67f09SDavid van Moolenbroek * necessary.
239*00b67f09SDavid van Moolenbroek */
240*00b67f09SDavid van Moolenbroek iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) +
241*00b67f09SDavid van Moolenbroek IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS);
242*00b67f09SDavid van Moolenbroek
243*00b67f09SDavid van Moolenbroek for (;;) {
244*00b67f09SDavid van Moolenbroek iter->buf6 = isc_mem_get(mctx, iter->buf6size);
245*00b67f09SDavid van Moolenbroek if (iter->buf6 == NULL) {
246*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
247*00b67f09SDavid van Moolenbroek goto ioctl_failure;
248*00b67f09SDavid van Moolenbroek }
249*00b67f09SDavid van Moolenbroek
250*00b67f09SDavid van Moolenbroek if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY,
251*00b67f09SDavid van Moolenbroek 0, 0, iter->buf6, iter->buf6size,
252*00b67f09SDavid van Moolenbroek &bytesReturned, 0, 0) == SOCKET_ERROR)
253*00b67f09SDavid van Moolenbroek {
254*00b67f09SDavid van Moolenbroek error = WSAGetLastError();
255*00b67f09SDavid van Moolenbroek if (error != WSAEFAULT && error != WSAENOBUFS) {
256*00b67f09SDavid van Moolenbroek errno = error;
257*00b67f09SDavid van Moolenbroek isc__strerror(error, strbuf, sizeof(strbuf));
258*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
259*00b67f09SDavid van Moolenbroek "sio address list query: %s",
260*00b67f09SDavid van Moolenbroek strbuf);
261*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
262*00b67f09SDavid van Moolenbroek goto ioctl6_failure;
263*00b67f09SDavid van Moolenbroek }
264*00b67f09SDavid van Moolenbroek /*
265*00b67f09SDavid van Moolenbroek * EINVAL. Retry with a bigger buffer.
266*00b67f09SDavid van Moolenbroek */
267*00b67f09SDavid van Moolenbroek } else
268*00b67f09SDavid van Moolenbroek break;
269*00b67f09SDavid van Moolenbroek
270*00b67f09SDavid van Moolenbroek if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) {
271*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
272*00b67f09SDavid van Moolenbroek "get interface configuration: "
273*00b67f09SDavid van Moolenbroek "maximum buffer size exceeded");
274*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
275*00b67f09SDavid van Moolenbroek goto ioctl6_failure;
276*00b67f09SDavid van Moolenbroek }
277*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter->buf6, iter->buf6size);
278*00b67f09SDavid van Moolenbroek
279*00b67f09SDavid van Moolenbroek iter->buf6size += IFCONF_SIZE_INCREMENT *
280*00b67f09SDavid van Moolenbroek sizeof(SOCKET_ADDRESS);
281*00b67f09SDavid van Moolenbroek }
282*00b67f09SDavid van Moolenbroek
283*00b67f09SDavid van Moolenbroek closesocket(iter->socket);
284*00b67f09SDavid van Moolenbroek
285*00b67f09SDavid van Moolenbroek inet_only:
286*00b67f09SDavid van Moolenbroek iter->magic = IFITER_MAGIC;
287*00b67f09SDavid van Moolenbroek *iterp = iter;
288*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
289*00b67f09SDavid van Moolenbroek
290*00b67f09SDavid van Moolenbroek ioctl6_failure:
291*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter->buf6, iter->buf6size);
292*00b67f09SDavid van Moolenbroek
293*00b67f09SDavid van Moolenbroek ioctl_failure:
294*00b67f09SDavid van Moolenbroek if (iter->buf4 != NULL)
295*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter->buf4, iter->buf4size);
296*00b67f09SDavid van Moolenbroek
297*00b67f09SDavid van Moolenbroek alloc_failure:
298*00b67f09SDavid van Moolenbroek if (iter->socket != INVALID_SOCKET)
299*00b67f09SDavid van Moolenbroek (void) closesocket(iter->socket);
300*00b67f09SDavid van Moolenbroek
301*00b67f09SDavid van Moolenbroek socket_failure:
302*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, iter, sizeof(*iter));
303*00b67f09SDavid van Moolenbroek return (result);
304*00b67f09SDavid van Moolenbroek }
305*00b67f09SDavid van Moolenbroek
306*00b67f09SDavid van Moolenbroek /*
307*00b67f09SDavid van Moolenbroek * Get information about the current interface to iter->current.
308*00b67f09SDavid van Moolenbroek * If successful, return ISC_R_SUCCESS.
309*00b67f09SDavid van Moolenbroek * If the interface has an unsupported address family, or if
310*00b67f09SDavid van Moolenbroek * some operation on it fails, return ISC_R_IGNORE to make
311*00b67f09SDavid van Moolenbroek * the higher-level iterator code ignore it.
312*00b67f09SDavid van Moolenbroek */
313*00b67f09SDavid van Moolenbroek
314*00b67f09SDavid van Moolenbroek static isc_result_t
internal_current(isc_interfaceiter_t * iter)315*00b67f09SDavid van Moolenbroek internal_current(isc_interfaceiter_t *iter) {
316*00b67f09SDavid van Moolenbroek BOOL ifNamed = FALSE;
317*00b67f09SDavid van Moolenbroek unsigned long flags;
318*00b67f09SDavid van Moolenbroek
319*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
320*00b67f09SDavid van Moolenbroek REQUIRE(iter->numIF >= 0);
321*00b67f09SDavid van Moolenbroek
322*00b67f09SDavid van Moolenbroek memset(&iter->current, 0, sizeof(iter->current));
323*00b67f09SDavid van Moolenbroek iter->current.af = AF_INET;
324*00b67f09SDavid van Moolenbroek
325*00b67f09SDavid van Moolenbroek get_addr(AF_INET, &iter->current.address,
326*00b67f09SDavid van Moolenbroek (struct sockaddr *)&(iter->IFData.iiAddress));
327*00b67f09SDavid van Moolenbroek
328*00b67f09SDavid van Moolenbroek /*
329*00b67f09SDavid van Moolenbroek * Get interface flags.
330*00b67f09SDavid van Moolenbroek */
331*00b67f09SDavid van Moolenbroek
332*00b67f09SDavid van Moolenbroek iter->current.flags = 0;
333*00b67f09SDavid van Moolenbroek flags = iter->IFData.iiFlags;
334*00b67f09SDavid van Moolenbroek
335*00b67f09SDavid van Moolenbroek if ((flags & IFF_UP) != 0)
336*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_UP;
337*00b67f09SDavid van Moolenbroek
338*00b67f09SDavid van Moolenbroek if ((flags & IFF_POINTTOPOINT) != 0) {
339*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_POINTTOPOINT;
340*00b67f09SDavid van Moolenbroek sprintf(iter->current.name, "PPP Interface %d", iter->numIF);
341*00b67f09SDavid van Moolenbroek ifNamed = TRUE;
342*00b67f09SDavid van Moolenbroek }
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek if ((flags & IFF_LOOPBACK) != 0) {
345*00b67f09SDavid van Moolenbroek iter->current.flags |= INTERFACE_F_LOOPBACK;
346*00b67f09SDavid van Moolenbroek sprintf(iter->current.name, "Loopback Interface %d",
347*00b67f09SDavid van Moolenbroek iter->numIF);
348*00b67f09SDavid van Moolenbroek ifNamed = TRUE;
349*00b67f09SDavid van Moolenbroek }
350*00b67f09SDavid van Moolenbroek
351*00b67f09SDavid van Moolenbroek /*
352*00b67f09SDavid van Moolenbroek * If the interface is point-to-point, get the destination address.
353*00b67f09SDavid van Moolenbroek */
354*00b67f09SDavid van Moolenbroek if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
355*00b67f09SDavid van Moolenbroek get_addr(AF_INET, &iter->current.dstaddress,
356*00b67f09SDavid van Moolenbroek (struct sockaddr *)&(iter->IFData.iiBroadcastAddress));
357*00b67f09SDavid van Moolenbroek }
358*00b67f09SDavid van Moolenbroek
359*00b67f09SDavid van Moolenbroek if (ifNamed == FALSE)
360*00b67f09SDavid van Moolenbroek sprintf(iter->current.name,
361*00b67f09SDavid van Moolenbroek "TCP/IP Interface %d", iter->numIF);
362*00b67f09SDavid van Moolenbroek
363*00b67f09SDavid van Moolenbroek /*
364*00b67f09SDavid van Moolenbroek * Get the network mask.
365*00b67f09SDavid van Moolenbroek */
366*00b67f09SDavid van Moolenbroek get_addr(AF_INET, &iter->current.netmask,
367*00b67f09SDavid van Moolenbroek (struct sockaddr *)&(iter->IFData.iiNetmask));
368*00b67f09SDavid van Moolenbroek
369*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
370*00b67f09SDavid van Moolenbroek }
371*00b67f09SDavid van Moolenbroek
372*00b67f09SDavid van Moolenbroek static isc_result_t
internal_current6(isc_interfaceiter_t * iter)373*00b67f09SDavid van Moolenbroek internal_current6(isc_interfaceiter_t *iter) {
374*00b67f09SDavid van Moolenbroek BOOL ifNamed = FALSE;
375*00b67f09SDavid van Moolenbroek int i;
376*00b67f09SDavid van Moolenbroek
377*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
378*00b67f09SDavid van Moolenbroek REQUIRE(iter->pos6 >= 0);
379*00b67f09SDavid van Moolenbroek REQUIRE(iter->buf6 != 0);
380*00b67f09SDavid van Moolenbroek
381*00b67f09SDavid van Moolenbroek memset(&iter->current, 0, sizeof(iter->current));
382*00b67f09SDavid van Moolenbroek iter->current.af = AF_INET6;
383*00b67f09SDavid van Moolenbroek
384*00b67f09SDavid van Moolenbroek get_addr(AF_INET6, &iter->current.address,
385*00b67f09SDavid van Moolenbroek iter->buf6->Address[iter->pos6].lpSockaddr);
386*00b67f09SDavid van Moolenbroek
387*00b67f09SDavid van Moolenbroek /*
388*00b67f09SDavid van Moolenbroek * Get interface flags.
389*00b67f09SDavid van Moolenbroek */
390*00b67f09SDavid van Moolenbroek
391*00b67f09SDavid van Moolenbroek iter->current.flags = INTERFACE_F_UP;
392*00b67f09SDavid van Moolenbroek
393*00b67f09SDavid van Moolenbroek if (ifNamed == FALSE)
394*00b67f09SDavid van Moolenbroek sprintf(iter->current.name,
395*00b67f09SDavid van Moolenbroek "TCP/IPv6 Interface %d", iter->pos6 + 1);
396*00b67f09SDavid van Moolenbroek
397*00b67f09SDavid van Moolenbroek for (i = 0; i< 16; i++)
398*00b67f09SDavid van Moolenbroek iter->current.netmask.type.in6.s6_addr[i] = 0xff;
399*00b67f09SDavid van Moolenbroek iter->current.netmask.family = AF_INET6;
400*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
401*00b67f09SDavid van Moolenbroek }
402*00b67f09SDavid van Moolenbroek
403*00b67f09SDavid van Moolenbroek /*
404*00b67f09SDavid van Moolenbroek * Step the iterator to the next interface. Unlike
405*00b67f09SDavid van Moolenbroek * isc_interfaceiter_next(), this may leave the iterator
406*00b67f09SDavid van Moolenbroek * positioned on an interface that will ultimately
407*00b67f09SDavid van Moolenbroek * be ignored. Return ISC_R_NOMORE if there are no more
408*00b67f09SDavid van Moolenbroek * interfaces, otherwise ISC_R_SUCCESS.
409*00b67f09SDavid van Moolenbroek */
410*00b67f09SDavid van Moolenbroek static isc_result_t
internal_next(isc_interfaceiter_t * iter)411*00b67f09SDavid van Moolenbroek internal_next(isc_interfaceiter_t *iter) {
412*00b67f09SDavid van Moolenbroek if (iter->numIF >= iter->v4IF)
413*00b67f09SDavid van Moolenbroek return (ISC_R_NOMORE);
414*00b67f09SDavid van Moolenbroek
415*00b67f09SDavid van Moolenbroek /*
416*00b67f09SDavid van Moolenbroek * The first one needs to be set up to point to the last
417*00b67f09SDavid van Moolenbroek * Element of the array. Go to the end and back up
418*00b67f09SDavid van Moolenbroek * Microsoft's implementation is peculiar for returning
419*00b67f09SDavid van Moolenbroek * the list in reverse order
420*00b67f09SDavid van Moolenbroek */
421*00b67f09SDavid van Moolenbroek
422*00b67f09SDavid van Moolenbroek if (iter->numIF == 0)
423*00b67f09SDavid van Moolenbroek iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF));
424*00b67f09SDavid van Moolenbroek
425*00b67f09SDavid van Moolenbroek iter->pos4--;
426*00b67f09SDavid van Moolenbroek if (&(iter->pos4) < &(iter->buf4))
427*00b67f09SDavid van Moolenbroek return (ISC_R_NOMORE);
428*00b67f09SDavid van Moolenbroek
429*00b67f09SDavid van Moolenbroek memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO));
430*00b67f09SDavid van Moolenbroek memmove(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO));
431*00b67f09SDavid van Moolenbroek iter->numIF++;
432*00b67f09SDavid van Moolenbroek
433*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
434*00b67f09SDavid van Moolenbroek }
435*00b67f09SDavid van Moolenbroek
436*00b67f09SDavid van Moolenbroek static isc_result_t
internal_next6(isc_interfaceiter_t * iter)437*00b67f09SDavid van Moolenbroek internal_next6(isc_interfaceiter_t *iter) {
438*00b67f09SDavid van Moolenbroek if (iter->pos6 == 0)
439*00b67f09SDavid van Moolenbroek return (ISC_R_NOMORE);
440*00b67f09SDavid van Moolenbroek iter->pos6--;
441*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
442*00b67f09SDavid van Moolenbroek }
443*00b67f09SDavid van Moolenbroek
444*00b67f09SDavid van Moolenbroek isc_result_t
isc_interfaceiter_current(isc_interfaceiter_t * iter,isc_interface_t * ifdata)445*00b67f09SDavid van Moolenbroek isc_interfaceiter_current(isc_interfaceiter_t *iter,
446*00b67f09SDavid van Moolenbroek isc_interface_t *ifdata) {
447*00b67f09SDavid van Moolenbroek REQUIRE(iter->result == ISC_R_SUCCESS);
448*00b67f09SDavid van Moolenbroek memmove(ifdata, &iter->current, sizeof(*ifdata));
449*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
450*00b67f09SDavid van Moolenbroek }
451*00b67f09SDavid van Moolenbroek
452*00b67f09SDavid van Moolenbroek isc_result_t
isc_interfaceiter_first(isc_interfaceiter_t * iter)453*00b67f09SDavid van Moolenbroek isc_interfaceiter_first(isc_interfaceiter_t *iter) {
454*00b67f09SDavid van Moolenbroek
455*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
456*00b67f09SDavid van Moolenbroek
457*00b67f09SDavid van Moolenbroek if (iter->buf6 != NULL)
458*00b67f09SDavid van Moolenbroek iter->pos6 = iter->buf6->iAddressCount;
459*00b67f09SDavid van Moolenbroek iter->result = ISC_R_SUCCESS;
460*00b67f09SDavid van Moolenbroek return (isc_interfaceiter_next(iter));
461*00b67f09SDavid van Moolenbroek }
462*00b67f09SDavid van Moolenbroek
463*00b67f09SDavid van Moolenbroek isc_result_t
isc_interfaceiter_next(isc_interfaceiter_t * iter)464*00b67f09SDavid van Moolenbroek isc_interfaceiter_next(isc_interfaceiter_t *iter) {
465*00b67f09SDavid van Moolenbroek isc_result_t result;
466*00b67f09SDavid van Moolenbroek
467*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
468*00b67f09SDavid van Moolenbroek REQUIRE(iter->result == ISC_R_SUCCESS);
469*00b67f09SDavid van Moolenbroek
470*00b67f09SDavid van Moolenbroek for (;;) {
471*00b67f09SDavid van Moolenbroek result = internal_next(iter);
472*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE) {
473*00b67f09SDavid van Moolenbroek result = internal_next6(iter);
474*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
475*00b67f09SDavid van Moolenbroek break;
476*00b67f09SDavid van Moolenbroek result = internal_current6(iter);
477*00b67f09SDavid van Moolenbroek if (result != ISC_R_IGNORE)
478*00b67f09SDavid van Moolenbroek break;
479*00b67f09SDavid van Moolenbroek } else if (result != ISC_R_SUCCESS)
480*00b67f09SDavid van Moolenbroek break;
481*00b67f09SDavid van Moolenbroek result = internal_current(iter);
482*00b67f09SDavid van Moolenbroek if (result != ISC_R_IGNORE)
483*00b67f09SDavid van Moolenbroek break;
484*00b67f09SDavid van Moolenbroek }
485*00b67f09SDavid van Moolenbroek iter->result = result;
486*00b67f09SDavid van Moolenbroek return (result);
487*00b67f09SDavid van Moolenbroek }
488*00b67f09SDavid van Moolenbroek
489*00b67f09SDavid van Moolenbroek void
isc_interfaceiter_destroy(isc_interfaceiter_t ** iterp)490*00b67f09SDavid van Moolenbroek isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
491*00b67f09SDavid van Moolenbroek isc_interfaceiter_t *iter;
492*00b67f09SDavid van Moolenbroek REQUIRE(iterp != NULL);
493*00b67f09SDavid van Moolenbroek iter = *iterp;
494*00b67f09SDavid van Moolenbroek REQUIRE(VALID_IFITER(iter));
495*00b67f09SDavid van Moolenbroek
496*00b67f09SDavid van Moolenbroek if (iter->buf4 != NULL)
497*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf4, iter->buf4size);
498*00b67f09SDavid van Moolenbroek if (iter->buf6 != NULL)
499*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter->buf6, iter->buf6size);
500*00b67f09SDavid van Moolenbroek
501*00b67f09SDavid van Moolenbroek iter->magic = 0;
502*00b67f09SDavid van Moolenbroek isc_mem_put(iter->mctx, iter, sizeof(*iter));
503*00b67f09SDavid van Moolenbroek *iterp = NULL;
504*00b67f09SDavid van Moolenbroek }
505