GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/netconfigs.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 161 216 74.5%
Functions: 13 16 81.2%
Branches: 47 98 48.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, 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 2 char const* gate_netconfig_print_status(gate_enumint_t status)
44 {
45
1/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2 switch (status)
46 {
47 case GATE_NETCONFIG_STATUS_UNKNOWN: return "Unknown";
48 case GATE_NETCONFIG_STATUS_DISABLED: return "Disabled";
49 2 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 2 char const* gate_netconfig_print_type(gate_enumint_t tp)
61 {
62
2/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2 switch (tp)
63 {
64 case GATE_NETCONFIG_TYPE_UNKNOWN: return "Unknown";
65 1 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 1 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(void)
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
1088 for (n = 0; ret && (n != cache_length); ++n)
1089 {
1090 gate_strbuilder_t builder;
1091 struct ipv6_cache* entry = &cache[n];
1092 if (entry->adapter_index != index)
1093 {
1094 continue;
1095 }
1096 gate_mem_clear(ptr_target, sizeof(gate_netconfig_address_t));
1097 gate_strbuilder_create_static(&builder, ptr_target->address, sizeof(ptr_target->address), 0);
1098 gate_strbuilder_append(&builder,
1099 GATE_PRINT_CSTR, "[", GATE_PRINT_H8, (entry->addr[0] & 0xff), GATE_PRINT_H8, (entry->addr[1] & 0xff),
1100 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[2] & 0xff), GATE_PRINT_H8, (entry->addr[3] & 0xff),
1101 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[4] & 0xff), GATE_PRINT_H8, (entry->addr[5] & 0xff),
1102 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[6] & 0xff), GATE_PRINT_H8, (entry->addr[7] & 0xff),
1103 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[8] & 0xff), GATE_PRINT_H8, (entry->addr[9] & 0xff),
1104 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[10] & 0xff), GATE_PRINT_H8, (entry->addr[11] & 0xff),
1105 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[12] & 0xff), GATE_PRINT_H8, (entry->addr[13] & 0xff),
1106 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, (entry->addr[14] & 0xff), GATE_PRINT_H8, (entry->addr[15] & 0xff),
1107 GATE_PRINT_CSTR, "]", GATE_PRINT_END);
1108
1109 if (entry->prefixlength)
1110 {
1111 gate_strbuilder_create_static(&builder, ptr_target->mask, sizeof(ptr_target->mask), 0);
1112 gate_strbuilder_append_uint32(&builder, entry->prefixlength);
1113 }
1114 ptr_target->addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP;
1115
1116 if (cb)
1117 {
1118 ret = cb(ptr_target, userparam);
1119 }
1120 }
1121 return ret;
1122 }
1123
1124
1125 /* minGW-32 does not support IPv6 headers */
1126 typedef struct gate_in6_addr
1127 {
1128 union {
1129 UCHAR Byte[16];
1130 USHORT Word[8];
1131 } u;
1132 } GATE_IN6_ADDR;
1133
1134 #ifndef in_addr6
1135 #define in_addr6 in6_addr
1136 #endif
1137
1138 typedef struct gate_sockaddr_in6
1139 {
1140 short sin6_family;
1141 USHORT sin6_port;
1142 ULONG sin6_flowinfo;
1143 struct gate_in6_addr sin6_addr;
1144 ULONG sin6_scope_id;
1145 } gate_sockaddr_in6_t;
1146
1147 #ifndef _S6_un
1148 #define _S6_un u
1149 #endif
1150
1151 #ifndef _S6_u8
1152 #define _S6_u8 Byte
1153 #endif
1154
1155 #ifndef s6_addr
1156 #define s6_addr _S6_un._S6_u8
1157 #endif
1158
1159
1160 gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam)
1161 {
1162 gate_result_t ret = GATE_RESULT_FAILED;
1163 PMIB_IPADDRTABLE ptr_ipaddrtable = NULL;
1164 PMIB_IPADDRROW ptr_ipaddrrow = NULL;
1165 PIP_ADAPTER_INFO ptr_adapter_info = NULL;
1166 PIP_ADAPTER_INFO ptr_adapter;
1167 PIP_ADAPTER_ADDRESSES ptr_adapter_addrs = NULL;
1168 PIP_ADAPTER_ADDRESSES ptr_addrs = NULL;
1169 PIP_ADAPTER_UNICAST_ADDRESS ptr_uni_addr;
1170 ULONG buffer_size;
1171 ULONG flags;
1172 DWORD errcode;
1173 DWORD ndx;
1174 gate_netconfig_address_t addr;
1175 gate_bool_t continue_enum = true;
1176 DWORD handled_indexes[512];
1177 DWORD handled_indexes_count = 0;
1178 struct ipv6_cache ipv6[64];
1179 DWORD ipv6_count = 0;
1180 struct gate_sockaddr_in6* ptr_sin6;
1181 struct ipv6_cache* ipv6_entry;
1182 gate_size_t n;
1183
1184 do
1185 {
1186 ret = load_iphlpapi();
1187 GATE_BREAK_IF_FAILED(ret);
1188
1189 if (iphlp.GetAdaptersAddresses && continue_enum)
1190 {
1191 /* try windows XP+ API for IPv6 adapters only */
1192 flags = GAA_FLAG_INCLUDE_PREFIX /*| GAA_FLAG_SKIP_ANYCAST*/ | GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST;
1193 buffer_size = sizeof(IP_ADAPTER_ADDRESSES);
1194 ptr_adapter_addrs = (PIP_ADAPTER_ADDRESSES)gate_mem_alloc(buffer_size);
1195 if (ptr_adapter_addrs == NULL)
1196 {
1197 ret = GATE_RESULT_OUTOFMEMORY;
1198 break;
1199 }
1200
1201 errcode = iphlp.GetAdaptersAddresses(AF_INET6, flags, NULL, ptr_adapter_addrs, &buffer_size);
1202 if (ERROR_BUFFER_OVERFLOW == errcode)
1203 {
1204 buffer_size += 1024;
1205 ptr_adapter_addrs = (PIP_ADAPTER_ADDRESSES)gate_mem_realloc(ptr_adapter_addrs, buffer_size);
1206 if (ptr_adapter_addrs == NULL)
1207 {
1208 ret = GATE_RESULT_OUTOFMEMORY;
1209 break;
1210 }
1211 errcode = iphlp.GetAdaptersAddresses(AF_INET6, flags, NULL, ptr_adapter_addrs, &buffer_size);
1212 }
1213 if (errcode != ERROR_SUCCESS)
1214 {
1215 ret = GATE_RESULT_FAILED;
1216 }
1217 else
1218 {
1219 ret = GATE_RESULT_OK;
1220 ptr_addrs = ptr_adapter_addrs;
1221 for (; continue_enum && (ptr_addrs != NULL); ptr_addrs = ptr_addrs->Next)
1222 {
1223 ndx = (ptr_addrs->IfIndex != 0) ? ptr_addrs->IfIndex : ptr_addrs->Ipv6IfIndex;
1224 if (nif && (nif->index != ndx))
1225 {
1226 /* adapter index was not queried */
1227 continue;
1228 }
1229 ptr_uni_addr = ptr_addrs->FirstUnicastAddress;
1230 while (ptr_uni_addr)
1231 {
1232 switch (ptr_uni_addr->Address.lpSockaddr->sa_family)
1233 {
1234 case AF_INET6:
1235 {
1236 /* add ipV6 data to cache */
1237 ptr_sin6 = (struct gate_sockaddr_in6*)ptr_uni_addr->Address.lpSockaddr;
1238 ipv6_entry = &ipv6[ipv6_count];
1239 ipv6_entry->adapter_index = ndx;
1240 for (n = 0; n != 16; ++n)
1241 {
1242 ipv6_entry->addr[n] = ptr_sin6->sin6_addr.s6_addr[n];
1243 }
1244 ipv6_entry->prefixlength = ptr_uni_addr->OnLinkPrefixLength;
1245 ++ipv6_count;
1246 break;
1247 }
1248 }
1249 ptr_uni_addr = ptr_uni_addr->Next;
1250 }
1251 }
1252 }
1253 }
1254
1255 if (iphlp.GetAdaptersInfo && continue_enum)
1256 {
1257 /* try Win2K/Win98 API */
1258 buffer_size = sizeof(IP_ADAPTER_INFO);
1259 ptr_adapter_info = (PIP_ADAPTER_INFO)gate_mem_alloc(buffer_size);
1260 if (ptr_adapter_info == NULL)
1261 {
1262 ret = GATE_RESULT_OUTOFMEMORY;
1263 break;
1264 }
1265 errcode = iphlp.GetAdaptersInfo(ptr_adapter_info, &buffer_size);
1266 if (errcode == ERROR_BUFFER_OVERFLOW)
1267 {
1268 ptr_adapter_info = (PIP_ADAPTER_INFO)gate_mem_realloc(ptr_adapter_info, buffer_size);
1269 if (ptr_adapter_info == NULL)
1270 {
1271 ret = GATE_RESULT_OUTOFMEMORY;
1272 break;
1273 }
1274 errcode = iphlp.GetAdaptersInfo(ptr_adapter_info, &buffer_size);
1275 }
1276 if (errcode != ERROR_SUCCESS)
1277 {
1278 ret = GATE_RESULT_FAILED;
1279 }
1280 else
1281 {
1282 ret = GATE_RESULT_OK;
1283 ptr_adapter = ptr_adapter_info;
1284 for (; continue_enum && (ptr_adapter != NULL); ptr_adapter = ptr_adapter->Next)
1285 {
1286 if (nif && (nif->index != ptr_adapter->Index))
1287 {
1288 /* adapter index was not queried */
1289 continue;
1290 }
1291 if (index_found(handled_indexes, handled_indexes_count, ptr_adapter->Index))
1292 {
1293 /* this nif index was already handled */
1294 continue;
1295 }
1296
1297 handled_indexes[handled_indexes_count] = ptr_adapter->Index;
1298 ++handled_indexes_count;
1299
1300 if (cb && continue_enum)
1301 {
1302 /* take IP address: */
1303 continue_enum = notify_all_addr_strings(&addr, &ptr_adapter->IpAddressList, true, GATE_NETCONFIG_ADDRTYPE_HOSTIP, cb, userparam);
1304 if (continue_enum)
1305 {
1306 continue_enum = notify_all_addr_strings(&addr, &ptr_adapter->GatewayList, false, GATE_NETCONFIG_ADDRTYPE_GATEWAY, cb, userparam);
1307 if (continue_enum)
1308 {
1309 continue_enum = notify_cached_ipv6_entries(ipv6, ipv6_count, ptr_adapter->Index, &addr, cb, userparam);
1310 }
1311 }
1312 }
1313 }
1314 }
1315 }
1316
1317 if (iphlp.GetIpAddrTable && continue_enum)
1318 {
1319 /* try NT4 API */
1320
1321 buffer_size = sizeof(MIB_IPADDRTABLE);
1322 ptr_ipaddrtable = (PMIB_IPADDRTABLE)gate_mem_alloc(buffer_size);
1323 if (NULL == ptr_ipaddrtable)
1324 {
1325 ret = GATE_RESULT_OUTOFMEMORY;
1326 break;
1327 }
1328
1329 errcode = iphlp.GetIpAddrTable(ptr_ipaddrtable, &buffer_size, FALSE);
1330 if (errcode == ERROR_INSUFFICIENT_BUFFER)
1331 {
1332 buffer_size += 1024; /* increase the buffer just in case new addresses have been added in parallel */
1333 ptr_ipaddrtable = (PMIB_IPADDRTABLE)gate_mem_realloc(ptr_ipaddrtable, buffer_size);
1334 if (NULL == ptr_ipaddrtable)
1335 {
1336 ret = GATE_RESULT_OUTOFMEMORY;
1337 break;
1338 }
1339 errcode = iphlp.GetIpAddrTable(ptr_ipaddrtable, &buffer_size, FALSE);
1340 }
1341 if (errcode != NO_ERROR)
1342 {
1343 ret = GATE_RESULT_FAILED;
1344 }
1345 else
1346 {
1347 ret = GATE_RESULT_OK;
1348 for (ndx = 0; continue_enum && (ndx != ptr_ipaddrtable->dwNumEntries); ++ndx)
1349 {
1350 ptr_ipaddrrow = &ptr_ipaddrtable->table[ndx];
1351 if (nif && nif->index != ptr_ipaddrrow->dwIndex)
1352 {
1353 /* the entry is not covered by the given net-interface object */
1354 continue;
1355 }
1356 if (index_found(handled_indexes, handled_indexes_count, ptr_ipaddrrow->dwIndex))
1357 {
1358 /* this nif index was already handled */
1359 continue;
1360 }
1361
1362 if (cb && ipaddrrow_to_netaddrr(ptr_ipaddrrow, &addr))
1363 {
1364 continue_enum = cb(&addr, userparam);
1365 }
1366 }
1367 }
1368 }
1369 if (!continue_enum)
1370 {
1371 break;
1372 }
1373
1374 } while (0);
1375
1376 if (ptr_adapter_addrs)
1377 {
1378 gate_mem_dealloc(ptr_adapter_addrs);
1379 }
1380
1381 if (ptr_ipaddrtable)
1382 {
1383 gate_mem_dealloc(ptr_ipaddrtable);
1384 }
1385 if (ptr_adapter_info)
1386 {
1387 gate_mem_dealloc(ptr_adapter_info);
1388 }
1389
1390 return ret;
1391 }
1392
1393 gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled)
1394 {
1395 GATE_UNUSED_ARG(nif);
1396 GATE_UNUSED_ARG(enabled);
1397 return GATE_RESULT_NOTIMPLEMENTED;
1398 }
1399
1400 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)
1401 {
1402 GATE_UNUSED_ARG(nif);
1403 GATE_UNUSED_ARG(addresses);
1404 GATE_UNUSED_ARG(addresses_count);
1405 return GATE_RESULT_NOTIMPLEMENTED;
1406 }
1407
1408 #endif /* GATE_SYSTEM_NETCONFIG_WINAPI_IMPL */
1409
1410
1411 #if defined(GATE_SYSTEM_NETCONFIG_POSIX_IMPL)
1412
1413 #include "gate/strings.h"
1414 #include "gate/platforms.h"
1415
1416 #include <unistd.h>
1417 #include <dlfcn.h>
1418 #include <sys/socket.h>
1419 #include <sys/ioctl.h>
1420 #include <arpa/inet.h>
1421 #include <netinet/in.h>
1422 #include <netinet/tcp.h>
1423 #include <net/if.h>
1424 #if !defined(GATE_SYS_DARWIN)
1425 # include <net/if_arp.h>
1426 #endif
1427 #include <net/route.h>
1428
1429 #if !defined(GATE_SYS_ANDROID)
1430 # include <ifaddrs.h>
1431 #else
1432 struct ifaddrs
1433 {
1434 struct ifaddrs* ifa_next;
1435 char* ifa_name;
1436 unsigned int ifa_flags;
1437 struct sockaddr* ifa_addr;
1438 struct sockaddr* ifa_netmask;
1439 union {
1440 struct sockaddr* ifu_broadaddr;
1441 struct sockaddr* ifu_dstaddr;
1442 } ifa_ifu;
1443 void* ifa_data;
1444 };
1445 #endif
1446
1447 #if defined(GATE_SYS_LINUX)
1448 # include <linux/netdevice.h>
1449 #endif
1450 #if defined(GATE_SYS_BSD)
1451 # include <sys/types.h>
1452 # include <sys/sysctl.h>
1453 #endif
1454
1455 typedef int(*getifaddrs_func_type)(struct ifaddrs** ifap);
1456 typedef void(*freeifaddrs_func_type)(struct ifaddrs* ifa);
1457
1458 typedef unsigned int (*if_nametoindex_func_type)(const char* ifname);
1459 typedef char* (*if_indextoname_func_type)(unsigned int ifindex, char* ifname);
1460
1461 static getifaddrs_func_type getifaddrs_func = NULL;
1462 static freeifaddrs_func_type freeifaddrs_func = NULL;
1463 static if_nametoindex_func_type if_nametoindex_func = NULL;
1464 static if_indextoname_func_type if_indextoname_func = NULL;
1465
1466 3 static void load_if_support_functions(void)
1467 {
1468 3 getifaddrs_func = (getifaddrs_func_type)gate_posix_global_sym("getifaddrs");
1469 3 freeifaddrs_func = (freeifaddrs_func_type)gate_posix_global_sym("freeifaddrs");
1470 3 if_nametoindex_func = (if_nametoindex_func_type)gate_posix_global_sym("if_nametoindex");
1471 3 if_indextoname_func = (if_indextoname_func_type)gate_posix_global_sym("if_indextoname");
1472 3 }
1473
1474 3 static int invoke_getifaddrs(struct ifaddrs** ifap)
1475 {
1476 3 load_if_support_functions();
1477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!getifaddrs_func)
1478 {
1479 return -1;
1480 }
1481 3 return getifaddrs_func(ifap);
1482 }
1483
1484 static unsigned int invoke_if_nametoindex(const char* ifname)
1485 {
1486 load_if_support_functions();
1487 if (!if_nametoindex_func)
1488 {
1489 return 0;
1490 }
1491 return if_nametoindex_func(ifname);
1492 }
1493
1494 3 static void invoke_freeifaddrs(struct ifaddrs* ifa)
1495 {
1496
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (freeifaddrs_func && ifa)
1497 {
1498 3 freeifaddrs_func(ifa);
1499 }
1500 3 }
1501
1502 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)
1503 {
1504 3 gate_mem_clear(ptr_req, sizeof(struct ifreq));
1505 3 gate_str_print_text(ptr_req->ifr_name, sizeof(ptr_req->ifr_name), if_name, if_name_len);
1506 3 return (-1 != ioctl(sockfd, request_id, ptr_req));
1507 }
1508
1509 2 static int get_if_flags(int sockfd, char const* if_name, gate_size_t if_name_len)
1510 {
1511 2 int ret = 0;
1512 struct ifreq req;
1513
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (run_ifreq(sockfd, &req, if_name, if_name_len, SIOCGIFFLAGS))
1514 {
1515 2 ret = req.ifr_flags;
1516 }
1517 2 return ret;
1518 }
1519
1520 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)
1521 {
1522 struct ifreq req;
1523 gate_strbuilder_t builder;
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 gate_uint8_t const* 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 gate_uint8_t const* 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 ifaddrs* all_ifaddrs = NULL;
1647
1648 do
1649 {
1650 1 struct ifconf ifc = GATE_INIT_EMPTY;
1651 struct ifreq* ptr_ifr;
1652 struct ifreq* ptr_ifr_end;
1653 char buffer[8192];
1654 char const* if_name;
1655 gate_size_t if_name_len;
1656 gate_size_t counter;
1657 int result;
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 1 result = invoke_getifaddrs(&all_ifaddrs);
1664
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (result == 0)
1665 {
1666 1 struct ifaddrs* ptr_ifaddrs = all_ifaddrs;
1667
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 while (ptr_ifaddrs)
1668 {
1669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ifaddrs_count >= sizeof(ifaddrs_lists) / sizeof(ifaddrs_lists[0]))
1670 {
1671 break;
1672 }
1673 5 ifaddrs_lists[ifaddrs_count] = ptr_ifaddrs;
1674 5 ++ifaddrs_count;
1675 5 ptr_ifaddrs = ptr_ifaddrs->ifa_next;
1676 }
1677 }
1678
1679 1 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sockfd == -1)
1681 {
1682 ret = GATE_RESULT_FAILED;
1683 break;
1684 }
1685
1686 1 ifc.ifc_len = sizeof(buffer);
1687 1 ifc.ifc_buf = buffer;
1688
1689 1 result = ioctl(sockfd, SIOCGIFCONF, &ifc);
1690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result == -1)
1691 {
1692 ret = GATE_RESULT_FAILED;
1693 break;
1694 }
1695
1696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!cb)
1697 {
1698 ret = GATE_RESULT_OK;
1699 break;
1700 }
1701
1702 1 ptr_ifr = ifc.ifc_req;
1703 1 ptr_ifr_end = ptr_ifr + (ifc.ifc_len / sizeof(struct ifreq));
1704 1 counter = 1;
1705
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)
1706 {
1707 int if_flags;
1708 gate_netconfig_nif_t nif_entry;
1709
1710 2 gate_mem_clear(&nif_entry, sizeof(nif_entry));
1711
1712 2 if_name = ptr_ifr->ifr_name;
1713 2 if_name_len = gate_str_length(if_name);
1714 2 gate_str_print_text(nif_entry.name, sizeof(nif_entry.name), if_name, if_name_len);
1715 2 gate_str_print_text(nif_entry.uid, sizeof(nif_entry.uid), if_name, if_name_len);
1716
1717 2 nif_entry.status = get_status_from_ifaddrs_list(ifaddrs_lists, ifaddrs_count, if_name, if_name_len, true);
1718 2 nif_entry.index = counter++;
1719
1720 2 if_flags = get_if_flags(sockfd, if_name, if_name_len);
1721
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (GATE_FLAG_ENABLED(if_flags, IFF_LOOPBACK))
1722 {
1723 1 nif_entry.type = GATE_NETCONFIG_TYPE_LOOPBACK;
1724 1 nif_entry.status = GATE_NETCONFIG_STATUS_ENABLED;
1725 }
1726 else
1727 {
1728 1 get_if_hardware_info(sockfd, if_name, if_name_len, nif_entry.address, sizeof(nif_entry.address), &nif_entry.type);
1729 }
1730
1731 2 continue_iteration = cb(&nif_entry, userparam);
1732 }
1733
1734
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)
1735 {
1736 gate_netconfig_nif_t nif_entry;
1737
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!ifaddrs_lists[ndx])
1738 {
1739 5 continue;
1740 }
1741
1742 gate_mem_clear(&nif_entry, sizeof(nif_entry));
1743
1744 if_name = ifaddrs_lists[ndx]->ifa_name;
1745 if_name_len = gate_str_length(if_name);
1746 gate_str_print_text(nif_entry.name, sizeof(nif_entry.name), if_name, if_name_len);
1747 gate_str_print_text(nif_entry.uid, sizeof(nif_entry.uid), if_name, if_name_len);
1748
1749 nif_entry.status = GATE_FLAG_ENABLED(ifaddrs_lists[ndx]->ifa_flags, IFF_UP)
1750 ? GATE_NETCONFIG_STATUS_ENABLED : GATE_NETCONFIG_STATUS_DISABLED;
1751 nif_entry.index = counter++;
1752
1753 if (sockfd != -1)
1754 {
1755 get_if_hardware_info(sockfd, if_name, if_name_len, nif_entry.address, sizeof(nif_entry.address), &nif_entry.type);
1756 }
1757
1758 continue_iteration = cb(&nif_entry, userparam);
1759 }
1760
1761 1 ret = GATE_RESULT_OK;
1762 } while (0);
1763
1764
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sockfd != -1)
1765 {
1766 1 close(sockfd);
1767 }
1768
1769 1 invoke_freeifaddrs(all_ifaddrs);
1770
1771 1 return ret;
1772 }
1773
1774 4 static void print_ipv4(char* buffer, gate_size_t buffer_len, struct sockaddr_in* in4)
1775 {
1776 gate_strbuilder_t builder;
1777 4 uint32_t ip4 = ntohl(in4->sin_addr.s_addr);
1778
1779 4 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
1780 12 gate_strbuilder_append(&builder,
1781 GATE_PRINT_UI8, ((ip4 >> 24) & 0xff), GATE_PRINT_CSTR, ".",
1782 4 GATE_PRINT_UI8, ((ip4 >> 16) & 0xff), GATE_PRINT_CSTR, ".",
1783 4 GATE_PRINT_UI8, ((ip4 >> 8) & 0xff), GATE_PRINT_CSTR, ".",
1784 GATE_PRINT_UI8, ((ip4) & 0xff), GATE_PRINT_END);
1785 4 }
1786
1787 1 static void print_ipv6(char* buffer, gate_size_t buffer_len, struct sockaddr_in6* in6)
1788 {
1789 gate_strbuilder_t builder;
1790 1 unsigned char const* ptr = (unsigned char const*)in6->sin6_addr.s6_addr;
1791 1 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
1792
1793 16 gate_strbuilder_append(&builder,
1794 2 GATE_PRINT_CSTR, "[", GATE_PRINT_H8, ptr[0], GATE_PRINT_H8, ptr[1],
1795 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[2], GATE_PRINT_H8, ptr[3],
1796 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[4], GATE_PRINT_H8, ptr[5],
1797 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[6], GATE_PRINT_H8, ptr[7],
1798 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[8], GATE_PRINT_H8, ptr[9],
1799 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[10], GATE_PRINT_H8, ptr[11],
1800 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[12], GATE_PRINT_H8, ptr[13],
1801 1 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[14], GATE_PRINT_H8, ptr[15],
1802 GATE_PRINT_CSTR, "]", GATE_PRINT_END);
1803 1 }
1804
1805
1806 2 gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam)
1807 {
1808 2 gate_result_t ret = GATE_RESULT_FAILED;
1809 2 struct ifaddrs* ptr_ifaddrs = NULL;
1810 do
1811 {
1812 struct ifaddrs* ptr_ifa;
1813 2 gate_bool_t continue_enum = true;
1814 2 int result = invoke_getifaddrs(&ptr_ifaddrs);
1815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (result == -1)
1816 {
1817 ret = GATE_RESULT_FAILED;
1818 break;
1819 }
1820
1821 2 ret = GATE_RESULT_OK;
1822
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 2 times.
12 for (ptr_ifa = ptr_ifaddrs; continue_enum && (ptr_ifa != NULL); ptr_ifa = ptr_ifa->ifa_next)
1823 {
1824 gate_netconfig_address_t addr;
1825
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
10 if (0 != gate_str_comp(ptr_ifa->ifa_name, nif->uid))
1826 {
1827 7 continue;
1828 }
1829
1830
3/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
5 switch (ptr_ifa->ifa_addr->sa_family)
1831 {
1832 2 case AF_INET:
1833 {
1834 2 gate_mem_clear(&addr, sizeof(addr));
1835 2 print_ipv4(addr.address, sizeof(addr.address), (struct sockaddr_in*)ptr_ifa->ifa_addr);
1836 2 print_ipv4(addr.mask, sizeof(addr.mask), (struct sockaddr_in*)ptr_ifa->ifa_netmask);
1837 2 addr.addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP;
1838 2 break;
1839 }
1840 1 case AF_INET6:
1841 {
1842 1 gate_mem_clear(&addr, sizeof(addr));
1843 1 print_ipv6(addr.address, sizeof(addr.address), (struct sockaddr_in6*)ptr_ifa->ifa_addr);
1844 1 addr.addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP;
1845 1 break;
1846 }
1847 2 default:
1848 {
1849 2 continue;
1850 }
1851 }
1852
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (cb)
1853 {
1854 3 continue_enum = cb(&addr, userparam);
1855 }
1856 }
1857
1858 } while (0);
1859
1860
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_ifaddrs)
1861 {
1862 2 invoke_freeifaddrs(ptr_ifaddrs);
1863 }
1864 2 return ret;
1865 }
1866
1867 gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled)
1868 {
1869 GATE_UNUSED_ARG(nif);
1870 GATE_UNUSED_ARG(enabled);
1871 return GATE_RESULT_NOTIMPLEMENTED;
1872 }
1873
1874 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)
1875 {
1876 GATE_UNUSED_ARG(nif);
1877 GATE_UNUSED_ARG(addresses);
1878 GATE_UNUSED_ARG(addresses_count);
1879 return GATE_RESULT_NOTIMPLEMENTED;
1880 }
1881
1882 #endif /* GATE_SYSTEM_NETCONFIG_POSIX_IMPL */
1883
1884
1885
1886
1887 #if defined(GATE_SYSTEM_NETCONFIG_NO_IMPL)
1888
1889 gate_result_t gate_netconfig_enum_nifs(gate_netcfg_enum_nif_callback_t cb, void* userparam)
1890 {
1891 GATE_UNUSED_ARG(cb);
1892 GATE_UNUSED_ARG(userparam);
1893 return GATE_RESULT_NOTIMPLEMENTED;
1894 }
1895
1896 gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam)
1897 {
1898 GATE_UNUSED_ARG(nif);
1899 GATE_UNUSED_ARG(cb);
1900 GATE_UNUSED_ARG(userparam);
1901 return GATE_RESULT_NOTIMPLEMENTED;
1902 }
1903
1904 gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled)
1905 {
1906 GATE_UNUSED_ARG(nif);
1907 GATE_UNUSED_ARG(enabled);
1908 return GATE_RESULT_NOTIMPLEMENTED;
1909 }
1910
1911 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)
1912 {
1913 GATE_UNUSED_ARG(nif);
1914 GATE_UNUSED_ARG(addresses);
1915 GATE_UNUSED_ARG(addresses_count);
1916 return GATE_RESULT_NOTIMPLEMENTED;
1917 }
1918
1919 #endif /* GATE_SYSTEM_NETCONFIG_NO_IMPL */
1920
1921