2021-03-09 22:24:35 +00:00
|
|
|
#include "net.hpp"
|
|
|
|
#include "net_if.hpp"
|
2020-05-08 17:23:21 +00:00
|
|
|
#include <stdexcept>
|
2022-07-09 15:05:52 +00:00
|
|
|
#include <llarp/constants/platform.hpp>
|
2019-10-22 15:08:52 +00:00
|
|
|
|
2018-02-01 17:06:49 +00:00
|
|
|
#include <arpa/inet.h>
|
2019-10-11 20:16:03 +00:00
|
|
|
|
2021-03-09 22:24:35 +00:00
|
|
|
#include "ip.hpp"
|
|
|
|
#include "ip_range.hpp"
|
2022-07-16 00:41:14 +00:00
|
|
|
#include <llarp/util/logging.hpp>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/util/str.hpp>
|
2018-02-01 17:07:01 +00:00
|
|
|
|
2021-03-02 22:49:25 +00:00
|
|
|
#ifdef ANDROID
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/android/ifaddrs.h>
|
2021-03-02 18:18:22 +00:00
|
|
|
#else
|
|
|
|
#include <ifaddrs.h>
|
|
|
|
#endif
|
|
|
|
|
2018-12-12 02:52:51 +00:00
|
|
|
#include <cstdio>
|
2020-06-24 13:24:07 +00:00
|
|
|
#include <list>
|
2022-07-09 15:05:52 +00:00
|
|
|
#include <type_traits>
|
2018-11-03 13:19:18 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
namespace llarp::net
|
2018-07-30 04:38:14 +00:00
|
|
|
{
|
2022-07-28 16:07:38 +00:00
|
|
|
class Platform_Impl : public Platform
|
2022-07-09 15:05:52 +00:00
|
|
|
{
|
|
|
|
template <typename Visit_t>
|
|
|
|
void
|
|
|
|
iter_all(Visit_t&& visit) const
|
2018-07-27 00:21:57 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
ifaddrs* addrs{nullptr};
|
|
|
|
if (getifaddrs(&addrs))
|
|
|
|
throw std::runtime_error{fmt::format("getifaddrs(): {}", strerror(errno))};
|
|
|
|
|
2022-10-06 18:47:18 +00:00
|
|
|
for (auto next = addrs; next; next = next->ifa_next)
|
2022-07-09 15:05:52 +00:00
|
|
|
visit(next);
|
|
|
|
|
|
|
|
freeifaddrs(addrs);
|
2019-07-03 14:32:51 +00:00
|
|
|
}
|
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
public:
|
2020-06-11 11:44:02 +00:00
|
|
|
std::string
|
2022-07-09 15:05:52 +00:00
|
|
|
LoopbackInterfaceName() const override
|
2020-06-11 11:44:02 +00:00
|
|
|
{
|
|
|
|
std::string ifname;
|
2022-07-09 15:05:52 +00:00
|
|
|
iter_all([this, &ifname](auto i) {
|
|
|
|
if (i and i->ifa_addr and i->ifa_addr->sa_family == AF_INET)
|
2020-06-11 11:44:02 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
const SockAddr addr{*i->ifa_addr};
|
|
|
|
if (IsLoopbackAddress(addr.getIP()))
|
2020-06-11 11:44:02 +00:00
|
|
|
{
|
|
|
|
ifname = i->ifa_name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (ifname.empty())
|
2022-07-09 15:05:52 +00:00
|
|
|
throw std::runtime_error{"we have no ipv4 loopback interface for some ungodly reason"};
|
2020-06-11 11:44:02 +00:00
|
|
|
return ifname;
|
|
|
|
}
|
2019-07-03 14:32:51 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
std::optional<std::string>
|
|
|
|
GetBestNetIF(int af) const override
|
|
|
|
{
|
|
|
|
std::optional<std::string> found;
|
|
|
|
iter_all([this, &found, af](auto i) {
|
|
|
|
if (found)
|
|
|
|
return;
|
|
|
|
if (i and i->ifa_addr and i->ifa_addr->sa_family == af)
|
2018-07-27 00:21:57 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
if (not IsBogon(*i->ifa_addr))
|
2018-07-27 00:21:57 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
found = i->ifa_name;
|
2018-07-27 00:21:57 +00:00
|
|
|
}
|
|
|
|
}
|
2022-07-09 15:05:52 +00:00
|
|
|
});
|
2018-09-03 12:03:43 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<IPRange>
|
|
|
|
FindFreeRange() const override
|
|
|
|
{
|
|
|
|
std::list<IPRange> currentRanges;
|
|
|
|
iter_all([¤tRanges](auto i) {
|
|
|
|
if (i and i->ifa_addr and i->ifa_addr->sa_family == AF_INET)
|
|
|
|
{
|
|
|
|
ipv4addr_t addr{reinterpret_cast<sockaddr_in*>(i->ifa_addr)->sin_addr.s_addr};
|
|
|
|
ipv4addr_t mask{reinterpret_cast<sockaddr_in*>(i->ifa_netmask)->sin_addr.s_addr};
|
|
|
|
currentRanges.emplace_back(IPRange::FromIPv4(addr, mask));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-10-06 18:45:42 +00:00
|
|
|
return IPRange::FindPrivateRange(currentRanges);
|
2020-06-24 13:24:07 +00:00
|
|
|
}
|
2022-07-09 15:05:52 +00:00
|
|
|
|
2022-10-20 22:23:14 +00:00
|
|
|
std::optional<int>
|
|
|
|
GetInterfaceIndex(ipaddr_t) const override
|
2020-06-24 13:24:07 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
// todo: implement me
|
|
|
|
return std::nullopt;
|
2019-09-09 12:10:26 +00:00
|
|
|
}
|
2018-10-03 10:35:39 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
std::optional<std::string>
|
|
|
|
FindFreeTun() const override
|
2018-10-03 10:35:39 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
int num = 0;
|
|
|
|
while (num < 255)
|
2018-10-03 10:35:39 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
std::string ifname = fmt::format("lokitun{}", num);
|
2022-07-21 11:19:43 +00:00
|
|
|
if (GetInterfaceAddr(ifname, AF_INET) == std::nullopt)
|
2022-07-09 15:05:52 +00:00
|
|
|
return ifname;
|
|
|
|
num++;
|
2018-10-03 10:35:39 +00:00
|
|
|
}
|
2021-02-16 15:59:18 +00:00
|
|
|
return std::nullopt;
|
2022-07-09 15:05:52 +00:00
|
|
|
}
|
2021-02-16 15:59:18 +00:00
|
|
|
|
2022-07-09 15:05:52 +00:00
|
|
|
std::optional<SockAddr>
|
|
|
|
GetInterfaceAddr(std::string_view ifname, int af) const override
|
2018-09-03 12:03:43 +00:00
|
|
|
{
|
2022-07-09 15:05:52 +00:00
|
|
|
std::optional<SockAddr> addr;
|
|
|
|
iter_all([&addr, af, ifname = std::string{ifname}](auto i) {
|
|
|
|
if (addr)
|
|
|
|
return;
|
|
|
|
if (i and i->ifa_addr and i->ifa_addr->sa_family == af and i->ifa_name == ifname)
|
|
|
|
addr = llarp::SockAddr{*i->ifa_addr};
|
|
|
|
});
|
|
|
|
return addr;
|
|
|
|
}
|
2022-05-20 17:10:04 +00:00
|
|
|
|
|
|
|
std::optional<SockAddr>
|
2022-07-09 15:05:52 +00:00
|
|
|
AllInterfaces(SockAddr fallback) const override
|
2018-09-03 12:03:43 +00:00
|
|
|
{
|
2022-05-20 17:10:04 +00:00
|
|
|
std::optional<SockAddr> found;
|
2022-07-09 15:05:52 +00:00
|
|
|
iter_all([fallback, &found](auto i) {
|
2022-05-20 17:10:04 +00:00
|
|
|
if (found)
|
|
|
|
return;
|
2022-07-09 15:05:52 +00:00
|
|
|
if (i == nullptr or i->ifa_addr == nullptr)
|
|
|
|
return;
|
|
|
|
if (i->ifa_addr->sa_family != fallback.Family())
|
|
|
|
return;
|
|
|
|
SockAddr addr{*i->ifa_addr};
|
|
|
|
if (addr == fallback)
|
|
|
|
found = addr;
|
2022-05-20 17:10:04 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// 0.0.0.0 is used in our compat shim as our public ip so we check for that special case
|
|
|
|
const auto zero = IPRange::FromIPv4(0, 0, 0, 0, 8);
|
2022-07-09 15:05:52 +00:00
|
|
|
// when we cannot find an address but we are looking for 0.0.0.0 just default to the old
|
|
|
|
// style
|
|
|
|
if (not found and (fallback.isIPv4() and zero.Contains(fallback.asIPv4())))
|
|
|
|
found = Wildcard(fallback.Family());
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
HasInterfaceAddress(ipaddr_t ip) const override
|
|
|
|
{
|
|
|
|
bool found{false};
|
|
|
|
iter_all([&found, ip](auto i) {
|
|
|
|
if (found)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (not(i and i->ifa_addr))
|
|
|
|
return;
|
|
|
|
const SockAddr addr{*i->ifa_addr};
|
|
|
|
found = addr.getIP() == ip;
|
|
|
|
});
|
2022-05-20 17:10:04 +00:00
|
|
|
return found;
|
2018-09-03 12:03:43 +00:00
|
|
|
}
|
2022-07-28 16:07:38 +00:00
|
|
|
std::vector<InterfaceInfo>
|
|
|
|
AllNetworkInterfaces() const override
|
|
|
|
{
|
|
|
|
std::unordered_map<std::string, InterfaceInfo> ifmap;
|
|
|
|
iter_all([&ifmap](auto* i) {
|
|
|
|
if (i == nullptr or i->ifa_addr == nullptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto fam = i->ifa_addr->sa_family;
|
|
|
|
if (fam != AF_INET and fam != AF_INET6)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto& ent = ifmap[i->ifa_name];
|
|
|
|
if (ent.name.empty())
|
|
|
|
{
|
|
|
|
ent.name = i->ifa_name;
|
|
|
|
ent.index = if_nametoindex(i->ifa_name);
|
|
|
|
}
|
|
|
|
SockAddr addr{*i->ifa_addr};
|
|
|
|
SockAddr mask{*i->ifa_netmask};
|
|
|
|
ent.addrs.emplace_back(addr.asIPv6(), mask.asIPv6());
|
|
|
|
});
|
|
|
|
std::vector<InterfaceInfo> all;
|
|
|
|
for (auto& [name, ent] : ifmap)
|
|
|
|
all.emplace_back(std::move(ent));
|
|
|
|
return all;
|
|
|
|
}
|
2022-07-09 15:05:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const Platform_Impl g_plat{};
|
|
|
|
|
|
|
|
const Platform*
|
|
|
|
Platform::Default_ptr()
|
|
|
|
{
|
|
|
|
return &g_plat;
|
|
|
|
}
|
|
|
|
} // namespace llarp::net
|