emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 094eb04: Fix MS-Windows build with mingw.org's MinGW


From: Eli Zaretskii
Subject: master 094eb04: Fix MS-Windows build with mingw.org's MinGW
Date: Tue, 26 Nov 2019 12:14:04 -0500 (EST)

branch: master
commit 094eb04ce5d8c1ccef78113c8cc6791d1d3b6bf8
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    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.
---
 src/w32.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/w32.c b/src/w32.c
index 76c2268..cb82d51 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]