GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/netconfigs.c
Date: 2025-12-12 23:40:09
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-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 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 #include <net/if_arp.h>
1425 #include <net/route.h>
1426
1427 #if !defined(GATE_SYS_ANDROID)
1428 # include <ifaddrs.h>
1429 #else
1430 struct ifaddrs
1431 {
1432 struct ifaddrs* ifa_next;
1433 char* ifa_name;
1434 unsigned int ifa_flags;
1435 struct sockaddr* ifa_addr;
1436 struct sockaddr* ifa_netmask;
1437 union {
1438 struct sockaddr* ifu_broadaddr;
1439 struct sockaddr* ifu_dstaddr;
1440 } ifa_ifu;
1441 void* ifa_data;
1442 };
1443 #endif
1444
1445 #if defined(GATE_SYS_LINUX)
1446 # include <linux/netdevice.h>
1447 #endif
1448 #if defined(GATE_SYS_BSD)
1449 # include <sys/types.h>
1450 # include <sys/sysctl.h>
1451 #endif
1452
1453 typedef int(*getifaddrs_func_type)(struct ifaddrs** ifap);
1454 typedef void(*freeifaddrs_func_type)(struct ifaddrs* ifa);
1455
1456 typedef unsigned int (*if_nametoindex_func_type)(const char* ifname);
1457 typedef char* (*if_indextoname_func_type)(unsigned int ifindex, char* ifname);
1458
1459 static getifaddrs_func_type getifaddrs_func = NULL;
1460 static freeifaddrs_func_type freeifaddrs_func = NULL;
1461 static if_nametoindex_func_type if_nametoindex_func = NULL;
1462 static if_indextoname_func_type if_indextoname_func = NULL;
1463
1464 3 static void load_if_support_functions(void)
1465 {
1466 3 getifaddrs_func = (getifaddrs_func_type)gate_posix_global_sym("getifaddrs");
1467 3 freeifaddrs_func = (freeifaddrs_func_type)gate_posix_global_sym("freeifaddrs");
1468 3 if_nametoindex_func = (if_nametoindex_func_type)gate_posix_global_sym("if_nametoindex");
1469 3 if_indextoname_func = (if_indextoname_func_type)gate_posix_global_sym("if_indextoname");
1470 3 }
1471
1472 3 static int invoke_getifaddrs(struct ifaddrs** ifap)
1473 {
1474 3 load_if_support_functions();
1475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!getifaddrs_func)
1476 {
1477 return -1;
1478 }
1479 3 return getifaddrs_func(ifap);
1480 }
1481
1482 static unsigned int invoke_if_nametoindex(const char* ifname)
1483 {
1484 load_if_support_functions();
1485 if (!if_nametoindex_func)
1486 {
1487 return 0;
1488 }
1489 return if_nametoindex_func(ifname);
1490 }
1491
1492 3 static void invoke_freeifaddrs(struct ifaddrs* ifa)
1493 {
1494
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)
1495 {
1496 3 freeifaddrs_func(ifa);
1497 }
1498 3 }
1499
1500 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)
1501 {
1502 3 gate_mem_clear(ptr_req, sizeof(struct ifreq));
1503 3 gate_str_print_text(ptr_req->ifr_name, sizeof(ptr_req->ifr_name), if_name, if_name_len);
1504 3 return (-1 != ioctl(sockfd, request_id, ptr_req));
1505 }
1506
1507 2 static int get_if_flags(int sockfd, char const* if_name, gate_size_t if_name_len)
1508 {
1509 2 int ret = 0;
1510 struct ifreq req;
1511
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (run_ifreq(sockfd, &req, if_name, if_name_len, SIOCGIFFLAGS))
1512 {
1513 2 ret = req.ifr_flags;
1514 }
1515 2 return ret;
1516 }
1517
1518 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)
1519 {
1520 struct ifreq req;
1521 gate_strbuilder_t builder;
1522
1523 #if defined(GATE_SYS_LINUX)
1524
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (run_ifreq(sockfd, &req, if_name, if_name_len, SIOCGIFHWADDR))
1525 {
1526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_type)
1527 {
1528
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)
1529 {
1530 case ARPHRD_LOOPBACK: *ptr_type = GATE_NETCONFIG_TYPE_LOOPBACK; break;
1531 1 case ARPHRD_ETHER:
1532 1 case ARPHRD_EETHER: *ptr_type = GATE_NETCONFIG_TYPE_ETHERNET; break;
1533 case ARPHRD_PPP: *ptr_type = GATE_NETCONFIG_TYPE_PPP; break;
1534 case ARPHRD_IEEE80211: *ptr_type = GATE_NETCONFIG_TYPE_WLAN; break;
1535 default: *ptr_type = GATE_NETCONFIG_TYPE_UNKNOWN; break;
1536 }
1537 }
1538
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_mac)
1539 {
1540 1 gate_uint8_t const* ptr_mac_bytes = (gate_uint8_t const*)&req.ifr_hwaddr.sa_data;
1541 1 gate_strbuilder_create_static(&builder, ptr_mac, mac_len, 0);
1542 1 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[0], 1, false);
1543 1 gate_strbuilder_append_chars(&builder, 1, ':');
1544 1 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[1], 1, false);
1545 1 gate_strbuilder_append_chars(&builder, 1, ':');
1546 1 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[2], 1, false);
1547 1 gate_strbuilder_append_chars(&builder, 1, ':');
1548 1 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[3], 1, false);
1549 1 gate_strbuilder_append_chars(&builder, 1, ':');
1550 1 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[4], 1, false);
1551 1 gate_strbuilder_append_chars(&builder, 1, ':');
1552 1 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[5], 1, false);
1553 }
1554 1 return true;
1555 }
1556 #endif
1557 #if defined(GATE_SYS_BSD)
1558 do
1559 {
1560 int sysctlparam[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
1561 size_t needed = 0;
1562 char buf[1024];
1563 struct if_msghdr* msghdr = NULL;
1564 sysctlparam[5] = invoke_if_nametoindex(if_name);
1565 if (sysctlparam[5] == 0)
1566 {
1567 break;
1568 }
1569 if (sysctl(sysctlparam, 6, NULL, &needed, NULL, 0) < 0)
1570 {
1571 break;
1572 }
1573 if (sysctl(sysctlparam, 6, buf, &needed, NULL, 0) < 0)
1574 {
1575 break;
1576 }
1577 msghdr = (struct if_msghdr*)buf;
1578
1579 if (ptr_type)
1580 {
1581 *ptr_type = GATE_NETCONFIG_TYPE_ETHERNET;
1582 }
1583 if (ptr_mac)
1584 {
1585 gate_uint8_t const* ptr_mac_bytes = (gate_uint8_t const*)msghdr;
1586 gate_strbuilder_create_static(&builder, ptr_mac, mac_len, 0);
1587 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[0], 1, false);
1588 gate_strbuilder_append_chars(&builder, 1, ':');
1589 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[1], 1, false);
1590 gate_strbuilder_append_chars(&builder, 1, ':');
1591 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[2], 1, false);
1592 gate_strbuilder_append_chars(&builder, 1, ':');
1593 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[3], 1, false);
1594 gate_strbuilder_append_chars(&builder, 1, ':');
1595 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[4], 1, false);
1596 gate_strbuilder_append_chars(&builder, 1, ':');
1597 gate_strbuilder_append_hex(&builder, &ptr_mac_bytes[5], 1, false);
1598 }
1599
1600 return true;
1601 } while (0);
1602
1603 #endif
1604 return false;
1605 }
1606
1607 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)
1608 {
1609 2 gate_enumint_t ret = GATE_NETCONFIG_STATUS_UNKNOWN;
1610 2 gate_size_t ndx = 0;
1611 gate_size_t len;
1612
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for (ndx = 0; ndx != list_count; ++ndx)
1613 {
1614
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 if (!ptr_ifaddrs_list[ndx])
1615 {
1616 3 continue;
1617 }
1618 7 len = gate_str_length(ptr_ifaddrs_list[ndx]->ifa_name);
1619
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))
1620 {
1621 /* interface found */
1622
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (GATE_FLAG_ENABLED(ptr_ifaddrs_list[ndx]->ifa_flags, IFF_UP))
1623 {
1624 5 ret = GATE_NETCONFIG_STATUS_ENABLED;
1625 }
1626 else if (ret != GATE_NETCONFIG_STATUS_ENABLED)
1627 {
1628 ret = GATE_NETCONFIG_STATUS_DISABLED;
1629 }
1630
1631
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (remove_entry)
1632 {
1633 5 ptr_ifaddrs_list[ndx] = NULL;
1634 }
1635 }
1636 }
1637 2 return ret;
1638 }
1639
1640 1 gate_result_t gate_netconfig_enum_nifs(gate_netcfg_enum_nif_callback_t cb, void* userparam)
1641 {
1642 1 gate_result_t ret = GATE_RESULT_FAILED;
1643 1 int sockfd = -1;
1644 1 struct ifaddrs* all_ifaddrs = NULL;
1645
1646 do
1647 {
1648 1 struct ifconf ifc = GATE_INIT_EMPTY;
1649 struct ifreq* ptr_ifr;
1650 struct ifreq* ptr_ifr_end;
1651 char buffer[8192];
1652 char const* if_name;
1653 gate_size_t if_name_len;
1654 gate_size_t counter;
1655 int result;
1656 1 struct ifaddrs* ifaddrs_lists[64] = GATE_INIT_EMPTY;
1657 1 gate_size_t ifaddrs_count = 0;
1658 gate_size_t ndx;
1659 1 gate_bool_t continue_iteration = true;
1660
1661 1 result = invoke_getifaddrs(&all_ifaddrs);
1662
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (result == 0)
1663 {
1664 1 struct ifaddrs* ptr_ifaddrs = all_ifaddrs;
1665
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 while (ptr_ifaddrs)
1666 {
1667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ifaddrs_count >= sizeof(ifaddrs_lists) / sizeof(ifaddrs_lists[0]))
1668 {
1669 break;
1670 }
1671 5 ifaddrs_lists[ifaddrs_count] = ptr_ifaddrs;
1672 5 ++ifaddrs_count;
1673 5 ptr_ifaddrs = ptr_ifaddrs->ifa_next;
1674 }
1675 }
1676
1677 1 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sockfd == -1)
1679 {
1680 ret = GATE_RESULT_FAILED;
1681 break;
1682 }
1683
1684 1 ifc.ifc_len = sizeof(buffer);
1685 1 ifc.ifc_buf = buffer;
1686
1687 1 result = ioctl(sockfd, SIOCGIFCONF, &ifc);
1688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result == -1)
1689 {
1690 ret = GATE_RESULT_FAILED;
1691 break;
1692 }
1693
1694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!cb)
1695 {
1696 ret = GATE_RESULT_OK;
1697 break;
1698 }
1699
1700 1 ptr_ifr = ifc.ifc_req;
1701 1 ptr_ifr_end = ptr_ifr + (ifc.ifc_len / sizeof(struct ifreq));
1702 1 counter = 1;
1703
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)
1704 {
1705 int if_flags;
1706 gate_netconfig_nif_t nif_entry;
1707
1708 2 gate_mem_clear(&nif_entry, sizeof(nif_entry));
1709
1710 2 if_name = ptr_ifr->ifr_name;
1711 2 if_name_len = gate_str_length(if_name);
1712 2 gate_str_print_text(nif_entry.name, sizeof(nif_entry.name), if_name, if_name_len);
1713 2 gate_str_print_text(nif_entry.uid, sizeof(nif_entry.uid), if_name, if_name_len);
1714
1715 2 nif_entry.status = get_status_from_ifaddrs_list(ifaddrs_lists, ifaddrs_count, if_name, if_name_len, true);
1716 2 nif_entry.index = counter++;
1717
1718 2 if_flags = get_if_flags(sockfd, if_name, if_name_len);
1719
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (GATE_FLAG_ENABLED(if_flags, IFF_LOOPBACK))
1720 {
1721 1 nif_entry.type = GATE_NETCONFIG_TYPE_LOOPBACK;
1722 1 nif_entry.status = GATE_NETCONFIG_STATUS_ENABLED;
1723 }
1724 else
1725 {
1726 1 get_if_hardware_info(sockfd, if_name, if_name_len, nif_entry.address, sizeof(nif_entry.address), &nif_entry.type);
1727 }
1728
1729 2 continue_iteration = cb(&nif_entry, userparam);
1730 }
1731
1732
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)
1733 {
1734 gate_netconfig_nif_t nif_entry;
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 4 static void print_ipv4(char* buffer, gate_size_t buffer_len, struct sockaddr_in* in4)
1773 {
1774 gate_strbuilder_t builder;
1775 4 uint32_t ip4 = ntohl(in4->sin_addr.s_addr);
1776
1777 4 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
1778 12 gate_strbuilder_append(&builder,
1779 GATE_PRINT_UI8, ((ip4 >> 24) & 0xff), GATE_PRINT_CSTR, ".",
1780 4 GATE_PRINT_UI8, ((ip4 >> 16) & 0xff), GATE_PRINT_CSTR, ".",
1781 4 GATE_PRINT_UI8, ((ip4 >> 8) & 0xff), GATE_PRINT_CSTR, ".",
1782 GATE_PRINT_UI8, ((ip4) & 0xff), GATE_PRINT_END);
1783 4 }
1784
1785 1 static void print_ipv6(char* buffer, gate_size_t buffer_len, struct sockaddr_in6* in6)
1786 {
1787 gate_strbuilder_t builder;
1788 1 unsigned char const* ptr = (unsigned char const*)in6->sin6_addr.s6_addr;
1789 1 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
1790
1791 16 gate_strbuilder_append(&builder,
1792 2 GATE_PRINT_CSTR, "[", GATE_PRINT_H8, ptr[0], GATE_PRINT_H8, ptr[1],
1793 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[2], GATE_PRINT_H8, ptr[3],
1794 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[4], GATE_PRINT_H8, ptr[5],
1795 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[6], GATE_PRINT_H8, ptr[7],
1796 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[8], GATE_PRINT_H8, ptr[9],
1797 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[10], GATE_PRINT_H8, ptr[11],
1798 2 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[12], GATE_PRINT_H8, ptr[13],
1799 1 GATE_PRINT_CSTR, ":", GATE_PRINT_H8, ptr[14], GATE_PRINT_H8, ptr[15],
1800 GATE_PRINT_CSTR, "]", GATE_PRINT_END);
1801 1 }
1802
1803
1804 2 gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam)
1805 {
1806 2 gate_result_t ret = GATE_RESULT_FAILED;
1807 2 struct ifaddrs* ptr_ifaddrs = NULL;
1808 do
1809 {
1810 struct ifaddrs* ptr_ifa;
1811 2 gate_bool_t continue_enum = true;
1812 2 int result = invoke_getifaddrs(&ptr_ifaddrs);
1813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (result == -1)
1814 {
1815 ret = GATE_RESULT_FAILED;
1816 break;
1817 }
1818
1819 2 ret = GATE_RESULT_OK;
1820
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)
1821 {
1822 gate_netconfig_address_t addr;
1823
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
10 if (0 != gate_str_comp(ptr_ifa->ifa_name, nif->uid))
1824 {
1825 7 continue;
1826 }
1827
1828
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)
1829 {
1830 2 case AF_INET:
1831 {
1832 2 gate_mem_clear(&addr, sizeof(addr));
1833 2 print_ipv4(addr.address, sizeof(addr.address), (struct sockaddr_in*)ptr_ifa->ifa_addr);
1834 2 print_ipv4(addr.mask, sizeof(addr.mask), (struct sockaddr_in*)ptr_ifa->ifa_netmask);
1835 2 addr.addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP;
1836 2 break;
1837 }
1838 1 case AF_INET6:
1839 {
1840 1 gate_mem_clear(&addr, sizeof(addr));
1841 1 print_ipv6(addr.address, sizeof(addr.address), (struct sockaddr_in6*)ptr_ifa->ifa_addr);
1842 1 addr.addrtype = GATE_NETCONFIG_ADDRTYPE_HOSTIP;
1843 1 break;
1844 }
1845 2 default:
1846 {
1847 2 continue;
1848 }
1849 }
1850
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (cb)
1851 {
1852 3 continue_enum = cb(&addr, userparam);
1853 }
1854 }
1855
1856 } while (0);
1857
1858
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_ifaddrs)
1859 {
1860 2 invoke_freeifaddrs(ptr_ifaddrs);
1861 }
1862 2 return ret;
1863 }
1864
1865 gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled)
1866 {
1867 GATE_UNUSED_ARG(nif);
1868 GATE_UNUSED_ARG(enabled);
1869 return GATE_RESULT_NOTIMPLEMENTED;
1870 }
1871
1872 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)
1873 {
1874 GATE_UNUSED_ARG(nif);
1875 GATE_UNUSED_ARG(addresses);
1876 GATE_UNUSED_ARG(addresses_count);
1877 return GATE_RESULT_NOTIMPLEMENTED;
1878 }
1879
1880 #endif /* GATE_SYSTEM_NETCONFIG_POSIX_IMPL */
1881
1882
1883
1884
1885 #if defined(GATE_SYSTEM_NETCONFIG_NO_IMPL)
1886
1887 gate_result_t gate_netconfig_enum_nifs(gate_netcfg_enum_nif_callback_t cb, void* userparam)
1888 {
1889 GATE_UNUSED_ARG(cb);
1890 GATE_UNUSED_ARG(userparam);
1891 return GATE_RESULT_NOTIMPLEMENTED;
1892 }
1893
1894 gate_result_t gate_netconfig_enum_addresses(gate_netconfig_nif_t const* nif, gate_netcfg_enum_addresses_callback_t cb, void* userparam)
1895 {
1896 GATE_UNUSED_ARG(nif);
1897 GATE_UNUSED_ARG(cb);
1898 GATE_UNUSED_ARG(userparam);
1899 return GATE_RESULT_NOTIMPLEMENTED;
1900 }
1901
1902 gate_result_t gate_netconfig_enable_nif(gate_netconfig_nif_t const* nif, gate_bool_t enabled)
1903 {
1904 GATE_UNUSED_ARG(nif);
1905 GATE_UNUSED_ARG(enabled);
1906 return GATE_RESULT_NOTIMPLEMENTED;
1907 }
1908
1909 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)
1910 {
1911 GATE_UNUSED_ARG(nif);
1912 GATE_UNUSED_ARG(addresses);
1913 GATE_UNUSED_ARG(addresses_count);
1914 return GATE_RESULT_NOTIMPLEMENTED;
1915 }
1916
1917 #endif /* GATE_SYSTEM_NETCONFIG_NO_IMPL */
1918
1919