Created
August 15, 2023 21:21
-
-
Save jnschulze/f327f7720f4b197c82f330b16b8bedbe to your computer and use it in GitHub Desktop.
Windows GetAdaptersAddresses test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <winsock2.h> | |
// Must be included after winsock2.h | |
#include <iphlpapi.h> | |
#include <cassert> | |
#include <format> | |
#include <iostream> | |
#pragma comment(lib, "Iphlpapi.lib") | |
namespace { | |
std::string Utf8FromUtf16(std::wstring_view utf16_string) { | |
if (utf16_string.empty()) { | |
return {}; | |
} | |
auto src_length = static_cast<int>(utf16_string.size()); | |
int target_length = | |
::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), | |
src_length, nullptr, 0, nullptr, nullptr); | |
std::string utf8_string; | |
if (target_length <= 0 || target_length > utf8_string.max_size()) { | |
return utf8_string; | |
} | |
utf8_string.resize(target_length); | |
int converted_length = ::WideCharToMultiByte( | |
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), src_length, | |
utf8_string.data(), target_length, nullptr, nullptr); | |
if (converted_length == 0) { | |
return {}; | |
} | |
return utf8_string; | |
} | |
std::string FamilyToString(int family) { | |
switch (family) { | |
case AF_INET: | |
return "AF_INET"; | |
case AF_INET6: | |
return "AF_INET6"; | |
case AF_UNSPEC: | |
return "AF_UNSPEC"; | |
default: | |
return "unknown"; | |
} | |
} | |
void GetAddresses(int type) { | |
ULONG size = 0; | |
DWORD flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | | |
GAA_FLAG_SKIP_DNS_SERVER; | |
auto status = GetAdaptersAddresses(type, flags, nullptr, nullptr, &size); | |
IP_ADAPTER_ADDRESSES* addrs = nullptr; | |
if (status == ERROR_BUFFER_OVERFLOW) { | |
addrs = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(size)); | |
// Get the addresses now we have the right buffer. | |
status = GetAdaptersAddresses(type, flags, nullptr, addrs, &size); | |
} | |
for (IP_ADAPTER_ADDRESSES* a = addrs; a != nullptr; a = a->Next) { | |
for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != nullptr; | |
u = u->Next) { | |
assert( | |
type == AF_UNSPEC || | |
(type == AF_INET && u->Address.lpSockaddr->sa_family == AF_INET) || | |
(type == AF_INET6 && u->Address.lpSockaddr->sa_family == AF_INET6)); | |
assert((a->Flags & IP_ADAPTER_IPV4_ENABLED && a->IfIndex != 0) || | |
(a->Flags & IP_ADAPTER_IPV6_ENABLED && a->Ipv6IfIndex != 0)); | |
assert(a->IfIndex == a->Ipv6IfIndex || | |
!!(a->Flags & IP_ADAPTER_IPV4_ENABLED) != | |
!!(a->Flags & IP_ADAPTER_IPV6_ENABLED)); | |
assert(type != AF_INET || a->Flags & IP_ADAPTER_IPV4_ENABLED); | |
assert(type != AF_INET6 || a->Flags & IP_ADAPTER_IPV6_ENABLED); | |
assert(a->IfIndex == a->Ipv6IfIndex || | |
(!(a->Flags & IP_ADAPTER_IPV4_ENABLED) || | |
!(a->Flags & IP_ADAPTER_IPV6_ENABLED))); | |
std::cout << std::format("'{}' -> family={}, ifIndex={}, Ipv6IfIndex={}", | |
Utf8FromUtf16(a->FriendlyName), | |
FamilyToString(u->Address.lpSockaddr->sa_family), | |
a->IfIndex, a->Ipv6IfIndex) | |
<< std::endl; | |
} | |
} | |
free(addrs); | |
} | |
void DumpAddresses(int family) { | |
std::cout << std::format("----{}----", FamilyToString(family)) << std::endl; | |
GetAddresses(family); | |
std::cout << std::endl << std::endl; | |
} | |
} // namespace | |
int main() { | |
DumpAddresses(AF_INET); | |
DumpAddresses(AF_INET6); | |
DumpAddresses(AF_UNSPEC); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
IPv4 + IPv6 enabled
IPv4 turned off
IPv6 turned off
Both IPv4 and IPv6 turned off