remove a ton of ded win32 code

pull/1228/head
Rick V 4 years ago
parent 938f40efe1
commit df634b7775
No known key found for this signature in database
GPG Key ID: C0EDC8723FDC3465

@ -76,17 +76,6 @@ operator==(const sockaddr_in6& a, const sockaddr_in6& b)
// microsoft c++ and mingw 64-bit builds call the normal function
#define DEFAULT_BUFFER_SIZE 15000
// the inline monkey patch for downlevel platforms
#ifndef _MSC_VER
extern "C" DWORD FAR PASCAL
_GetAdaptersAddresses(
ULONG Family,
ULONG Flags,
PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen);
#endif
// in any case, we still need to implement some form of
// getifaddrs(3) with compatible semantics on NT...
// daemon.ini section [bind] will have something like
@ -282,357 +271,15 @@ _llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
return true;
}
#if 0
/* Supports both IPv4 and IPv6 addressing. The size of IP_ADAPTER_ADDRESSES
* changes between Windows XP, XP SP1, and Vista with additional members.
*
* Interfaces that are not "operationally up" will typically return a host
* IP address with the defined IPv4 link-local prefix 169.254.0.0/16.
* Adapters with a static configured IP address but down will return both
* the IPv4 link-local prefix and the static address.
*
* It is easier to say "not up" rather than "down" as this API returns six
* effective down status values: down, testing, unknown, dormant, not present,
* and lower layer down.
*
* Available in Windows XP and Wine 1.3.
*
* NOTE(despair): an inline implementation is provided, much like
* getaddrinfo(3) for old hosts. See "win32_intrnl.*"
*/
static bool
_llarp_nt_getadaptersaddresses(struct llarp_nt_ifaddrs_t** ifap)
{
DWORD dwSize = DEFAULT_BUFFER_SIZE, dwRet;
IP_ADAPTER_ADDRESSES *pAdapterAddresses = nullptr, *adapter;
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
#ifdef DEBUG
fprintf(stderr, "IP_ADAPTER_ADDRESSES buffer length %lu bytes.\n", dwSize);
#endif
pAdapterAddresses = (IP_ADAPTER_ADDRESSES*)_llarp_nt_heap_alloc(dwSize);
dwRet = _GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterAddresses);
pAdapterAddresses = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS:
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return FALSE;
default:
errno = _doserrno;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return FALSE;
}
/* count valid adapters */
int n = 0, k = 0;
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
for(IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
unicast; unicast = unicast->Next)
{
/* ensure IP adapter */
if(AF_INET != unicast->Address.lpSockaddr->sa_family
&& AF_INET6 != unicast->Address.lpSockaddr->sa_family)
{
continue;
}
++n;
}
}
/* contiguous block for adapter list */
struct _llarp_nt_ifaddrs_t* ifa =
llarp_nt_new0(struct _llarp_nt_ifaddrs_t, n);
struct _llarp_nt_ifaddrs_t* ift = ifa;
/* now populate list */
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
int unicastIndex = 0;
for(IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
unicast; unicast = unicast->Next, ++unicastIndex)
{
/* ensure IP adapter */
if(AF_INET != unicast->Address.lpSockaddr->sa_family
&& AF_INET6 != unicast->Address.lpSockaddr->sa_family)
{
continue;
}
/* address */
ift->_ifa.ifa_addr = (sockaddr*)&ift->_addr;
memcpy(ift->_ifa.ifa_addr, unicast->Address.lpSockaddr,
unicast->Address.iSockaddrLength);
/* name */
#ifdef DEBUG
fprintf(stderr, "name:%s IPv4 index:%lu IPv6 index:%lu\n",
adapter->AdapterName, adapter->IfIndex, adapter->Ipv6IfIndex);
#endif
ift->_ifa.ifa_name = ift->_name;
StringCchCopyN(ift->_ifa.ifa_name, 256, adapter->AdapterName, 256);
/* flags */
ift->_ifa.ifa_flags = 0;
if(IfOperStatusUp == adapter->OperStatus)
ift->_ifa.ifa_flags |= IFF_UP;
if(IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
ift->_ifa.ifa_flags |= IFF_LOOPBACK;
if(!(adapter->Flags & IP_ADAPTER_NO_MULTICAST))
ift->_ifa.ifa_flags |= IFF_MULTICAST;
/* netmask */
ift->_ifa.ifa_netmask = (sockaddr*)&ift->_netmask;
/* pre-Vista must hunt for matching prefix in linked list, otherwise use
* OnLinkPrefixLength from IP_ADAPTER_UNICAST_ADDRESS structure.
* FirstPrefix requires Windows XP SP1, from SP1 to pre-Vista provides a
* single adapter prefix for each IP address. Vista and later provides
* host IP address prefix, subnet IP address, and subnet broadcast IP
* address. In addition there is a multicast and broadcast address
* prefix.
*/
ULONG prefixLength = 0;
#if defined(_WIN32) && (_WIN32_WINNT >= 0x0600)
/* For a unicast IPv4 address, any value greater than 32 is an illegal
* value. For a unicast IPv6 address, any value greater than 128 is an
* illegal value. A value of 255 is commonly used to represent an illegal
* value.
*
* Windows 7 SP1 returns 64 for Teredo links which is incorrect.
*/
#define IN6_IS_ADDR_TEREDO(addr) (((const uint32_t*)(addr))[0] == ntohl(0x20010000))
if(AF_INET6 == unicast->Address.lpSockaddr->sa_family &&
/* TunnelType only applies to one interface on the adapter and no
* convenient method is provided to determine which.
*/
TUNNEL_TYPE_TEREDO == adapter->TunnelType &&
/* Test the interface with the known Teredo network prefix.
*/
IN6_IS_ADDR_TEREDO(
&((struct sockaddr_in6*)(unicast->Address.lpSockaddr))->sin6_addr)
&&
/* Test that this version is actually wrong, subsequent releases from
* Microsoft may resolve the issue.
*/
32 != unicast->OnLinkPrefixLength)
{
#ifdef DEBUG
fprintf(stderr,
"IPv6 Teredo tunneling adapter %s prefix length is an "
"illegal value %lu, overriding to 32.\n",
adapter->AdapterName, unicast->OnLinkPrefixLength);
#endif
prefixLength = 32;
}
else
prefixLength = unicast->OnLinkPrefixLength;
#else
/* The order of linked IP_ADAPTER_UNICAST_ADDRESS structures pointed to by
* the FirstUnicastAddress member does not have any relationship with the
* order of linked IP_ADAPTER_PREFIX structures pointed to by the
* FirstPrefix member.
*
* Example enumeration:
* [ no subnet ]
* ::1/128 - address
* ff00::%1/8 - multicast (no IPv6 broadcast)
* 127.0.0.0/8 - subnet
* 127.0.0.1/32 - address
* 127.255.255.255/32 - subnet broadcast
* 224.0.0.0/4 - multicast
* 255.255.255.255/32 - broadcast
*
* Which differs from most adapters listing three IPv6:
* fe80::%10/64 - subnet
* fe80::51e9:5fe5:4202:325a%10/128 - address
* ff00::%10/8 - multicast
*
* !IfOperStatusUp IPv4 addresses are skipped:
* fe80::%13/64 - subnet
* fe80::d530:946d:e8df:8c91%13/128 - address
* ff00::%13/8 - multicast
* [ no subnet ]
* [ no address ]
* 224.0.0.0/4 - multicast
* 255.255.255.255/32 - broadcast
*
* On PTP links no multicast or broadcast addresses are returned:
* [ no subnet ]
* fe80::5efe:10.203.9.30/128 - address
* [ no multicast ]
* [ no multicast ]
* [ no broadcast ]
*
* Active primary IPv6 interfaces are a bit overloaded:
* ::/0 - default route
* 2001::/32 - global subnet
* 2001:0:4137:9e76:2443:d6:ba87:1a2a/128 - global address
* fe80::/64 - link-local subnet
* fe80::2443:d6:ba87:1a2a/128 - link-local address
* ff00::/8 - multicast
*/
#define IN_LINKLOCAL(a) ((((uint32_t)(a)) & 0xaffff0000) == 0xa9fe0000)
for(IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix;
prefix = prefix->Next)
{
LPSOCKADDR lpSockaddr = prefix->Address.lpSockaddr;
if(lpSockaddr->sa_family != unicast->Address.lpSockaddr->sa_family)
continue;
/* special cases */
/* RFC2863: IPv4 interface not up */
if(AF_INET == lpSockaddr->sa_family
&& adapter->OperStatus != IfOperStatusUp)
{
/* RFC3927: link-local IPv4 always has 16-bit CIDR */
if(IN_LINKLOCAL(
ntohl(((struct sockaddr_in*)(unicast->Address.lpSockaddr))
->sin_addr.s_addr)))
{
#ifdef DEBUG
fprintf(stderr,
"Assuming 16-bit prefix length for link-local IPv4 "
"adapter %s.\n",
adapter->AdapterName);
#endif
prefixLength = 16;
}
else
{
#ifdef DEBUG
fprintf(stderr, "Prefix length unavailable for IPv4 adapter %s.\n",
adapter->AdapterName);
#endif
}
break;
}
/* default IPv6 route */
if(AF_INET6 == lpSockaddr->sa_family && 0 == prefix->PrefixLength
&& IN6_IS_ADDR_UNSPECIFIED(
&((struct sockaddr_in6*)(lpSockaddr))->sin6_addr))
{
#ifdef DEBUG
fprintf(stderr,
"Ingoring unspecified address prefix on IPv6 adapter %s.\n",
adapter->AdapterName);
#endif
continue;
}
/* Assume unicast address for first prefix of operational adapter */
if(AF_INET == lpSockaddr->sa_family)
assert(!IN_MULTICAST(
ntohl(((struct sockaddr_in*)(lpSockaddr))->sin_addr.s_addr)));
if(AF_INET6 == lpSockaddr->sa_family)
assert(!IN6_IS_ADDR_MULTICAST(
&((struct sockaddr_in6*)(lpSockaddr))->sin6_addr));
/* Assume subnet or host IP address for XP backward compatibility */
prefixLength = prefix->PrefixLength;
break;
}
#endif /* defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 ) */
/* map prefix to netmask */
ift->_ifa.ifa_netmask->sa_family = unicast->Address.lpSockaddr->sa_family;
switch(unicast->Address.lpSockaddr->sa_family)
{
case AF_INET:
if(0 == prefixLength || prefixLength > 32)
{
#ifdef DEBUG
fprintf(stderr,
"IPv4 adapter %s prefix length is an illegal value "
"%lu, overriding to 32.\n",
adapter->AdapterName, prefixLength);
#endif
prefixLength = 32;
}
/* NB: left-shift of full bit-width is undefined in C standard. */
((struct sockaddr_in*)ift->_ifa.ifa_netmask)->sin_addr.s_addr =
htonl(0xffffffffU << (32 - prefixLength));
break;
case AF_INET6:
if(0 == prefixLength || prefixLength > 128)
{
#ifdef DEBUG
fprintf(stderr,
"IPv6 adapter %s prefix length is an illegal value "
"%lu, overriding to 128.\n",
adapter->AdapterName, prefixLength);
#endif
prefixLength = 128;
}
for(LONG i = prefixLength, j = 0; i > 0; i -= 8, ++j)
{
((struct sockaddr_in6*)ift->_ifa.ifa_netmask)
->sin6_addr.s6_addr[j] =
i >= 8 ? 0xff : (ULONG)((0xffU << (8 - i)) & 0xffU);
}
break;
}
/* next */
if(k++ < (n - 1))
{
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
}
else
{
ift->_ifa.ifa_next = nullptr;
}
}
}
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
*ifap = (struct llarp_nt_ifaddrs_t*)ifa;
return TRUE;
}
#endif
// an implementation of if_nametoindex(3) based on GetAdapterIndex(2)
// with a fallback to GetAdaptersAddresses(2) commented out for now
// unless it becomes evident that the first codepath fails in certain
// edge cases?
static unsigned
_llarp_nt_getadaptersaddresses_nametoindex(const char* ifname)
_llarp_nt_nametoindex(const char* ifname)
{
ULONG ifIndex;
DWORD /* dwSize = 4096,*/ dwRet;
// IP_ADAPTER_ADDRESSES *pAdapterAddresses = nullptr, *adapter;
DWORD dwRet;
char szAdapterName[256];
if (!ifname)
@ -645,64 +292,6 @@ _llarp_nt_getadaptersaddresses_nametoindex(const char* ifname)
return ifIndex;
else
return 0;
#if 0
/* fallback to finding index via iterating adapter list */
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
pAdapterAddresses = (IP_ADAPTER_ADDRESSES*)_llarp_nt_heap_alloc(dwSize);
dwRet = _GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterAddresses);
pAdapterAddresses = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS:
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
default:
errno = _doserrno;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
}
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
if(0 == strcmp(szAdapterName, adapter->AdapterName))
{
// ifIndex = AF_INET6 == iffamily ? adapter->Ipv6IfIndex :
// adapter->IfIndex;
_llarp_nt_heap_free(pAdapterAddresses);
return ifIndex;
}
}
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
#endif
}
// the emulated getifaddrs(3) itself.
@ -730,7 +319,7 @@ llarp_nt_if_nametoindex(const char* ifname)
{
if (!ifname)
return 0;
return _llarp_nt_getadaptersaddresses_nametoindex(ifname);
return _llarp_nt_nametoindex(ifname);
}
// fix up names for win32

@ -14,10 +14,6 @@
#include <net/net.h>
#include <windows.h>
#include <iphlpapi.h>
#if WINNT_CROSS_COMPILE && !NTSTATUS
typedef LONG NTSTATUS;
#endif
#include "win32_intrnl.h"
const char*
inet_ntop(int af, const void* src, char* dst, size_t size)
@ -95,212 +91,4 @@ inet_pton(int af, const char* src, void* dst)
return 0;
}
typedef struct _InterfaceIndexTable
{
DWORD numIndexes;
IF_INDEX indexes[1];
} InterfaceIndexTable;
// windows 2000
// todo(despair86): implement IPv6 detection using
// the ipv6 preview stack/adv net pack from 1999/2001
DWORD FAR PASCAL
_GetAdaptersAddresses(
ULONG Family,
ULONG Flags,
PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen)
{
InterfaceIndexTable* indexTable;
IFInfo ifInfo;
int i;
ULONG ret, requiredSize = 0;
PIP_ADAPTER_ADDRESSES currentAddress;
PUCHAR currentLocation;
HANDLE tcpFile;
(void)(Family);
if (!pOutBufLen)
return ERROR_INVALID_PARAMETER;
if (Reserved)
return ERROR_INVALID_PARAMETER;
indexTable = getInterfaceIndexTable();
if (!indexTable)
return ERROR_NOT_ENOUGH_MEMORY;
ret = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(ret))
return ERROR_NO_DATA;
for (i = indexTable->numIndexes; i >= 0; i--)
{
if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
/* The whole struct */
requiredSize += sizeof(IP_ADAPTER_ADDRESSES);
/* Friendly name */
if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
requiredSize += strlen((char*)ifInfo.if_info.ent.if_descr) + 1; // FIXME
/* Adapter name */
requiredSize += strlen((char*)ifInfo.if_info.ent.if_descr) + 1;
/* Unicast address */
if (!(Flags & GAA_FLAG_SKIP_UNICAST))
requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
/* FIXME: Implement multicast, anycast, and dns server stuff */
/* FIXME: Implement dns suffix and description */
requiredSize += 2 * sizeof(WCHAR);
/* We're only going to implement what's required for XP SP0 */
}
}
#ifdef DEBUG
fprintf(stderr, "size: %ld, requiredSize: %ld\n", *pOutBufLen, requiredSize);
#endif
if (!pAdapterAddresses || *pOutBufLen < requiredSize)
{
*pOutBufLen = requiredSize;
closeTcpFile(tcpFile);
free(indexTable);
return ERROR_BUFFER_OVERFLOW;
}
RtlZeroMemory(pAdapterAddresses, requiredSize);
/* Let's set up the pointers */
currentAddress = pAdapterAddresses;
for (i = indexTable->numIndexes; i >= 0; i--)
{
if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
currentLocation = (PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES);
/* FIXME: Friendly name */
if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
currentAddress->FriendlyName = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
}
/* Adapter name */
currentAddress->AdapterName = (PVOID)currentLocation;
currentLocation += strlen((char*)ifInfo.if_info.ent.if_descr) + 1;
/* Unicast address */
if (!(Flags & GAA_FLAG_SKIP_UNICAST))
{
currentAddress->FirstUnicastAddress = (PVOID)currentLocation;
currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
currentAddress->FirstUnicastAddress->Address.lpSockaddr = (PVOID)currentLocation;
currentLocation += sizeof(struct sockaddr);
}
/* FIXME: Implement multicast, anycast, and dns server stuff */
/* FIXME: Implement dns suffix and description */
currentAddress->DnsSuffix = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
currentAddress->Description = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
currentAddress->Next = (PVOID)currentLocation;
/* Terminate the last address correctly */
if (i == 0)
currentAddress->Next = NULL;
/* We're only going to implement what's required for XP SP0 */
currentAddress = currentAddress->Next;
}
}
/* Now again, for real this time */
currentAddress = pAdapterAddresses;
for (i = indexTable->numIndexes; i >= 0; i--)
{
if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
/* Make sure we're not looping more than we hoped for */
assert(currentAddress);
/* Alignment information */
currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES);
currentAddress->IfIndex = indexTable->indexes[i];
/* Adapter name */
strcpy(currentAddress->AdapterName, (char*)ifInfo.if_info.ent.if_descr);
if (!(Flags & GAA_FLAG_SKIP_UNICAST))
{
currentAddress->FirstUnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
currentAddress->FirstUnicastAddress->Flags = 0; // FIXME
currentAddress->FirstUnicastAddress->Next =
NULL; // FIXME: Support more than one address per adapter
currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
memcpy(
currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data,
&ifInfo.ip_addr.iae_addr,
sizeof(ifInfo.ip_addr.iae_addr));
currentAddress->FirstUnicastAddress->Address.iSockaddrLength =
sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT);
currentAddress->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther; // FIXME
currentAddress->FirstUnicastAddress->SuffixOrigin = IpSuffixOriginOther; // FIXME
currentAddress->FirstUnicastAddress->DadState = IpDadStatePreferred; // FIXME
currentAddress->FirstUnicastAddress->ValidLifetime = 0xFFFFFFFF; // FIXME
currentAddress->FirstUnicastAddress->PreferredLifetime = 0xFFFFFFFF; // FIXME
currentAddress->FirstUnicastAddress->LeaseLifetime = 0xFFFFFFFF; // FIXME
}
/* FIXME: Implement multicast, anycast, and dns server stuff */
currentAddress->FirstAnycastAddress = NULL;
currentAddress->FirstMulticastAddress = NULL;
currentAddress->FirstDnsServerAddress = NULL;
/* FIXME: Implement dns suffix, description, and friendly name */
currentAddress->DnsSuffix[0] = UNICODE_NULL;
currentAddress->Description[0] = UNICODE_NULL;
currentAddress->FriendlyName[0] = UNICODE_NULL;
/* Physical Address */
memcpy(
currentAddress->PhysicalAddress,
ifInfo.if_info.ent.if_physaddr,
ifInfo.if_info.ent.if_physaddrlen);
currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen;
/* Flags */
currentAddress->Flags = 0; // FIXME
/* MTU */
currentAddress->Mtu = ifInfo.if_info.ent.if_mtu;
/* Interface type */
currentAddress->IfType = ifInfo.if_info.ent.if_type;
/* Operational status */
if (ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING)
currentAddress->OperStatus = IfOperStatusUp;
else
currentAddress->OperStatus = IfOperStatusDown;
/* We're only going to implement what's required for XP SP0 */
/* Move to the next address */
currentAddress = currentAddress->Next;
}
}
closeTcpFile(tcpFile);
free(indexTable);
return NO_ERROR;
}
#endif

@ -1,566 +1,3 @@
#if defined(__MINGW32__) && !defined(_WIN64)
/*
* All the user-mode scaffolding necessary to backport GetAdaptersAddresses(2))
* to the NT 5.x series. See further comments for any limitations.
* NOTE: this is dead code, i haven't had time to debug it yet due to illness.
* For now, downlevel platforms use GetAdaptersInfo(2) which is inet4 only.
* -despair86 20/08/18
*/
#include <assert.h>
#include <stdio.h>
// apparently mingw-w64 loses its shit over this
// but only for 32-bit builds, naturally
#ifdef WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#endif
// these need to be in a specific order
#include <windows.h>
#include <winternl.h>
#include <tdi.h>
#include "win32_intrnl.h"
const PWCHAR TcpFileName = L"\\Device\\Tcp";
// from ntdll.dll
typedef void(FAR PASCAL* pRtlInitUString)(UNICODE_STRING*, const WCHAR*);
typedef NTSTATUS(FAR PASCAL* pNTOpenFile)(
HANDLE*, ACCESS_MASK, OBJECT_ATTRIBUTES*, IO_STATUS_BLOCK*, ULONG, ULONG);
typedef NTSTATUS(FAR PASCAL* pNTClose)(HANDLE);
#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
#define _TCP_CTL_CODE(Function, Method, Access) CTL_CODE(FSCTL_TCP_BASE, Function, Method, Access)
#define IOCTL_TCP_QUERY_INFORMATION_EX _TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef struct _InterfaceIndexTable
{
DWORD numIndexes;
DWORD numAllocated;
DWORD indexes[1];
} InterfaceIndexTable;
NTSTATUS
tdiGetMibForIfEntity(HANDLE tcpFile, TDIEntityID* ent, IFEntrySafelySized* entry)
{
TCP_REQUEST_QUERY_INFORMATION_EX req;
NTSTATUS status = 0;
DWORD returnSize;
#ifdef DEBUG
fprintf(
stderr,
"TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n",
(int)tcpFile,
(int)ent->tei_instance);
#endif
memset(&req, 0, sizeof(req));
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = 1;
req.ID.toi_entity = *ent;
status = DeviceIoControl(
tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entry,
sizeof(*entry),
&returnSize,
NULL);
if (!status)
{
perror("IOCTL Failed\n");
return 0xc0000001;
}
fprintf(
stderr,
"TdiGetMibForIfEntity() => {\n"
" if_index ....................... %lx\n"
" if_type ........................ %lx\n"
" if_mtu ......................... %ld\n"
" if_speed ....................... %lx\n"
" if_physaddrlen ................. %ld\n",
entry->ent.if_index,
entry->ent.if_type,
entry->ent.if_mtu,
entry->ent.if_speed,
entry->ent.if_physaddrlen);
fprintf(
stderr,
" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
" if_descr ....................... %s\n",
entry->ent.if_physaddr[0] & 0xff,
entry->ent.if_physaddr[1] & 0xff,
entry->ent.if_physaddr[2] & 0xff,
entry->ent.if_physaddr[3] & 0xff,
entry->ent.if_physaddr[4] & 0xff,
entry->ent.if_physaddr[5] & 0xff,
entry->ent.if_descr);
fprintf(stderr, "} status %08lx\n", status);
return 0;
}
static NTSTATUS
tdiGetSetOfThings(
HANDLE tcpFile,
DWORD toiClass,
DWORD toiType,
DWORD toiId,
DWORD teiEntity,
DWORD teiInstance,
DWORD fixedPart,
DWORD entrySize,
PVOID* tdiEntitySet,
PDWORD numEntries)
{
TCP_REQUEST_QUERY_INFORMATION_EX req;
PVOID entitySet = 0;
NTSTATUS status = 0;
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES,
arraySize = entrySize * MAX_TDI_ENTITIES;
memset(&req, 0, sizeof(req));
req.ID.toi_class = toiClass;
req.ID.toi_type = toiType;
req.ID.toi_id = toiId;
req.ID.toi_entity.tei_entity = teiEntity;
req.ID.toi_entity.tei_instance = teiInstance;
/* There's a subtle problem here...
* If an interface is added at this exact instant, (as if by a PCMCIA
* card insertion), the array will still not have enough entries after
* have allocated it after the first DeviceIoControl call.
*
* We'll get around this by repeating until the number of interfaces
* stabilizes.
*/
do
{
status = DeviceIoControl(
tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
0,
0,
&allocationSizeForEntityArray,
NULL);
if (!status)
return 0xc0000001;
arraySize = allocationSizeForEntityArray;
entitySet = HeapAlloc(GetProcessHeap(), 0, arraySize);
if (!entitySet)
{
status = ((NTSTATUS)0xC000009A);
return status;
}
status = DeviceIoControl(
tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entitySet,
arraySize,
&allocationSizeForEntityArray,
NULL);
/* This is why we have the loop -- we might have added an adapter */
if (arraySize == allocationSizeForEntityArray)
break;
HeapFree(GetProcessHeap(), 0, entitySet);
entitySet = 0;
if (!status)
return 0xc0000001;
} while (TRUE); /* We break if the array we received was the size we
* expected. Therefore, we got here because it wasn't */
*numEntries = (arraySize - fixedPart) / entrySize;
*tdiEntitySet = entitySet;
return 0;
}
static NTSTATUS
tdiGetEntityIDSet(HANDLE tcpFile, TDIEntityID** entitySet, PDWORD numEntities)
{
NTSTATUS status = tdiGetSetOfThings(
tcpFile,
INFO_CLASS_GENERIC,
INFO_TYPE_PROVIDER,
ENTITY_LIST_ID,
GENERIC_ENTITY,
0,
0,
sizeof(TDIEntityID),
(PVOID*)entitySet,
numEntities);
return status;
}
NTSTATUS
tdiGetIpAddrsForIpEntity(HANDLE tcpFile, TDIEntityID* ent, IPAddrEntry** addrs, PDWORD numAddrs)
{
NTSTATUS status;
#ifdef DEBUG
fprintf(
stderr,
"TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%lx)\n",
tcpFile,
ent->tei_instance);
#endif
status = tdiGetSetOfThings(
tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
0x102,
CL_NL_ENTITY,
ent->tei_instance,
0,
sizeof(IPAddrEntry),
(PVOID*)addrs,
numAddrs);
return status;
}
static VOID
tdiFreeThingSet(PVOID things)
{
HeapFree(GetProcessHeap(), 0, things);
}
NTSTATUS
openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess)
{
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
pRtlInitUString _RtlInitUnicodeString;
pNTOpenFile _NTOpenFile;
HANDLE ntdll;
ntdll = GetModuleHandle("ntdll.dll");
_RtlInitUnicodeString = (pRtlInitUString)GetProcAddress(ntdll, "RtlInitUnicodeString");
_NTOpenFile = (pNTOpenFile)GetProcAddress(ntdll, "NtOpenFile");
_RtlInitUnicodeString(&fileName, TcpFileName);
InitializeObjectAttributes(&objectAttributes, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = _NTOpenFile(
tcpFile,
DesiredAccess | SYNCHRONIZE,
&objectAttributes,
&ioStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
/* String does not need to be freed: it points to the constant
* string we provided */
if (!NT_SUCCESS(status))
*tcpFile = INVALID_HANDLE_VALUE;
return status;
}
VOID
closeTcpFile(HANDLE h)
{
pNTClose _NTClose;
HANDLE ntdll = GetModuleHandle("ntdll.dll");
_NTClose = (pNTClose)GetProcAddress(ntdll, "NtClose");
assert(h != INVALID_HANDLE_VALUE);
_NTClose(h);
}
BOOL
isLoopback(HANDLE tcpFile, TDIEntityID* loop_maybe)
{
IFEntrySafelySized entryInfo;
NTSTATUS status;
status = tdiGetMibForIfEntity(tcpFile, loop_maybe, &entryInfo);
return NT_SUCCESS(status) && (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK);
}
BOOL
isIpEntity(HANDLE tcpFile, TDIEntityID* ent)
{
UNREFERENCED_PARAMETER(tcpFile);
return (ent->tei_entity == CL_NL_ENTITY || ent->tei_entity == CO_NL_ENTITY);
}
NTSTATUS
getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID* ent)
{
DWORD numEntities = 0;
DWORD numRoutes = 0;
TDIEntityID* entitySet = 0;
NTSTATUS status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
unsigned i;
if (!NT_SUCCESS(status))
return status;
for (i = 0; i < numEntities; i++)
{
if (isIpEntity(tcpFile, &entitySet[i]))
{
fprintf(stderr, "Entity %d is an IP Entity\n", i);
if (numRoutes == index)
break;
else
numRoutes++;
}
}
if (numRoutes == index && i < numEntities)
{
fprintf(
stderr,
"Index %lu is entity #%d - %04lx:%08lx\n",
index,
i,
entitySet[i].tei_entity,
entitySet[i].tei_instance);
memcpy(ent, &entitySet[i], sizeof(*ent));
tdiFreeThingSet(entitySet);
return 0;
}
else
{
tdiFreeThingSet(entitySet);
return 0xc000001;
}
}
BOOL
isInterface(TDIEntityID* if_maybe)
{
return if_maybe->tei_entity == IF_ENTITY;
}
NTSTATUS
getInterfaceInfoSet(HANDLE tcpFile, IFInfo** infoSet, PDWORD numInterfaces)
{
DWORD numEntities;
TDIEntityID* entIDSet = NULL;
NTSTATUS status = tdiGetEntityIDSet(tcpFile, &entIDSet, &numEntities);
IFInfo* infoSetInt = 0;
int curInterf = 0;
unsigned i;
if (!NT_SUCCESS(status))
{
fprintf(stderr, "getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status);
return status;
}
infoSetInt = HeapAlloc(GetProcessHeap(), 0, sizeof(IFInfo) * numEntities);
if (infoSetInt)
{
for (i = 0; i < numEntities; i++)
{
if (isInterface(&entIDSet[i]))
{
infoSetInt[curInterf].entity_id = entIDSet[i];
status = tdiGetMibForIfEntity(tcpFile, &entIDSet[i], &infoSetInt[curInterf].if_info);
fprintf(stderr, "tdiGetMibForIfEntity: %08lx\n", status);
if (NT_SUCCESS(status))
{
DWORD numAddrs;
IPAddrEntry* addrs;
TDIEntityID ip_ent;
unsigned j;
status = getNthIpEntity(tcpFile, curInterf, &ip_ent);
if (NT_SUCCESS(status))
status = tdiGetIpAddrsForIpEntity(tcpFile, &ip_ent, &addrs, &numAddrs);
for (j = 0; NT_SUCCESS(status) && j < numAddrs; j++)
{
fprintf(
stderr,
"ADDR %d: index %ld (target %ld)\n",
j,
addrs[j].iae_index,
infoSetInt[curInterf].if_info.ent.if_index);
if (addrs[j].iae_index == infoSetInt[curInterf].if_info.ent.if_index)
{
memcpy(&infoSetInt[curInterf].ip_addr, &addrs[j], sizeof(addrs[j]));
curInterf++;
break;
}
}
if (NT_SUCCESS(status))
tdiFreeThingSet(addrs);
}
}
}
tdiFreeThingSet(entIDSet);
if (NT_SUCCESS(status))
{
*infoSet = infoSetInt;
*numInterfaces = curInterf;
}
else
{
HeapFree(GetProcessHeap(), 0, infoSetInt);
}
return status;
}
else
{
tdiFreeThingSet(entIDSet);
return ((NTSTATUS)0xC000009A);
}
}
NTSTATUS
getInterfaceInfoByName(HANDLE tcpFile, char* name, IFInfo* info)
{
IFInfo* ifInfo;
DWORD numInterfaces;
unsigned i;
NTSTATUS status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
if (NT_SUCCESS(status))
{
for (i = 0; i < numInterfaces; i++)
{
if (!strcmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name))
{
memcpy(info, &ifInfo[i], sizeof(*info));
break;
}
}
HeapFree(GetProcessHeap(), 0, ifInfo);
return i < numInterfaces ? 0 : 0xc0000001;
}
return status;
}
NTSTATUS
getInterfaceInfoByIndex(HANDLE tcpFile, DWORD index, IFInfo* info)
{
IFInfo* ifInfo;
DWORD numInterfaces;
NTSTATUS status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
unsigned i;
if (NT_SUCCESS(status))
{
for (i = 0; i < numInterfaces; i++)
{
if (ifInfo[i].if_info.ent.if_index == index)
{
memcpy(info, &ifInfo[i], sizeof(*info));
break;
}
}
HeapFree(GetProcessHeap(), 0, ifInfo);
return i < numInterfaces ? 0 : 0xc0000001;
}
return status;
}
NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile, char* name, DWORD index, IFInfo* ifInfo)
{
NTSTATUS status = name ? getInterfaceInfoByName(tcpFile, name, ifInfo)
: getInterfaceInfoByIndex(tcpFile, index, ifInfo);
if (!NT_SUCCESS(status))
{
fprintf(stderr, "getIPAddrEntryForIf returning %lx\n", status);
}
return status;
}
InterfaceIndexTable*
getInterfaceIndexTableInt(BOOL nonLoopbackOnly)
{
DWORD numInterfaces, curInterface = 0;
unsigned i;
IFInfo* ifInfo;
InterfaceIndexTable* ret = 0;
HANDLE tcpFile;
NTSTATUS status = openTcpFile(&tcpFile, FILE_READ_DATA);
ifInfo = NULL;
if (NT_SUCCESS(status))
{
status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
fprintf(
stderr,
"InterfaceInfoSet: %08lx, %04lx:%08lx\n",
status,
ifInfo->entity_id.tei_entity,
ifInfo->entity_id.tei_instance);
if (NT_SUCCESS(status))
{
ret = (InterfaceIndexTable*)calloc(
1, sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
if (ret)
{
ret->numAllocated = numInterfaces;
fprintf(stderr, "NumInterfaces = %ld\n", numInterfaces);
for (i = 0; i < numInterfaces; i++)
{
fprintf(stderr, "Examining interface %d\n", i);
if (!nonLoopbackOnly || !isLoopback(tcpFile, &ifInfo[i].entity_id))
{
fprintf(stderr, "Interface %d matches (%ld)\n", i, curInterface);
ret->indexes[curInterface++] = ifInfo[i].if_info.ent.if_index;
}
}
ret->numIndexes = curInterface;
}
tdiFreeThingSet(ifInfo);
}
closeTcpFile(tcpFile);
}
return ret;
}
InterfaceIndexTable*
getInterfaceIndexTable(void)
{
return getInterfaceIndexTableInt(FALSE);
}
#endif
// there's probably an use case for a _newer_ implementation
// of pthread_setname_np(3), in fact, I may just merge _this_
// upstream...

@ -1,110 +0,0 @@
#ifndef WIN32_INTRNL_H
#define WIN32_INTRNL_H
#if defined(__MINGW32__) && !defined(_WIN64)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
#include <tdiinfo.h>
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;
/* forward declare, each module has their own idea of what this is */
typedef struct _InterfaceIndexTable InterfaceIndexTable;
typedef struct IFEntry
{
ulong if_index;
ulong if_type;
ulong if_mtu;
ulong if_speed;
ulong if_physaddrlen;
uchar if_physaddr[8];
ulong if_adminstatus;
ulong if_operstatus;
ulong if_lastchange;
ulong if_inoctets;
ulong if_inucastpkts;
ulong if_innucastpkts;
ulong if_indiscards;
ulong if_inerrors;
ulong if_inunknownprotos;
ulong if_outoctets;
ulong if_outucastpkts;
ulong if_outnucastpkts;
ulong if_outdiscards;
ulong if_outerrors;
ulong if_outqlen;
ulong if_descrlen;
uchar if_descr[1];
} IFEntry;
typedef struct IPAddrEntry
{
ulong iae_addr;
ulong iae_index;
ulong iae_mask;
ulong iae_bcastaddr;
ulong iae_reasmsize;
ushort iae_context;
ushort iae_pad;
} IPAddrEntry;
typedef union _IFEntrySafelySized {
CHAR MaxSize[sizeof(DWORD) + sizeof(IFEntry) + 128 + 1];
IFEntry ent;
} IFEntrySafelySized;
#ifndef IFENT_SOFTWARE_LOOPBACK
#define IFENT_SOFTWARE_LOOPBACK 24 /* This is an SNMP constant from rfc1213 */
#endif /*IFENT_SOFTWARE_LOOPBACK*/
/* Encapsulates information about an interface */
typedef struct _IFInfo
{
TDIEntityID entity_id;
IFEntrySafelySized if_info;
IPAddrEntry ip_addr;
} IFInfo;
/* functions */
NTSTATUS
openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess);
VOID
closeTcpFile(HANDLE h);
BOOL
isLoopback(HANDLE tcpFile, TDIEntityID* loop_maybe);
BOOL
isIpEntity(HANDLE tcpFile, TDIEntityID* ent);
NTSTATUS
getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID* ent);
BOOL
isInterface(TDIEntityID* if_maybe);
NTSTATUS
getInterfaceInfoSet(HANDLE tcpFile, IFInfo** infoSet, PDWORD numInterfaces);
NTSTATUS
getInterfaceInfoByName(HANDLE tcpFile, char* name, IFInfo* info);
NTSTATUS
getInterfaceInfoByIndex(HANDLE tcpFile, DWORD index, IFInfo* info);
NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile, char* name, DWORD index, IFInfo* ifInfo);
InterfaceIndexTable*
getInterfaceIndexTableInt(BOOL nonLoopbackOnly);
InterfaceIndexTable*
getInterfaceIndexTable(void);
#endif
#endif
Loading…
Cancel
Save