GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/netconfigs.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 106 218 48.6%
Functions: 8 16 50.0%
Branches: 33 98 33.7%

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