diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec index 500267c5b7..1a1f8f757d 100644 --- a/dlls/iphlpapi/iphlpapi.spec +++ b/dlls/iphlpapi/iphlpapi.spec @@ -147,7 +147,7 @@ @ stub GetUdpStatsFromStack @ stdcall GetUdpTable( ptr ptr long ) @ stub GetUdpTableFromStack -#@ stub GetUnicastIpAddressEntry +@ stdcall GetUnicastIpAddressEntry( ptr ) #@ stub GetUnicastIpAddressTable @ stdcall GetUniDirectionalAdapterInfo( ptr ptr ) @ stdcall Icmp6CreateFile() diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 1daf54d617..12767c3960 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2467,6 +2467,73 @@ DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder, return ret; } +DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW *row) +{ + IP_ADAPTER_ADDRESSES *aa, *ptr; + ULONG size = 0; + DWORD ret; + + TRACE("%p\n", row); + + if (!row) + return ERROR_INVALID_PARAMETER; + + ret = GetAdaptersAddresses(row->Address.si_family, 0, NULL, NULL, &size); + if (ret != ERROR_BUFFER_OVERFLOW) + return ret; + if (!(ptr = HeapAlloc(GetProcessHeap(), 0, size))) + return ERROR_OUTOFMEMORY; + if ((ret = GetAdaptersAddresses(row->Address.si_family, 0, NULL, ptr, &size))) + { + HeapFree(GetProcessHeap(), 0, ptr); + return ret; + } + + ret = ERROR_FILE_NOT_FOUND; + for (aa = ptr; aa; aa = aa->Next) + { + IP_ADAPTER_UNICAST_ADDRESS *ua; + + if (aa->u.s.IfIndex != row->InterfaceIndex && + memcmp(&aa->Luid, &row->InterfaceLuid, sizeof(row->InterfaceLuid))) + continue; + ret = ERROR_NOT_FOUND; + + ua = aa->FirstUnicastAddress; + while (ua) + { + SOCKADDR_INET *uaaddr = (SOCKADDR_INET *)ua->Address.lpSockaddr; + + if ((row->Address.si_family == WS_AF_INET6 && + !memcmp(&row->Address.Ipv6.sin6_addr, &uaaddr->Ipv6.sin6_addr, sizeof(uaaddr->Ipv6.sin6_addr))) || + (row->Address.si_family == WS_AF_INET && + row->Address.Ipv4.sin_addr.S_un.S_addr == uaaddr->Ipv4.sin_addr.S_un.S_addr)) + { + memcpy(&row->InterfaceLuid, &aa->Luid, sizeof(aa->Luid)); + row->InterfaceIndex = aa->u.s.IfIndex; + row->PrefixOrigin = ua->PrefixOrigin; + row->SuffixOrigin = ua->SuffixOrigin; + row->ValidLifetime = ua->ValidLifetime; + row->PreferredLifetime = ua->PreferredLifetime; + row->OnLinkPrefixLength = ua->OnLinkPrefixLength; + row->SkipAsSource = 0; + row->DadState = ua->DadState; + if (row->Address.si_family == WS_AF_INET6) + row->ScopeId.u.Value = row->Address.Ipv6.sin6_scope_id; + else + row->ScopeId.u.Value = 0; + NtQuerySystemTime(&row->CreationTimeStamp); + HeapFree(GetProcessHeap(), 0, ptr); + return NO_ERROR; + } + ua = ua->Next; + } + } + HeapFree(GetProcessHeap(), 0, ptr); + + return ret; +} + /****************************************************************** * GetUniDirectionalAdapterInfo (IPHLPAPI.@) * diff --git a/include/netioapi.h b/include/netioapi.h index 035743146f..0e777c70c0 100644 --- a/include/netioapi.h +++ b/include/netioapi.h @@ -82,6 +82,22 @@ typedef struct _MIB_IF_TABLE2 MIB_IF_ROW2 Table[1]; } MIB_IF_TABLE2, *PMIB_IF_TABLE2; +typedef struct _MIB_UNICASTIPADDRESS_ROW +{ + SOCKADDR_INET Address; + NET_LUID InterfaceLuid; + NET_IFINDEX InterfaceIndex; + NL_PREFIX_ORIGIN PrefixOrigin; + NL_SUFFIX_ORIGIN SuffixOrigin; + ULONG ValidLifetime; + ULONG PreferredLifetime; + UINT8 OnLinkPrefixLength; + BOOLEAN SkipAsSource; + NL_DAD_STATE DadState; + SCOPE_ID ScopeId; + LARGE_INTEGER CreationTimeStamp; +} MIB_UNICASTIPADDRESS_ROW, *PMIB_UNICASTIPADDRESS_ROW; + DWORD WINAPI ConvertInterfaceGuidToLuid(const GUID*,NET_LUID*); DWORD WINAPI ConvertInterfaceIndexToLuid(NET_IFINDEX,NET_LUID*); DWORD WINAPI ConvertInterfaceLuidToGuid(const NET_LUID*,GUID*); @@ -92,5 +108,6 @@ DWORD WINAPI ConvertInterfaceNameToLuidA(const char*,NET_LUID*); DWORD WINAPI ConvertInterfaceNameToLuidW(const WCHAR*,NET_LUID*); void WINAPI FreeMibTable(void*); DWORD WINAPI GetIfEntry2(MIB_IF_ROW2*); +DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW*); #endif /* __WINE_NETIOAPI_H */ diff --git a/include/ws2def.h b/include/ws2def.h index cbd6f741fc..fa21c06b50 100644 --- a/include/ws2def.h +++ b/include/ws2def.h @@ -27,6 +27,8 @@ #define WS(x) x #endif +typedef USHORT ADDRESS_FAMILY; + #ifndef __CSADDR_DEFINED__ #define __CSADDR_DEFINED__ @@ -78,6 +80,17 @@ typedef enum { ScopeLevelGlobal = 14 } SCOPE_LEVEL; +typedef struct +{ + union { + struct { + ULONG Zone : 28; + ULONG Level : 4; + } DUMMYSTRUCTNAME; + ULONG Value; + } DUMMYUNIONNAME; +} SCOPE_ID, *PSCOPE_ID; + typedef struct _WSABUF { ULONG len; diff --git a/include/ws2ipdef.h b/include/ws2ipdef.h index ca47caaab2..e13cf6e3bb 100644 --- a/include/ws2ipdef.h +++ b/include/ws2ipdef.h @@ -135,6 +135,13 @@ typedef struct WS(sockaddr_in6_pair) PSOCKADDR_IN6 DestinationAddress; } SOCKADDR_IN6_PAIR, *PSOCKADDR_IN6_PAIR; +typedef union _SOCKADDR_INET +{ + SOCKADDR_IN Ipv4; + SOCKADDR_IN6 Ipv6; + ADDRESS_FAMILY si_family; +} SOCKADDR_INET, *PSOCKADDR_INET; + /* * Multicast group information */