22#include "pubnub_internal.h"
33
44#include "core/pubnub_dns_servers.h"
5- #include "lib/pubnub_parse_ipv4_addr.h"
65#include "core/pubnub_assert.h"
76#include "core/pubnub_log.h"
87
98#include <winsock2.h>
109#include <iphlpapi.h>
11- #include <stdio.h>
1210#include <windows.h>
13-
11+ #include <string.h>
1412
1513#pragma comment(lib, "IPHLPAPI.lib")
1614
17-
1815#define MALLOC (x ) HeapAlloc(GetProcessHeap(), 0, (x))
1916#define FREE (x ) HeapFree(GetProcessHeap(), 0, (x))
2017
18+
19+ /* Check if an IPv4 address already exists in the array */
20+ static int ipv4_already_exists (
21+ const struct pubnub_ipv4_address * array ,
22+ const size_t count ,
23+ const unsigned char new_ip [4 ])
24+ {
25+ for (size_t i = 0 ; i < count ; i ++ ) {
26+ if (memcmp (array [i ].ipv4 , new_ip , 4 ) == 0 ) {
27+ return 1 ; /* Found duplicate */
28+ }
29+ }
30+ return 0 ; /* Not found */
31+ }
32+
2133int pubnub_dns_read_system_servers_ipv4 (struct pubnub_ipv4_address * o_ipv4 , size_t n )
2234{
23- FIXED_INFO * pFixedInfo ;
24- ULONG ulOutBufLen ;
25- DWORD dwRetVal ;
26- IP_ADDR_STRING * pIPAddr ;
27- unsigned j ;
28-
29- pFixedInfo = (FIXED_INFO * )MALLOC (sizeof (FIXED_INFO ));
30- if (pFixedInfo == NULL ) {
31- PUBNUB_LOG_ERROR (
32- "Error allocating memory needed to call GetNetworkParams\n" );
33- return -1 ;
35+ ULONG buflen ;
36+ DWORD ret ;
37+ IP_ADAPTER_ADDRESSES * addrs ;
38+ IP_ADAPTER_ADDRESSES * aa ;
39+ IP_ADAPTER_DNS_SERVER_ADDRESS * ds ;
40+ const struct sockaddr_in * sin ;
41+ DWORD net_addr ;
42+ unsigned j ;
43+ unsigned char temp_ip [4 ];
44+
45+ if (!o_ipv4 || n == 0 ) {
46+ return 0 ;
3447 }
35- ulOutBufLen = sizeof (FIXED_INFO );
36-
37- // Make an initial call to GetAdaptersInfo to get
38- // the necessary size into the ulOutBufLen variable
39- if (GetNetworkParams (pFixedInfo , & ulOutBufLen ) == ERROR_BUFFER_OVERFLOW ) {
40- FREE (pFixedInfo );
41- pFixedInfo = (FIXED_INFO * )MALLOC (ulOutBufLen );
42- if (pFixedInfo == NULL ) {
43- PUBNUB_LOG_ERROR (
44- "Error allocating memory needed to call GetNetworkParams\n" );
45- return -1 ;
46- }
48+
49+ buflen = 0 ;
50+ j = 0 ;
51+
52+ /* Get required buffer size */
53+ ret = GetAdaptersAddresses (
54+ AF_INET ,
55+ GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST , /* keep DNS servers */
56+ NULL , NULL , & buflen
57+ );
58+
59+ if (ret != ERROR_BUFFER_OVERFLOW || buflen == 0 ) {
60+ PUBNUB_LOG_ERROR ("GetAdaptersAddresses preflight failed: %lu\n" , (unsigned long )ret );
61+ return -1 ;
4762 }
48- dwRetVal = GetNetworkParams (pFixedInfo , & ulOutBufLen );
49- if (NO_ERROR == dwRetVal ) {
50- j = 0 ;
51- pIPAddr = & pFixedInfo -> DnsServerList ;
52- while ((j < n ) && pIPAddr ) {
53- struct pubnub_ipv4_address addr ;
54- if (pubnub_parse_ipv4_addr (pIPAddr -> IpAddress .String , & addr ) == 0 ) {
55- memcpy (o_ipv4 [j ++ ].ipv4 , addr .ipv4 , sizeof o_ipv4 [0 ].ipv4 );
56- }
57- pIPAddr = pIPAddr -> Next ;
58- }
63+
64+ addrs = (IP_ADAPTER_ADDRESSES * )MALLOC (buflen );
65+ if (!addrs ) {
66+ PUBNUB_LOG_ERROR ("OOM allocating %lu for GetAdaptersAddresses\n" , (unsigned long )buflen );
67+ return -1 ;
5968 }
60- else {
61- PUBNUB_LOG_ERROR ("GetNetworkParams failed with error: %d\n" , dwRetVal );
62- FREE (pFixedInfo );
69+
70+ /* Get adapter information */
71+ ret = GetAdaptersAddresses (
72+ AF_INET ,
73+ GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST , /* keep DNS servers */
74+ NULL , addrs , & buflen
75+ );
76+ if (ret != NO_ERROR ) {
77+ PUBNUB_LOG_ERROR ("GetAdaptersAddresses failed: %lu\n" , (unsigned long )ret );
78+ FREE (addrs );
6379 return -1 ;
6480 }
6581
66- FREE (pFixedInfo );
82+ /* Enumerate adapters and collect unique DNS servers */
83+ for (aa = addrs ; aa && j < n ; aa = aa -> Next ) {
84+ for (ds = aa -> FirstDnsServerAddress ; ds && j < n ; ds = ds -> Next ) {
85+ if (!ds -> Address .lpSockaddr ||
86+ ds -> Address .lpSockaddr -> sa_family != AF_INET ) {
87+ continue ;
88+ }
89+
90+ sin = (const struct sockaddr_in * )ds -> Address .lpSockaddr ;
91+ net_addr = sin -> sin_addr .S_un .S_addr ;
92+ if (net_addr == 0 ) {
93+ continue ; /* skip 0.0.0.0 */
94+ }
95+
96+ /* Convert from network order to host order, then extract bytes */
97+ {
98+ DWORD host_addr = ntohl (net_addr );
99+ temp_ip [0 ] = (unsigned char )((host_addr >> 24 ) & 0xFF );
100+ temp_ip [1 ] = (unsigned char )((host_addr >> 16 ) & 0xFF );
101+ temp_ip [2 ] = (unsigned char )((host_addr >> 8 ) & 0xFF );
102+ temp_ip [3 ] = (unsigned char )( host_addr & 0xFF );
103+ }
104+
105+ if (!ipv4_already_exists (o_ipv4 , j , temp_ip )) {
106+ o_ipv4 [j ].ipv4 [0 ] = temp_ip [0 ];
107+ o_ipv4 [j ].ipv4 [1 ] = temp_ip [1 ];
108+ o_ipv4 [j ].ipv4 [2 ] = temp_ip [2 ];
109+ o_ipv4 [j ].ipv4 [3 ] = temp_ip [3 ];
110+ ++ j ;
111+ }
112+ }
113+ }
67114
68- return j ;
115+ FREE (addrs );
116+ return (int )j ;
69117}
0 commit comments