Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
12 | | notice, this list of conditions and the following disclaimer in the | | ||
13 | | documentation and/or other materials provided with the distribution. | | ||
14 | | | | ||
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | #include "gate/system/netconfigs.h" | ||
30 | #include "gate/results.h" | ||
31 | |||
32 | #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_WINSTORE) || defined(GATE_SYS_WIN16) || defined(GATE_SYS_BEOS) | ||
33 | # define GATE_SYSTEM_NETCONFIG_NO_IMPL 1 | ||
34 | #elif defined(GATE_SYS_WIN) | ||
35 | # define GATE_SYSTEM_NETCONFIG_WINAPI_IMPL 1 | ||
36 | #elif defined(GATE_SYS_POSIX) | ||
37 | # define GATE_SYSTEM_NETCONFIG_POSIX_IMPL 1 | ||
38 | #else | ||
39 | # define GATE_SYSTEM_NETCONFIG_NO_IMPL 1 | ||
40 | #endif | ||
41 | |||
42 | |||
43 | ✗ | char const* gate_netconfig_print_status(gate_enumint_t status) | |
44 | { | ||
45 | ✗ | switch (status) | |
46 | { | ||
47 | ✗ | case GATE_NETCONFIG_STATUS_UNKNOWN: return "Unknown"; | |
48 | ✗ | case GATE_NETCONFIG_STATUS_DISABLED: return "Disabled"; | |
49 | ✗ | case GATE_NETCONFIG_STATUS_ENABLED: return "Enabled"; | |
50 | ✗ | case GATE_NETCONFIG_STATUS_NONFUNCT: return "Non-functional"; | |
51 | ✗ | case GATE_NETCONFIG_STATUS_OPERATIONAL: return "Operational"; | |
52 | ✗ | case GATE_NETCONFIG_STATUS_CONNECTING: return "Connecting"; | |
53 | ✗ | case GATE_NETCONFIG_STATUS_CONNECTED: return "Connected"; | |
54 | ✗ | case GATE_NETCONFIG_STATUS_DISCONNECTED: return "Disconnected"; | |
55 | ✗ | case GATE_NETCONFIG_STATUS_ERROR: return "Error"; | |
56 | } | ||
57 | ✗ | return NULL; | |
58 | } | ||
59 | |||
60 | ✗ | char const* gate_netconfig_print_type(gate_enumint_t tp) | |
61 | { | ||
62 | ✗ | switch (tp) | |
63 | { | ||
64 | ✗ | case GATE_NETCONFIG_TYPE_UNKNOWN: return "Unknown"; | |
65 | ✗ | case GATE_NETCONFIG_TYPE_ETHERNET: return "Ethernet"; | |
66 | ✗ | case GATE_NETCONFIG_TYPE_TOKENRING: return "Tokenring"; | |
67 | ✗ | case GATE_NETCONFIG_TYPE_FDDI: return "FDDI"; | |
68 | ✗ | case GATE_NETCONFIG_TYPE_PPP: return "PPP"; | |
69 | ✗ | case GATE_NETCONFIG_TYPE_LOOPBACK: return "Loopback"; | |
70 | ✗ | case GATE_NETCONFIG_TYPE_WLAN: return "WLAN"; | |
71 | ✗ | case GATE_NETCONFIG_TYPE_SLIP: return "SLIP"; | |
72 | ✗ | case GATE_NETCONFIG_TYPE_OTHER: return "Other"; | |
73 | } | ||
74 | ✗ | return NULL; | |
75 | } | ||
76 | |||
77 | |||
78 | |||
79 | #if defined(GATE_SYSTEM_NETCONFIG_WINAPI_IMPL) | ||
80 | |||
81 | #include "gate/net/platform/socket_api.h" | ||
82 | #include "gate/platforms.h" | ||
83 | |||
84 | //#include <iphlpapi.h> | ||
85 | |||
86 | typedef enum | ||
87 | { | ||
88 | IpPrefixOriginOther = 0, | ||
89 | IpPrefixOriginManual, | ||
90 | IpPrefixOriginWellKnown, | ||
91 | IpPrefixOriginDhcp, | ||
92 | IpPrefixOriginRouterAdvertisement | ||
93 | } IP_PREFIX_ORIGIN; | ||
94 | |||
95 | typedef enum | ||
96 | { | ||
97 | IpSuffixOriginOther = 0, | ||
98 | IpSuffixOriginManual, | ||
99 | IpSuffixOriginWellKnown, | ||
100 | IpSuffixOriginDhcp, | ||
101 | IpSuffixOriginLinkLayerAddress, | ||
102 | IpSuffixOriginRandom | ||
103 | } IP_SUFFIX_ORIGIN; | ||
104 | |||
105 | typedef enum | ||
106 | { | ||
107 | IpDadStateInvalid = 0, | ||
108 | IpDadStateTentative, | ||
109 | IpDadStateDuplicate, | ||
110 | IpDadStateDeprecated, | ||
111 | IpDadStatePreferred | ||
112 | } IP_DAD_STATE; | ||
113 | |||
114 | #if defined(GATE_COMPILER_MSVC98) | ||
115 | typedef gate_unsigned_long_long_t UINT8; | ||
116 | #endif | ||
117 | |||
118 | typedef struct _IP_ADAPTER_UNICAST_ADDRESS | ||
119 | { | ||
120 | union | ||
121 | { | ||
122 | struct | ||
123 | { | ||
124 | ULONG Length; | ||
125 | DWORD Flags; | ||
126 | }; | ||
127 | }; | ||
128 | struct _IP_ADAPTER_UNICAST_ADDRESS* Next; | ||
129 | SOCKET_ADDRESS Address; | ||
130 | IP_PREFIX_ORIGIN PrefixOrigin; | ||
131 | IP_SUFFIX_ORIGIN SuffixOrigin; | ||
132 | IP_DAD_STATE DadState; | ||
133 | ULONG ValidLifetime; | ||
134 | ULONG PreferredLifetime; | ||
135 | ULONG LeaseLifetime; | ||
136 | UINT8 OnLinkPrefixLength; /* only on Vista+ */ | ||
137 | } IP_ADAPTER_UNICAST_ADDRESS, * PIP_ADAPTER_UNICAST_ADDRESS; | ||
138 | |||
139 | typedef struct _IP_ADAPTER_ANYCAST_ADDRESS | ||
140 | { | ||
141 | union | ||
142 | { | ||
143 | ULONGLONG Alignment; | ||
144 | struct | ||
145 | { | ||
146 | ULONG Length; | ||
147 | DWORD Flags; | ||
148 | }; | ||
149 | }; | ||
150 | struct _IP_ADAPTER_ANYCAST_ADDRESS* Next; | ||
151 | SOCKET_ADDRESS Address; | ||
152 | } IP_ADAPTER_ANYCAST_ADDRESS, * PIP_ADAPTER_ANYCAST_ADDRESS; | ||
153 | |||
154 | typedef struct _IP_ADAPTER_MULTICAST_ADDRESS | ||
155 | { | ||
156 | union | ||
157 | { | ||
158 | ULONGLONG Alignment; | ||
159 | struct | ||
160 | { | ||
161 | ULONG Length; | ||
162 | DWORD Flags; | ||
163 | }; | ||
164 | }; | ||
165 | struct _IP_ADAPTER_MULTICAST_ADDRESS* Next; | ||
166 | SOCKET_ADDRESS Address; | ||
167 | } IP_ADAPTER_MULTICAST_ADDRESS, * PIP_ADAPTER_MULTICAST_ADDRESS; | ||
168 | |||
169 | typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS | ||
170 | { | ||
171 | union | ||
172 | { | ||
173 | ULONGLONG Alignment; | ||
174 | struct | ||
175 | { | ||
176 | ULONG Length; | ||
177 | DWORD Reserved; | ||
178 | }; | ||
179 | }; | ||
180 | struct _IP_ADAPTER_DNS_SERVER_ADDRESS* Next; | ||
181 | SOCKET_ADDRESS Address; | ||
182 | } IP_ADAPTER_DNS_SERVER_ADDRESS, * PIP_ADAPTER_DNS_SERVER_ADDRESS; | ||
183 | |||
184 | typedef enum | ||
185 | { | ||
186 | IfOperStatusUp = 1, | ||
187 | IfOperStatusDown, | ||
188 | IfOperStatusTesting, | ||
189 | IfOperStatusUnknown, | ||
190 | IfOperStatusDormant, | ||
191 | IfOperStatusNotPresent, | ||
192 | IfOperStatusLowerLayerDown | ||
193 | } IF_OPER_STATUS; | ||
194 | |||
195 | typedef struct _IP_ADAPTER_PREFIX { | ||
196 | union | ||
197 | { | ||
198 | ULONGLONG Alignment; | ||
199 | struct | ||
200 | { | ||
201 | ULONG Length; | ||
202 | DWORD Flags; | ||
203 | }; | ||
204 | }; | ||
205 | struct _IP_ADAPTER_PREFIX* Next; | ||
206 | SOCKET_ADDRESS Address; | ||
207 | ULONG PrefixLength; | ||
208 | } IP_ADAPTER_PREFIX, * PIP_ADAPTER_PREFIX; | ||
209 | |||
210 | #ifndef MAX_ADAPTER_DESCRIPTION_LENGTH | ||
211 | #define MAX_ADAPTER_DESCRIPTION_LENGTH 128 | ||
212 | #endif | ||
213 | |||
214 | #ifndef MAX_ADAPTER_NAME_LENGTH | ||
215 | #define MAX_ADAPTER_NAME_LENGTH 256 | ||
216 | #endif | ||
217 | |||
218 | #ifndef MAX_ADAPTER_ADDRESS_LENGTH | ||
219 | #define MAX_ADAPTER_ADDRESS_LENGTH 8 | ||
220 | #endif | ||
221 | |||
222 | typedef struct _GATE_IP_ADAPTER_ADDRESSES | ||
223 | { | ||
224 | union | ||
225 | { | ||
226 | ULONGLONG Alignment; | ||
227 | struct | ||
228 | { | ||
229 | ULONG Length; | ||
230 | DWORD IfIndex; | ||
231 | }; | ||
232 | }; | ||
233 | struct _GATE_IP_ADAPTER_ADDRESSES* Next; | ||
234 | PCHAR AdapterName; | ||
235 | PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; | ||
236 | PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; | ||
237 | PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; | ||
238 | PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; | ||
239 | PWCHAR DnsSuffix; | ||
240 | PWCHAR Description; | ||
241 | PWCHAR FriendlyName; | ||
242 | BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; | ||
243 | DWORD PhysicalAddressLength; | ||
244 | union | ||
245 | { | ||
246 | DWORD Flags; | ||
247 | struct { | ||
248 | ULONG DdnsEnabled : 1; | ||
249 | ULONG RegisterAdapterSuffix : 1; | ||
250 | ULONG Dhcpv4Enabled : 1; | ||
251 | ULONG ReceiveOnly : 1; | ||
252 | ULONG NoMulticast : 1; | ||
253 | ULONG Ipv6OtherStatefulConfig : 1; | ||
254 | ULONG NetbiosOverTcpipEnabled : 1; | ||
255 | ULONG Ipv4Enabled : 1; | ||
256 | ULONG Ipv6Enabled : 1; | ||
257 | ULONG Ipv6ManagedAddressConfigurationSupported : 1; | ||
258 | }; | ||
259 | }; | ||
260 | DWORD Mtu; | ||
261 | DWORD IfType; | ||
262 | IF_OPER_STATUS OperStatus; | ||
263 | DWORD Ipv6IfIndex; | ||
264 | DWORD ZoneIndices[16]; | ||
265 | PIP_ADAPTER_PREFIX FirstPrefix; | ||
266 | } IP_ADAPTER_ADDRESSES, * PIP_ADAPTER_ADDRESSES; | ||
267 | |||
268 | typedef struct { | ||
269 | char String[4 * 4]; | ||
270 | } IP_ADDRESS_STRING, * PIP_ADDRESS_STRING, IP_MASK_STRING, * PIP_MASK_STRING; | ||
271 | |||
272 | |||
273 | typedef struct _IP_ADDR_STRING { | ||
274 | struct _IP_ADDR_STRING* Next; | ||
275 | IP_ADDRESS_STRING IpAddress; | ||
276 | IP_MASK_STRING IpMask; | ||
277 | DWORD Context; | ||
278 | } IP_ADDR_STRING, * PIP_ADDR_STRING; | ||
279 | |||
280 | |||
281 | typedef struct _IP_ADAPTER_INFO | ||
282 | { | ||
283 | struct _IP_ADAPTER_INFO* Next; | ||
284 | DWORD ComboIndex; | ||
285 | char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; | ||
286 | char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; | ||
287 | UINT AddressLength; | ||
288 | BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; | ||
289 | DWORD Index; | ||
290 | UINT Type; | ||
291 | UINT DhcpEnabled; | ||
292 | PIP_ADDR_STRING CurrentIpAddress; | ||
293 | IP_ADDR_STRING IpAddressList; | ||
294 | IP_ADDR_STRING GatewayList; | ||
295 | IP_ADDR_STRING DhcpServer; | ||
296 | BOOL HaveWins; | ||
297 | IP_ADDR_STRING PrimaryWinsServer; | ||
298 | IP_ADDR_STRING SecondaryWinsServer; | ||
299 | time_t LeaseObtained; | ||
300 | time_t LeaseExpires; | ||
301 | } IP_ADAPTER_INFO, * PIP_ADAPTER_INFO; | ||
302 | |||
303 | #ifndef MAX_INTERFACE_NAME_LEN | ||
304 | #define MAX_INTERFACE_NAME_LEN 256 | ||
305 | #endif | ||
306 | |||
307 | #ifndef MAXLEN_PHYSADDR | ||
308 | #define MAXLEN_PHYSADDR 8 | ||
309 | #endif | ||
310 | |||
311 | #ifndef MAXLEN_IFDESCR | ||
312 | #define MAXLEN_IFDESCR 256 | ||
313 | #endif | ||
314 | |||
315 | #ifndef ANY_SIZE | ||
316 | #define ANY_SIZE 1 | ||
317 | #endif | ||
318 | |||
319 | typedef struct _MIB_IFROW { | ||
320 | WCHAR wszName[MAX_INTERFACE_NAME_LEN]; | ||
321 | DWORD dwIndex; | ||
322 | DWORD dwType; | ||
323 | DWORD dwMtu; | ||
324 | DWORD dwSpeed; | ||
325 | DWORD dwPhysAddrLen; | ||
326 | BYTE bPhysAddr[MAXLEN_PHYSADDR]; | ||
327 | DWORD dwAdminStatus; | ||
328 | DWORD dwOperStatus; | ||
329 | DWORD dwLastChange; | ||
330 | DWORD dwInOctets; | ||
331 | DWORD dwInUcastPkts; | ||
332 | DWORD dwInNUcastPkts; | ||
333 | DWORD dwInDiscards; | ||
334 | DWORD dwInErrors; | ||
335 | DWORD dwInUnknownProtos; | ||
336 | DWORD dwOutOctets; | ||
337 | DWORD dwOutUcastPkts; | ||
338 | DWORD dwOutNUcastPkts; | ||
339 | DWORD dwOutDiscards; | ||
340 | DWORD dwOutErrors; | ||
341 | DWORD dwOutQLen; | ||
342 | DWORD dwDescrLen; | ||
343 | BYTE bDescr[MAXLEN_IFDESCR]; | ||
344 | } MIB_IFROW, * PMIB_IFROW; | ||
345 | |||
346 | |||
347 | typedef struct _MIB_IFTABLE | ||
348 | { | ||
349 | DWORD dwNumEntries; | ||
350 | MIB_IFROW table[ANY_SIZE]; | ||
351 | } MIB_IFTABLE, * PMIB_IFTABLE; | ||
352 | |||
353 | typedef union _NET_LUID_LH | ||
354 | { | ||
355 | ULONG64 Value; | ||
356 | struct | ||
357 | { | ||
358 | ULONG64 Reserved : 24; | ||
359 | ULONG64 NetLuidIndex : 24; | ||
360 | ULONG64 IfType : 16; | ||
361 | }Info; | ||
362 | } NET_LUID_LH, * PNET_LUID_LH; | ||
363 | |||
364 | typedef NET_LUID_LH NET_LUID; | ||
365 | typedef NET_LUID* PNET_LUID; | ||
366 | |||
367 | typedef ULONG NET_IFINDEX, * PNET_IFINDEX; | ||
368 | #if defined(GATE_COMPILER_MSVC98) | ||
369 | typedef USHORT NET_IFTYPE, * PNET_IFTYPE; | ||
370 | #else | ||
371 | typedef UINT16 NET_IFTYPE, * PNET_IFTYPE; | ||
372 | #endif | ||
373 | |||
374 | #define IF_MAX_STRING_SIZE 256 | ||
375 | #define IF_MAX_PHYS_ADDRESS_LENGTH 32 | ||
376 | |||
377 | typedef ULONG IFTYPE; | ||
378 | |||
379 | typedef enum { | ||
380 | TUNNEL_TYPE_NONE = 0, | ||
381 | TUNNEL_TYPE_OTHER = 1, | ||
382 | TUNNEL_TYPE_DIRECT = 2, | ||
383 | TUNNEL_TYPE_6TO4 = 11, | ||
384 | TUNNEL_TYPE_ISATAP = 13, | ||
385 | TUNNEL_TYPE_TEREDO = 14, | ||
386 | TUNNEL_TYPE_IPHTTPS = 15, | ||
387 | } TUNNEL_TYPE, * PTUNNEL_TYPE; | ||
388 | |||
389 | typedef enum _NDIS_MEDIUM | ||
390 | { | ||
391 | NdisMedium802_3, | ||
392 | NdisMedium802_5, | ||
393 | NdisMediumFddi, | ||
394 | NdisMediumWan, | ||
395 | NdisMediumLocalTalk, | ||
396 | NdisMediumDix, // defined for convenience, not a real medium | ||
397 | NdisMediumArcnetRaw, | ||
398 | NdisMediumArcnet878_2, | ||
399 | NdisMediumAtm, | ||
400 | NdisMediumWirelessWan, | ||
401 | NdisMediumIrda, | ||
402 | NdisMediumBpc, | ||
403 | NdisMediumCoWan, | ||
404 | NdisMedium1394, | ||
405 | NdisMediumInfiniBand, | ||
406 | NdisMediumTunnel, | ||
407 | NdisMediumNative802_11, | ||
408 | NdisMediumLoopback, | ||
409 | NdisMediumWiMAX, | ||
410 | NdisMediumIP, | ||
411 | |||
412 | NdisMediumMax // Not a real medium, defined as an upper-bound | ||
413 | } NDIS_MEDIUM, * PNDIS_MEDIUM; | ||
414 | |||
415 | typedef enum _NDIS_PHYSICAL_MEDIUM | ||
416 | { | ||
417 | NdisPhysicalMediumUnspecified, | ||
418 | NdisPhysicalMediumWirelessLan, | ||
419 | NdisPhysicalMediumCableModem, | ||
420 | NdisPhysicalMediumPhoneLine, | ||
421 | NdisPhysicalMediumPowerLine, | ||
422 | NdisPhysicalMediumDSL, // includes ADSL and UADSL (G.Lite) | ||
423 | NdisPhysicalMediumFibreChannel, | ||
424 | NdisPhysicalMedium1394, | ||
425 | NdisPhysicalMediumWirelessWan, | ||
426 | NdisPhysicalMediumNative802_11, | ||
427 | NdisPhysicalMediumBluetooth, | ||
428 | NdisPhysicalMediumInfiniband, | ||
429 | NdisPhysicalMediumWiMax, | ||
430 | NdisPhysicalMediumUWB, | ||
431 | NdisPhysicalMedium802_3, | ||
432 | NdisPhysicalMedium802_5, | ||
433 | NdisPhysicalMediumIrda, | ||
434 | NdisPhysicalMediumWiredWAN, | ||
435 | NdisPhysicalMediumWiredCoWan, | ||
436 | NdisPhysicalMediumOther, | ||
437 | NdisPhysicalMediumNative802_15_4, | ||
438 | NdisPhysicalMediumMax // Not a real physical type, defined as an upper-bound | ||
439 | } NDIS_PHYSICAL_MEDIUM, * PNDIS_PHYSICAL_MEDIUM; | ||
440 | |||
441 | typedef enum _NET_IF_ACCESS_TYPE | ||
442 | { | ||
443 | NET_IF_ACCESS_LOOPBACK = 1, | ||
444 | NET_IF_ACCESS_BROADCAST = 2, | ||
445 | NET_IF_ACCESS_POINT_TO_POINT = 3, | ||
446 | NET_IF_ACCESS_POINT_TO_MULTI_POINT = 4, | ||
447 | NET_IF_ACCESS_MAXIMUM = 5 | ||
448 | } NET_IF_ACCESS_TYPE, * PNET_IF_ACCESS_TYPE; | ||
449 | |||
450 | typedef enum _NET_IF_DIRECTION_TYPE | ||
451 | { | ||
452 | NET_IF_DIRECTION_SENDRECEIVE, | ||
453 | NET_IF_DIRECTION_SENDONLY, | ||
454 | NET_IF_DIRECTION_RECEIVEONLY, | ||
455 | NET_IF_DIRECTION_MAXIMUM | ||
456 | } NET_IF_DIRECTION_TYPE, * PNET_IF_DIRECTION_TYPE; | ||
457 | |||
458 | typedef enum _NET_IF_ADMIN_STATUS // ifAdminStatus | ||
459 | { | ||
460 | NET_IF_ADMIN_STATUS_UP = 1, | ||
461 | NET_IF_ADMIN_STATUS_DOWN = 2, | ||
462 | NET_IF_ADMIN_STATUS_TESTING = 3 | ||
463 | } NET_IF_ADMIN_STATUS, * PNET_IF_ADMIN_STATUS; | ||
464 | |||
465 | typedef enum _NET_IF_MEDIA_CONNECT_STATE | ||
466 | { | ||
467 | MediaConnectStateUnknown, | ||
468 | MediaConnectStateConnected, | ||
469 | MediaConnectStateDisconnected | ||
470 | } NET_IF_MEDIA_CONNECT_STATE, * PNET_IF_MEDIA_CONNECT_STATE; | ||
471 | |||
472 | typedef GUID NET_IF_NETWORK_GUID, * PNET_IF_NETWORK_GUID; | ||
473 | |||
474 | typedef enum _NET_IF_CONNECTION_TYPE | ||
475 | { | ||
476 | NET_IF_CONNECTION_DEDICATED = 1, | ||
477 | NET_IF_CONNECTION_PASSIVE = 2, | ||
478 | NET_IF_CONNECTION_DEMAND = 3, | ||
479 | NET_IF_CONNECTION_MAXIMUM = 4 | ||
480 | } NET_IF_CONNECTION_TYPE, * PNET_IF_CONNECTION_TYPE; | ||
481 | |||
482 | typedef struct _MIB_IF_ROW2 { | ||
483 | // | ||
484 | // Key structure. Sorted by preference. | ||
485 | // | ||
486 | NET_LUID InterfaceLuid; | ||
487 | NET_IFINDEX InterfaceIndex; | ||
488 | |||
489 | // | ||
490 | // Read-Only fields. | ||
491 | // | ||
492 | GUID InterfaceGuid; | ||
493 | WCHAR Alias[IF_MAX_STRING_SIZE + 1]; | ||
494 | WCHAR Description[IF_MAX_STRING_SIZE + 1]; | ||
495 | ULONG PhysicalAddressLength; | ||
496 | UCHAR PhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]; | ||
497 | UCHAR PermanentPhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]; | ||
498 | |||
499 | ULONG Mtu; | ||
500 | IFTYPE Type; // Interface Type. | ||
501 | TUNNEL_TYPE TunnelType; // Tunnel Type, if Type = IF_TUNNEL. | ||
502 | NDIS_MEDIUM MediaType; | ||
503 | NDIS_PHYSICAL_MEDIUM PhysicalMediumType; | ||
504 | NET_IF_ACCESS_TYPE AccessType; | ||
505 | NET_IF_DIRECTION_TYPE DirectionType; | ||
506 | struct { | ||
507 | BOOLEAN HardwareInterface : 1; | ||
508 | BOOLEAN FilterInterface : 1; | ||
509 | BOOLEAN ConnectorPresent : 1; | ||
510 | BOOLEAN NotAuthenticated : 1; | ||
511 | BOOLEAN NotMediaConnected : 1; | ||
512 | BOOLEAN Paused : 1; | ||
513 | BOOLEAN LowPower : 1; | ||
514 | BOOLEAN EndPointInterface : 1; | ||
515 | } InterfaceAndOperStatusFlags; | ||
516 | |||
517 | IF_OPER_STATUS OperStatus; | ||
518 | NET_IF_ADMIN_STATUS AdminStatus; | ||
519 | NET_IF_MEDIA_CONNECT_STATE MediaConnectState; | ||
520 | NET_IF_NETWORK_GUID NetworkGuid; | ||
521 | NET_IF_CONNECTION_TYPE ConnectionType; | ||
522 | |||
523 | // | ||
524 | // Statistics. | ||
525 | // | ||
526 | ULONG64 TransmitLinkSpeed; | ||
527 | ULONG64 ReceiveLinkSpeed; | ||
528 | |||
529 | ULONG64 InOctets; | ||
530 | ULONG64 InUcastPkts; | ||
531 | ULONG64 InNUcastPkts; | ||
532 | ULONG64 InDiscards; | ||
533 | ULONG64 InErrors; | ||
534 | ULONG64 InUnknownProtos; | ||
535 | ULONG64 InUcastOctets; | ||
536 | ULONG64 InMulticastOctets; | ||
537 | ULONG64 InBroadcastOctets; | ||
538 | ULONG64 OutOctets; | ||
539 | ULONG64 OutUcastPkts; | ||
540 | ULONG64 OutNUcastPkts; | ||
541 | ULONG64 OutDiscards; | ||
542 | ULONG64 OutErrors; | ||
543 | ULONG64 OutUcastOctets; | ||
544 | ULONG64 OutMulticastOctets; | ||
545 | ULONG64 OutBroadcastOctets; | ||
546 | ULONG64 OutQLen; | ||
547 | } MIB_IF_ROW2, * PMIB_IF_ROW2; | ||
548 | |||
549 | typedef struct _MIB_IF_TABLE2 { | ||
550 | ULONG NumEntries; | ||
551 | MIB_IF_ROW2 Table[ANY_SIZE]; | ||
552 | } MIB_IF_TABLE2, * PMIB_IF_TABLE2; | ||
553 | |||
554 | |||
555 | typedef struct _MIB_IPADDRROW { | ||
556 | DWORD dwAddr; | ||
557 | DWORD dwIndex; | ||
558 | DWORD dwMask; | ||
559 | DWORD dwBCastAddr; | ||
560 | DWORD dwReasmSize; | ||
561 | unsigned short unused1; | ||
562 | unsigned short wType; | ||
563 | } MIB_IPADDRROW, * PMIB_IPADDRROW; | ||
564 | |||
565 | typedef struct _MIB_IPADDRTABLE { | ||
566 | DWORD dwNumEntries; | ||
567 | MIB_IPADDRROW table[ANY_SIZE]; | ||
568 | } MIB_IPADDRTABLE, * PMIB_IPADDRTABLE; | ||
569 | |||
570 | #define GAA_FLAG_SKIP_UNICAST 0x0001 | ||
571 | #define GAA_FLAG_SKIP_ANYCAST 0x0002 | ||
572 | #define GAA_FLAG_SKIP_MULTICAST 0x0004 | ||
573 | #define GAA_FLAG_SKIP_DNS_SERVER 0x0008 | ||
574 | #define GAA_FLAG_INCLUDE_PREFIX 0x0010 | ||
575 | #define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020 | ||
576 | #define GAA_FLAG_INCLUDE_WINS_INFO 0x0040 | ||
577 | #define GAA_FLAG_INCLUDE_GATEWAYS 0x0080 | ||
578 | #define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100 | ||
579 | #define GAA_FLAG_INCLUDE_ALL_COMPARTMENTS 0x0200 | ||
580 | #define GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER 0x0400 | ||
581 | #define GAA_FLAG_SKIP_DNS_INFO 0x0800 | ||
582 | |||
583 | |||
584 | |||
585 | typedef struct | ||
586 | { | ||
587 | DWORD(WINAPI* GetAdaptersInfo)(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen); | ||
588 | DWORD(WINAPI* GetIfTable)(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder); | ||
589 | DWORD(WINAPI* GetIpAddrTable)(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder); | ||
590 | ULONG(WINAPI* GetAdaptersAddresses)(ULONG Family, ULONG Flags, PVOID Reserved, PIP_ADAPTER_ADDRESSES AdapterAddresses, PULONG SizePointer); | ||
591 | DWORD(WINAPI* GetIfTable2)(PMIB_IF_TABLE2* Table); | ||
592 | VOID(WINAPI* FreeMibTable)(PVOID Memory); | ||
593 | } win32_iphlpapi; | ||
594 | |||
595 | static win32_iphlpapi iphlp; | ||
596 | |||
597 | static gate_result_t load_iphlpapi() | ||
598 | { | ||
599 | static HMODULE hmod_iphlpapi = NULL; | ||
600 | HMODULE hmod = NULL; | ||
601 | |||
602 | if (NULL == hmod_iphlpapi) | ||
603 | { | ||
604 | hmod = gate_win32_load_library(_T("iphlpapi"), 0); | ||
605 | if (hmod == NULL) | ||
606 | { | ||
607 | return GATE_RESULT_NOTAVAILABLE; | ||
608 | } | ||
609 | gate_win32_get_proc_address(hmod, "GetAdaptersInfo", &iphlp.GetAdaptersInfo); | ||
610 | gate_win32_get_proc_address(hmod, "GetIfTable", &iphlp.GetIfTable); | ||
611 | gate_win32_get_proc_address(hmod, "GetIpAddrTable", &iphlp.GetIpAddrTable); | ||
612 | gate_win32_get_proc_address(hmod, "GetAdaptersAddresses", &iphlp.GetAdaptersAddresses); | ||
613 | gate_win32_get_proc_address(hmod, "GetIfTable2", &iphlp.GetIfTable2); | ||
614 | gate_win32_get_proc_address(hmod, "FreeMibTable", &iphlp.FreeMibTable); | ||
615 | hmod_iphlpapi = hmod; | ||
616 | } | ||
617 | return GATE_RESULT_OK; | ||
618 | } | ||
619 | |||
620 | #define GATE_MIB_IF_TYPE_OTHER 1 | ||
621 | #define GATE_MIB_IF_TYPE_ETHERNET 6 | ||
622 | #define GATE_MIB_IF_TYPE_TOKENRING 9 | ||
623 | #define GATE_MIB_IF_TYPE_FDDI 15 | ||
624 | #define GATE_MIB_IF_TYPE_PPP 23 | ||
625 | #define GATE_MIB_IF_TYPE_LOOPBACK 24 | ||
626 | #define GATE_MIB_IF_TYPE_SLIP 28 | ||
627 | #define GATE_IF_TYPE_IEEE80211 71 | ||
628 | |||
629 | #define GATE_IF_OPER_STATUS_NON_OPERATIONAL 0 | ||
630 | #define GATE_IF_OPER_STATUS_UNREACHABLE 1 | ||
631 | #define GATE_IF_OPER_STATUS_DISCONNECTED 2 | ||
632 | #define GATE_IF_OPER_STATUS_CONNECTING 3 | ||
633 | #define GATE_IF_OPER_STATUS_CONNECTED 4 | ||
634 | #define GATE_IF_OPER_STATUS_OPERATIONAL 5 | ||
635 | |||
636 | static void print_mac(gate_uint8_t const* ptr_bytes, gate_size_t len, char* text, gate_size_t text_len) | ||
637 | { | ||
638 | gate_strbuilder_t builder; | ||
639 | gate_size_t ndx; | ||
640 | |||
641 | gate_strbuilder_create_static(&builder, text, text_len, 0); | ||
642 | for (ndx = 0; ndx != len; ++ndx) | ||
643 | { | ||
644 | if (ndx != 0) | ||
645 | { | ||
646 | gate_strbuilder_append_chars(&builder, 1, ':'); | ||
647 | } | ||
648 | gate_strbuilder_append_hex(&builder, &ptr_bytes[ndx], 1, false); | ||
649 | } | ||
650 | |||
651 | } | ||
652 | |||
653 | static unsigned convert_nif_type(DWORD tp) | ||
654 | { | ||
655 | switch (tp) | ||
656 | { | ||
657 | case GATE_MIB_IF_TYPE_OTHER: return GATE_NETCONFIG_TYPE_OTHER; | ||
658 | case GATE_MIB_IF_TYPE_ETHERNET: return GATE_NETCONFIG_TYPE_ETHERNET; | ||
659 | case GATE_MIB_IF_TYPE_TOKENRING: return GATE_NETCONFIG_TYPE_TOKENRING; | ||
660 | case GATE_MIB_IF_TYPE_FDDI: return GATE_NETCONFIG_TYPE_FDDI; | ||
661 | case GATE_MIB_IF_TYPE_PPP: return GATE_NETCONFIG_TYPE_PPP; | ||
662 | case GATE_MIB_IF_TYPE_LOOPBACK: return GATE_NETCONFIG_TYPE_LOOPBACK; | ||
663 | case GATE_MIB_IF_TYPE_SLIP: return GATE_NETCONFIG_TYPE_SLIP; | ||
664 | case GATE_IF_TYPE_IEEE80211: return GATE_NETCONFIG_TYPE_WLAN; | ||
665 | default: return GATE_NETCONFIG_TYPE_UNKNOWN; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | static gate_bool_t mibrow_2_nif(MIB_IFROW const* ptr_row, gate_netconfig_nif_t* ptr_nif) | ||
670 | { | ||
671 | gate_size_t pos1, pos2; | ||
672 | gate_size_t namelen = gate_str16_length_max(ptr_row->wszName, sizeof(ptr_row->wszName) / sizeof(ptr_row->wszName[0])); | ||
673 | |||
674 | gate_mem_clear(ptr_nif, sizeof(gate_netconfig_nif_t)); | ||
675 | |||
676 | /* get UID */ | ||
677 | pos1 = gate_str16_char_pos(ptr_row->wszName, namelen, '{', 0); | ||
678 | if (pos1 == GATE_STR_NPOS) | ||
679 | { | ||
680 | /* NT/9x: No GUID-string, use index instead */ | ||
681 | ptr_nif->uid[0] = '#'; | ||
682 | gate_str_print_uint(&ptr_nif->uid[1], sizeof(ptr_nif->uid) - 1, ptr_row->dwIndex, 0); | ||
683 | } | ||
684 | else | ||
685 | { | ||
686 | pos2 = gate_str16_char_pos(ptr_row->wszName, namelen, '}', pos1 + 1); | ||
687 | if (pos2 == GATE_STR_NPOS) | ||
688 | { | ||
689 | /* error: invalid guid string */ | ||
690 | return false; | ||
691 | } | ||
692 | gate_str_utf16_2_utf8(&ptr_row->wszName[pos1 + 1], pos2 - pos1 - 1, ptr_nif->uid, sizeof(ptr_nif->uid)); | ||
693 | } | ||
694 | |||
695 | gate_str_print_text(ptr_nif->name, sizeof(ptr_nif->name), (char const*)&ptr_row->bDescr[0], ptr_row->dwDescrLen); | ||
696 | |||
697 | ptr_nif->index = (gate_size_t)ptr_row->dwIndex; | ||
698 | |||
699 | ptr_nif->type = convert_nif_type(ptr_row->dwType); | ||
700 | |||
701 | switch (ptr_row->dwOperStatus) | ||
702 | { | ||
703 | case GATE_IF_OPER_STATUS_NON_OPERATIONAL: ptr_nif->status = GATE_NETCONFIG_STATUS_DISABLED; break; | ||
704 | case GATE_IF_OPER_STATUS_UNREACHABLE: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_NONFUNCT; break; | ||
705 | case GATE_IF_OPER_STATUS_DISCONNECTED: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_DISCONNECTED; break; | ||
706 | case GATE_IF_OPER_STATUS_CONNECTING: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_CONNECTING; break; | ||
707 | case GATE_IF_OPER_STATUS_CONNECTED: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_CONNECTED; break; | ||
708 | case GATE_IF_OPER_STATUS_OPERATIONAL: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_OPERATIONAL; break; | ||
709 | default: ptr_nif->status = GATE_NETCONFIG_STATUS_UNKNOWN; break; | ||
710 | } | ||
711 | |||
712 | print_mac(&ptr_row->bPhysAddr[0], ptr_row->dwPhysAddrLen, ptr_nif->address, sizeof(ptr_nif->address)); | ||
713 | |||
714 | return true; | ||
715 | } | ||
716 | |||
717 | static gate_bool_t is_nif_enabled(IP_ADAPTER_INFO const* ptr_info) | ||
718 | { | ||
719 | static gate_string_t const str_uninit = GATE_STRING_INIT_STATIC("0.0.0.0"); | ||
720 | gate_string_t str; | ||
721 | gate_string_create_static_len(&str, | ||
722 | ptr_info->IpAddressList.IpAddress.String, | ||
723 | gate_str_length_max(ptr_info->IpAddressList.IpAddress.String, sizeof(ptr_info->IpAddressList.IpAddress.String))); | ||
724 | if (gate_string_is_empty(&str)) | ||
725 | { | ||
726 | return false; | ||
727 | } | ||
728 | return !(gate_string_equals(&str, &str_uninit)); | ||
729 | } | ||
730 | |||
731 | static gate_bool_t info_2_nif(IP_ADAPTER_INFO const* ptr_info, gate_netconfig_nif_t* ptr_nif) | ||
732 | { | ||
733 | gate_size_t pos1, pos2; | ||
734 | gate_size_t namelen = gate_str_length_max(ptr_info->AdapterName, sizeof(ptr_info->AdapterName)); | ||
735 | |||
736 | gate_mem_clear(ptr_nif, sizeof(gate_netconfig_nif_t)); | ||
737 | |||
738 | /* get UID */ | ||
739 | pos1 = gate_str_char_pos(ptr_info->AdapterName, namelen, '{', 0); | ||
740 | if (pos1 == GATE_STR_NPOS) | ||
741 | { | ||
742 | return false; | ||
743 | } | ||
744 | pos2 = gate_str_char_pos(ptr_info->AdapterName, namelen, '}', pos1 + 1); | ||
745 | if (pos2 == GATE_STR_NPOS) | ||
746 | { | ||
747 | return false; | ||
748 | } | ||
749 | gate_str_print_text(ptr_nif->uid, sizeof(ptr_nif->uid), &ptr_info->AdapterName[pos1 + 1], pos2 - pos1 - 1); | ||
750 | |||
751 | /* get name: */ | ||
752 | gate_str_print_text(ptr_nif->name, sizeof(ptr_nif->name), | ||
753 | ptr_info->Description, | ||
754 | gate_str_length_max(ptr_info->Description, sizeof(ptr_info->Description))); | ||
755 | |||
756 | /* get MAC: */ | ||
757 | print_mac(&ptr_info->Address[0], ptr_info->AddressLength, ptr_nif->address, sizeof(ptr_nif->address)); | ||
758 | |||
759 | ptr_nif->type = convert_nif_type(ptr_info->Type); | ||
760 | ptr_nif->status = is_nif_enabled(ptr_info) | ||
761 | ? (GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_OPERATIONAL) | ||
762 | : GATE_NETCONFIG_STATUS_DISABLED; | ||
763 | ptr_nif->index = ptr_info->Index; | ||
764 | return true; | ||
765 | } | ||
766 | |||
767 | static gate_bool_t mibrow2_2_nif(MIB_IF_ROW2 const* ptr_row, gate_netconfig_nif_t* ptr_nif) | ||
768 | { | ||
769 | //gate_size_t pos1, pos2; | ||
770 | //gate_size_t namelen = gate_str16_length_max(ptr_row->Alias, sizeof(ptr_row->Alias) / sizeof(ptr_row->Alias[0])); | ||
771 | |||
772 | gate_mem_clear(ptr_nif, sizeof(gate_netconfig_nif_t)); | ||
773 | |||
774 | if (ptr_row->InterfaceAndOperStatusFlags.FilterInterface) | ||
775 | { | ||
776 | return false; | ||
777 | } | ||
778 | |||
779 | /* get UID */ | ||
780 | gate_str_print_hex_uint32(&ptr_nif->uid[0], 8, ptr_row->InterfaceGuid.Data1, true); | ||
781 | ptr_nif->uid[8] = '-'; | ||
782 | gate_str_print_hex_uint16(&ptr_nif->uid[9], 4, ptr_row->InterfaceGuid.Data2, true); | ||
783 | ptr_nif->uid[13] = '-'; | ||
784 | gate_str_print_hex_uint16(&ptr_nif->uid[14], 4, ptr_row->InterfaceGuid.Data3, true); | ||
785 | ptr_nif->uid[18] = '-'; | ||
786 | gate_str_print_hex_byte(&ptr_nif->uid[19], 2, ptr_row->InterfaceGuid.Data4[0], true); | ||
787 | gate_str_print_hex_byte(&ptr_nif->uid[21], 2, ptr_row->InterfaceGuid.Data4[1], true); | ||
788 | ptr_nif->uid[23] = '-'; | ||
789 | gate_str_print_hex_byte(&ptr_nif->uid[24], 2, ptr_row->InterfaceGuid.Data4[2], true); | ||
790 | gate_str_print_hex_byte(&ptr_nif->uid[26], 2, ptr_row->InterfaceGuid.Data4[3], true); | ||
791 | gate_str_print_hex_byte(&ptr_nif->uid[28], 2, ptr_row->InterfaceGuid.Data4[4], true); | ||
792 | gate_str_print_hex_byte(&ptr_nif->uid[30], 2, ptr_row->InterfaceGuid.Data4[5], true); | ||
793 | gate_str_print_hex_byte(&ptr_nif->uid[32], 2, ptr_row->InterfaceGuid.Data4[6], true); | ||
794 | gate_str_print_hex_byte(&ptr_nif->uid[34], 2, ptr_row->InterfaceGuid.Data4[7], true); | ||
795 | ptr_nif->uid[36] = '\0'; | ||
796 | |||
797 | gate_str_utf16_2_utf8(&ptr_row->Description[0], gate_str16_length(&ptr_row->Description[0]), ptr_nif->name, sizeof(ptr_nif->name)); | ||
798 | |||
799 | ptr_nif->index = (gate_size_t)ptr_row->InterfaceIndex; | ||
800 | |||
801 | ptr_nif->type = convert_nif_type(ptr_row->Type); | ||
802 | |||
803 | switch (ptr_row->OperStatus) | ||
804 | { | ||
805 | /* case GATE_IF_OPER_STATUS_NON_OPERATIONAL: ptr_nif->status = GATE_NETCONFIG_STATUS_DISABLED; break; */ | ||
806 | case GATE_IF_OPER_STATUS_UNREACHABLE: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_NONFUNCT; break; | ||
807 | case GATE_IF_OPER_STATUS_DISCONNECTED: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_DISCONNECTED; break; | ||
808 | case GATE_IF_OPER_STATUS_CONNECTING: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_CONNECTING; break; | ||
809 | case GATE_IF_OPER_STATUS_CONNECTED: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_CONNECTED; break; | ||
810 | case GATE_IF_OPER_STATUS_OPERATIONAL: ptr_nif->status = GATE_NETCONFIG_STATUS_ENABLED | GATE_NETCONFIG_STATUS_OPERATIONAL; break; | ||
811 | default: ptr_nif->status = GATE_NETCONFIG_STATUS_UNKNOWN; break; | ||
812 | } | ||
813 | |||
814 | print_mac(&ptr_row->PhysicalAddress[0], ptr_row->PhysicalAddressLength, ptr_nif->address, sizeof(ptr_nif->address)); | ||
815 | |||
816 | return true; | ||
817 | } | ||
818 | |||
819 | |||
820 | |||
821 | static gate_bool_t index_found(DWORD const* ptr_list, DWORD list_count, DWORD test_index) | ||
822 | { | ||
823 | DWORD ndx; | ||
824 | for (ndx = 0; ndx != list_count; ++ndx) | ||
825 | { | ||
826 | if (ptr_list[ndx] == test_index) | ||
827 | { | ||
828 | return true; | ||
829 | } | ||
830 | } | ||
831 | return false; | ||
832 | } | ||
833 | |||
834 | gate_result_t gate_netconfig_enum_nifs(gate_netcfg_enum_nif_callback_t cb, void* userparam) | ||
835 | { | ||
836 | gate_result_t result; | ||
837 | ULONG infosize = 0; | ||
838 | DWORD err_code; | ||
839 | DWORD ndx; | ||
840 | IP_ADAPTER_INFO* ptr_adainfo = NULL; | ||
841 | IP_ADAPTER_INFO* ptr_info; | ||
842 | MIB_IFTABLE* ptr_iftable = NULL; | ||
843 | MIB_IFROW* ptr_row; | ||
844 | PMIB_IF_TABLE2 ptr_iftable2 = NULL; | ||
845 | MIB_IF_ROW2* ptr_row2; | ||
846 | gate_netconfig_nif_t nif; | ||
847 | DWORD handled_indexes[512]; | ||
848 | DWORD handled_indexes_count = 0; | ||
849 | gate_bool_t canceled_by_callback = false; | ||
850 | |||
851 | do | ||
852 | { | ||
853 | result = load_iphlpapi(); | ||
854 | GATE_BREAK_IF_FAILED(result); | ||
855 | |||
856 | /* try winvista+ APIs first: */ | ||
857 | do | ||
858 | { | ||
859 | if (!iphlp.GetIfTable2 || !iphlp.FreeMibTable) | ||
860 | { | ||
861 | /* api not supported */ | ||
862 | break; | ||
863 | } | ||
864 | |||
865 | err_code = iphlp.GetIfTable2(&ptr_iftable2); | ||
866 | if (NO_ERROR != err_code) | ||
867 | { | ||
868 | result = GATE_RESULT_FAILED; | ||
869 | break; | ||
870 | } | ||
871 | |||
872 | for (ndx = 0; (ndx != ptr_iftable2->NumEntries) && !canceled_by_callback; ++ndx) | ||
873 | { | ||
874 | ptr_row2 = &ptr_iftable2->Table[ndx]; | ||
875 | if (index_found(handled_indexes, handled_indexes_count, ptr_row2->InterfaceIndex)) | ||
876 | { | ||
877 | /* this index was handled by previous code block*/ | ||
878 | continue; | ||
879 | } | ||
880 | if (mibrow2_2_nif(ptr_row2, &nif)) | ||
881 | { | ||
882 | handled_indexes[handled_indexes_count] = (DWORD)nif.index; | ||
883 | ++handled_indexes_count; | ||
884 | |||
885 | canceled_by_callback = !cb(&nif, userparam); | ||
886 | } | ||
887 | } | ||
888 | } while (0); | ||
889 | |||
890 | if (canceled_by_callback) | ||
891 | { | ||
892 | break; | ||
893 | } | ||
894 | |||
895 | |||
896 | /* try Win2K API: */ | ||
897 | do | ||
898 | { | ||
899 | if (!iphlp.GetAdaptersInfo) | ||
900 | { | ||
901 | break; | ||
902 | } | ||
903 | infosize = sizeof(IP_ADAPTER_INFO); | ||
904 | ptr_adainfo = (IP_ADAPTER_INFO*)gate_mem_alloc(infosize); | ||
905 | if (!ptr_adainfo) | ||
906 | { | ||
907 | result = GATE_RESULT_OUTOFMEMORY; | ||
908 | break; | ||
909 | } | ||
910 | err_code = iphlp.GetAdaptersInfo(ptr_adainfo, &infosize); | ||
911 | if (err_code == ERROR_BUFFER_OVERFLOW) | ||
912 | { | ||
913 | ptr_adainfo = (IP_ADAPTER_INFO*)gate_mem_realloc(ptr_adainfo, infosize); | ||
914 | if (!ptr_adainfo) | ||
915 | { | ||
916 | result = GATE_RESULT_OUTOFMEMORY; | ||
917 | break; | ||
918 | } | ||
919 | err_code = iphlp.GetAdaptersInfo(ptr_adainfo, &infosize); | ||
920 | } | ||
921 | if (ERROR_SUCCESS != err_code) | ||
922 | { | ||
923 | result = GATE_RESULT_FAILED; | ||
924 | break; | ||
925 | } | ||
926 | ptr_info = ptr_adainfo; | ||
927 | do | ||
928 | { | ||
929 | if (index_found(handled_indexes, handled_indexes_count, ptr_info->Index) || canceled_by_callback) | ||
930 | { | ||
931 | /* this index was handled by previous code block*/ | ||
932 | continue; | ||
933 | } | ||
934 | |||
935 | if (info_2_nif(ptr_info, &nif)) | ||
936 | { | ||
937 | handled_indexes[handled_indexes_count] = (DWORD)nif.index; | ||
938 | ++handled_indexes_count; | ||
939 | |||
940 | canceled_by_callback = !cb(&nif, userparam); | ||
941 | } | ||
942 | } while (NULL != (ptr_info = ptr_info->Next)); | ||
943 | } while (0); | ||
944 | |||
945 | if (canceled_by_callback) | ||
946 | { | ||
947 | break; | ||
948 | } | ||
949 | |||
950 | |||
951 | /* try NT4/Win9x API */ | ||
952 | do | ||
953 | { | ||
954 | if (!iphlp.GetIfTable) | ||
955 | { | ||
956 | break; | ||
957 | } | ||
958 | |||
959 | infosize = 0; | ||
960 | iphlp.GetIfTable(NULL, &infosize, FALSE); | ||
961 | if (infosize != 0) | ||
962 | { | ||
963 | infosize += 1024; | ||
964 | ptr_iftable = (MIB_IFTABLE*)gate_mem_alloc((gate_size_t)infosize); | ||
965 | if (ptr_iftable == NULL) | ||
966 | { | ||
967 | result = GATE_RESULT_OUTOFMEMORY; | ||
968 | break; | ||
969 | } | ||
970 | gate_mem_clear(ptr_iftable, infosize); | ||
971 | err_code = iphlp.GetIfTable(ptr_iftable, &infosize, FALSE); | ||
972 | if (NO_ERROR != err_code) | ||
973 | { | ||
974 | result = GATE_RESULT_FAILED; | ||
975 | break; | ||
976 | } | ||
977 | for (ndx = 0; (ndx != ptr_iftable->dwNumEntries) && !canceled_by_callback; ++ndx) | ||
978 | { | ||
979 | ptr_row = &ptr_iftable->table[ndx]; | ||
980 | if (index_found(handled_indexes, handled_indexes_count, ptr_row->dwIndex)) | ||
981 | { | ||
982 | /* this index was handled by previous code block*/ | ||
983 | continue; | ||
984 | } | ||
985 | if (mibrow_2_nif(ptr_row, &nif)) | ||
986 | { | ||
987 | handled_indexes[handled_indexes_count] = (DWORD)nif.index; | ||
988 | ++handled_indexes_count; | ||
989 | |||
990 | canceled_by_callback = !cb(&nif, userparam); | ||
991 | } | ||
992 | } | ||
993 | } | ||
994 | } while (0); | ||
995 | |||
996 | if (canceled_by_callback) | ||
997 | { | ||
998 | break; | ||
999 | } | ||
1000 | |||
1001 | } while (0); | ||
1002 | |||
1003 | if (ptr_iftable) | ||
1004 | { | ||
1005 | gate_mem_dealloc(ptr_iftable); | ||
1006 | } | ||
1007 | if (ptr_adainfo) | ||
1008 | { | ||
1009 | gate_mem_dealloc(ptr_adainfo); | ||
1010 | } | ||
1011 | if (ptr_iftable2) | ||
1012 | { | ||
1013 | iphlp.FreeMibTable(ptr_iftable2); | ||
1014 | } | ||
1015 | return result; | ||
1016 | } | ||
1017 | |||
1018 | static void print_ipv4_addr(gate_strbuilder_t* ptr_builder, DWORD dwIP) | ||
1019 | { | ||
1020 | gate_strbuilder_append_uint32(ptr_builder, (dwIP & 0x000000ff)); | ||
1021 | gate_strbuilder_append_chars(ptr_builder, 1, '.'); | ||
1022 | gate_strbuilder_append_uint32(ptr_builder, (dwIP & 0x0000ff00) >> 8); | ||
1023 | gate_strbuilder_append_chars(ptr_builder, 1, '.'); | ||
1024 | gate_strbuilder_append_uint32(ptr_builder, (dwIP & 0x00ff0000) >> 16); | ||
1025 | gate_strbuilder_append_chars(ptr_builder, 1, '.'); | ||
1026 | gate_strbuilder_append_uint32(ptr_builder, (dwIP & 0xff000000) >> 24); | ||
1027 | } | ||
1028 | |||
1029 | static gate_bool_t ipaddrrow_to_netaddrr(PMIB_IPADDRROW row, gate_netconfig_address_t* addr) | ||
1030 | { | ||
1031 | gate_strbuilder_t builder; | ||
1032 | |||
1033 | gate_mem_clear(addr, sizeof(gate_netconfig_address_t)); | ||
1034 | |||
1035 | gate_strbuilder_create_static(&builder, addr->address, sizeof(addr->address), 0); | ||
1036 | print_ipv4_addr(&builder, row->dwAddr); | ||
1037 | |||
1038 | gate_strbuilder_create_static(&builder, addr->mask, sizeof(addr->mask), 0); | ||
1039 | print_ipv4_addr(&builder, row->dwMask); | ||
1040 | |||
1041 | addr->addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP; | ||
1042 | addr->flags = 0; | ||
1043 | return true; | ||
1044 | } | ||
1045 | |||
1046 | static gate_bool_t notify_all_addr_strings(gate_netconfig_address_t* ptr_target, IP_ADDR_STRING* ptr_addr_string, gate_bool_t add_mask, gate_enumint_t addr_type, | ||
1047 | gate_netcfg_enum_addresses_callback_t cb, void* userparam) | ||
1048 | { | ||
1049 | gate_bool_t ret = true; | ||
1050 | gate_size_t addr_len; | ||
1051 | gate_size_t mask_len; | ||
1052 | |||
1053 | while (ptr_addr_string && ret) | ||
1054 | { | ||
1055 | gate_mem_clear(ptr_target, sizeof(gate_netconfig_address_t)); | ||
1056 | addr_len = gate_str_length(ptr_addr_string->IpAddress.String); | ||
1057 | gate_str_print_text(ptr_target->address, sizeof(ptr_target->address), ptr_addr_string->IpAddress.String, addr_len); | ||
1058 | if (add_mask) | ||
1059 | { | ||
1060 | mask_len = gate_str_length(ptr_addr_string->IpMask.String); | ||
1061 | gate_str_print_text(ptr_target->mask, sizeof(ptr_target->mask), ptr_addr_string->IpMask.String, mask_len); | ||
1062 | } | ||
1063 | ptr_target->addrtype = addr_type; | ||
1064 | ptr_target->flags = 0; | ||
1065 | |||
1066 | if (addr_len > 0) | ||
1067 | { | ||
1068 | ret &= cb(ptr_target, userparam); | ||
1069 | } | ||
1070 | |||
1071 | ptr_addr_string = ptr_addr_string->Next; | ||
1072 | } | ||
1073 | return true; | ||
1074 | } | ||
1075 | |||
1076 | struct ipv6_cache | ||
1077 | { | ||
1078 | DWORD adapter_index; | ||
1079 | BYTE addr[16]; | ||
1080 | DWORD prefixlength; | ||
1081 | }; | ||
1082 | |||
1083 | static gate_bool_t notify_cached_ipv6_entries(struct ipv6_cache* cache, DWORD cache_length, DWORD index, gate_netconfig_address_t* ptr_target, gate_netcfg_enum_addresses_callback_t cb, void* userparam) | ||
1084 | { | ||
1085 | gate_bool_t ret = true; | ||
1086 | DWORD n; | ||
1087 | struct ipv6_cache* entry; | ||
1088 | gate_strbuilder_t builder; | ||
1089 | |||
1090 | for (n = 0; ret && (n != cache_length); ++n) | ||
1091 | { | ||
1092 | entry = &cache[n]; | ||
1093 | if (entry->adapter_index != index) | ||
1094 | { | ||
1095 | continue; | ||
1096 | } | ||
1097 | gate_mem_clear(ptr_target, sizeof(gate_netconfig_address_t)); | ||
1098 | gate_strbuilder_create_static(&builder, ptr_target->address, sizeof(ptr_target->address), 0); | ||
1099 | gate_strbuilder_append(&builder, | ||
1100 | GATE_PRINT_CSTR, "[", GATE_PRINT_H8, (entry->addr[0] & 0xff), GATE_PRINT_H8, (entry->addr[1] & 0xff), | ||
1101 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[2] & 0xff), GATE_PRINT_H8, (entry->addr[3] & 0xff), | ||
1102 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[4] & 0xff), GATE_PRINT_H8, (entry->addr[5] & 0xff), | ||
1103 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[6] & 0xff), GATE_PRINT_H8, (entry->addr[7] & 0xff), | ||
1104 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[8] & 0xff), GATE_PRINT_H8, (entry->addr[9] & 0xff), | ||
1105 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[10] & 0xff), GATE_PRINT_H8, (entry->addr[11] & 0xff), | ||
1106 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[12] & 0xff), GATE_PRINT_H8, (entry->addr[13] & 0xff), | ||
1107 | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[14] & 0xff), GATE_PRINT_H8, (entry->addr[15] & 0xff), | ||
1108 | GATE_PRINT_CSTR, "]", GATE_PRINT_END); | ||
1109 | |||
1110 | if (entry->prefixlength) | ||
1111 | { | ||
1112 | gate_strbuilder_create_static(&builder, ptr_target->mask, sizeof(ptr_target->mask), 0); | ||
1113 | gate_strbuilder_append_uint32(&builder, entry->prefixlength); | ||
1114 | } | ||
1115 | ptr_target->addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP; | ||
1116 | |||
1117 | if (cb) | ||
1118 | { | ||
1119 | ret = cb(ptr_target, userparam); | ||
1120 | } | ||
1121 | } | ||
1122 | return ret; | ||
1123 | } | ||
1124 | |||
1125 | |||
1126 | /* minGW-32 does not support IPv6 headers */ | ||
1127 | typedef struct gate_in6_addr | ||
1128 | { | ||
1129 | union { | ||
1130 | UCHAR Byte[16]; | ||
1131 | USHORT Word[8]; | ||
1132 | } u; | ||
1133 | } GATE_IN6_ADDR; | ||
1134 | |||
1135 | #ifndef in_addr6 | ||
1136 | #define in_addr6 in6_addr | ||
1137 | #endif | ||
1138 | |||
1139 | typedef struct gate_sockaddr_in6 | ||
1140 | { | ||
1141 | short sin6_family; | ||
1142 | USHORT sin6_port; | ||
1143 | ULONG sin6_flowinfo; | ||
1144 | struct gate_in6_addr sin6_addr; | ||
1145 | ULONG sin6_scope_id; | ||
1146 | } gate_sockaddr_in6_t; | ||
1147 | |||
1148 | #ifndef _S6_un | ||
1149 | #define _S6_un u | ||
1150 | #endif | ||
1151 | |||
1152 | #ifndef _S6_u8 | ||
1153 | #define _S6_u8 Byte | ||
1154 | #endif | ||
1155 | |||
1156 | #ifndef s6_addr | ||
1157 | #define s6_addr _S6_un._S6_u8 | ||
1158 | #endif | ||
1159 | |||
1160 | |||
1161 | gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam) | ||
1162 | { | ||
1163 | gate_result_t ret = GATE_RESULT_FAILED; | ||
1164 | PMIB_IPADDRTABLE ptr_ipaddrtable = NULL; | ||
1165 | PMIB_IPADDRROW ptr_ipaddrrow = NULL; | ||
1166 | PIP_ADAPTER_INFO ptr_adapter_info = NULL; | ||
1167 | PIP_ADAPTER_INFO ptr_adapter; | ||
1168 | PIP_ADAPTER_ADDRESSES ptr_adapter_addrs = NULL; | ||
1169 | PIP_ADAPTER_ADDRESSES ptr_addrs = NULL; | ||
1170 | PIP_ADAPTER_UNICAST_ADDRESS ptr_uni_addr; | ||
1171 | ULONG buffer_size; | ||
1172 | ULONG flags; | ||
1173 | DWORD errcode; | ||
1174 | DWORD ndx; | ||
1175 | gate_netconfig_address_t addr; | ||
1176 | gate_bool_t continue_enum = true; | ||
1177 | DWORD handled_indexes[512]; | ||
1178 | DWORD handled_indexes_count = 0; | ||
1179 | struct ipv6_cache ipv6[64]; | ||
1180 | DWORD ipv6_count = 0; | ||
1181 | struct gate_sockaddr_in6* ptr_sin6; | ||
1182 | struct ipv6_cache* ipv6_entry; | ||
1183 | gate_size_t n; | ||
1184 | |||
1185 | do | ||
1186 | { | ||
1187 | ret = load_iphlpapi(); | ||
1188 | GATE_BREAK_IF_FAILED(ret); | ||
1189 | |||
1190 | if (iphlp.GetAdaptersAddresses && continue_enum) | ||
1191 | { | ||
1192 | /* try windows XP+ API for IPv6 adapters only */ | ||
1193 | flags = GAA_FLAG_INCLUDE_PREFIX /*| GAA_FLAG_SKIP_ANYCAST*/ | GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST; | ||
1194 | buffer_size = sizeof(IP_ADAPTER_ADDRESSES); | ||
1195 | ptr_adapter_addrs = (PIP_ADAPTER_ADDRESSES)gate_mem_alloc(buffer_size); | ||
1196 | if (ptr_adapter_addrs == NULL) | ||
1197 | { | ||
1198 | ret = GATE_RESULT_OUTOFMEMORY; | ||
1199 | break; | ||
1200 | } | ||
1201 | |||
1202 | errcode = iphlp.GetAdaptersAddresses(AF_INET6, flags, NULL, ptr_adapter_addrs, &buffer_size); | ||
1203 | if (ERROR_BUFFER_OVERFLOW == errcode) | ||
1204 | { | ||
1205 | buffer_size += 1024; | ||
1206 | ptr_adapter_addrs = (PIP_ADAPTER_ADDRESSES)gate_mem_realloc(ptr_adapter_addrs, buffer_size); | ||
1207 | if (ptr_adapter_addrs == NULL) | ||
1208 | { | ||
1209 | ret = GATE_RESULT_OUTOFMEMORY; | ||
1210 | break; | ||
1211 | } | ||
1212 | errcode = iphlp.GetAdaptersAddresses(AF_INET6, flags, NULL, ptr_adapter_addrs, &buffer_size); | ||
1213 | } | ||
1214 | if (errcode != ERROR_SUCCESS) | ||
1215 | { | ||
1216 | ret = GATE_RESULT_FAILED; | ||
1217 | } | ||
1218 | else | ||
1219 | { | ||
1220 | ret = GATE_RESULT_OK; | ||
1221 | ptr_addrs = ptr_adapter_addrs; | ||
1222 | for (; continue_enum && (ptr_addrs != NULL); ptr_addrs = ptr_addrs->Next) | ||
1223 | { | ||
1224 | ndx = (ptr_addrs->IfIndex != 0) ? ptr_addrs->IfIndex : ptr_addrs->Ipv6IfIndex; | ||
1225 | if (nif && (nif->index != ndx)) | ||
1226 | { | ||
1227 | /* adapter index was not queried */ | ||
1228 | continue; | ||
1229 | } | ||
1230 | ptr_uni_addr = ptr_addrs->FirstUnicastAddress; | ||
1231 | while (ptr_uni_addr) | ||
1232 | { | ||
1233 | switch (ptr_uni_addr->Address.lpSockaddr->sa_family) | ||
1234 | { | ||
1235 | case AF_INET6: | ||
1236 | { | ||
1237 | /* add ipV6 data to cache */ | ||
1238 | ptr_sin6 = (struct gate_sockaddr_in6*)ptr_uni_addr->Address.lpSockaddr; | ||
1239 | ipv6_entry = &ipv6[ipv6_count]; | ||
1240 | ipv6_entry->adapter_index = ndx; | ||
1241 | for (n = 0; n != 16; ++n) | ||
1242 | { | ||
1243 | ipv6_entry->addr[n] = ptr_sin6->sin6_addr.s6_addr[n]; | ||
1244 | } | ||
1245 | ipv6_entry->prefixlength = ptr_uni_addr->OnLinkPrefixLength; | ||
1246 | ++ipv6_count; | ||
1247 | break; | ||
1248 | } | ||
1249 | } | ||
1250 | ptr_uni_addr = ptr_uni_addr->Next; | ||
1251 | } | ||
1252 | } | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | if (iphlp.GetAdaptersInfo && continue_enum) | ||
1257 | { | ||
1258 | /* try Win2K/Win98 API */ | ||
1259 | buffer_size = sizeof(IP_ADAPTER_INFO); | ||
1260 | ptr_adapter_info = (PIP_ADAPTER_INFO)gate_mem_alloc(buffer_size); | ||
1261 | if (ptr_adapter_info == NULL) | ||
1262 | { | ||
1263 | ret = GATE_RESULT_OUTOFMEMORY; | ||
1264 | break; | ||
1265 | } | ||
1266 | errcode = iphlp.GetAdaptersInfo(ptr_adapter_info, &buffer_size); | ||
1267 | if (errcode == ERROR_BUFFER_OVERFLOW) | ||
1268 | { | ||
1269 | ptr_adapter_info = (PIP_ADAPTER_INFO)gate_mem_realloc(ptr_adapter_info, buffer_size); | ||
1270 | if (ptr_adapter_info == NULL) | ||
1271 | { | ||
1272 | ret = GATE_RESULT_OUTOFMEMORY; | ||
1273 | break; | ||
1274 | } | ||
1275 | errcode = iphlp.GetAdaptersInfo(ptr_adapter_info, &buffer_size); | ||
1276 | } | ||
1277 | if (errcode != ERROR_SUCCESS) | ||
1278 | { | ||
1279 | ret = GATE_RESULT_FAILED; | ||
1280 | } | ||
1281 | else | ||
1282 | { | ||
1283 | ret = GATE_RESULT_OK; | ||
1284 | ptr_adapter = ptr_adapter_info; | ||
1285 | for (; continue_enum && (ptr_adapter != NULL); ptr_adapter = ptr_adapter->Next) | ||
1286 | { | ||
1287 | if (nif && (nif->index != ptr_adapter->Index)) | ||
1288 | { | ||
1289 | /* adapter index was not queried */ | ||
1290 | continue; | ||
1291 | } | ||
1292 | if (index_found(handled_indexes, handled_indexes_count, ptr_adapter->Index)) | ||
1293 | { | ||
1294 | /* this nif index was already handled */ | ||
1295 | continue; | ||
1296 | } | ||
1297 | |||
1298 | handled_indexes[handled_indexes_count] = ptr_adapter->Index; | ||
1299 | ++handled_indexes_count; | ||
1300 | |||
1301 | if (cb && continue_enum) | ||
1302 | { | ||
1303 | /* take IP address: */ | ||
1304 | continue_enum = notify_all_addr_strings(&addr, &ptr_adapter->IpAddressList, true, GATE_NETCONFIG_ADDRTYPE_HOSTIP, cb, userparam); | ||
1305 | if (continue_enum) | ||
1306 | { | ||
1307 | continue_enum = notify_all_addr_strings(&addr, &ptr_adapter->GatewayList, false, GATE_NETCONFIG_ADDRTYPE_GATEWAY, cb, userparam); | ||
1308 | if (continue_enum) | ||
1309 | { | ||
1310 | continue_enum = notify_cached_ipv6_entries(ipv6, ipv6_count, ptr_adapter->Index, &addr, cb, userparam); | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1314 | } | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | if (iphlp.GetIpAddrTable && continue_enum) | ||
1319 | { | ||
1320 | /* try NT4 API */ | ||
1321 | |||
1322 | buffer_size = sizeof(MIB_IPADDRTABLE); | ||
1323 | ptr_ipaddrtable = (PMIB_IPADDRTABLE)gate_mem_alloc(buffer_size); | ||
1324 | if (NULL == ptr_ipaddrtable) | ||
1325 | { | ||
1326 | ret = GATE_RESULT_OUTOFMEMORY; | ||
1327 | break; | ||
1328 | } | ||
1329 | |||
1330 | errcode = iphlp.GetIpAddrTable(ptr_ipaddrtable, &buffer_size, FALSE); | ||
1331 | if (errcode == ERROR_INSUFFICIENT_BUFFER) | ||
1332 | { | ||
1333 | buffer_size += 1024; /* increase the buffer just in case new addresses have been added in parallel */ | ||
1334 | ptr_ipaddrtable = (PMIB_IPADDRTABLE)gate_mem_realloc(ptr_ipaddrtable, buffer_size); | ||
1335 | if (NULL == ptr_ipaddrtable) | ||
1336 | { | ||
1337 | ret = GATE_RESULT_OUTOFMEMORY; | ||
1338 | break; | ||
1339 | } | ||
1340 | errcode = iphlp.GetIpAddrTable(ptr_ipaddrtable, &buffer_size, FALSE); | ||
1341 | } | ||
1342 | if (errcode != NO_ERROR) | ||
1343 | { | ||
1344 | ret = GATE_RESULT_FAILED; | ||
1345 | } | ||
1346 | else | ||
1347 | { | ||
1348 | ret = GATE_RESULT_OK; | ||
1349 | for (ndx = 0; continue_enum && (ndx != ptr_ipaddrtable->dwNumEntries); ++ndx) | ||
1350 | { | ||
1351 | ptr_ipaddrrow = &ptr_ipaddrtable->table[ndx]; | ||
1352 | if (nif && nif->index != ptr_ipaddrrow->dwIndex) | ||
1353 | { | ||
1354 | /* the entry is not covered by the given net-interface object */ | ||
1355 | continue; | ||
1356 | } | ||
1357 | if (index_found(handled_indexes, handled_indexes_count, ptr_ipaddrrow->dwIndex)) | ||
1358 | { | ||
1359 | /* this nif index was already handled */ | ||
1360 | continue; | ||
1361 | } | ||
1362 | |||
1363 | if (cb && ipaddrrow_to_netaddrr(ptr_ipaddrrow, &addr)) | ||
1364 | { | ||
1365 | continue_enum = cb(&addr, userparam); | ||
1366 | } | ||
1367 | } | ||
1368 | } | ||
1369 | } | ||
1370 | if (!continue_enum) | ||
1371 | { | ||
1372 | break; | ||
1373 | } | ||
1374 | |||
1375 | } while (0); | ||
1376 | |||
1377 | if (ptr_adapter_addrs) | ||
1378 | { | ||
1379 | gate_mem_dealloc(ptr_adapter_addrs); | ||
1380 | } | ||
1381 | |||
1382 | if (ptr_ipaddrtable) | ||
1383 | { | ||
1384 | gate_mem_dealloc(ptr_ipaddrtable); | ||
1385 | } | ||
1386 | if (ptr_adapter_info) | ||
1387 | { | ||
1388 | gate_mem_dealloc(ptr_adapter_info); | ||
1389 | } | ||
1390 | |||
1391 | return ret; | ||
1392 | } | ||
1393 | |||
1394 | gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled) | ||
1395 | { | ||
1396 | GATE_UNUSED_ARG(nif); | ||
1397 | GATE_UNUSED_ARG(enabled); | ||
1398 | return GATE_RESULT_NOTIMPLEMENTED; | ||
1399 | } | ||
1400 | |||
1401 | gate_result_t gate_netconfig_setup_nif_addresses(gate_netconfig_nif_t const* nif, gate_netconfig_address_t const* addresses, gate_size_t addresses_count) | ||
1402 | { | ||
1403 | GATE_UNUSED_ARG(nif); | ||
1404 | GATE_UNUSED_ARG(addresses); | ||
1405 | GATE_UNUSED_ARG(addresses_count); | ||
1406 | return GATE_RESULT_NOTIMPLEMENTED; | ||
1407 | } | ||
1408 | |||
1409 | #endif /* GATE_SYSTEM_NETCONFIG_WINAPI_IMPL */ | ||
1410 | |||
1411 | |||
1412 | #if defined(GATE_SYSTEM_NETCONFIG_POSIX_IMPL) | ||
1413 | |||
1414 | #include "gate/strings.h" | ||
1415 | #include "gate/platforms.h" | ||
1416 | |||
1417 | #include <unistd.h> | ||
1418 | #include <dlfcn.h> | ||
1419 | #include <sys/socket.h> | ||
1420 | #include <sys/ioctl.h> | ||
1421 | #include <arpa/inet.h> | ||
1422 | #include <netinet/in.h> | ||
1423 | #include <netinet/tcp.h> | ||
1424 | #include <net/if.h> | ||
1425 | #include <net/if_arp.h> | ||
1426 | #include <net/route.h> | ||
1427 | |||
1428 | #if !defined(GATE_SYS_ANDROID) | ||
1429 | # include <ifaddrs.h> | ||
1430 | #else | ||
1431 | struct ifaddrs | ||
1432 | { | ||
1433 | struct ifaddrs* ifa_next; | ||
1434 | char* ifa_name; | ||
1435 | unsigned int ifa_flags; | ||
1436 | struct sockaddr* ifa_addr; | ||
1437 | struct sockaddr* ifa_netmask; | ||
1438 | union { | ||
1439 | struct sockaddr* ifu_broadaddr; | ||
1440 | struct sockaddr* ifu_dstaddr; | ||
1441 | } ifa_ifu; | ||
1442 | void* ifa_data; | ||
1443 | }; | ||
1444 | #endif | ||
1445 | |||
1446 | #if defined(GATE_SYS_LINUX) | ||
1447 | # include <linux/netdevice.h> | ||
1448 | #endif | ||
1449 | #if defined(GATE_SYS_BSD) | ||
1450 | # include <sys/types.h> | ||
1451 | # include <sys/sysctl.h> | ||
1452 | #endif | ||
1453 | |||
1454 | typedef int(*getifaddrs_func_type)(struct ifaddrs** ifap); | ||
1455 | typedef void(*freeifaddrs_func_type)(struct ifaddrs* ifa); | ||
1456 | |||
1457 | typedef unsigned int (*if_nametoindex_func_type)(const char* ifname); | ||
1458 | typedef char* (*if_indextoname_func_type)(unsigned int ifindex, char* ifname); | ||
1459 | |||
1460 | static getifaddrs_func_type getifaddrs_func = NULL; | ||
1461 | static freeifaddrs_func_type freeifaddrs_func = NULL; | ||
1462 | static if_nametoindex_func_type if_nametoindex_func = NULL; | ||
1463 | static if_indextoname_func_type if_indextoname_func = NULL; | ||
1464 | |||
1465 | 1 | static void load_if_support_functions() | |
1466 | { | ||
1467 | 1 | getifaddrs_func = (getifaddrs_func_type)gate_posix_global_sym("getifaddrs"); | |
1468 | 1 | freeifaddrs_func = (freeifaddrs_func_type)gate_posix_global_sym("freeifaddrs"); | |
1469 | 1 | if_nametoindex_func = (if_nametoindex_func_type)gate_posix_global_sym("if_nametoindex"); | |
1470 | 1 | if_indextoname_func = (if_indextoname_func_type)gate_posix_global_sym("if_indextoname"); | |
1471 | 1 | } | |
1472 | |||
1473 | 1 | static int invoke_getifaddrs(struct ifaddrs** ifap) | |
1474 | { | ||
1475 | 1 | load_if_support_functions(); | |
1476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!getifaddrs_func) |
1477 | { | ||
1478 | ✗ | return -1; | |
1479 | } | ||
1480 | 1 | return getifaddrs_func(ifap); | |
1481 | } | ||
1482 | |||
1483 | ✗ | static unsigned int invoke_if_nametoindex(const char* ifname) | |
1484 | { | ||
1485 | ✗ | load_if_support_functions(); | |
1486 | ✗ | if (!if_nametoindex_func) | |
1487 | { | ||
1488 | ✗ | return 0; | |
1489 | } | ||
1490 | ✗ | return if_nametoindex_func(ifname); | |
1491 | } | ||
1492 | |||
1493 | 1 | static void invoke_freeifaddrs(struct ifaddrs* ifa) | |
1494 | { | ||
1495 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if (freeifaddrs_func && ifa) |
1496 | { | ||
1497 | 1 | freeifaddrs_func(ifa); | |
1498 | } | ||
1499 | 1 | } | |
1500 | |||
1501 | 3 | static gate_bool_t run_ifreq(int sockfd, struct ifreq* ptr_req, char const* if_name, gate_size_t if_name_len, unsigned long request_id) | |
1502 | { | ||
1503 | 3 | gate_mem_clear(ptr_req, sizeof(struct ifreq)); | |
1504 | 3 | gate_str_print_text(ptr_req->ifr_name, sizeof(ptr_req->ifr_name), if_name, if_name_len); | |
1505 | 3 | return (-1 != ioctl(sockfd, request_id, ptr_req)); | |
1506 | } | ||
1507 | |||
1508 | 2 | static int get_if_flags(int sockfd, char const* if_name, gate_size_t if_name_len) | |
1509 | { | ||
1510 | 2 | int ret = 0; | |
1511 | struct ifreq req; | ||
1512 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (run_ifreq(sockfd, &req, if_name, if_name_len, SIOCGIFFLAGS)) |
1513 | { | ||
1514 | 2 | ret = req.ifr_flags; | |
1515 | } | ||
1516 | 2 | return ret; | |
1517 | } | ||
1518 | |||
1519 | 1 | static gate_bool_t get_if_hardware_info(int sockfd, char const* if_name, gate_size_t if_name_len, char* ptr_mac, gate_size_t mac_len, gate_enumint_t* ptr_type) | |
1520 | { | ||
1521 | struct ifreq req; | ||
1522 | gate_strbuilder_t builder; | ||
1523 | gate_uint8_t const* ptr_mac_bytes; | ||
1524 | |||
1525 | #if defined(GATE_SYS_LINUX) | ||
1526 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (run_ifreq(sockfd, &req, if_name, if_name_len, SIOCGIFHWADDR)) |
1527 | { | ||
1528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ptr_type) |
1529 | { | ||
1530 |
1/5✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | switch (req.ifr_hwaddr.sa_family) |
1531 | { | ||
1532 | ✗ | case ARPHRD_LOOPBACK: *ptr_type = GATE_NETCONFIG_TYPE_LOOPBACK; break; | |
1533 | 1 | case ARPHRD_ETHER: | |
1534 | 1 | case ARPHRD_EETHER: *ptr_type = GATE_NETCONFIG_TYPE_ETHERNET; break; | |
1535 | ✗ | case ARPHRD_PPP: *ptr_type = GATE_NETCONFIG_TYPE_PPP; break; | |
1536 | ✗ | case ARPHRD_IEEE80211: *ptr_type = GATE_NETCONFIG_TYPE_WLAN; break; | |
1537 | ✗ | default: *ptr_type = GATE_NETCONFIG_TYPE_UNKNOWN; break; | |
1538 | } | ||
1539 | ✗ | } | |
1540 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ptr_mac) |
1541 | { | ||
1542 | 1 | ptr_mac_bytes = (gate_uint8_t const*)&req.ifr_hwaddr.sa_data; | |
1543 | 1 | gate_strbuilder_create_static(&builder, ptr_mac, mac_len, 0); | |
1544 | 1 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[0], 1, false); | |
1545 | 1 | gate_strbuilder_append_chars(&builder, 1, ':'); | |
1546 | 1 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[1], 1, false); | |
1547 | 1 | gate_strbuilder_append_chars(&builder, 1, ':'); | |
1548 | 1 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[2], 1, false); | |
1549 | 1 | gate_strbuilder_append_chars(&builder, 1, ':'); | |
1550 | 1 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[3], 1, false); | |
1551 | 1 | gate_strbuilder_append_chars(&builder, 1, ':'); | |
1552 | 1 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[4], 1, false); | |
1553 | 1 | gate_strbuilder_append_chars(&builder, 1, ':'); | |
1554 | 1 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[5], 1, false); | |
1555 | } | ||
1556 | 1 | return true; | |
1557 | } | ||
1558 | #endif | ||
1559 | #if defined(GATE_SYS_BSD) | ||
1560 | do | ||
1561 | { | ||
1562 | int sysctlparam[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; | ||
1563 | size_t needed = 0; | ||
1564 | char buf[1024]; | ||
1565 | struct if_msghdr* msghdr = NULL; | ||
1566 | sysctlparam[5] = invoke_if_nametoindex(if_name); | ||
1567 | if (sysctlparam[5] == 0) | ||
1568 | { | ||
1569 | break; | ||
1570 | } | ||
1571 | if (sysctl(sysctlparam, 6, NULL, &needed, NULL, 0) < 0) | ||
1572 | { | ||
1573 | break; | ||
1574 | } | ||
1575 | if (sysctl(sysctlparam, 6, buf, &needed, NULL, 0) < 0) | ||
1576 | { | ||
1577 | break; | ||
1578 | } | ||
1579 | msghdr = (struct if_msghdr*)buf; | ||
1580 | |||
1581 | if (ptr_type) | ||
1582 | { | ||
1583 | *ptr_type = GATE_NETCONFIG_TYPE_ETHERNET; | ||
1584 | } | ||
1585 | if (ptr_mac) | ||
1586 | { | ||
1587 | ptr_mac_bytes = (gate_uint8_t const*)msghdr; | ||
1588 | gate_strbuilder_create_static(&builder, ptr_mac, mac_len, 0); | ||
1589 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[0], 1, false); | ||
1590 | gate_strbuilder_append_chars(&builder, 1, ':'); | ||
1591 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[1], 1, false); | ||
1592 | gate_strbuilder_append_chars(&builder, 1, ':'); | ||
1593 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[2], 1, false); | ||
1594 | gate_strbuilder_append_chars(&builder, 1, ':'); | ||
1595 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[3], 1, false); | ||
1596 | gate_strbuilder_append_chars(&builder, 1, ':'); | ||
1597 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[4], 1, false); | ||
1598 | gate_strbuilder_append_chars(&builder, 1, ':'); | ||
1599 | gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[5], 1, false); | ||
1600 | } | ||
1601 | |||
1602 | return true; | ||
1603 | } while (0); | ||
1604 | |||
1605 | #endif | ||
1606 | ✗ | return false; | |
1607 | } | ||
1608 | |||
1609 | 2 | static gate_enumint_t get_status_from_ifaddrs_list(struct ifaddrs** ptr_ifaddrs_list, gate_size_t list_count, char const* if_name, gate_size_t if_name_len, gate_bool_t remove_entry) | |
1610 | { | ||
1611 | 2 | gate_enumint_t ret = GATE_NETCONFIG_STATUS_UNKNOWN; | |
1612 | 2 | gate_size_t ndx = 0; | |
1613 | gate_size_t len; | ||
1614 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
|
12 | for (ndx = 0; ndx != list_count; ++ndx) |
1615 | { | ||
1616 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | if (!ptr_ifaddrs_list[ndx]) |
1617 | { | ||
1618 | 3 | continue; | |
1619 | } | ||
1620 | 7 | len = gate_str_length(ptr_ifaddrs_list[ndx]->ifa_name); | |
1621 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
|
7 | if (0 == gate_str_compare(if_name, if_name_len, ptr_ifaddrs_list[ndx]->ifa_name, len)) |
1622 | { | ||
1623 | /* interface found */ | ||
1624 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (GATE_FLAG_ENABLED(ptr_ifaddrs_list[ndx]->ifa_flags, IFF_UP)) |
1625 | { | ||
1626 | 5 | ret = GATE_NETCONFIG_STATUS_ENABLED; | |
1627 | } | ||
1628 | ✗ | else if (ret != GATE_NETCONFIG_STATUS_ENABLED) | |
1629 | { | ||
1630 | ✗ | ret = GATE_NETCONFIG_STATUS_DISABLED; | |
1631 | } | ||
1632 | |||
1633 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (remove_entry) |
1634 | { | ||
1635 | 5 | ptr_ifaddrs_list[ndx] = NULL; | |
1636 | } | ||
1637 | } | ||
1638 | } | ||
1639 | 2 | return ret; | |
1640 | } | ||
1641 | |||
1642 | 1 | gate_result_t gate_netconfig_enum_nifs(gate_netcfg_enum_nif_callback_t cb, void* userparam) | |
1643 | { | ||
1644 | 1 | gate_result_t ret = GATE_RESULT_FAILED; | |
1645 | 1 | int sockfd = -1; | |
1646 | 1 | struct ifconf ifc = GATE_INIT_EMPTY; | |
1647 | struct ifreq* ptr_ifr; | ||
1648 | struct ifreq* ptr_ifr_end; | ||
1649 | char buffer[8192]; | ||
1650 | char const* if_name; | ||
1651 | gate_size_t if_name_len; | ||
1652 | gate_size_t counter; | ||
1653 | int result; | ||
1654 | int if_flags; | ||
1655 | gate_netconfig_nif_t nif_entry; | ||
1656 | 1 | struct ifaddrs* all_ifaddrs = NULL; | |
1657 | 1 | struct ifaddrs* ptr_ifaddrs = NULL; | |
1658 | 1 | struct ifaddrs* ifaddrs_lists[64] = GATE_INIT_EMPTY; | |
1659 | 1 | gate_size_t ifaddrs_count = 0; | |
1660 | gate_size_t ndx; | ||
1661 | 1 | gate_bool_t continue_iteration = true; | |
1662 | |||
1663 | do | ||
1664 | { | ||
1665 | 1 | result = invoke_getifaddrs(&all_ifaddrs); | |
1666 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (result == 0) |
1667 | { | ||
1668 | 1 | ptr_ifaddrs = all_ifaddrs; | |
1669 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | while (ptr_ifaddrs) |
1670 | { | ||
1671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (ifaddrs_count >= sizeof(ifaddrs_lists) / sizeof(ifaddrs_lists[0])) |
1672 | { | ||
1673 | ✗ | break; | |
1674 | } | ||
1675 | 5 | ifaddrs_lists[ifaddrs_count] = ptr_ifaddrs; | |
1676 | 5 | ++ifaddrs_count; | |
1677 | 5 | ptr_ifaddrs = ptr_ifaddrs->ifa_next; | |
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | 1 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); | |
1682 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (sockfd == -1) |
1683 | { | ||
1684 | ✗ | ret = GATE_RESULT_FAILED; | |
1685 | ✗ | break; | |
1686 | } | ||
1687 | |||
1688 | 1 | ifc.ifc_len = sizeof(buffer); | |
1689 | 1 | ifc.ifc_buf = buffer; | |
1690 | |||
1691 | 1 | result = ioctl(sockfd, SIOCGIFCONF, &ifc); | |
1692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (result == -1) |
1693 | { | ||
1694 | ✗ | ret = GATE_RESULT_FAILED; | |
1695 | ✗ | break; | |
1696 | } | ||
1697 | |||
1698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!cb) |
1699 | { | ||
1700 | ✗ | ret = GATE_RESULT_OK; | |
1701 | ✗ | break; | |
1702 | } | ||
1703 | |||
1704 | 1 | ptr_ifr = ifc.ifc_req; | |
1705 | 1 | ptr_ifr_end = ptr_ifr + (ifc.ifc_len / sizeof(struct ifreq)); | |
1706 | 1 | counter = 1; | |
1707 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
3 | for (; (ptr_ifr < ptr_ifr_end) && continue_iteration; ++ptr_ifr) |
1708 | { | ||
1709 | 2 | gate_mem_clear(&nif_entry, sizeof(nif_entry)); | |
1710 | |||
1711 | 2 | if_name = ptr_ifr->ifr_name; | |
1712 | 2 | if_name_len = gate_str_length(if_name); | |
1713 | 2 | gate_str_print_text(nif_entry.name, sizeof(nif_entry.name), if_name, if_name_len); | |
1714 | 2 | gate_str_print_text(nif_entry.uid, sizeof(nif_entry.uid), if_name, if_name_len); | |
1715 | |||
1716 | 2 | nif_entry.status = get_status_from_ifaddrs_list(ifaddrs_lists, ifaddrs_count, if_name, if_name_len, true); | |
1717 | 2 | nif_entry.index = counter++; | |
1718 | |||
1719 | 2 | if_flags = get_if_flags(sockfd, if_name, if_name_len); | |
1720 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (GATE_FLAG_ENABLED(if_flags, IFF_LOOPBACK)) |
1721 | { | ||
1722 | 1 | nif_entry.type = GATE_NETCONFIG_TYPE_LOOPBACK; | |
1723 | 1 | nif_entry.status = GATE_NETCONFIG_STATUS_ENABLED; | |
1724 | } | ||
1725 | else | ||
1726 | { | ||
1727 | 1 | get_if_hardware_info(sockfd, if_name, if_name_len, nif_entry.address, sizeof(nif_entry.address), &nif_entry.type); | |
1728 | } | ||
1729 | |||
1730 | 2 | continue_iteration = cb(&nif_entry, userparam); | |
1731 | } | ||
1732 | |||
1733 |
3/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
6 | for (ndx = 0; (ndx != ifaddrs_count) && continue_iteration; ++ndx) |
1734 | { | ||
1735 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (!ifaddrs_lists[ndx]) |
1736 | { | ||
1737 | 5 | continue; | |
1738 | } | ||
1739 | |||
1740 | ✗ | gate_mem_clear(&nif_entry, sizeof(nif_entry)); | |
1741 | |||
1742 | ✗ | if_name = ifaddrs_lists[ndx]->ifa_name; | |
1743 | ✗ | if_name_len = gate_str_length(if_name); | |
1744 | ✗ | gate_str_print_text(nif_entry.name, sizeof(nif_entry.name), if_name, if_name_len); | |
1745 | ✗ | gate_str_print_text(nif_entry.uid, sizeof(nif_entry.uid), if_name, if_name_len); | |
1746 | |||
1747 | ✗ | nif_entry.status = GATE_FLAG_ENABLED(ifaddrs_lists[ndx]->ifa_flags, IFF_UP) | |
1748 | ✗ | ? GATE_NETCONFIG_STATUS_ENABLED : GATE_NETCONFIG_STATUS_DISABLED; | |
1749 | ✗ | nif_entry.index = counter++; | |
1750 | |||
1751 | ✗ | if (sockfd != -1) | |
1752 | { | ||
1753 | ✗ | get_if_hardware_info(sockfd, if_name, if_name_len, nif_entry.address, sizeof(nif_entry.address), &nif_entry.type); | |
1754 | } | ||
1755 | |||
1756 | ✗ | continue_iteration = cb(&nif_entry, userparam); | |
1757 | } | ||
1758 | |||
1759 | 1 | ret = GATE_RESULT_OK; | |
1760 | } while (0); | ||
1761 | |||
1762 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (sockfd != -1) |
1763 | { | ||
1764 | 1 | close(sockfd); | |
1765 | } | ||
1766 | |||
1767 | 1 | invoke_freeifaddrs(all_ifaddrs); | |
1768 | |||
1769 | 1 | return ret; | |
1770 | } | ||
1771 | |||
1772 | ✗ | static void print_ipv4(char* buffer, gate_size_t buffer_len, struct sockaddr_in* in4) | |
1773 | { | ||
1774 | gate_strbuilder_t builder; | ||
1775 | ✗ | uint32_t ip4 = ntohl(in4->sin_addr.s_addr); | |
1776 | |||
1777 | ✗ | gate_strbuilder_create_static(&builder, buffer, buffer_len, 0); | |
1778 | ✗ | gate_strbuilder_append(&builder, | |
1779 | GATE_PRINT_UI8, ((ip4 >> 24) & 0xff), GATE_PRINT_CSTR, ".", | ||
1780 | ✗ | GATE_PRINT_UI8, ((ip4 >> 16) & 0xff), GATE_PRINT_CSTR, ".", | |
1781 | ✗ | GATE_PRINT_UI8, ((ip4 >> 8) & 0xff), GATE_PRINT_CSTR, ".", | |
1782 | GATE_PRINT_UI8, ((ip4) & 0xff), GATE_PRINT_END); | ||
1783 | ✗ | } | |
1784 | |||
1785 | ✗ | static void print_ipv6(char* buffer, gate_size_t buffer_len, struct sockaddr_in6* in6) | |
1786 | { | ||
1787 | gate_strbuilder_t builder; | ||
1788 | ✗ | unsigned char const* ptr = (unsigned char const*)in6->sin6_addr.s6_addr; | |
1789 | ✗ | gate_strbuilder_create_static(&builder, buffer, buffer_len, 0); | |
1790 | |||
1791 | ✗ | gate_strbuilder_append(&builder, | |
1792 | ✗ | GATE_PRINT_CSTR, "[", GATE_PRINT_H8, ptr[0], GATE_PRINT_H8, ptr[1], | |
1793 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[2], GATE_PRINT_H8, ptr[3], | |
1794 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[4], GATE_PRINT_H8, ptr[5], | |
1795 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[6], GATE_PRINT_H8, ptr[7], | |
1796 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[8], GATE_PRINT_H8, ptr[9], | |
1797 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[10], GATE_PRINT_H8, ptr[11], | |
1798 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[12], GATE_PRINT_H8, ptr[13], | |
1799 | ✗ | GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[14], GATE_PRINT_H8, ptr[15], | |
1800 | GATE_PRINT_CSTR, "]", GATE_PRINT_END); | ||
1801 | ✗ | } | |
1802 | |||
1803 | |||
1804 | ✗ | gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam) | |
1805 | { | ||
1806 | ✗ | gate_result_t ret = GATE_RESULT_FAILED; | |
1807 | ✗ | struct ifaddrs* ptr_ifaddrs = NULL; | |
1808 | struct ifaddrs* ptr_ifa; | ||
1809 | int result; | ||
1810 | char const* if_name; | ||
1811 | gate_size_t if_name_len; | ||
1812 | gate_netconfig_address_t addr; | ||
1813 | ✗ | gate_bool_t continue_enum = true; | |
1814 | |||
1815 | do | ||
1816 | { | ||
1817 | ✗ | result = invoke_getifaddrs(&ptr_ifaddrs); | |
1818 | ✗ | if (result == -1) | |
1819 | { | ||
1820 | ✗ | ret = GATE_RESULT_FAILED; | |
1821 | ✗ | break; | |
1822 | } | ||
1823 | |||
1824 | ✗ | ret = GATE_RESULT_OK; | |
1825 | ✗ | ptr_ifa = ptr_ifaddrs; | |
1826 | ✗ | for (ptr_ifa = ptr_ifaddrs; continue_enum && (ptr_ifa != NULL); ptr_ifa = ptr_ifa->ifa_next) | |
1827 | { | ||
1828 | ✗ | if (0 != gate_str_comp(ptr_ifa->ifa_name, nif->uid)) | |
1829 | { | ||
1830 | ✗ | continue; | |
1831 | } | ||
1832 | ✗ | switch (ptr_ifa->ifa_addr->sa_family) | |
1833 | { | ||
1834 | ✗ | case AF_INET: | |
1835 | { | ||
1836 | ✗ | gate_mem_clear(&addr, sizeof(addr)); | |
1837 | ✗ | print_ipv4(addr.address, sizeof(addr.address), (struct sockaddr_in*)ptr_ifa->ifa_addr); | |
1838 | ✗ | print_ipv4(addr.mask, sizeof(addr.mask), (struct sockaddr_in*)ptr_ifa->ifa_netmask); | |
1839 | ✗ | addr.addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP; | |
1840 | ✗ | break; | |
1841 | } | ||
1842 | ✗ | case AF_INET6: | |
1843 | { | ||
1844 | ✗ | gate_mem_clear(&addr, sizeof(addr)); | |
1845 | ✗ | print_ipv6(addr.address, sizeof(addr.address), (struct sockaddr_in6*)ptr_ifa->ifa_addr); | |
1846 | ✗ | addr.addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP; | |
1847 | ✗ | break; | |
1848 | } | ||
1849 | ✗ | default: | |
1850 | { | ||
1851 | ✗ | continue; | |
1852 | break; | ||
1853 | } | ||
1854 | } | ||
1855 | ✗ | if (cb) | |
1856 | { | ||
1857 | ✗ | continue_enum = cb(&addr, userparam); | |
1858 | } | ||
1859 | } | ||
1860 | |||
1861 | } while (0); | ||
1862 | |||
1863 | ✗ | if (ptr_ifaddrs) | |
1864 | { | ||
1865 | ✗ | invoke_freeifaddrs(ptr_ifaddrs); | |
1866 | } | ||
1867 | ✗ | return ret; | |
1868 | } | ||
1869 | |||
1870 | ✗ | gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled) | |
1871 | { | ||
1872 | GATE_UNUSED_ARG(nif); | ||
1873 | GATE_UNUSED_ARG(enabled); | ||
1874 | ✗ | return GATE_RESULT_NOTIMPLEMENTED; | |
1875 | } | ||
1876 | |||
1877 | ✗ | gate_result_t gate_netconfig_setup_nif_addresses(gate_netconfig_nif_t const* nif, gate_netconfig_address_t const* addresses, gate_size_t addresses_count) | |
1878 | { | ||
1879 | GATE_UNUSED_ARG(nif); | ||
1880 | GATE_UNUSED_ARG(addresses); | ||
1881 | GATE_UNUSED_ARG(addresses_count); | ||
1882 | ✗ | return GATE_RESULT_NOTIMPLEMENTED; | |
1883 | } | ||
1884 | |||
1885 | #endif /* GATE_SYSTEM_NETCONFIG_POSIX_IMPL */ | ||
1886 | |||
1887 | |||
1888 | |||
1889 | |||
1890 | #if defined(GATE_SYSTEM_NETCONFIG_NO_IMPL) | ||
1891 | |||
1892 | gate_result_t gate_netconfig_enum_nifs(gate_netcfg_enum_nif_callback_t cb, void* userparam) | ||
1893 | { | ||
1894 | GATE_UNUSED_ARG(cb); | ||
1895 | GATE_UNUSED_ARG(userparam); | ||
1896 | return GATE_RESULT_NOTIMPLEMENTED; | ||
1897 | } | ||
1898 | |||
1899 | gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam) | ||
1900 | { | ||
1901 | GATE_UNUSED_ARG(nif); | ||
1902 | GATE_UNUSED_ARG(cb); | ||
1903 | GATE_UNUSED_ARG(userparam); | ||
1904 | return GATE_RESULT_NOTIMPLEMENTED; | ||
1905 | } | ||
1906 | |||
1907 | gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled) | ||
1908 | { | ||
1909 | GATE_UNUSED_ARG(nif); | ||
1910 | GATE_UNUSED_ARG(enabled); | ||
1911 | return GATE_RESULT_NOTIMPLEMENTED; | ||
1912 | } | ||
1913 | |||
1914 | gate_result_t gate_netconfig_setup_nif_addresses(gate_netconfig_nif_t const* nif, gate_netconfig_address_t const* addresses, gate_size_t addresses_count) | ||
1915 | { | ||
1916 | GATE_UNUSED_ARG(nif); | ||
1917 | GATE_UNUSED_ARG(addresses); | ||
1918 | GATE_UNUSED_ARG(addresses_count); | ||
1919 | return GATE_RESULT_NOTIMPLEMENTED; | ||
1920 | } | ||
1921 | |||
1922 | #endif /* GATE_SYSTEM_NETCONFIG_NO_IMPL */ | ||
1923 | |||
1924 |