#include "net.hpp" #include "net_if.hpp" #include #include #include "ip.hpp" #include "ip_range.hpp" #include #include #include #include #include #include #include namespace llarp::net { class Platform_Impl : public Platform { /// visit all adapters (not addresses). windows serves net info per adapter unlink posix which /// gives a list of all distinct addresses. template void iter_adapters(Visit_t&& visit, int af = AF_UNSPEC) const { ULONG sz{}; GetAdaptersAddresses(af, 0, nullptr, nullptr, &sz); auto ptr = std::make_unique(sz); auto* addrs = reinterpret_cast(ptr.get()); if (auto err = GetAdaptersAddresses(af, 0, nullptr, addrs, &sz); err != ERROR_SUCCESS) throw llarp::win32::error{err, "GetAdaptersAddresses()"}; for (auto* addr = addrs; addr->Next; addr = addr->Next) visit(addr); } template bool adapter_has_ip(adapter_t* a, ipaddr_t ip) const { for (auto* addr = a->FirstUnicastAddress; addr->Next; addr = addr->Next) { SockAddr saddr{*addr->Address.lpSockaddr}; LogDebug(fmt::format("'{}' has address '{}'", a->AdapterName, saddr)); if (saddr.getIP() == ip) return true; } return false; } template bool adapter_has_fam(adapter_t* a, int af) const { for (auto* addr = a->FirstUnicastAddress; addr->Next; addr = addr->Next) { SockAddr saddr{*addr->Address.lpSockaddr}; if (saddr.Family() == af) return true; } return false; } public: std::optional GetInterfaceIndex(ipaddr_t ip) const override { std::optional found; int af{AF_INET}; if (std::holds_alternative(ip)) af = AF_INET6; iter_adapters( [&found, ip, this](auto* adapter) { if (found) return; LogDebug(fmt::format( "visit adapter looking for '{}': '{}' idx={}", ip, adapter->AdapterName, adapter->IfIndex)); if (adapter_has_ip(adapter, ip)) { found = adapter->IfIndex; } }, af); return found; } std::optional GetInterfaceAddr(std::string_view name, int af) const override { std::optional found; iter_adapters([name = std::string{name}, af, &found, this](auto* a) { if (found) return; if (std::string{a->AdapterName} != name) return; if (adapter_has_fam(a, af)) found = SockAddr{*a->FirstUnicastAddress->Address.lpSockaddr}; }); return found; } std::optional AllInterfaces(SockAddr fallback) const override { // windows seems to not give a shit about source address return fallback.isIPv6() ? SockAddr{"[::]"} : SockAddr{"0.0.0.0"}; } std::optional FindFreeTun() const override { return "lokitun0"; } std::optional GetBestNetIF(int) const override { // TODO: implement me ? return std::nullopt; } std::optional FindFreeRange() const override { std::list currentRanges; iter_adapters([¤tRanges](auto* i) { for (auto* addr = i->FirstUnicastAddress; addr and addr->Next; addr = addr->Next) { SockAddr saddr{*addr->Address.lpSockaddr}; currentRanges.emplace_back( saddr.asIPv6(), ipaddr_netmask_bits(addr->OnLinkPrefixLength, addr->Address.lpSockaddr->sa_family)); } }); auto ownsRange = [¤tRanges](const IPRange& range) -> bool { for (const auto& ownRange : currentRanges) { if (ownRange * range) return true; } return false; }; // generate possible ranges to in order of attempts std::list possibleRanges; for (byte_t oct = 16; oct < 32; ++oct) { possibleRanges.emplace_back(IPRange::FromIPv4(172, oct, 0, 1, 16)); } for (byte_t oct = 0; oct < 255; ++oct) { possibleRanges.emplace_back(IPRange::FromIPv4(10, oct, 0, 1, 16)); } for (byte_t oct = 0; oct < 255; ++oct) { possibleRanges.emplace_back(IPRange::FromIPv4(192, 168, oct, 1, 24)); } // for each possible range pick the first one we don't own for (const auto& range : possibleRanges) { if (not ownsRange(range)) return range; } return std::nullopt; } std::string LoopbackInterfaceName() const override { // todo: implement me? does windows even have a loopback? return ""; } bool HasInterfaceAddress(ipaddr_t ip) const override { return GetInterfaceIndex(ip) != std::nullopt; } std::vector AllNetworkInterfaces() const override { std::vector all; iter_adapters([&all](auto* a) { auto& cur = all.emplace_back(); cur.index = a->IfIndex; cur.name = a->AdapterName; for (auto* addr = a->FirstUnicastAddress; addr and addr->Next; addr = addr->Next) { SockAddr saddr{*addr->Address.lpSockaddr}; cur.addrs.emplace_back( saddr.asIPv6(), ipaddr_netmask_bits(addr->OnLinkPrefixLength, addr->Address.lpSockaddr->sa_family)); } }); return all; } }; const Platform_Impl g_plat{}; const Platform* Platform::Default_ptr() { return &g_plat; } } // namespace llarp::net