diff options
| author | Eli Zaretskii | 2019-11-26 19:13:12 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2019-11-26 19:13:12 +0200 |
| commit | 094eb04ce5d8c1ccef78113c8cc6791d1d3b6bf8 (patch) | |
| tree | c9eaab424dacf2b29f3942541bc800c686d04e8d | |
| parent | 52eca2d3bdef293e9f5d64aa2b9ca36f1e00e817 (diff) | |
| download | emacs-094eb04ce5d8c1ccef78113c8cc6791d1d3b6bf8.tar.gz emacs-094eb04ce5d8c1ccef78113c8cc6791d1d3b6bf8.zip | |
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.
| -rw-r--r-- | src/w32.c | 80 |
1 files changed, 79 insertions, 1 deletions
| @@ -242,8 +242,22 @@ typedef struct _REPARSE_DATA_BUFFER { | |||
| 242 | #undef recvfrom | 242 | #undef recvfrom |
| 243 | #undef sendto | 243 | #undef sendto |
| 244 | 244 | ||
| 245 | /* We need at least XP level for GetAdaptersAddresses stuff. */ | ||
| 246 | #if _WIN32_WINNT < 0x0501 | ||
| 247 | # undef ORIG_WIN32_WINNT | ||
| 248 | # define ORIG_WIN32_WINNT _WIN32_WINNT | ||
| 249 | # undef _WIN32_WINNT | ||
| 250 | # define _WIN32_WINNT 0x0501 | ||
| 251 | #endif | ||
| 252 | |||
| 245 | #include <iphlpapi.h> /* should be after winsock2.h */ | 253 | #include <iphlpapi.h> /* should be after winsock2.h */ |
| 246 | 254 | ||
| 255 | #ifdef ORIG_WIN32_WINNT | ||
| 256 | # undef _WIN32_WINNT | ||
| 257 | # define _WIN32_WINNT ORIG_WIN32_WINNT | ||
| 258 | # undef ORIG_WIN32_WINNT | ||
| 259 | #endif | ||
| 260 | |||
| 247 | #include <wincrypt.h> | 261 | #include <wincrypt.h> |
| 248 | 262 | ||
| 249 | #include <c-strcase.h> | 263 | #include <c-strcase.h> |
| @@ -9432,6 +9446,40 @@ network_interface_get_info (Lisp_Object ifname) | |||
| 9432 | return res; | 9446 | return res; |
| 9433 | } | 9447 | } |
| 9434 | 9448 | ||
| 9449 | static bool | ||
| 9450 | address_prefix_match (int family, struct sockaddr *address, | ||
| 9451 | struct sockaddr *prefix_address, ULONG prefix_len) | ||
| 9452 | { | ||
| 9453 | UINT8 *address_data; | ||
| 9454 | UINT8 *prefix_address_data; | ||
| 9455 | int i; | ||
| 9456 | |||
| 9457 | if (family == AF_INET6) | ||
| 9458 | { | ||
| 9459 | address_data = (UINT8 *) &(((struct sockaddr_in6 *) address)->sin6_addr); | ||
| 9460 | prefix_address_data = | ||
| 9461 | (UINT8 *) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr); | ||
| 9462 | } | ||
| 9463 | else | ||
| 9464 | { | ||
| 9465 | address_data = (UINT8 *) &(((struct sockaddr_in *) address)->sin_addr); | ||
| 9466 | prefix_address_data = | ||
| 9467 | (UINT8 *) &(((struct sockaddr_in *) prefix_address)->sin_addr); | ||
| 9468 | } | ||
| 9469 | |||
| 9470 | for (i = 0; i < prefix_len >> 3; i++) | ||
| 9471 | { | ||
| 9472 | if (address_data[i] != prefix_address_data[i]) | ||
| 9473 | return false; | ||
| 9474 | } | ||
| 9475 | |||
| 9476 | if (prefix_len % 8) | ||
| 9477 | return (prefix_address_data[i] == | ||
| 9478 | (address_data[i] & (0xff << (8 - prefix_len % 8)))); | ||
| 9479 | |||
| 9480 | return true; | ||
| 9481 | } | ||
| 9482 | |||
| 9435 | Lisp_Object | 9483 | Lisp_Object |
| 9436 | network_interface_list (bool full, unsigned short match) | 9484 | network_interface_list (bool full, unsigned short match) |
| 9437 | { | 9485 | { |
| @@ -9586,7 +9634,37 @@ network_interface_list (bool full, unsigned short match) | |||
| 9586 | byte order, so convert from host to network order | 9634 | byte order, so convert from host to network order |
| 9587 | when generating the netmask. */ | 9635 | when generating the netmask. */ |
| 9588 | int i; | 9636 | int i; |
| 9589 | ULONG numbits = address->OnLinkPrefixLength; | 9637 | ULONG numbits; |
| 9638 | if (w32_major_version >= 6) /* Vista or later */ | ||
| 9639 | { | ||
| 9640 | #if _WIN32_WINNT >= 0x0600 | ||
| 9641 | numbits = address->OnLinkPrefixLength; | ||
| 9642 | #else | ||
| 9643 | /* Kludge alert! OnLinkPrefixLength is only defined | ||
| 9644 | when compiling for Vista and later. */ | ||
| 9645 | numbits = *(UINT8 *) (address->LeaseLifetime | ||
| 9646 | + sizeof (address->LeaseLifetime)); | ||
| 9647 | #endif | ||
| 9648 | } | ||
| 9649 | else /* Windows XP */ | ||
| 9650 | { | ||
| 9651 | IP_ADAPTER_PREFIX *prefix = adapter->FirstPrefix; | ||
| 9652 | numbits = 0; | ||
| 9653 | for ( ; prefix; prefix = prefix->Next) | ||
| 9654 | { | ||
| 9655 | /* We want the longest matching prefix. */ | ||
| 9656 | if (prefix->Address.lpSockaddr->sa_family | ||
| 9657 | != ifa_addr->sa_family | ||
| 9658 | || prefix->PrefixLength <= numbits) | ||
| 9659 | continue; | ||
| 9660 | if (address_prefix_match (ifa_addr->sa_family, ifa_addr, | ||
| 9661 | prefix->Address.lpSockaddr, | ||
| 9662 | prefix->PrefixLength)) | ||
| 9663 | numbits = prefix->PrefixLength; | ||
| 9664 | } | ||
| 9665 | if (!numbits) | ||
| 9666 | numbits = (ifa_addr->sa_family == AF_INET6) ? 128 : 32; | ||
| 9667 | } | ||
| 9590 | for (i = 0; i < addr_len; i++) | 9668 | for (i = 0; i < addr_len; i++) |
| 9591 | { | 9669 | { |
| 9592 | if (numbits >= 32) | 9670 | if (numbits >= 32) |