llarp/net/net.hpp
Namespaces
| Name |
|---|
| llarp [crypto.hpp] |
| llarp::net |
Classes
| Name | |
|---|---|
| class | llarp::net::Platform network platform (all methods virtual so it can be mocked by unit tests) |
Functions
| Name | |
|---|---|
| bool | operator==(const in_addr & a, const in_addr & b) |
| bool | operator==(const in6_addr & a, const in6_addr & b) |
| bool | operator==(const sockaddr_in & a, const sockaddr_in & b) |
| bool | operator==(const sockaddr_in6 & a, const sockaddr_in6 & b) |
| bool | operator==(const sockaddr & a, const sockaddr & b) |
| bool | operator<(const in_addr & a, const in_addr & b) |
| bool | operator<(const in6_addr & a, const in6_addr & b) |
| bool | operator<(const sockaddr_in6 & a, const sockaddr_in6 & b) |
Functions Documentation
function operator==
inline bool operator==(
const in_addr & a,
const in_addr & b
)
function operator==
inline bool operator==(
const in6_addr & a,
const in6_addr & b
)
function operator==
inline bool operator==(
const sockaddr_in & a,
const sockaddr_in & b
)
function operator==
inline bool operator==(
const sockaddr_in6 & a,
const sockaddr_in6 & b
)
function operator==
inline bool operator==(
const sockaddr & a,
const sockaddr & b
)
function operator<
inline bool operator<(
const in_addr & a,
const in_addr & b
)
function operator<
inline bool operator<(
const in6_addr & a,
const in6_addr & b
)
function operator<
inline bool operator<(
const sockaddr_in6 & a,
const sockaddr_in6 & b
)
Source code
#pragma once
#include "uint128.hpp"
#include "address_info.hpp"
#include "net_int.hpp"
#include "net.h"
#include "ip_range.hpp"
#include "sock_addr.hpp"
#include <llarp/util/mem.hpp>
#include <llarp/util/bits.hpp>
#include "interface_info.hpp"
#include <functional>
#include <cstdlib> // for itoa
#include <vector>
// for addrinfo
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "bogon_ranges.hpp"
namespace llarp
{
inline int
cmp(const in_addr& a, const in_addr& b)
{
return memcmp(&a, &b, sizeof(in_addr));
}
inline int
cmp(const in6_addr& a, const in6_addr& b)
{
return memcmp(&a, &b, sizeof(in6_addr));
}
namespace net
{
class Platform
{
public:
Platform() = default;
virtual ~Platform() = default;
Platform(const Platform&) = delete;
Platform(Platform&&) = delete;
static const Platform*
Default_ptr();
virtual std::optional<SockAddr>
AllInterfaces(SockAddr pubaddr) const = 0;
inline SockAddr
Wildcard(int af = AF_INET) const
{
if (af == AF_INET)
{
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
return SockAddr{addr};
}
if (af == AF_INET6)
{
sockaddr_in6 addr6{};
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(0);
addr6.sin6_addr = IN6ADDR_ANY_INIT;
return SockAddr{addr6};
}
throw std::invalid_argument{fmt::format("{} is not a valid address family", af)};
}
inline SockAddr
WildcardWithPort(port_t port, int af = AF_INET) const
{
auto addr = Wildcard(af);
addr.setPort(port);
return addr;
}
virtual std::string
LoopbackInterfaceName() const = 0;
virtual bool
HasInterfaceAddress(ipaddr_t ip) const = 0;
inline bool
IsLoopbackAddress(ipaddr_t ip) const
{
const IPRange loopback4 = IPRange::FromIPv4(127, 0, 0, 0, 8);
const IPRange loopback6{
net::ipv6addr_t::from_host(uint128_t{0UL, 1UL}), netmask_ipv6_bits(128)};
return var::visit(
[&loopback4, &loopback6](auto&& ip) {
return loopback4.Contains(ip) or loopback6.Contains(ip);
},
ip);
}
inline bool
IsWildcardAddress(ipaddr_t ip) const
{
return var::visit([](auto&& ip) { return not ip.n; }, ip);
}
virtual std::optional<std::string>
GetBestNetIF(int af = AF_INET) const = 0;
inline std::optional<SockAddr>
MaybeInferPublicAddr(port_t default_port, int af = AF_INET) const
{
std::optional<SockAddr> maybe_addr;
if (auto maybe_ifname = GetBestNetIF(af))
maybe_addr = GetInterfaceAddr(*maybe_ifname, af);
if (maybe_addr)
maybe_addr->setPort(default_port);
return maybe_addr;
}
virtual std::optional<IPRange>
FindFreeRange() const = 0;
virtual std::optional<std::string>
FindFreeTun() const = 0;
virtual std::optional<SockAddr>
GetInterfaceAddr(std::string_view ifname, int af = AF_INET) const = 0;
inline std::optional<net::ipv6addr_t>
GetInterfaceIPv6Address(std::string_view ifname) const
{
if (auto maybe_addr = GetInterfaceAddr(ifname, AF_INET6))
return maybe_addr->getIPv6();
return std::nullopt;
}
inline bool
IsBogon(const SockAddr& addr) const
{
return IsBogonIP(addr.getIPv6());
}
inline bool
IsBogonRange(const IPRange& range) const
{
// special case for 0.0.0.0/0
if (range.IsV4() and range.netmask_bits == netmask_ipv6_bits(96))
return false;
// special case for ::/0
if (IsWildcardAddress(range.netmask_bits))
return false;
return IsBogonIP(range.addr) or IsBogonIP(range.HighestAddr());
}
inline bool
IsBogonIP(const net::ipaddr_t& addr) const
{
return IsBogonIP(var::visit(
[](auto&& ip) {
if constexpr (std::is_same_v<net::ipv4addr_t, std::decay_t<decltype(ip)>>)
return ExpandV4(ip);
else
return ip;
},
addr));
}
inline bool
IsBogonIP(const net::ipv6addr_t& addr) const
{
if (not IPRange::V4MappedRange().Contains(addr))
{
for (const auto& v6_range : bogonRanges_v6)
{
if (v6_range.Contains(addr))
return true;
}
return false;
}
const auto v4_addr = net::TruncateV6(addr);
for (const auto& v4_range : bogonRanges_v4)
{
if (v4_range.Contains(v4_addr))
return true;
}
return false;
}
virtual std::optional<int>
GetInterfaceIndex(ipaddr_t ip) const = 0;
virtual std::vector<InterfaceInfo>
AllNetworkInterfaces() const = 0;
};
} // namespace net
} // namespace llarp
inline bool
operator==(const in_addr& a, const in_addr& b)
{
return llarp::cmp(a, b) == 0;
}
inline bool
operator==(const in6_addr& a, const in6_addr& b)
{
return llarp::cmp(a, b) == 0;
}
inline bool
operator==(const sockaddr_in& a, const sockaddr_in& b)
{
return a.sin_port == b.sin_port and a.sin_addr.s_addr == b.sin_addr.s_addr;
}
inline bool
operator==(const sockaddr_in6& a, const sockaddr_in6& b)
{
return a.sin6_port == b.sin6_port and a.sin6_addr == b.sin6_addr;
}
inline bool
operator==(const sockaddr& a, const sockaddr& b)
{
if (a.sa_family != b.sa_family)
return false;
switch (a.sa_family)
{
case AF_INET:
return reinterpret_cast<const sockaddr_in&>(a) == reinterpret_cast<const sockaddr_in&>(b);
case AF_INET6:
return reinterpret_cast<const sockaddr_in6&>(a) == reinterpret_cast<const sockaddr_in6&>(b);
default:
return false;
}
}
inline bool
operator<(const in_addr& a, const in_addr& b)
{
return llarp::cmp(a, b) < 0;
}
inline bool
operator<(const in6_addr& a, const in6_addr& b)
{
return llarp::cmp(a, b) < 0;
}
inline bool
operator<(const sockaddr_in6& a, const sockaddr_in6& b)
{
return std::tie(a.sin6_addr, a.sin6_port) < std::tie(b.sin6_addr, b.sin6_port);
}
Updated on 2026-01-10 at 22:49:45 +0000