|
|
@ -19,10 +19,6 @@ namespace llarp
|
|
|
|
/// shared utility functions
|
|
|
|
/// shared utility functions
|
|
|
|
///
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
|
|
constexpr auto addrIsV4 = [](const in6_addr& addr) -> bool {
|
|
|
|
|
|
|
|
return addr.s6_addr[10] == 0xff and addr.s6_addr[11] == 0xff;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
SockAddr::init()
|
|
|
|
SockAddr::init()
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -31,13 +27,9 @@ namespace llarp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
SockAddr::applySIITBytes()
|
|
|
|
SockAddr::applyIPv4MapBytes()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
|
|
|
|
std::memcpy(m_addr.sin6_addr.s6_addr, ipv4_map_prefix.data(), ipv4_map_prefix.size());
|
|
|
|
|
|
|
|
|
|
|
|
// SIIT == Stateless IP/ICMP Translation (represent IPv4 with IPv6)
|
|
|
|
|
|
|
|
ip6[10] = 0xff;
|
|
|
|
|
|
|
|
ip6[11] = 0xff;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SockAddr::SockAddr()
|
|
|
|
SockAddr::SockAddr()
|
|
|
@ -52,9 +44,8 @@ namespace llarp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port)
|
|
|
|
SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port)
|
|
|
|
|
|
|
|
: SockAddr{a, b, c, d}
|
|
|
|
{
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
|
|
|
|
setIPv4(a, b, c, d);
|
|
|
|
|
|
|
|
setPort(port);
|
|
|
|
setPort(port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SockAddr::SockAddr(std::string_view addr)
|
|
|
|
SockAddr::SockAddr(std::string_view addr)
|
|
|
@ -62,6 +53,12 @@ namespace llarp
|
|
|
|
init();
|
|
|
|
init();
|
|
|
|
fromString(addr);
|
|
|
|
fromString(addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SockAddr::SockAddr(std::string_view addr, uint16_t port)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
init();
|
|
|
|
|
|
|
|
setPort(port);
|
|
|
|
|
|
|
|
fromString(addr, false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SockAddr::SockAddr(const AddressInfo& info) : SockAddr{info.ip}
|
|
|
|
SockAddr::SockAddr(const AddressInfo& info) : SockAddr{info.ip}
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -89,9 +86,9 @@ namespace llarp
|
|
|
|
SockAddr::operator=(const sockaddr& other)
|
|
|
|
SockAddr::operator=(const sockaddr& other)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (other.sa_family == AF_INET6)
|
|
|
|
if (other.sa_family == AF_INET6)
|
|
|
|
*this = (const sockaddr_in6&)other;
|
|
|
|
*this = reinterpret_cast<const sockaddr_in6&>(other);
|
|
|
|
else if (other.sa_family == AF_INET)
|
|
|
|
else if (other.sa_family == AF_INET)
|
|
|
|
*this = (const sockaddr_in&)other;
|
|
|
|
*this = reinterpret_cast<const sockaddr_in&>(other);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
throw std::invalid_argument("Invalid sockaddr (not AF_INET or AF_INET6)");
|
|
|
|
throw std::invalid_argument("Invalid sockaddr (not AF_INET or AF_INET6)");
|
|
|
|
|
|
|
|
|
|
|
@ -107,7 +104,7 @@ namespace llarp
|
|
|
|
SockAddr::operator=(const sockaddr_in& other)
|
|
|
|
SockAddr::operator=(const sockaddr_in& other)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
init();
|
|
|
|
applySIITBytes();
|
|
|
|
applyIPv4MapBytes();
|
|
|
|
|
|
|
|
|
|
|
|
// avoid byte order conversion (this is NBO -> NBO)
|
|
|
|
// avoid byte order conversion (this is NBO -> NBO)
|
|
|
|
memcpy(m_addr.sin6_addr.s6_addr + 12, &other.sin_addr.s_addr, sizeof(in_addr));
|
|
|
|
memcpy(m_addr.sin6_addr.s6_addr + 12, &other.sin_addr.s_addr, sizeof(in_addr));
|
|
|
@ -130,7 +127,7 @@ namespace llarp
|
|
|
|
init();
|
|
|
|
init();
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&m_addr, &other, sizeof(sockaddr_in6));
|
|
|
|
memcpy(&m_addr, &other, sizeof(sockaddr_in6));
|
|
|
|
if (addrIsV4(other.sin6_addr))
|
|
|
|
if (ipv6_is_mapped_ipv4(other.sin6_addr))
|
|
|
|
setIPv4(
|
|
|
|
setIPv4(
|
|
|
|
other.sin6_addr.s6_addr[12],
|
|
|
|
other.sin6_addr.s6_addr[12],
|
|
|
|
other.sin6_addr.s6_addr[13],
|
|
|
|
other.sin6_addr.s6_addr[13],
|
|
|
@ -153,7 +150,7 @@ namespace llarp
|
|
|
|
init();
|
|
|
|
init();
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&m_addr.sin6_addr.s6_addr, &other.s6_addr, sizeof(m_addr.sin6_addr.s6_addr));
|
|
|
|
memcpy(&m_addr.sin6_addr.s6_addr, &other.s6_addr, sizeof(m_addr.sin6_addr.s6_addr));
|
|
|
|
if (addrIsV4(other))
|
|
|
|
if (ipv6_is_mapped_ipv4(other))
|
|
|
|
setIPv4(other.s6_addr[12], other.s6_addr[13], other.s6_addr[14], other.s6_addr[15]);
|
|
|
|
setIPv4(other.s6_addr[12], other.s6_addr[13], other.s6_addr[14], other.s6_addr[15]);
|
|
|
|
m_empty = false;
|
|
|
|
m_empty = false;
|
|
|
|
|
|
|
|
|
|
|
@ -202,7 +199,7 @@ namespace llarp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
SockAddr::fromString(std::string_view str)
|
|
|
|
SockAddr::fromString(std::string_view str, bool allow_port)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (str.empty())
|
|
|
|
if (str.empty())
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -233,33 +230,19 @@ namespace llarp
|
|
|
|
if (ipSplits.size() != 4)
|
|
|
|
if (ipSplits.size() != 4)
|
|
|
|
throw std::invalid_argument(stringify(str, " is not a valid IPv4 address"));
|
|
|
|
throw std::invalid_argument(stringify(str, " is not a valid IPv4 address"));
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t ipBytes[4] = {0};
|
|
|
|
std::array<uint8_t, 4> ipBytes;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
if (not parse_int(ipSplits[i], ipBytes[i]))
|
|
|
|
auto byteStr = ipSplits[i];
|
|
|
|
throw std::runtime_error(stringify(str, " contains invalid numeric value"));
|
|
|
|
auto result = std::from_chars(byteStr.data(), byteStr.data() + byteStr.size(), ipBytes[i]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.ec != std::errc())
|
|
|
|
|
|
|
|
throw std::runtime_error(stringify(str, " contains invalid number"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.ptr != (byteStr.data() + byteStr.size()))
|
|
|
|
|
|
|
|
throw std::runtime_error(stringify(str, " contains non-numeric values"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// attempt port before setting IPv4 bytes
|
|
|
|
// attempt port before setting IPv4 bytes
|
|
|
|
if (splits.size() == 2)
|
|
|
|
if (splits.size() == 2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint16_t port = 0;
|
|
|
|
if (not allow_port)
|
|
|
|
auto portStr = splits[1];
|
|
|
|
throw std::runtime_error{stringify("invalid ip address (port not allowed here): ", str)};
|
|
|
|
auto result = std::from_chars(portStr.data(), portStr.data() + portStr.size(), port);
|
|
|
|
uint16_t port;
|
|
|
|
|
|
|
|
if (not parse_int(splits[1], port))
|
|
|
|
if (result.ec != std::errc())
|
|
|
|
throw std::runtime_error{stringify(splits[1], " is not a valid port")};
|
|
|
|
throw std::runtime_error(stringify(str, " contains invalid port"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.ptr != (portStr.data() + portStr.size()))
|
|
|
|
|
|
|
|
throw std::runtime_error(stringify(str, " contains junk after port"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setPort(port);
|
|
|
|
setPort(port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -278,7 +261,7 @@ namespace llarp
|
|
|
|
|
|
|
|
|
|
|
|
if (ip6[10] == 0xff and ip6[11] == 0xff)
|
|
|
|
if (ip6[10] == 0xff and ip6[11] == 0xff)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// treat SIIT like IPv4
|
|
|
|
// handle IPv4 mapped addrs
|
|
|
|
constexpr auto MaxIPv4PlusPortStringSize = 22;
|
|
|
|
constexpr auto MaxIPv4PlusPortStringSize = 22;
|
|
|
|
str.reserve(MaxIPv4PlusPortStringSize);
|
|
|
|
str.reserve(MaxIPv4PlusPortStringSize);
|
|
|
|
char buf[128] = {0x0};
|
|
|
|
char buf[128] = {0x0};
|
|
|
@ -317,7 +300,7 @@ namespace llarp
|
|
|
|
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
|
|
|
|
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
|
|
|
|
llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr));
|
|
|
|
llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr));
|
|
|
|
|
|
|
|
|
|
|
|
applySIITBytes();
|
|
|
|
applyIPv4MapBytes();
|
|
|
|
|
|
|
|
|
|
|
|
ip6[12] = a;
|
|
|
|
ip6[12] = a;
|
|
|
|
ip6[13] = b;
|
|
|
|
ip6[13] = b;
|
|
|
|