Commit 094eb04c authored by Eli Zaretskii's avatar Eli Zaretskii

Fix MS-Windows build with mingw.org's MinGW

mingw.org's MinGW by default targets Windows 9X, so
_WIN32_WINNT is set to a value that bypasses declarations
in system headers we need to compile network_interface_list.
Also, the code needed a workaround for Windows XP, where
some functionality is missing from the GetAdaptersAddresses
API.

* src/w32.c (_WIN32_WINNT): Define to 0x0501, if the value is
lower, temporarily while processing iphlpapi.h.
(address_prefix_match): New helper function.
(network_interface_list): Work around the fact that the
OnLinkPrefixLength member of IP_ADAPTER_UNICAST_ADDRESS is not
available when _WIN32_WINNT < 0x0600.  On Windows XP use
special code that calls address_prefix_match to compute the
network prefix length.
parent 52eca2d3
Pipeline #4165 failed with stage
in 64 minutes and 39 seconds
......@@ -242,8 +242,22 @@ typedef struct _REPARSE_DATA_BUFFER {
#undef recvfrom
#undef sendto
/* We need at least XP level for GetAdaptersAddresses stuff. */
#if _WIN32_WINNT < 0x0501
# undef ORIG_WIN32_WINNT
# define ORIG_WIN32_WINNT _WIN32_WINNT
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
#endif
#include <iphlpapi.h> /* should be after winsock2.h */
#ifdef ORIG_WIN32_WINNT
# undef _WIN32_WINNT
# define _WIN32_WINNT ORIG_WIN32_WINNT
# undef ORIG_WIN32_WINNT
#endif
#include <wincrypt.h>
#include <c-strcase.h>
......@@ -9432,6 +9446,40 @@ network_interface_get_info (Lisp_Object ifname)
return res;
}
static bool
address_prefix_match (int family, struct sockaddr *address,
struct sockaddr *prefix_address, ULONG prefix_len)
{
UINT8 *address_data;
UINT8 *prefix_address_data;
int i;
if (family == AF_INET6)
{
address_data = (UINT8 *) &(((struct sockaddr_in6 *) address)->sin6_addr);
prefix_address_data =
(UINT8 *) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr);
}
else
{
address_data = (UINT8 *) &(((struct sockaddr_in *) address)->sin_addr);
prefix_address_data =
(UINT8 *) &(((struct sockaddr_in *) prefix_address)->sin_addr);
}
for (i = 0; i < prefix_len >> 3; i++)
{
if (address_data[i] != prefix_address_data[i])
return false;
}
if (prefix_len % 8)
return (prefix_address_data[i] ==
(address_data[i] & (0xff << (8 - prefix_len % 8))));
return true;
}
Lisp_Object
network_interface_list (bool full, unsigned short match)
{
......@@ -9586,7 +9634,37 @@ network_interface_list (bool full, unsigned short match)
byte order, so convert from host to network order
when generating the netmask. */
int i;
ULONG numbits = address->OnLinkPrefixLength;
ULONG numbits;
if (w32_major_version >= 6) /* Vista or later */
{
#if _WIN32_WINNT >= 0x0600
numbits = address->OnLinkPrefixLength;
#else
/* Kludge alert! OnLinkPrefixLength is only defined
when compiling for Vista and later. */
numbits = *(UINT8 *) (address->LeaseLifetime
+ sizeof (address->LeaseLifetime));
#endif
}
else /* Windows XP */
{
IP_ADAPTER_PREFIX *prefix = adapter->FirstPrefix;
numbits = 0;
for ( ; prefix; prefix = prefix->Next)
{
/* We want the longest matching prefix. */
if (prefix->Address.lpSockaddr->sa_family
!= ifa_addr->sa_family
|| prefix->PrefixLength <= numbits)
continue;
if (address_prefix_match (ifa_addr->sa_family, ifa_addr,
prefix->Address.lpSockaddr,
prefix->PrefixLength))
numbits = prefix->PrefixLength;
}
if (!numbits)
numbits = (ifa_addr->sa_family == AF_INET6) ? 128 : 32;
}
for (i = 0; i < addr_len; i++)
{
if (numbits >= 32)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment