Skip to content

Instantly share code, notes, and snippets.

@jnschulze
Created August 15, 2023 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnschulze/f327f7720f4b197c82f330b16b8bedbe to your computer and use it in GitHub Desktop.
Save jnschulze/f327f7720f4b197c82f330b16b8bedbe to your computer and use it in GitHub Desktop.
Windows GetAdaptersAddresses test
#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);
}
@jnschulze
Copy link
Author

IPv4 + IPv6 enabled

----AF_INET----
'Ethernet 4' -> family=AF_INET, ifIndex=23, Ipv6IfIndex=23


----AF_INET6----
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23


----AF_UNSPEC----
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET, ifIndex=23, Ipv6IfIndex=23

IPv4 turned off

----AF_INET----


----AF_INET6----
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23


----AF_UNSPEC----
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23
'Ethernet 4' -> family=AF_INET6, ifIndex=23, Ipv6IfIndex=23

IPv6 turned off

----AF_INET----
'Ethernet 4' -> family=AF_INET, ifIndex=23, Ipv6IfIndex=0


----AF_INET6----


----AF_UNSPEC----
'Ethernet 4' -> family=AF_INET, ifIndex=23, Ipv6IfIndex=0

Both IPv4 and IPv6 turned off

----AF_INET----



----AF_INET6----



----AF_UNSPEC----

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment