From dff170712ff78d766955c18891fd5dbc8d0b486b Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Mon, 4 May 2020 15:17:16 -0600 Subject: [PATCH] Gut Addr, replace with stubbed SockAddr and IpAddress --- llarp/net/ip_address.hpp | 53 ++++ llarp/net/net_addr.cpp | 505 --------------------------------------- llarp/net/net_addr.hpp | 169 ------------- llarp/net/sock_addr.hpp | 21 ++ 4 files changed, 74 insertions(+), 674 deletions(-) create mode 100644 llarp/net/ip_address.hpp delete mode 100644 llarp/net/net_addr.cpp delete mode 100644 llarp/net/net_addr.hpp create mode 100644 llarp/net/sock_addr.hpp diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp new file mode 100644 index 000000000..82f3c6d36 --- /dev/null +++ b/llarp/net/ip_address.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +namespace llarp +{ + /// A struct that can represent either an IPv4 or IPv6 address. It is meant for representation + /// purposes only (e.g. serialization/deserialization). In addition, it also optionally stores + /// a port. + /// + /// As a convenience, it can produce a SockAddr for dealing with network libraries which depend + /// sockaddr structs. However, it does not keep this as a member variable and isn't responsible + /// for its lifetime/memory/etc. + struct IpAddress + { + /// Constructor. Takes a string which can be an IPv4 or IPv6 address optionally followed by + /// a colon and a port. + IpAddress(std::string_view str); + + /// Constructor. Takes an IP address (as above) and a port. The string may not contain a port. + IpAddress(std::string_view str, int32_t port); + + /// Return the port. Returns -1 if no port has been provided. + int32_t + getPort() const; + + /// Set the port. + void + setPort(uint16_t port); + + /// Returns true if this is an IPv4 address (or an IPv6 address representing an IPv4 address), + /// false otherwise. + /// TODO: could return an int (e.g. 4 or 6) or an enum + bool + isIPv4(); + + /// Creates an instance of SockAddr representing this IpAddress. + SockAddr + createSockAddr() const; + + // TODO: other utility functions left over from Addr which may be useful + // isTenPrivate(uint32_t byte); + // isOneSevenPrivate(uint32_t byte); + // isOneNinePrivate(uint32_t byte); + // IsBogon() const; + // isPrivate() const; + // struct Hash + // operator<(const Addr& other) const; + // operator==(const Addr& other) const; + // operator=(const sockaddr& other); + }; +} // namespace llarp diff --git a/llarp/net/net_addr.cpp b/llarp/net/net_addr.cpp deleted file mode 100644 index 8f7f43c21..000000000 --- a/llarp/net/net_addr.cpp +++ /dev/null @@ -1,505 +0,0 @@ -#include -#include -#include - -// for addrinfo -#ifndef _WIN32 -#include -#include -#include -#else -#include -#include -#include -#define inet_aton(x, y) inet_pton(AF_INET, x, y) -#endif - -#include - -namespace llarp -{ - Addr::Addr() - { - llarp::Zero(&_addr4, sizeof(_addr4)); - _addr4.sin_family = AF_INET; - llarp::Zero(&_addr, sizeof(_addr)); - _addr.sin6_family = AF_INET6; - } - Addr::~Addr() = default; - - void - Addr::port(uint16_t port) - { - _addr4.sin_port = htons(port); - _addr.sin6_port = htons(port); - } - - in6_addr* - Addr::addr6() - { - return (in6_addr*)&_addr.sin6_addr.s6_addr[0]; - } - - in_addr* - Addr::addr4() - { - return (in_addr*)&_addr.sin6_addr.s6_addr[12]; - } - - const in6_addr* - Addr::addr6() const - { - return (const in6_addr*)&_addr.sin6_addr.s6_addr[0]; - } - - const in_addr* - Addr::addr4() const - { - return (const in_addr*)&_addr.sin6_addr.s6_addr[12]; - } - - Addr::Addr(std::string_view str) : Addr() - { - if (not FromString(str)) - throw std::invalid_argument(stringify("failed to parse bullshit value: ", str)); - } - - Addr::Addr(std::string_view str, const uint16_t p_port) : Addr() - { - if (not FromString(str)) - throw std::invalid_argument(stringify("failed to parse bullshit value: ", str)); - this->port(p_port); - } - - Addr::Addr(std::string_view addr_str, std::string_view port_str) - : Addr(addr_str, std::strtoul(port_str.data(), nullptr, 10)) - { - } - - bool - Addr::FromString(std::string_view in) - { - // TODO: this will overwrite port, which may not be specified in the input string - Zero(&_addr, sizeof(sockaddr_in6)); - - std::string ipPortion; - auto pPosition = in.find(':'); - if (pPosition != std::string_view::npos) - { - // parse port - const std::string portStr = std::string(in.substr(pPosition + 1)); - uint16_t port = std::atoi(portStr.c_str()); - this->port(port); - - ipPortion = std::string(in.substr(0, pPosition)); - } - else - { - ipPortion = std::string(in); - } - - struct addrinfo hint, *res = nullptr; - int ret; - - memset(&hint, '\0', sizeof hint); - - hint.ai_family = PF_UNSPEC; - hint.ai_flags = AI_NUMERICHOST; - - if (pPosition != std::string_view::npos) - { - ret = getaddrinfo( - std::string(in.begin(), in.begin() + pPosition).c_str(), nullptr, &hint, &res); - } - else - { - ret = getaddrinfo(std::string(in).c_str(), nullptr, &hint, &res); - } - - if (ret) - { - LogError("failed to determine address family: ", in); - return false; - } - - if (res->ai_family == AF_INET6) - { - LogError("IPv6 address not supported yet", in); - return false; - } - if (res->ai_family != AF_INET) - { - LogError("Address family not supported yet", in); - return false; - } - - // put it in _addr4 - struct in_addr* addr = &_addr4.sin_addr; - if (inet_aton(ipPortion.c_str(), addr) == 0) - { - LogError("failed to parse ", in); - return false; - } - - _addr.sin6_family = res->ai_family; - _addr4.sin_family = res->ai_family; -#if ((__APPLE__ && __MACH__) || __FreeBSD__) - _addr4.sin_len = sizeof(in_addr); -#endif - // set up SIIT - uint8_t* addrptr = _addr.sin6_addr.s6_addr; - addrptr[11] = 0xff; - addrptr[10] = 0xff; - memcpy(12 + addrptr, &addr->s_addr, sizeof(in_addr)); - freeaddrinfo(res); - - return true; - } - - bool - Addr::from_4int(const uint8_t one, const uint8_t two, const uint8_t three, const uint8_t four) - { - Zero(&_addr, sizeof(sockaddr_in6)); - struct in_addr* addr = &_addr4.sin_addr; - auto* ip = (unsigned char*)&(addr->s_addr); - - _addr.sin6_family = AF_INET; // set ipv4 mode - _addr4.sin_family = AF_INET; - _addr4.sin_port = 0; - -#if ((__APPLE__ && __MACH__) || __FreeBSD__) - _addr4.sin_len = sizeof(in_addr); -#endif - // FIXME: watch endian - ip[0] = one; - ip[1] = two; - ip[2] = three; - ip[3] = four; - // set up SIIT - uint8_t* addrptr = _addr.sin6_addr.s6_addr; - addrptr[11] = 0xff; - addrptr[10] = 0xff; - memcpy(12 + addrptr, &addr->s_addr, sizeof(in_addr)); - // copy ipv6 SIIT into _addr4 - memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr)); - return true; - } - - Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three, const uint8_t four) : Addr() - { - this->from_4int(one, two, three, four); - } - - Addr::Addr( - const uint8_t one, - const uint8_t two, - const uint8_t three, - const uint8_t four, - const uint16_t p_port) - : Addr() - { - this->from_4int(one, two, three, four); - this->port(p_port); - } - - Addr::Addr(const AddressInfo& other) : Addr() - { - memcpy(addr6(), other.ip.s6_addr, 16); - _addr.sin6_port = htons(other.port); - if (ipv6_is_siit(other.ip)) - { - _addr4.sin_family = AF_INET; - _addr4.sin_port = htons(other.port); - _addr.sin6_family = AF_INET; - memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr)); - } - else - _addr.sin6_family = AF_INET6; - } - - Addr::Addr(const sockaddr_in& other) : Addr() - { - Zero(&_addr, sizeof(sockaddr_in6)); - _addr.sin6_family = AF_INET; - uint8_t* addrptr = _addr.sin6_addr.s6_addr; - uint16_t* port = &_addr.sin6_port; - // SIIT - memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr, sizeof(in_addr)); - addrptr[11] = 0xff; - addrptr[10] = 0xff; - *port = ((sockaddr_in*)(&other))->sin_port; - _addr4.sin_family = AF_INET; - _addr4.sin_port = *port; - memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr)); - } - - Addr::Addr(const sockaddr_in6& other) : Addr() - { - memcpy(addr6(), other.sin6_addr.s6_addr, 16); - _addr.sin6_port = htons(other.sin6_port); - auto ptr = &_addr.sin6_addr.s6_addr[0]; - // TODO: detect SIIT better - if (ptr[11] == 0xff && ptr[10] == 0xff && ptr[9] == 0 && ptr[8] == 0 && ptr[7] == 0 - && ptr[6] == 0 && ptr[5] == 0 && ptr[4] == 0 && ptr[3] == 0 && ptr[2] == 0 && ptr[1] == 0 - && ptr[0] == 0) - { - _addr4.sin_family = AF_INET; - _addr4.sin_port = htons(other.sin6_port); - _addr.sin6_family = AF_INET; - memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr)); - } - else - _addr.sin6_family = AF_INET6; - } - - Addr::Addr(const sockaddr& other) : Addr() - { - Zero(&_addr, sizeof(sockaddr_in6)); - _addr.sin6_family = other.sa_family; - uint8_t* addrptr = _addr.sin6_addr.s6_addr; - uint16_t* port = &_addr.sin6_port; - switch (other.sa_family) - { - case AF_INET: - // SIIT - memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr, sizeof(in_addr)); - addrptr[11] = 0xff; - addrptr[10] = 0xff; - *port = ((sockaddr_in*)(&other))->sin_port; - _addr4.sin_family = AF_INET; - _addr4.sin_port = *port; - memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr)); - break; - case AF_INET6: - memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr, 16); - *port = ((sockaddr_in6*)(&other))->sin6_port; - break; - // TODO : sockaddr_ll - default: - throw std::invalid_argument("bad address family"); - } - } - - std::string - Addr::ToString() const - { - std::stringstream ss; - ss << (*this); - return std::string(ss.str().c_str()); - } - - std::ostream& - operator<<(std::ostream& out, const Addr& a) - { - char tmp[128] = {0}; - const void* ptr = nullptr; - if (a.af() == AF_INET6) - { - out << "["; - ptr = a.addr6(); - } - else - { - ptr = a.addr4(); - } - if (inet_ntop(a.af(), (void*)ptr, tmp, sizeof(tmp))) - { - out << tmp; - if (a.af() == AF_INET6) - out << "]"; - } - return out << ":" << a.port(); - } - - void - Addr::CopyInto(sockaddr* other) const - { - void *dst, *src; - uint16_t* ptr; - size_t slen; - switch (af()) - { - case AF_INET: - { - auto* ipv4_dst = (sockaddr_in*)other; - dst = (void*)&ipv4_dst->sin_addr.s_addr; - src = (void*)&_addr4.sin_addr.s_addr; - ptr = &((sockaddr_in*)other)->sin_port; - slen = sizeof(in_addr); - break; - } - case AF_INET6: - { - dst = (void*)((sockaddr_in6*)other)->sin6_addr.s6_addr; - src = (void*)_addr.sin6_addr.s6_addr; - ptr = &((sockaddr_in6*)other)->sin6_port; - slen = sizeof(in6_addr); - break; - } - default: - { - return; - } - } - memcpy(dst, src, slen); - *ptr = htons(port()); - other->sa_family = af(); - } - - int - Addr::af() const - { - return _addr.sin6_family; - } - - uint16_t - Addr::port() const - { - return ntohs(_addr.sin6_port); - } - - Addr::operator const sockaddr*() const - { - if (af() == AF_INET) - return (const sockaddr*)&_addr4; - - return (const sockaddr*)&_addr; - } - - Addr::operator sockaddr*() const - { - if (af() == AF_INET) - return (sockaddr*)&_addr4; - - return (sockaddr*)&_addr; - } - - bool - Addr::operator<(const Addr& other) const - { - if (af() == AF_INET && other.af() == AF_INET) - return port() < other.port() || addr4()->s_addr < other.addr4()->s_addr; - - return port() < other.port() || *addr6() < *other.addr6() || af() < other.af(); - } - - bool - Addr::operator==(const Addr& other) const - { - if (af() != other.af() || port() != other.port()) - return false; - - if (af() == AF_INET) - return addr4()->s_addr == other.addr4()->s_addr; - - return memcmp(addr6(), other.addr6(), 16) == 0; - } - - Addr& - Addr::operator=(const sockaddr& other) - { - Zero(&_addr, sizeof(sockaddr_in6)); - _addr.sin6_family = other.sa_family; - uint8_t* addrptr = _addr.sin6_addr.s6_addr; - uint16_t* port = &_addr.sin6_port; - switch (other.sa_family) - { - case AF_INET: - // SIIT - memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr, sizeof(in_addr)); - addrptr[11] = 0xff; - addrptr[10] = 0xff; - *port = ((sockaddr_in*)(&other))->sin_port; - _addr4.sin_family = AF_INET; - _addr4.sin_port = *port; - memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr)); - break; - case AF_INET6: - memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr, 16); - *port = ((sockaddr_in6*)(&other))->sin6_port; - break; - // TODO : sockaddr_ll - default: - break; - } - return *this; - } - - bool - Addr::sameAddr(const Addr& other) const - { - return memcmp(addr6(), other.addr6(), 16) == 0; - } - - bool - Addr::operator!=(const Addr& other) const - { - return !(*this == other); - } - - bool - Addr::isTenPrivate(uint32_t byte) - { - uint8_t byte1 = byte >> 24 & 0xff; - return byte1 == 10; - } - - bool - Addr::isOneSevenPrivate(uint32_t byte) - { - uint8_t byte1 = byte >> 24 & 0xff; - uint8_t byte2 = (0x00ff0000 & byte) >> 16; - return byte1 == 172 && (byte2 >= 16 || byte2 <= 31); - } - - bool - Addr::isOneNinePrivate(uint32_t byte) - { - uint8_t byte1 = byte >> 24 & 0xff; - uint8_t byte2 = (0x00ff0000 & byte) >> 16; - return byte1 == 192 && byte2 == 168; - } - - /// return true if our ipv4 address is a bogon - /// TODO: ipv6 - bool - Addr::IsBogon() const - { - return IsIPv4Bogon(xtohl()); - } - - socklen_t - Addr::SockLen() const - { - if (af() == AF_INET) - return sizeof(sockaddr_in); - - return sizeof(sockaddr_in6); - } - - bool - Addr::isPrivate() const - { - return IsBogon(); - } - - bool - Addr::isLoopback() const - { - return (ntohl(addr4()->s_addr)) >> 24 == 127; - } - - struct Hash - { - std::size_t - operator()(Addr const& a) const noexcept - { - if (a.af() == AF_INET) - { - return a.port() ^ a.addr4()->s_addr; - } - static const uint8_t empty[16] = {0}; - return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port(); - } - }; // end struct Hash -} // namespace llarp diff --git a/llarp/net/net_addr.hpp b/llarp/net/net_addr.hpp deleted file mode 100644 index c771e44c5..000000000 --- a/llarp/net/net_addr.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef LLARP_NET_ADDR_HPP -#define LLARP_NET_ADDR_HPP - -#include -#include -#include -#include - -#include -#include - -namespace llarp -{ - // real work - struct Addr - { - // network order - sockaddr_in6 _addr; - sockaddr_in _addr4; - ~Addr(); - - Addr(); - - Addr(std::string_view str); - - Addr(std::string_view str, const uint16_t p_port); - - Addr(std::string_view addr_str, std::string_view port_str); - - void - port(uint16_t port); - - in6_addr* - addr6(); - - in_addr* - addr4(); - - const in6_addr* - addr6() const; - - const in_addr* - addr4() const; - - bool - FromString(std::string_view str); - - bool - from_4int(const uint8_t one, const uint8_t two, const uint8_t three, const uint8_t four); - - Addr(const uint8_t one, const uint8_t two, const uint8_t three, const uint8_t four); - - Addr( - const uint8_t one, - const uint8_t two, - const uint8_t three, - const uint8_t four, - const uint16_t p_port); - - Addr(const AddressInfo& other); - Addr(const sockaddr_in& other); - Addr(const sockaddr_in6& other); - Addr(const sockaddr& other); - - std::string - ToString() const; - - friend std::ostream& - operator<<(std::ostream& out, const Addr& a); - - operator const sockaddr*() const; - - operator sockaddr*() const; - - void - CopyInto(sockaddr* other) const; - - int - af() const; - - uint16_t - port() const; - - bool - operator<(const Addr& other) const; - - bool - operator==(const Addr& other) const; - - Addr& - operator=(const sockaddr& other); - - inline uint32_t - tohl() const - { - return ntohl(addr4()->s_addr); - } - - inline huint32_t - xtohl() const - { - return huint32_t{ntohl(addr4()->s_addr)}; - } - - inline uint32_t - ton() const - { - return addr4()->s_addr; - } - - inline nuint32_t - xtonl() const - { - return nuint32_t{addr4()->s_addr}; - } - - bool - sameAddr(const Addr& other) const; - - bool - operator!=(const Addr& other) const; - - inline uint32_t - getHostLong() - { - in_addr_t addr = this->addr4()->s_addr; - uint32_t byte = ntohl(addr); - return byte; - } - - bool - isTenPrivate(uint32_t byte); - - bool - isOneSevenPrivate(uint32_t byte); - - bool - isOneNinePrivate(uint32_t byte); - - /// return true if our ipv4 address is a bogon - /// TODO: ipv6 - bool - IsBogon() const; - - socklen_t - SockLen() const; - - bool - isPrivate() const; - - bool - isLoopback() const; - - struct Hash - { - std::size_t - operator()(Addr const& a) const noexcept - { - if (a.af() == AF_INET) - { - return a.port() ^ a.addr4()->s_addr; - } - static const uint8_t empty[16] = {0}; - return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port(); - } - }; - }; // end struct -} // namespace llarp -#endif diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp new file mode 100644 index 000000000..3ef429a17 --- /dev/null +++ b/llarp/net/sock_addr.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace llarp +{ + /// A simple SockAddr wrapper which provides a sockaddr_in (IPv4). Memory management is handled + /// in constructor and destructor (if needed) and copying is disabled. + /// + /// This is immutable. + struct SockAddr + { + sockaddr_in _addr4; + + 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); + SockAddr(uint32_t addr); + SockAddr(std::string_view addr); + }; +} // namespace llarp