iphlpapi: Add support for GAA_FLAG_INCLUDE_PREFIX in GetAdaptersAddresses.
This commit is contained in:
parent
d66f7cdb52
commit
5674f16649
|
@ -886,7 +886,7 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs)
|
||||
ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs, SOCKET_ADDRESS **masks)
|
||||
{
|
||||
struct ifaddrs *ifa;
|
||||
ULONG ret;
|
||||
|
@ -906,10 +906,14 @@ ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_ad
|
|||
{
|
||||
*addrs = HeapAlloc(GetProcessHeap(), 0, n * (sizeof(SOCKET_ADDRESS) +
|
||||
sizeof(struct WS_sockaddr_in6)));
|
||||
if (*addrs)
|
||||
*masks = HeapAlloc(GetProcessHeap(), 0, n * (sizeof(SOCKET_ADDRESS) +
|
||||
sizeof(struct WS_sockaddr_in6)));
|
||||
if (*addrs && *masks)
|
||||
{
|
||||
struct WS_sockaddr_in6 *next_addr = (struct WS_sockaddr_in6 *)(
|
||||
(BYTE *)*addrs + n * sizeof(SOCKET_ADDRESS));
|
||||
struct WS_sockaddr_in6 *mask_addr = (struct WS_sockaddr_in6 *)(
|
||||
(BYTE *)*masks + n * sizeof(SOCKET_ADDRESS));
|
||||
|
||||
for (p = ifa, n = 0; p; p = p->ifa_next)
|
||||
{
|
||||
|
@ -917,6 +921,7 @@ ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_ad
|
|||
!strcmp(name, p->ifa_name))
|
||||
{
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)p->ifa_addr;
|
||||
struct sockaddr_in6 *mask = (struct sockaddr_in6 *)p->ifa_netmask;
|
||||
|
||||
next_addr->sin6_family = WS_AF_INET6;
|
||||
next_addr->sin6_port = addr->sin6_port;
|
||||
|
@ -927,6 +932,16 @@ ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_ad
|
|||
(*addrs)[n].lpSockaddr = (LPSOCKADDR)next_addr;
|
||||
(*addrs)[n].iSockaddrLength = sizeof(struct WS_sockaddr_in6);
|
||||
next_addr++;
|
||||
|
||||
mask_addr->sin6_family = WS_AF_INET6;
|
||||
mask_addr->sin6_port = mask->sin6_port;
|
||||
mask_addr->sin6_flowinfo = mask->sin6_flowinfo;
|
||||
memcpy(&mask_addr->sin6_addr, &mask->sin6_addr,
|
||||
sizeof(mask_addr->sin6_addr));
|
||||
mask_addr->sin6_scope_id = mask->sin6_scope_id;
|
||||
(*masks)[n].lpSockaddr = (LPSOCKADDR)mask_addr;
|
||||
(*masks)[n].iSockaddrLength = sizeof(struct WS_sockaddr_in6);
|
||||
mask_addr++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
@ -934,12 +949,17 @@ ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_ad
|
|||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, *addrs);
|
||||
HeapFree(GetProcessHeap(), 0, *masks);
|
||||
ret = ERROR_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*addrs = NULL;
|
||||
*num_addrs = 0;
|
||||
*masks = NULL;
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
freeifaddrs(ifa);
|
||||
|
@ -1073,10 +1093,11 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs)
|
||||
ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs, SOCKET_ADDRESS **masks)
|
||||
{
|
||||
*addrs = NULL;
|
||||
*num_addrs = 0;
|
||||
*masks = NULL;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,8 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
|
|||
/* Returns the IPv6 addresses for a particular interface index.
|
||||
* Returns NO_ERROR on success, something else on failure.
|
||||
*/
|
||||
ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs) DECLSPEC_HIDDEN;
|
||||
ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs,
|
||||
SOCKET_ADDRESS **masks) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Converts the network-order bytes in addr to a printable string. Returns
|
||||
* string.
|
||||
|
|
|
@ -623,7 +623,7 @@ static NET_IF_CONNECTION_TYPE connectionTypeFromMibType(DWORD mib_type)
|
|||
}
|
||||
}
|
||||
|
||||
static ULONG v4addressesFromIndex(IF_INDEX index, DWORD **addrs, ULONG *num_addrs)
|
||||
static ULONG v4addressesFromIndex(IF_INDEX index, DWORD **addrs, ULONG *num_addrs, DWORD **masks)
|
||||
{
|
||||
ULONG ret, i, j;
|
||||
MIB_IPADDRTABLE *at;
|
||||
|
@ -639,9 +639,20 @@ static ULONG v4addressesFromIndex(IF_INDEX index, DWORD **addrs, ULONG *num_addr
|
|||
HeapFree(GetProcessHeap(), 0, at);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
if (!(*masks = HeapAlloc(GetProcessHeap(), 0, *num_addrs * sizeof(DWORD))))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, *addrs);
|
||||
HeapFree(GetProcessHeap(), 0, at);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
for (i = 0, j = 0; i < at->dwNumEntries; i++)
|
||||
{
|
||||
if (at->table[i].dwIndex == index) (*addrs)[j++] = at->table[i].dwAddr;
|
||||
if (at->table[i].dwIndex == index)
|
||||
{
|
||||
(*addrs)[j] = at->table[i].dwAddr;
|
||||
(*masks)[j] = at->table[i].dwMask;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, at);
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -724,41 +735,35 @@ static PMIB_IPFORWARDROW findIPv4Gateway(DWORD index,
|
|||
static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index,
|
||||
IP_ADAPTER_ADDRESSES *aa, ULONG *size)
|
||||
{
|
||||
ULONG ret = ERROR_SUCCESS, i, num_v4addrs = 0, num_v4_gateways = 0, num_v6addrs = 0, total_size;
|
||||
DWORD *v4addrs = NULL;
|
||||
SOCKET_ADDRESS *v6addrs = NULL;
|
||||
ULONG ret = ERROR_SUCCESS, i, j, num_v4addrs = 0, num_v4_gateways = 0, num_v6addrs = 0, total_size;
|
||||
DWORD *v4addrs = NULL, *v4masks = NULL;
|
||||
SOCKET_ADDRESS *v6addrs = NULL, *v6masks = NULL;
|
||||
PMIB_IPFORWARDTABLE routeTable = NULL;
|
||||
|
||||
if (family == WS_AF_INET)
|
||||
{
|
||||
if (!(flags & GAA_FLAG_SKIP_UNICAST))
|
||||
ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
|
||||
ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs, &v4masks);
|
||||
|
||||
if (!ret && flags & GAA_FLAG_INCLUDE_ALL_GATEWAYS)
|
||||
{
|
||||
ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE,
|
||||
GetProcessHeap(), 0);
|
||||
if (!ret)
|
||||
num_v4_gateways = count_v4_gateways(index, routeTable);
|
||||
ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE, GetProcessHeap(), 0);
|
||||
if (!ret) num_v4_gateways = count_v4_gateways(index, routeTable);
|
||||
}
|
||||
}
|
||||
else if (family == WS_AF_INET6)
|
||||
{
|
||||
if (!(flags & GAA_FLAG_SKIP_UNICAST))
|
||||
ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
|
||||
ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs, &v6masks);
|
||||
}
|
||||
else if (family == WS_AF_UNSPEC)
|
||||
{
|
||||
if (!(flags & GAA_FLAG_SKIP_UNICAST))
|
||||
ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
|
||||
ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs, &v4masks);
|
||||
|
||||
if (!ret && flags & GAA_FLAG_INCLUDE_ALL_GATEWAYS)
|
||||
{
|
||||
ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE,
|
||||
GetProcessHeap(), 0);
|
||||
if (!ret)
|
||||
num_v4_gateways = count_v4_gateways(index, routeTable);
|
||||
ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE, GetProcessHeap(), 0);
|
||||
if (!ret) num_v4_gateways = count_v4_gateways(index, routeTable);
|
||||
}
|
||||
if (!ret && !(flags & GAA_FLAG_SKIP_UNICAST))
|
||||
ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
|
||||
if (!ret) ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs, &v6masks);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -768,6 +773,9 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
|
|||
if (ret)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, v4addrs);
|
||||
HeapFree(GetProcessHeap(), 0, v4masks);
|
||||
HeapFree(GetProcessHeap(), 0, v6addrs);
|
||||
HeapFree(GetProcessHeap(), 0, v6masks);
|
||||
HeapFree(GetProcessHeap(), 0, routeTable);
|
||||
return ret;
|
||||
}
|
||||
|
@ -777,6 +785,14 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
|
|||
total_size += IF_NAMESIZE * sizeof(WCHAR);
|
||||
if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
|
||||
total_size += IF_NAMESIZE * sizeof(WCHAR);
|
||||
if (flags & GAA_FLAG_INCLUDE_PREFIX)
|
||||
{
|
||||
total_size += sizeof(IP_ADAPTER_PREFIX) * num_v4addrs;
|
||||
total_size += sizeof(IP_ADAPTER_PREFIX) * num_v6addrs;
|
||||
total_size += sizeof(struct sockaddr_in) * num_v4addrs;
|
||||
for (i = 0; i < num_v6addrs; i++)
|
||||
total_size += v6masks[i].iSockaddrLength;
|
||||
}
|
||||
total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v4addrs;
|
||||
total_size += sizeof(struct sockaddr_in) * num_v4addrs;
|
||||
total_size += (sizeof(IP_ADAPTER_GATEWAY_ADDRESS) + sizeof(SOCKADDR_IN)) * num_v4_gateways;
|
||||
|
@ -841,7 +857,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
|
|||
ptr += sizeof(SOCKADDR_IN);
|
||||
}
|
||||
}
|
||||
if (num_v4addrs)
|
||||
if (num_v4addrs && !(flags & GAA_FLAG_SKIP_UNICAST))
|
||||
{
|
||||
IP_ADAPTER_UNICAST_ADDRESS *ua;
|
||||
struct WS_sockaddr_in *sa;
|
||||
|
@ -871,7 +887,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
|
|||
}
|
||||
}
|
||||
}
|
||||
if (num_v6addrs)
|
||||
if (num_v6addrs && !(flags & GAA_FLAG_SKIP_UNICAST))
|
||||
{
|
||||
IP_ADAPTER_UNICAST_ADDRESS *ua;
|
||||
struct WS_sockaddr_in6 *sa;
|
||||
|
@ -908,6 +924,99 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
|
|||
}
|
||||
}
|
||||
}
|
||||
if (num_v4addrs && (flags & GAA_FLAG_INCLUDE_PREFIX))
|
||||
{
|
||||
IP_ADAPTER_PREFIX *prefix;
|
||||
|
||||
prefix = aa->FirstPrefix = (IP_ADAPTER_PREFIX *)ptr;
|
||||
for (i = 0; i < num_v4addrs; i++)
|
||||
{
|
||||
char addr_buf[16];
|
||||
struct WS_sockaddr_in *sa;
|
||||
|
||||
prefix->u.s.Length = sizeof(*prefix);
|
||||
prefix->u.s.Flags = 0;
|
||||
prefix->Next = NULL;
|
||||
prefix->Address.iSockaddrLength = sizeof(struct sockaddr_in);
|
||||
prefix->Address.lpSockaddr = (SOCKADDR *)((char *)prefix + prefix->u.s.Length);
|
||||
|
||||
sa = (struct WS_sockaddr_in *)prefix->Address.lpSockaddr;
|
||||
sa->sin_family = WS_AF_INET;
|
||||
sa->sin_addr.S_un.S_addr = v4addrs[i] & v4masks[i];
|
||||
sa->sin_port = 0;
|
||||
|
||||
prefix->PrefixLength = 0;
|
||||
for (j = 0; j < sizeof(*v4masks) * 8; j++)
|
||||
{
|
||||
if (v4masks[i] & 1 << j) prefix->PrefixLength++;
|
||||
else break;
|
||||
}
|
||||
TRACE("IPv4 network: %s/%u\n",
|
||||
debugstr_ipv4((const in_addr_t *)&sa->sin_addr.S_un.S_addr, addr_buf),
|
||||
prefix->PrefixLength);
|
||||
|
||||
ptr += prefix->u.s.Length + prefix->Address.iSockaddrLength;
|
||||
if (i < num_v4addrs - 1)
|
||||
{
|
||||
prefix->Next = (IP_ADAPTER_PREFIX *)ptr;
|
||||
prefix = prefix->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_v6addrs && (flags & GAA_FLAG_INCLUDE_PREFIX))
|
||||
{
|
||||
IP_ADAPTER_PREFIX *prefix;
|
||||
|
||||
if (aa->FirstPrefix)
|
||||
{
|
||||
for (prefix = aa->FirstPrefix; prefix->Next; prefix = prefix->Next)
|
||||
;
|
||||
prefix->Next = (IP_ADAPTER_PREFIX *)ptr;
|
||||
prefix = (IP_ADAPTER_PREFIX *)ptr;
|
||||
}
|
||||
else
|
||||
prefix = aa->FirstPrefix = (IP_ADAPTER_PREFIX *)ptr;
|
||||
for (i = 0; i < num_v6addrs; i++)
|
||||
{
|
||||
char addr_buf[46];
|
||||
struct WS_sockaddr_in6 *sa;
|
||||
const IN6_ADDR *addr, *mask;
|
||||
BOOL done = FALSE;
|
||||
|
||||
prefix->u.s.Length = sizeof(*prefix);
|
||||
prefix->u.s.Flags = 0;
|
||||
prefix->Next = NULL;
|
||||
prefix->Address.iSockaddrLength = sizeof(struct sockaddr_in6);
|
||||
prefix->Address.lpSockaddr = (SOCKADDR *)((char *)prefix + prefix->u.s.Length);
|
||||
|
||||
sa = (struct WS_sockaddr_in6 *)prefix->Address.lpSockaddr;
|
||||
sa->sin6_family = WS_AF_INET6;
|
||||
sa->sin6_port = 0;
|
||||
sa->sin6_flowinfo = 0;
|
||||
addr = &((struct WS_sockaddr_in6 *)v6addrs[i].lpSockaddr)->sin6_addr;
|
||||
mask = &((struct WS_sockaddr_in6 *)v6masks[i].lpSockaddr)->sin6_addr;
|
||||
for (j = 0; j < 8; j++) sa->sin6_addr.u.Word[j] = addr->u.Word[j] & mask->u.Word[j];
|
||||
sa->sin6_scope_id = 0;
|
||||
|
||||
prefix->PrefixLength = 0;
|
||||
for (i = 0; i < 8 && !done; i++)
|
||||
{
|
||||
for (j = 0; j < sizeof(WORD) * 8 && !done; j++)
|
||||
{
|
||||
if (mask->u.Word[i] & 1 << j) prefix->PrefixLength++;
|
||||
else done = TRUE;
|
||||
}
|
||||
}
|
||||
TRACE("IPv6 network: %s/%u\n", debugstr_ipv6(sa, addr_buf), prefix->PrefixLength);
|
||||
|
||||
ptr += prefix->u.s.Length + prefix->Address.iSockaddrLength;
|
||||
if (i < num_v6addrs - 1)
|
||||
{
|
||||
prefix->Next = (IP_ADAPTER_PREFIX *)ptr;
|
||||
prefix = prefix->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buflen = MAX_INTERFACE_PHYSADDR;
|
||||
getInterfacePhysicalByIndex(index, &buflen, aa->PhysicalAddress, &type);
|
||||
|
@ -925,7 +1034,9 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
|
|||
*size = total_size;
|
||||
HeapFree(GetProcessHeap(), 0, routeTable);
|
||||
HeapFree(GetProcessHeap(), 0, v6addrs);
|
||||
HeapFree(GetProcessHeap(), 0, v6masks);
|
||||
HeapFree(GetProcessHeap(), 0, v4addrs);
|
||||
HeapFree(GetProcessHeap(), 0, v4masks);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue