From d1dadb530c27bb364d769b11b38a98fcd10eecbc Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 9 Mar 2021 12:02:41 -0400 Subject: [PATCH] SockAddr endian cleanups & add uint128 ctors - Make SockAddr endian arguments explicit - Consolidate port-less contructors and port constructors into one with a default port of 0. - Add {h,n}uint128_t ctors for construction from IPv6 addrs --- llarp/handlers/tun.cpp | 8 ++-- llarp/net/net_int.cpp | 21 ++++++++-- llarp/net/net_int.hpp | 13 +++--- llarp/net/sock_addr.cpp | 79 +++++++++++++++++++++++++++++-------- llarp/net/sock_addr.hpp | 52 ++++++++++++++++++------ test/net/test_llarp_net.cpp | 28 +++++++++++++ 6 files changed, 160 insertions(+), 41 deletions(-) diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 38b611c22..9069a6467 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -61,8 +61,8 @@ namespace llarp hdr->ttl = 64; hdr->frag_off = htons(0b0100000000000000); - hdr->saddr = from.getIPv4(); - hdr->daddr = to.getIPv4(); + hdr->saddr = from.getIPv4().n; + hdr->daddr = to.getIPv4().n; // make udp packet uint8_t* ptr = pkt.buf + 20; @@ -98,8 +98,8 @@ namespace llarp const uint8_t* ptr = pkt.buf + ip_header_size; const auto dst = ToNet(pkt.dstv4()); const auto src = ToNet(pkt.srcv4()); - const SockAddr laddr{src.n, *reinterpret_cast(ptr)}; - const SockAddr raddr{dst.n, *reinterpret_cast(ptr + 2)}; + const SockAddr laddr{src, nuint16_t{*reinterpret_cast(ptr)}}; + const SockAddr raddr{dst, nuint16_t{*reinterpret_cast(ptr + 2)}}; OwnedBuffer buf{pkt.sz - (udp_header_size + ip_header_size)}; std::copy_n(ptr + udp_header_size, buf.sz, buf.buf.get()); diff --git a/llarp/net/net_int.cpp b/llarp/net/net_int.cpp index 8db35d889..caecb7ab4 100644 --- a/llarp/net/net_int.cpp +++ b/llarp/net/net_int.cpp @@ -4,27 +4,42 @@ namespace llarp { - template <> + huint16_t + ToHost(nuint16_t n) + { + return xntohs(n); + } + huint32_t ToHost(nuint32_t n) { return xntohl(n); } - template <> + huint128_t + ToHost(nuint128_t n) + { + return {ntoh128(n.n)}; + } + nuint16_t ToNet(huint16_t h) { return xhtons(h); } - template <> nuint32_t ToNet(huint32_t h) { return xhtonl(h); } + nuint128_t + ToNet(huint128_t h) + { + return {hton128(h.h)}; + } + template <> void huint32_t::ToV6(V6Container& c) diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index 2faf244e6..61d5ff589 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -220,14 +220,13 @@ namespace llarp return huint16_t{ntohs(x.n)}; } - template - huint_t - ToHost(nuint_t h); - - template - nuint_t - ToNet(huint_t h); + huint16_t ToHost(nuint16_t); + huint32_t ToHost(nuint32_t); + huint128_t ToHost(nuint128_t); + nuint16_t ToNet(huint16_t); + nuint32_t ToNet(huint32_t); + nuint128_t ToNet(huint128_t); } // namespace llarp namespace std diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index d8a9644fc..37d3a3586 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -39,23 +39,32 @@ namespace llarp init(); } - SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d) + SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, huint16_t port) { init(); setIPv4(a, b, c, d); + setPort(port); } - SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port) - : SockAddr{a, b, c, d} + SockAddr::SockAddr(nuint32_t ip, nuint16_t port) { + init(); + setIPv4(ip); setPort(port); } - SockAddr::SockAddr(uint32_t ip, uint16_t port) + SockAddr::SockAddr(huint128_t ip, huint16_t port) { init(); - setIPv4(ip); - setPort(ntohs(port)); + setIPv6(ip); + setPort(port); + } + + SockAddr::SockAddr(nuint128_t ip, nuint16_t port) + { + init(); + setIPv6(ip); + setPort(port); } SockAddr::SockAddr(std::string_view addr) @@ -66,13 +75,13 @@ namespace llarp SockAddr::SockAddr(std::string_view addr, uint16_t port) { init(); - setPort(port); + setPort(huint16_t{port}); fromString(addr, false); } SockAddr::SockAddr(const AddressInfo& info) : SockAddr{info.ip} { - setPort(info.port); + setPort(huint16_t{info.port}); } SockAddr::SockAddr(const SockAddr& other) @@ -138,12 +147,14 @@ namespace llarp memcpy(&m_addr, &other, sizeof(sockaddr_in6)); if (ipv6_is_mapped_ipv4(other.sin6_addr)) + { setIPv4( other.sin6_addr.s6_addr[12], other.sin6_addr.s6_addr[13], other.sin6_addr.s6_addr[14], other.sin6_addr.s6_addr[15]); - setPort(ntohs(other.sin6_port)); + m_addr4.sin_port = m_addr.sin6_port; + } m_empty = false; return *this; @@ -161,7 +172,10 @@ namespace llarp memcpy(&m_addr.sin6_addr.s6_addr, &other.s6_addr, sizeof(m_addr.sin6_addr.s6_addr)); if (ipv6_is_mapped_ipv4(other)) + { setIPv4(other.s6_addr[12], other.s6_addr[13], other.s6_addr[14], other.s6_addr[15]); + m_addr4.sin_port = m_addr.sin6_port; + } m_empty = false; return *this; @@ -302,14 +316,14 @@ namespace llarp return m_empty; } - uint32_t + nuint32_t SockAddr::getIPv4() const { - return m_addr4.sin_addr.s_addr; + return {m_addr4.sin_addr.s_addr}; } void - SockAddr::setIPv4(uint32_t ip) + SockAddr::setIPv4(nuint32_t ip) { uint8_t* ip6 = m_addr.sin6_addr.s6_addr; llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr)); @@ -317,10 +331,16 @@ namespace llarp applyIPv4MapBytes(); std::memcpy(ip6 + 12, &ip, 4); - m_addr4.sin_addr.s_addr = ip; + m_addr4.sin_addr.s_addr = ip.n; m_empty = false; } + void + SockAddr::setIPv4(huint32_t ip) + { + setIPv4(ToNet(ip)); + } + void SockAddr::setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { @@ -339,10 +359,37 @@ namespace llarp } void - SockAddr::setPort(uint16_t port) + SockAddr::setIPv6(huint128_t ip) + { + return setIPv6(ToNet(ip)); + } + + void + SockAddr::setIPv6(nuint128_t ip) + { + std::memcpy(&m_addr.sin6_addr, &ip, sizeof(m_addr.sin6_addr)); + if (ipv6_is_mapped_ipv4(m_addr.sin6_addr)) + { + setIPv4( + m_addr.sin6_addr.s6_addr[12], + m_addr.sin6_addr.s6_addr[13], + m_addr.sin6_addr.s6_addr[14], + m_addr.sin6_addr.s6_addr[15]); + m_addr4.sin_port = m_addr.sin6_port; + } + } + + void + SockAddr::setPort(nuint16_t port) + { + m_addr.sin6_port = port.n; + m_addr4.sin_port = port.n; + } + + void + SockAddr::setPort(huint16_t port) { - m_addr.sin6_port = htons(port); - m_addr4.sin_port = htons(port); + setPort(ToNet(port)); } uint16_t diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index 336ef426b..adfbdfcc7 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -27,11 +27,20 @@ namespace llarp struct SockAddr { SockAddr(); - SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d); - SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port); + // IPv4 constructors: + SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, huint16_t port = {0}); + SockAddr(nuint32_t ip, nuint16_t port); + SockAddr(huint32_t ip, huint16_t port); + + // IPv6 (or IPv4 if given a special IPv4-mapped IPv6 addr) in host order (including port). + SockAddr(huint128_t ip, huint16_t port = {0}); + // IPv6 (or IPv4 if given a special IPv4-mapped IPv6 addr) in network order. NB: port is also + // in network order! + SockAddr(nuint128_t ip, nuint16_t port = {0}); + + // String ctors SockAddr(std::string_view addr); - SockAddr(std::string_view addr, uint16_t port); - SockAddr(uint32_t ip, uint16_t port); + SockAddr(std::string_view addr, uint16_t port); // port is in native (host) order SockAddr(const AddressInfo&); @@ -81,23 +90,44 @@ namespace llarp void setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d); - /// port is in host order void - setIPv4(uint32_t ip); + setIPv4(nuint32_t ip); void - setPort(uint16_t port); + setIPv4(huint32_t ip); - /// port is in host order + void + setIPv6(huint128_t ip); + + void + setIPv6(nuint128_t ip); + + void + setPort(huint16_t port); + + void + setPort(nuint16_t port); + + // Port is a native (host) value + void + setPort(uint16_t port) + { + setPort(huint16_t{port}); + } + + /// port is always returned in native (host) order uint16_t getPort() const; - huint128_t - asIPv6() const; /// in network order - uint32_t + nuint128_t + getIPv6() const; + nuint32_t getIPv4() const; + /// in host order + huint128_t + asIPv6() const; huint32_t asIPv4() const; diff --git a/test/net/test_llarp_net.cpp b/test/net/test_llarp_net.cpp index 9c504e83b..aea061bd4 100644 --- a/test/net/test_llarp_net.cpp +++ b/test/net/test_llarp_net.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include @@ -102,3 +103,30 @@ TEST_CASE("Bogon") REQUIRE_FALSE(llarp::IsIPv4Bogon(llarp::ipaddr_ipv4_bits(79, 12, 3, 4))); } } + +TEST_CASE("uint128_t") +{ + SECTION("layout") + { + llarp::uint128_t i{0x0011223f44556677ULL, 0x8899aabbc3ddeeffULL}; + REQUIRE(oxenmq::to_hex(std::string_view{reinterpret_cast(&i), sizeof(i)}) == +#ifdef __BIG_ENDIAN__ + "0011223f445566778899aabbc3ddeeff" +#else + "ffeeddc3bbaa9988776655443f221100" +#endif + ); + } + SECTION("ntoh") + { + llarp::uint128_t i{0x0011223f44556677ULL, 0x8899aabbc3ddeeffULL}; + auto be = ntoh128(i); + REQUIRE(be == llarp::uint128_t{0xffeeddc3bbaa9988ULL, 0x776655443f221100ULL}); + } + SECTION("hton") + { + llarp::uint128_t i{0x0011223f44556677ULL, 0x8899aabbc3ddeeffULL}; + auto be = ntoh128(i); + REQUIRE(be == llarp::uint128_t{0xffeeddc3bbaa9988ULL, 0x776655443f221100ULL}); + } +}