11bbe3d1eSWilliam A. Kennington III #pragma once 2bb0eaccbSWilliam A. Kennington III #include <fmt/core.h> 3bb0eaccbSWilliam A. Kennington III #include <net/ethernet.h> 41bbe3d1eSWilliam A. Kennington III #include <netinet/in.h> 51bbe3d1eSWilliam A. Kennington III 6bb0eaccbSWilliam A. Kennington III #include <algorithm> 7bb0eaccbSWilliam A. Kennington III #include <array> 871de63a2SWilliam A. Kennington III #include <numeric> 9de70ccf6SWilliam A. Kennington III #include <optional> 101bbe3d1eSWilliam A. Kennington III #include <string> 11bb0eaccbSWilliam A. Kennington III #include <string_view> 12bb0eaccbSWilliam A. Kennington III #include <type_traits> 13dd9ef815SWilliam A. Kennington III #include <unordered_map> 14f7dce2e8SWilly Tu #include <unordered_set> 151bbe3d1eSWilliam A. Kennington III #include <variant> 161bbe3d1eSWilliam A. Kennington III 17454a0deeSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept 18454a0deeSWilliam A. Kennington III { 19454a0deeSWilliam A. Kennington III return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6, 20454a0deeSWilliam A. Kennington III rhs.ether_addr_octet); 21454a0deeSWilliam A. Kennington III } 22454a0deeSWilliam A. Kennington III 23454a0deeSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept 24454a0deeSWilliam A. Kennington III { 25454a0deeSWilliam A. Kennington III return lhs.s_addr == rhs.s_addr; 26454a0deeSWilliam A. Kennington III } 27454a0deeSWilliam A. Kennington III 28454a0deeSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept 29454a0deeSWilliam A. Kennington III { 30454a0deeSWilliam A. Kennington III return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32); 31454a0deeSWilliam A. Kennington III } 32454a0deeSWilliam A. Kennington III 331bbe3d1eSWilliam A. Kennington III namespace phosphor 341bbe3d1eSWilliam A. Kennington III { 351bbe3d1eSWilliam A. Kennington III namespace network 361bbe3d1eSWilliam A. Kennington III { 371bbe3d1eSWilliam A. Kennington III 381bbe3d1eSWilliam A. Kennington III // Byte representations for common address types in network byte order 39bb0eaccbSWilliam A. Kennington III using InAddrAny = std::variant<in_addr, in6_addr>; 40b9d7cbacSWilliam A. Kennington III class IfAddr 41b9d7cbacSWilliam A. Kennington III { 42b9d7cbacSWilliam A. Kennington III private: 43b9d7cbacSWilliam A. Kennington III InAddrAny addr; 44b9d7cbacSWilliam A. Kennington III uint8_t pfx; 45b9d7cbacSWilliam A. Kennington III 46b9d7cbacSWilliam A. Kennington III static void invalidPfx(uint8_t pfx); 47b9d7cbacSWilliam A. Kennington III 48b9d7cbacSWilliam A. Kennington III public: 4989d734b9SPatrick Williams constexpr IfAddr() : addr({}), pfx(0) {} 50b9d7cbacSWilliam A. Kennington III 51b9d7cbacSWilliam A. Kennington III constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx) 52b9d7cbacSWilliam A. Kennington III { 53b9d7cbacSWilliam A. Kennington III std::visit( 54b9d7cbacSWilliam A. Kennington III [pfx](auto v) { 55b9d7cbacSWilliam A. Kennington III if (sizeof(v) * 8 < pfx) 56b9d7cbacSWilliam A. Kennington III { 57b9d7cbacSWilliam A. Kennington III invalidPfx(pfx); 58b9d7cbacSWilliam A. Kennington III } 59b9d7cbacSWilliam A. Kennington III }, 60b9d7cbacSWilliam A. Kennington III addr); 61b9d7cbacSWilliam A. Kennington III } 62b9d7cbacSWilliam A. Kennington III 63b9d7cbacSWilliam A. Kennington III constexpr auto getAddr() const 64b9d7cbacSWilliam A. Kennington III { 65b9d7cbacSWilliam A. Kennington III return addr; 66b9d7cbacSWilliam A. Kennington III } 67b9d7cbacSWilliam A. Kennington III 68b9d7cbacSWilliam A. Kennington III constexpr auto getPfx() const 69b9d7cbacSWilliam A. Kennington III { 70b9d7cbacSWilliam A. Kennington III return pfx; 71b9d7cbacSWilliam A. Kennington III } 72b9d7cbacSWilliam A. Kennington III 73b9d7cbacSWilliam A. Kennington III constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept 74b9d7cbacSWilliam A. Kennington III { 75b9d7cbacSWilliam A. Kennington III return addr == rhs.addr && pfx == rhs.pfx; 76b9d7cbacSWilliam A. Kennington III } 77b9d7cbacSWilliam A. Kennington III }; 781bbe3d1eSWilliam A. Kennington III 79454a0deeSWilliam A. Kennington III /** @class InterfaceInfo 80454a0deeSWilliam A. Kennington III * @brief Information about interfaces from the kernel 81454a0deeSWilliam A. Kennington III */ 82454a0deeSWilliam A. Kennington III struct InterfaceInfo 83454a0deeSWilliam A. Kennington III { 84*9c441fd4SWilliam A. Kennington III unsigned short type; 85454a0deeSWilliam A. Kennington III unsigned idx; 86454a0deeSWilliam A. Kennington III unsigned flags; 87454a0deeSWilliam A. Kennington III std::optional<std::string> name = std::nullopt; 88454a0deeSWilliam A. Kennington III std::optional<ether_addr> mac = std::nullopt; 89454a0deeSWilliam A. Kennington III std::optional<unsigned> mtu = std::nullopt; 90454a0deeSWilliam A. Kennington III std::optional<unsigned> parent_idx = std::nullopt; 91454a0deeSWilliam A. Kennington III std::optional<std::string> kind = std::nullopt; 92454a0deeSWilliam A. Kennington III std::optional<uint16_t> vlan_id = std::nullopt; 93454a0deeSWilliam A. Kennington III 94454a0deeSWilliam A. Kennington III constexpr bool operator==(const InterfaceInfo& rhs) const noexcept 95454a0deeSWilliam A. Kennington III { 96454a0deeSWilliam A. Kennington III return idx == rhs.idx && flags == rhs.flags && name == rhs.name && 97454a0deeSWilliam A. Kennington III mac == rhs.mac && mtu == rhs.mtu && 98454a0deeSWilliam A. Kennington III parent_idx == rhs.parent_idx && kind == rhs.kind && 99454a0deeSWilliam A. Kennington III vlan_id == rhs.vlan_id; 100454a0deeSWilliam A. Kennington III } 101454a0deeSWilliam A. Kennington III }; 102454a0deeSWilliam A. Kennington III 1036a92363eSWilliam A. Kennington III /** @class AddressInfo 1046a92363eSWilliam A. Kennington III * @brief Information about a addresses from the kernel 1056a92363eSWilliam A. Kennington III */ 1066a92363eSWilliam A. Kennington III struct AddressInfo 1076a92363eSWilliam A. Kennington III { 1086a92363eSWilliam A. Kennington III unsigned ifidx; 1096a92363eSWilliam A. Kennington III IfAddr ifaddr; 1106a92363eSWilliam A. Kennington III uint8_t scope; 1116a92363eSWilliam A. Kennington III uint32_t flags; 112454a0deeSWilliam A. Kennington III 113454a0deeSWilliam A. Kennington III constexpr bool operator==(const AddressInfo& rhs) const noexcept 114454a0deeSWilliam A. Kennington III { 115454a0deeSWilliam A. Kennington III return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr && 116454a0deeSWilliam A. Kennington III scope == rhs.scope && flags == rhs.flags; 117454a0deeSWilliam A. Kennington III } 1186a92363eSWilliam A. Kennington III }; 1196a92363eSWilliam A. Kennington III 120a8426902SWilliam A. Kennington III /** @class NeighborInfo 121a8426902SWilliam A. Kennington III * @brief Information about a neighbor from the kernel 122a8426902SWilliam A. Kennington III */ 123a8426902SWilliam A. Kennington III struct NeighborInfo 124a8426902SWilliam A. Kennington III { 125a8426902SWilliam A. Kennington III unsigned ifidx; 126454a0deeSWilliam A. Kennington III uint16_t state; 127d3615144SWilliam A. Kennington III std::optional<InAddrAny> addr; 128a8426902SWilliam A. Kennington III std::optional<ether_addr> mac; 129454a0deeSWilliam A. Kennington III 130454a0deeSWilliam A. Kennington III constexpr bool operator==(const NeighborInfo& rhs) const noexcept 131454a0deeSWilliam A. Kennington III { 132454a0deeSWilliam A. Kennington III return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr && 133454a0deeSWilliam A. Kennington III mac == rhs.mac; 134454a0deeSWilliam A. Kennington III } 135a8426902SWilliam A. Kennington III }; 136a8426902SWilliam A. Kennington III 137dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view> 138dd9ef815SWilliam A. Kennington III { 139dd9ef815SWilliam A. Kennington III using is_transparent = void; 140dd9ef815SWilliam A. Kennington III }; 141dd9ef815SWilliam A. Kennington III template <typename V> 142dd9ef815SWilliam A. Kennington III using string_umap = 143dd9ef815SWilliam A. Kennington III std::unordered_map<std::string, V, string_hash, std::equal_to<>>; 14496444795SWilliam A. Kennington III using string_uset = 14596444795SWilliam A. Kennington III std::unordered_set<std::string, string_hash, std::equal_to<>>; 146dd9ef815SWilliam A. Kennington III 1473e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept 148991a8e81SWilliam A. Kennington III { 149991a8e81SWilliam A. Kennington III return 0; 150991a8e81SWilliam A. Kennington III } 151991a8e81SWilliam A. Kennington III 152991a8e81SWilliam A. Kennington III template <typename T, typename... Args> 153becda1aaSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept 154991a8e81SWilliam A. Kennington III { 155991a8e81SWilliam A. Kennington III const std::size_t seed = hash_multi(args...); 156991a8e81SWilliam A. Kennington III return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 157991a8e81SWilliam A. Kennington III } 158991a8e81SWilliam A. Kennington III 159bb0eaccbSWilliam A. Kennington III namespace detail 160bb0eaccbSWilliam A. Kennington III { 161bb0eaccbSWilliam A. Kennington III 16271de63a2SWilliam A. Kennington III template <typename T, uint8_t size = sizeof(T)> 16371de63a2SWilliam A. Kennington III struct BswapAlign 16471de63a2SWilliam A. Kennington III { 16571de63a2SWilliam A. Kennington III using type = T; 16671de63a2SWilliam A. Kennington III }; 16771de63a2SWilliam A. Kennington III 16871de63a2SWilliam A. Kennington III template <typename T> 16971de63a2SWilliam A. Kennington III struct BswapAlign<T, 2> 17071de63a2SWilliam A. Kennington III { 17171de63a2SWilliam A. Kennington III using type alignas(uint16_t) = T; 17271de63a2SWilliam A. Kennington III }; 17371de63a2SWilliam A. Kennington III 17471de63a2SWilliam A. Kennington III template <typename T> 17571de63a2SWilliam A. Kennington III struct BswapAlign<T, 4> 17671de63a2SWilliam A. Kennington III { 17771de63a2SWilliam A. Kennington III using type alignas(uint32_t) = T; 17871de63a2SWilliam A. Kennington III }; 17971de63a2SWilliam A. Kennington III 18071de63a2SWilliam A. Kennington III template <typename T> 18171de63a2SWilliam A. Kennington III struct BswapAlign<T, 8> 18271de63a2SWilliam A. Kennington III { 18371de63a2SWilliam A. Kennington III using type alignas(uint64_t) = T; 18471de63a2SWilliam A. Kennington III }; 18571de63a2SWilliam A. Kennington III 18671de63a2SWilliam A. Kennington III template <typename T> 18771de63a2SWilliam A. Kennington III constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept 18871de63a2SWilliam A. Kennington III { 18971de63a2SWilliam A. Kennington III static_assert(std::is_trivially_copyable_v<T>); 19071de63a2SWilliam A. Kennington III if constexpr (sizeof(T) == 2) 19171de63a2SWilliam A. Kennington III { 19271de63a2SWilliam A. Kennington III reinterpret_cast<uint16_t&>(n) = 19371de63a2SWilliam A. Kennington III __builtin_bswap16(reinterpret_cast<uint16_t&>(n)); 19471de63a2SWilliam A. Kennington III } 19571de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 4) 19671de63a2SWilliam A. Kennington III { 19771de63a2SWilliam A. Kennington III reinterpret_cast<uint32_t&>(n) = 19871de63a2SWilliam A. Kennington III __builtin_bswap32(reinterpret_cast<uint32_t&>(n)); 19971de63a2SWilliam A. Kennington III } 20071de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 8) 20171de63a2SWilliam A. Kennington III { 20271de63a2SWilliam A. Kennington III reinterpret_cast<uint64_t&>(n) = 20371de63a2SWilliam A. Kennington III __builtin_bswap64(reinterpret_cast<uint64_t&>(n)); 20471de63a2SWilliam A. Kennington III } 20571de63a2SWilliam A. Kennington III else 20671de63a2SWilliam A. Kennington III { 20771de63a2SWilliam A. Kennington III auto b = reinterpret_cast<std::byte*>(&n); 20871de63a2SWilliam A. Kennington III std::reverse(b, b + sizeof(n)); 20971de63a2SWilliam A. Kennington III } 21071de63a2SWilliam A. Kennington III return n; 21171de63a2SWilliam A. Kennington III } 21271de63a2SWilliam A. Kennington III 21371de63a2SWilliam A. Kennington III } // namespace detail 21471de63a2SWilliam A. Kennington III 21571de63a2SWilliam A. Kennington III template <typename T> 21671de63a2SWilliam A. Kennington III constexpr T bswap(T n) noexcept 21771de63a2SWilliam A. Kennington III { 21871de63a2SWilliam A. Kennington III return detail::bswapInt<T>(n); 21971de63a2SWilliam A. Kennington III } 22071de63a2SWilliam A. Kennington III 22171de63a2SWilliam A. Kennington III template <typename T> 22271de63a2SWilliam A. Kennington III constexpr T hton(T n) noexcept 22371de63a2SWilliam A. Kennington III { 22471de63a2SWilliam A. Kennington III if constexpr (std::endian::native == std::endian::big) 22571de63a2SWilliam A. Kennington III { 22671de63a2SWilliam A. Kennington III return n; 22771de63a2SWilliam A. Kennington III } 22871de63a2SWilliam A. Kennington III else if constexpr (std::endian::native == std::endian::little) 22971de63a2SWilliam A. Kennington III { 23071de63a2SWilliam A. Kennington III return bswap(n); 23171de63a2SWilliam A. Kennington III } 23271de63a2SWilliam A. Kennington III else 23371de63a2SWilliam A. Kennington III { 23471de63a2SWilliam A. Kennington III static_assert(std::is_same_v<T, void>); 23571de63a2SWilliam A. Kennington III } 23671de63a2SWilliam A. Kennington III } 23771de63a2SWilliam A. Kennington III 23871de63a2SWilliam A. Kennington III template <typename T> 23971de63a2SWilliam A. Kennington III constexpr T ntoh(T n) noexcept 24071de63a2SWilliam A. Kennington III { 24171de63a2SWilliam A. Kennington III return hton(n); 24271de63a2SWilliam A. Kennington III } 24371de63a2SWilliam A. Kennington III 24471de63a2SWilliam A. Kennington III namespace detail 24571de63a2SWilliam A. Kennington III { 246238ef992SWilliam A. Kennington III inline constexpr auto charLookup = []() { 247238ef992SWilliam A. Kennington III std::array<int8_t, 256> ret; 248238ef992SWilliam A. Kennington III std::fill(ret.begin(), ret.end(), -1); 249238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 10; ++i) 250238ef992SWilliam A. Kennington III { 251238ef992SWilliam A. Kennington III ret[i + '0'] = i; 252238ef992SWilliam A. Kennington III } 253238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 26; ++i) 254238ef992SWilliam A. Kennington III { 255238ef992SWilliam A. Kennington III ret[i + 'A'] = i + 10; 256238ef992SWilliam A. Kennington III ret[i + 'a'] = i + 10; 257238ef992SWilliam A. Kennington III } 258238ef992SWilliam A. Kennington III return ret; 259238ef992SWilliam A. Kennington III }(); 260dd7c7b34SWilliam A. Kennington III inline constexpr auto intLookup = []() { 261dd7c7b34SWilliam A. Kennington III std::array<char, 36> ret; 262dd7c7b34SWilliam A. Kennington III for (int8_t i = 0; i < 10; ++i) 263dd7c7b34SWilliam A. Kennington III { 264dd7c7b34SWilliam A. Kennington III ret[i] = i + '0'; 265238ef992SWilliam A. Kennington III } 266dd7c7b34SWilliam A. Kennington III for (int8_t i = 0; i < 26; ++i) 267dd7c7b34SWilliam A. Kennington III { 268dd7c7b34SWilliam A. Kennington III ret[i + 10] = i + 'a'; 269dd7c7b34SWilliam A. Kennington III } 270dd7c7b34SWilliam A. Kennington III return ret; 271dd7c7b34SWilliam A. Kennington III }(); 272dd7c7b34SWilliam A. Kennington III } // namespace detail 273238ef992SWilliam A. Kennington III 274238ef992SWilliam A. Kennington III template <typename T, uint8_t base> 275238ef992SWilliam A. Kennington III struct DecodeInt 276238ef992SWilliam A. Kennington III { 277238ef992SWilliam A. Kennington III static_assert(base > 1 && base <= 36); 278238ef992SWilliam A. Kennington III static_assert(std::is_unsigned_v<T>); 279238ef992SWilliam A. Kennington III 280238ef992SWilliam A. Kennington III constexpr T operator()(std::string_view str) const 281238ef992SWilliam A. Kennington III { 282238ef992SWilliam A. Kennington III if (str.empty()) 283238ef992SWilliam A. Kennington III { 284238ef992SWilliam A. Kennington III throw std::invalid_argument("Empty Str"); 285238ef992SWilliam A. Kennington III } 286238ef992SWilliam A. Kennington III constexpr auto max = std::numeric_limits<T>::max(); 28789d734b9SPatrick Williams auto ret = std::accumulate(str.begin(), str.end(), T{}, 28889d734b9SPatrick Williams [&](T r, char c) { 289238ef992SWilliam A. Kennington III auto v = detail::charLookup[c]; 290238ef992SWilliam A. Kennington III if (v < 0 || v >= base) 291238ef992SWilliam A. Kennington III { 292238ef992SWilliam A. Kennington III throw std::invalid_argument("Invalid numeral"); 293238ef992SWilliam A. Kennington III } 294238ef992SWilliam A. Kennington III if constexpr (std::popcount(base) == 1) 295238ef992SWilliam A. Kennington III { 296238ef992SWilliam A. Kennington III constexpr auto shift = std::countr_zero(base); 297238ef992SWilliam A. Kennington III constexpr auto maxshift = max >> shift; 298238ef992SWilliam A. Kennington III if (r > maxshift) 299238ef992SWilliam A. Kennington III { 300238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 301238ef992SWilliam A. Kennington III } 302238ef992SWilliam A. Kennington III return (r << shift) | v; 303238ef992SWilliam A. Kennington III } 304238ef992SWilliam A. Kennington III else 305238ef992SWilliam A. Kennington III { 306238ef992SWilliam A. Kennington III constexpr auto maxbase = max / base; 307238ef992SWilliam A. Kennington III if (r > maxbase) 308238ef992SWilliam A. Kennington III { 309238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 310238ef992SWilliam A. Kennington III } 311238ef992SWilliam A. Kennington III r *= base; 312238ef992SWilliam A. Kennington III if (max - v < r) 313238ef992SWilliam A. Kennington III { 314238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 315238ef992SWilliam A. Kennington III } 316238ef992SWilliam A. Kennington III return r + v; 317238ef992SWilliam A. Kennington III } 318238ef992SWilliam A. Kennington III }); 319238ef992SWilliam A. Kennington III return ret; 320238ef992SWilliam A. Kennington III } 321238ef992SWilliam A. Kennington III }; 322238ef992SWilliam A. Kennington III 323dd7c7b34SWilliam A. Kennington III template <typename T, uint8_t base> 324dd7c7b34SWilliam A. Kennington III struct EncodeInt 325dd7c7b34SWilliam A. Kennington III { 326dd7c7b34SWilliam A. Kennington III static_assert(base > 1 && base <= 36); 327dd7c7b34SWilliam A. Kennington III static_assert(std::is_unsigned_v<T>); 328dd7c7b34SWilliam A. Kennington III 329dd7c7b34SWilliam A. Kennington III static constexpr uint8_t buf_size = []() { 330dd7c7b34SWilliam A. Kennington III T v = std::numeric_limits<T>::max(); 331dd7c7b34SWilliam A. Kennington III uint8_t i = 0; 332dd7c7b34SWilliam A. Kennington III for (; v != 0; ++i) 333dd7c7b34SWilliam A. Kennington III { 334dd7c7b34SWilliam A. Kennington III v /= base; 335dd7c7b34SWilliam A. Kennington III } 336dd7c7b34SWilliam A. Kennington III return i; 337dd7c7b34SWilliam A. Kennington III }(); 338dd7c7b34SWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 339dd7c7b34SWilliam A. Kennington III 340dd7c7b34SWilliam A. Kennington III constexpr uint8_t reverseFill(char* buf, T v) const noexcept 341dd7c7b34SWilliam A. Kennington III { 342dd7c7b34SWilliam A. Kennington III uint8_t i = 0; 343dd7c7b34SWilliam A. Kennington III do 344dd7c7b34SWilliam A. Kennington III { 345dd7c7b34SWilliam A. Kennington III if constexpr (std::popcount(base) == 1) 346dd7c7b34SWilliam A. Kennington III { 347dd7c7b34SWilliam A. Kennington III buf[i++] = detail::intLookup[v & 0xf]; 348dd7c7b34SWilliam A. Kennington III v >>= 4; 349dd7c7b34SWilliam A. Kennington III } 350dd7c7b34SWilliam A. Kennington III else 351dd7c7b34SWilliam A. Kennington III { 352dd7c7b34SWilliam A. Kennington III buf[i++] = detail::intLookup[v % base]; 353dd7c7b34SWilliam A. Kennington III v /= base; 354dd7c7b34SWilliam A. Kennington III } 355dd7c7b34SWilliam A. Kennington III } while (v > 0); 356dd7c7b34SWilliam A. Kennington III return i; 357dd7c7b34SWilliam A. Kennington III } 358dd7c7b34SWilliam A. Kennington III 359dd7c7b34SWilliam A. Kennington III constexpr char* operator()(char* buf, T v) const noexcept 360dd7c7b34SWilliam A. Kennington III { 361dd7c7b34SWilliam A. Kennington III uint8_t i = reverseFill(buf, v); 362dd7c7b34SWilliam A. Kennington III std::reverse(buf, buf + i); 363dd7c7b34SWilliam A. Kennington III return buf + i; 364dd7c7b34SWilliam A. Kennington III } 365dd7c7b34SWilliam A. Kennington III 366dd7c7b34SWilliam A. Kennington III constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept 367dd7c7b34SWilliam A. Kennington III { 368dd7c7b34SWilliam A. Kennington III uint8_t i = reverseFill(buf, v); 369dd7c7b34SWilliam A. Kennington III auto end = buf + std::max(i, min_width); 370dd7c7b34SWilliam A. Kennington III std::fill(buf + i, end, '0'); 371dd7c7b34SWilliam A. Kennington III std::reverse(buf, end); 372dd7c7b34SWilliam A. Kennington III return end; 373dd7c7b34SWilliam A. Kennington III } 374dd7c7b34SWilliam A. Kennington III }; 375dd7c7b34SWilliam A. Kennington III 376b01d08fdSWilliam A. Kennington III template <typename T> 377b01d08fdSWilliam A. Kennington III struct ToAddr 37889d734b9SPatrick Williams {}; 379b01d08fdSWilliam A. Kennington III 380b01d08fdSWilliam A. Kennington III template <> 381b01d08fdSWilliam A. Kennington III struct ToAddr<ether_addr> 382b01d08fdSWilliam A. Kennington III { 383b01d08fdSWilliam A. Kennington III constexpr ether_addr operator()(std::string_view str) const 384b01d08fdSWilliam A. Kennington III { 385b01d08fdSWilliam A. Kennington III constexpr DecodeInt<uint8_t, 16> di; 386b01d08fdSWilliam A. Kennington III ether_addr ret; 387b01d08fdSWilliam A. Kennington III if (str.size() == 12 && str.find(":") == str.npos) 388b01d08fdSWilliam A. Kennington III { 389b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 6; ++i) 390b01d08fdSWilliam A. Kennington III { 391b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(i * 2, 2)); 392b01d08fdSWilliam A. Kennington III } 393b01d08fdSWilliam A. Kennington III } 394b01d08fdSWilliam A. Kennington III else 395b01d08fdSWilliam A. Kennington III { 396b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 5; ++i) 397b01d08fdSWilliam A. Kennington III { 398b01d08fdSWilliam A. Kennington III auto loc = str.find(":"); 399b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(0, loc)); 400b01d08fdSWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 401b01d08fdSWilliam A. Kennington III if (str.empty()) 402b01d08fdSWilliam A. Kennington III { 403b01d08fdSWilliam A. Kennington III throw std::invalid_argument("Missing mac data"); 404b01d08fdSWilliam A. Kennington III } 405b01d08fdSWilliam A. Kennington III } 406b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[5] = di(str); 407b01d08fdSWilliam A. Kennington III } 408b01d08fdSWilliam A. Kennington III return ret; 409b01d08fdSWilliam A. Kennington III } 410b01d08fdSWilliam A. Kennington III }; 411b01d08fdSWilliam A. Kennington III 412df1178e0SWilliam A. Kennington III template <> 413df1178e0SWilliam A. Kennington III struct ToAddr<in_addr> 414df1178e0SWilliam A. Kennington III { 415df1178e0SWilliam A. Kennington III constexpr in_addr operator()(std::string_view str) const 416df1178e0SWilliam A. Kennington III { 417df1178e0SWilliam A. Kennington III constexpr DecodeInt<uint8_t, 10> di; 418df1178e0SWilliam A. Kennington III uint32_t addr = {}; 419df1178e0SWilliam A. Kennington III for (size_t i = 0; i < 3; ++i) 420df1178e0SWilliam A. Kennington III { 421df1178e0SWilliam A. Kennington III auto loc = str.find("."); 422df1178e0SWilliam A. Kennington III addr |= di(str.substr(0, loc)); 423df1178e0SWilliam A. Kennington III addr <<= 8; 424df1178e0SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 425df1178e0SWilliam A. Kennington III if (str.empty()) 426df1178e0SWilliam A. Kennington III { 427df1178e0SWilliam A. Kennington III throw std::invalid_argument("Missing addr data"); 428df1178e0SWilliam A. Kennington III } 429df1178e0SWilliam A. Kennington III } 430df1178e0SWilliam A. Kennington III addr |= di(str); 431df1178e0SWilliam A. Kennington III return {hton(addr)}; 432df1178e0SWilliam A. Kennington III } 433df1178e0SWilliam A. Kennington III }; 434df1178e0SWilliam A. Kennington III 435ec496a86SWilliam A. Kennington III template <> 436ec496a86SWilliam A. Kennington III struct ToAddr<in6_addr> 437ec496a86SWilliam A. Kennington III { 438ec496a86SWilliam A. Kennington III constexpr in6_addr operator()(std::string_view str) const 439ec496a86SWilliam A. Kennington III { 440ec496a86SWilliam A. Kennington III constexpr DecodeInt<uint16_t, 16> di; 441ec496a86SWilliam A. Kennington III in6_addr ret = {}; 442ec496a86SWilliam A. Kennington III size_t i = 0; 443ec496a86SWilliam A. Kennington III while (i < 8) 444ec496a86SWilliam A. Kennington III { 445ec496a86SWilliam A. Kennington III auto loc = str.find(':'); 446ec496a86SWilliam A. Kennington III if (i == 6 && loc == str.npos) 447ec496a86SWilliam A. Kennington III { 448ec496a86SWilliam A. Kennington III ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr; 449ec496a86SWilliam A. Kennington III return ret; 450ec496a86SWilliam A. Kennington III } 451ec496a86SWilliam A. Kennington III if (loc != 0 && !str.empty()) 452ec496a86SWilliam A. Kennington III { 453ec496a86SWilliam A. Kennington III ret.s6_addr16[i++] = hton(di(str.substr(0, loc))); 454ec496a86SWilliam A. Kennington III } 455ec496a86SWilliam A. Kennington III if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':') 456ec496a86SWilliam A. Kennington III { 457ec496a86SWilliam A. Kennington III str.remove_prefix(loc + 2); 458ec496a86SWilliam A. Kennington III break; 459ec496a86SWilliam A. Kennington III } 460ec496a86SWilliam A. Kennington III else if (str.empty()) 461ec496a86SWilliam A. Kennington III { 462ec496a86SWilliam A. Kennington III throw std::invalid_argument("IPv6 Data"); 463ec496a86SWilliam A. Kennington III } 464ec496a86SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 465ec496a86SWilliam A. Kennington III } 466ec496a86SWilliam A. Kennington III if (str.starts_with(':')) 467ec496a86SWilliam A. Kennington III { 468ec496a86SWilliam A. Kennington III throw std::invalid_argument("Extra separator"); 469ec496a86SWilliam A. Kennington III } 470ec496a86SWilliam A. Kennington III size_t j = 7; 471ec496a86SWilliam A. Kennington III if (!str.empty() && i < 6 && str.find('.') != str.npos) 472ec496a86SWilliam A. Kennington III { 473ec496a86SWilliam A. Kennington III auto loc = str.rfind(':'); 474ec496a86SWilliam A. Kennington III ret.s6_addr32[3] = 475ec496a86SWilliam A. Kennington III ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1)) 476ec496a86SWilliam A. Kennington III .s_addr; 477ec496a86SWilliam A. Kennington III str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc); 478ec496a86SWilliam A. Kennington III j -= 2; 479ec496a86SWilliam A. Kennington III } 480ec496a86SWilliam A. Kennington III while (!str.empty() && j > i) 481ec496a86SWilliam A. Kennington III { 482ec496a86SWilliam A. Kennington III auto loc = str.rfind(':'); 483ec496a86SWilliam A. Kennington III ret.s6_addr16[j--] = 484ec496a86SWilliam A. Kennington III hton(di(str.substr(loc == str.npos ? 0 : loc + 1))); 485ec496a86SWilliam A. Kennington III str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc); 486ec496a86SWilliam A. Kennington III } 487ec496a86SWilliam A. Kennington III if (!str.empty()) 488ec496a86SWilliam A. Kennington III { 489ec496a86SWilliam A. Kennington III throw std::invalid_argument("Too much data"); 490ec496a86SWilliam A. Kennington III } 491ec496a86SWilliam A. Kennington III return ret; 492ec496a86SWilliam A. Kennington III } 493ec496a86SWilliam A. Kennington III }; 494ec496a86SWilliam A. Kennington III 495ead7198cSWilliam A. Kennington III template <> 496ead7198cSWilliam A. Kennington III struct ToAddr<InAddrAny> 497ead7198cSWilliam A. Kennington III { 498ead7198cSWilliam A. Kennington III constexpr InAddrAny operator()(std::string_view str) const 499ead7198cSWilliam A. Kennington III { 500ead7198cSWilliam A. Kennington III if (str.find(':') == str.npos) 501ead7198cSWilliam A. Kennington III { 502ead7198cSWilliam A. Kennington III return ToAddr<in_addr>{}(str); 503ead7198cSWilliam A. Kennington III } 504ead7198cSWilliam A. Kennington III return ToAddr<in6_addr>{}(str); 505ead7198cSWilliam A. Kennington III } 506ead7198cSWilliam A. Kennington III }; 507ead7198cSWilliam A. Kennington III 508ead7198cSWilliam A. Kennington III template <> 509ead7198cSWilliam A. Kennington III struct ToAddr<IfAddr> 510ead7198cSWilliam A. Kennington III { 511ead7198cSWilliam A. Kennington III constexpr IfAddr operator()(std::string_view str) const 512ead7198cSWilliam A. Kennington III { 513ead7198cSWilliam A. Kennington III auto pos = str.rfind('/'); 514ead7198cSWilliam A. Kennington III if (pos == str.npos) 515ead7198cSWilliam A. Kennington III { 516ead7198cSWilliam A. Kennington III throw std::invalid_argument("Invalid IfAddr"); 517ead7198cSWilliam A. Kennington III } 518ead7198cSWilliam A. Kennington III return {ToAddr<InAddrAny>{}(str.substr(0, pos)), 519ead7198cSWilliam A. Kennington III DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))}; 520ead7198cSWilliam A. Kennington III } 521ead7198cSWilliam A. Kennington III }; 522ead7198cSWilliam A. Kennington III 52355bdc36cSWilliam A. Kennington III template <typename T> 52455bdc36cSWilliam A. Kennington III struct ToStr 52589d734b9SPatrick Williams {}; 52655bdc36cSWilliam A. Kennington III 52755bdc36cSWilliam A. Kennington III template <> 52855bdc36cSWilliam A. Kennington III struct ToStr<char> 52955bdc36cSWilliam A. Kennington III { 53055bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 1; 53155bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 53255bdc36cSWilliam A. Kennington III 53355bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, char v) const noexcept 53455bdc36cSWilliam A. Kennington III { 53555bdc36cSWilliam A. Kennington III buf[0] = v; 53655bdc36cSWilliam A. Kennington III return buf + 1; 53755bdc36cSWilliam A. Kennington III } 53855bdc36cSWilliam A. Kennington III }; 53955bdc36cSWilliam A. Kennington III 54055bdc36cSWilliam A. Kennington III template <> 54155bdc36cSWilliam A. Kennington III struct ToStr<ether_addr> 54255bdc36cSWilliam A. Kennington III { 54355bdc36cSWilliam A. Kennington III // 6 octets * 2 hex chars + 5 separators 54455bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 17; 54555bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 54655bdc36cSWilliam A. Kennington III 54755bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, ether_addr v) const noexcept 54855bdc36cSWilliam A. Kennington III { 54955bdc36cSWilliam A. Kennington III for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3) 55055bdc36cSWilliam A. Kennington III { 55155bdc36cSWilliam A. Kennington III *ptr = ':'; 55255bdc36cSWilliam A. Kennington III } 55355bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 6; ++i) 55455bdc36cSWilliam A. Kennington III { 55555bdc36cSWilliam A. Kennington III char* tmp = buf + i * 3; 55655bdc36cSWilliam A. Kennington III uint8_t byte = v.ether_addr_octet[i]; 55755bdc36cSWilliam A. Kennington III EncodeInt<uint8_t, 16>{}(tmp, byte, 2); 55855bdc36cSWilliam A. Kennington III } 55955bdc36cSWilliam A. Kennington III return buf + buf_size; 56055bdc36cSWilliam A. Kennington III } 56155bdc36cSWilliam A. Kennington III }; 56255bdc36cSWilliam A. Kennington III 56355bdc36cSWilliam A. Kennington III template <> 56455bdc36cSWilliam A. Kennington III struct ToStr<in_addr> 56555bdc36cSWilliam A. Kennington III { 56655bdc36cSWilliam A. Kennington III // 4 octets * 3 dec chars + 3 separators 56755bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 15; 56855bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 56955bdc36cSWilliam A. Kennington III 57055bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, in_addr v) const noexcept 57155bdc36cSWilliam A. Kennington III { 57255bdc36cSWilliam A. Kennington III auto n = bswap(ntoh(v.s_addr)); 57355bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 3; ++i) 57455bdc36cSWilliam A. Kennington III { 57555bdc36cSWilliam A. Kennington III buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.'); 57655bdc36cSWilliam A. Kennington III n >>= 8; 57755bdc36cSWilliam A. Kennington III } 57855bdc36cSWilliam A. Kennington III return EncodeInt<uint8_t, 10>{}(buf, n & 0xff); 57955bdc36cSWilliam A. Kennington III } 58055bdc36cSWilliam A. Kennington III }; 58155bdc36cSWilliam A. Kennington III 58255bdc36cSWilliam A. Kennington III template <> 58355bdc36cSWilliam A. Kennington III struct ToStr<in6_addr> 58455bdc36cSWilliam A. Kennington III { 58555bdc36cSWilliam A. Kennington III // 8 hextets * 4 hex chars + 7 separators 58655bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 39; 58755bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 58855bdc36cSWilliam A. Kennington III 58955bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, in6_addr v) const noexcept 59055bdc36cSWilliam A. Kennington III { 59155bdc36cSWilliam A. Kennington III // IPv4 in IPv6 Addr 59255bdc36cSWilliam A. Kennington III if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 && 59355bdc36cSWilliam A. Kennington III v.s6_addr32[2] == hton(uint32_t(0xffff))) 59455bdc36cSWilliam A. Kennington III { 59555bdc36cSWilliam A. Kennington III constexpr auto prefix = std::string_view("::ffff:"); 59655bdc36cSWilliam A. Kennington III return ToStr<in_addr>{}( 59755bdc36cSWilliam A. Kennington III std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]}); 59855bdc36cSWilliam A. Kennington III } 59955bdc36cSWilliam A. Kennington III 60055bdc36cSWilliam A. Kennington III size_t skip_start = 0; 60155bdc36cSWilliam A. Kennington III size_t skip_size = 0; 60255bdc36cSWilliam A. Kennington III { 60355bdc36cSWilliam A. Kennington III size_t new_start = 0; 60455bdc36cSWilliam A. Kennington III size_t new_size = 0; 60555bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 9; ++i) 60655bdc36cSWilliam A. Kennington III { 60755bdc36cSWilliam A. Kennington III if (i < 8 && v.s6_addr16[i] == 0) 60855bdc36cSWilliam A. Kennington III { 60955bdc36cSWilliam A. Kennington III if (new_start + new_size == i) 61055bdc36cSWilliam A. Kennington III { 61155bdc36cSWilliam A. Kennington III new_size++; 61255bdc36cSWilliam A. Kennington III } 61355bdc36cSWilliam A. Kennington III else 61455bdc36cSWilliam A. Kennington III { 61555bdc36cSWilliam A. Kennington III new_start = i; 61655bdc36cSWilliam A. Kennington III new_size = 1; 61755bdc36cSWilliam A. Kennington III } 61855bdc36cSWilliam A. Kennington III } 61955bdc36cSWilliam A. Kennington III else if (new_start + new_size == i && new_size > skip_size) 62055bdc36cSWilliam A. Kennington III { 62155bdc36cSWilliam A. Kennington III skip_start = new_start; 62255bdc36cSWilliam A. Kennington III skip_size = new_size; 62355bdc36cSWilliam A. Kennington III } 62455bdc36cSWilliam A. Kennington III } 62555bdc36cSWilliam A. Kennington III } 62655bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 8; ++i) 62755bdc36cSWilliam A. Kennington III { 62855bdc36cSWilliam A. Kennington III if (i == skip_start && skip_size > 1) 62955bdc36cSWilliam A. Kennington III { 63055bdc36cSWilliam A. Kennington III if (i == 0) 63155bdc36cSWilliam A. Kennington III { 63255bdc36cSWilliam A. Kennington III *(buf++) = ':'; 63355bdc36cSWilliam A. Kennington III } 63455bdc36cSWilliam A. Kennington III *(buf++) = ':'; 63555bdc36cSWilliam A. Kennington III i += skip_size - 1; 63655bdc36cSWilliam A. Kennington III continue; 63755bdc36cSWilliam A. Kennington III } 63855bdc36cSWilliam A. Kennington III buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i])); 63955bdc36cSWilliam A. Kennington III if (i < 7) 64055bdc36cSWilliam A. Kennington III { 64155bdc36cSWilliam A. Kennington III *(buf++) = ':'; 64255bdc36cSWilliam A. Kennington III } 64355bdc36cSWilliam A. Kennington III } 64455bdc36cSWilliam A. Kennington III return buf; 64555bdc36cSWilliam A. Kennington III } 64655bdc36cSWilliam A. Kennington III }; 64755bdc36cSWilliam A. Kennington III 64855bdc36cSWilliam A. Kennington III template <> 64955bdc36cSWilliam A. Kennington III struct ToStr<InAddrAny> 65055bdc36cSWilliam A. Kennington III { 65155bdc36cSWilliam A. Kennington III // IPv6 is the bigger of the addrs 65255bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size; 65355bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 65455bdc36cSWilliam A. Kennington III 65555bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, InAddrAny v) const noexcept 65655bdc36cSWilliam A. Kennington III { 65755bdc36cSWilliam A. Kennington III return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); }, 65855bdc36cSWilliam A. Kennington III v); 65955bdc36cSWilliam A. Kennington III } 66055bdc36cSWilliam A. Kennington III }; 66155bdc36cSWilliam A. Kennington III 66255bdc36cSWilliam A. Kennington III template <> 66355bdc36cSWilliam A. Kennington III struct ToStr<IfAddr> 66455bdc36cSWilliam A. Kennington III { 66555bdc36cSWilliam A. Kennington III // InAddrAny + sep + 3 prefix chars 66655bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4; 66755bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 66855bdc36cSWilliam A. Kennington III 66955bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, IfAddr v) const noexcept 67055bdc36cSWilliam A. Kennington III { 67155bdc36cSWilliam A. Kennington III buf = ToStr<InAddrAny>{}(buf, v.getAddr()); 67255bdc36cSWilliam A. Kennington III buf = ToStr<char>{}(buf, '/'); 67355bdc36cSWilliam A. Kennington III return EncodeInt<uint8_t, 10>{}(buf, v.getPfx()); 67455bdc36cSWilliam A. Kennington III } 67555bdc36cSWilliam A. Kennington III }; 67655bdc36cSWilliam A. Kennington III 677238ef992SWilliam A. Kennington III namespace detail 678238ef992SWilliam A. Kennington III { 67971de63a2SWilliam A. Kennington III 680bb0eaccbSWilliam A. Kennington III template <typename T> 681bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 682bb0eaccbSWilliam A. Kennington III { 683bb0eaccbSWilliam A. Kennington III return false; 684bb0eaccbSWilliam A. Kennington III } 685bb0eaccbSWilliam A. Kennington III 686bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs> 687bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 688bb0eaccbSWilliam A. Kennington III { 689bb0eaccbSWilliam A. Kennington III return vcontains<T, Vs...>() || std::is_same_v<T, V>; 690bb0eaccbSWilliam A. Kennington III } 691bb0eaccbSWilliam A. Kennington III 692bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types> 693bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool> 694bb0eaccbSWilliam A. Kennington III veq(T t, std::variant<Types...> v) noexcept 695bb0eaccbSWilliam A. Kennington III { 696bb0eaccbSWilliam A. Kennington III return std::visit( 697bb0eaccbSWilliam A. Kennington III [t](auto v) { 698bb0eaccbSWilliam A. Kennington III if constexpr (std::is_same_v<T, decltype(v)>) 699bb0eaccbSWilliam A. Kennington III { 700bb0eaccbSWilliam A. Kennington III return v == t; 701bb0eaccbSWilliam A. Kennington III } 702bb0eaccbSWilliam A. Kennington III else 703bb0eaccbSWilliam A. Kennington III { 704bb0eaccbSWilliam A. Kennington III return false; 705bb0eaccbSWilliam A. Kennington III } 706bb0eaccbSWilliam A. Kennington III }, 707bb0eaccbSWilliam A. Kennington III v); 708bb0eaccbSWilliam A. Kennington III } 709bb0eaccbSWilliam A. Kennington III 710bb0eaccbSWilliam A. Kennington III template <typename T> 71155bdc36cSWilliam A. Kennington III struct ToStrBuf 712bb0eaccbSWilliam A. Kennington III { 713bb0eaccbSWilliam A. Kennington III public: 71455bdc36cSWilliam A. Kennington III constexpr std::string_view operator()(T v) noexcept 715bb0eaccbSWilliam A. Kennington III { 71655bdc36cSWilliam A. Kennington III return {buf.data(), ToStr<T>{}(buf.data(), v)}; 71755bdc36cSWilliam A. Kennington III } 718bb0eaccbSWilliam A. Kennington III 719bb0eaccbSWilliam A. Kennington III private: 72055bdc36cSWilliam A. Kennington III typename ToStr<T>::buf_type buf; 721bb0eaccbSWilliam A. Kennington III }; 722bb0eaccbSWilliam A. Kennington III 72355bdc36cSWilliam A. Kennington III template <typename T> 72455bdc36cSWilliam A. Kennington III struct Format 725bb0eaccbSWilliam A. Kennington III { 726bb0eaccbSWilliam A. Kennington III private: 727bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 728bb0eaccbSWilliam A. Kennington III 729bb0eaccbSWilliam A. Kennington III public: 730bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 731bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 732bb0eaccbSWilliam A. Kennington III { 733bb0eaccbSWilliam A. Kennington III return ctx.begin(); 734bb0eaccbSWilliam A. Kennington III } 735bb0eaccbSWilliam A. Kennington III 736bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 737bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 738bb0eaccbSWilliam A. Kennington III { 73955bdc36cSWilliam A. Kennington III return formatter.format(ToStrBuf<T>{}(v), ctx); 740bb0eaccbSWilliam A. Kennington III } 741bb0eaccbSWilliam A. Kennington III }; 742bb0eaccbSWilliam A. Kennington III } // namespace detail 7431bbe3d1eSWilliam A. Kennington III } // namespace network 7441bbe3d1eSWilliam A. Kennington III } // namespace phosphor 7453e471c5fSWilliam A. Kennington III 7463e471c5fSWilliam A. Kennington III template <typename... Ts> 7473e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>> 7483e471c5fSWilliam A. Kennington III { 7493e471c5fSWilliam A. Kennington III constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept 7503e471c5fSWilliam A. Kennington III { 7513e471c5fSWilliam A. Kennington III return std::apply(phosphor::network::hash_multi<Ts...>, t); 7523e471c5fSWilliam A. Kennington III } 7533e471c5fSWilliam A. Kennington III }; 754bb0eaccbSWilliam A. Kennington III 755653114fcSWilliam A. Kennington III template <> 756653114fcSWilliam A. Kennington III struct std::hash<in_addr> 757653114fcSWilliam A. Kennington III { 758653114fcSWilliam A. Kennington III std::size_t operator()(in_addr addr) const noexcept; 759653114fcSWilliam A. Kennington III }; 760653114fcSWilliam A. Kennington III 761653114fcSWilliam A. Kennington III template <> 762653114fcSWilliam A. Kennington III struct std::hash<in6_addr> 763653114fcSWilliam A. Kennington III { 764653114fcSWilliam A. Kennington III std::size_t operator()(in6_addr addr) const noexcept; 765653114fcSWilliam A. Kennington III }; 766653114fcSWilliam A. Kennington III 767b9d7cbacSWilliam A. Kennington III template <> 768b9d7cbacSWilliam A. Kennington III struct std::hash<phosphor::network::IfAddr> 769b9d7cbacSWilliam A. Kennington III { 770b9d7cbacSWilliam A. Kennington III std::size_t operator()(phosphor::network::IfAddr addr) const noexcept; 771b9d7cbacSWilliam A. Kennington III }; 772b9d7cbacSWilliam A. Kennington III 773bb0eaccbSWilliam A. Kennington III namespace fmt 774bb0eaccbSWilliam A. Kennington III { 775bb0eaccbSWilliam A. Kennington III template <> 77655bdc36cSWilliam A. Kennington III struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr> 77789d734b9SPatrick Williams {}; 778bb0eaccbSWilliam A. Kennington III template <> 77955bdc36cSWilliam A. Kennington III struct formatter<in_addr> : phosphor::network::detail::Format<in_addr> 78089d734b9SPatrick Williams {}; 781bb0eaccbSWilliam A. Kennington III template <> 78255bdc36cSWilliam A. Kennington III struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr> 78389d734b9SPatrick Williams {}; 784bb0eaccbSWilliam A. Kennington III template <> 78589d734b9SPatrick Williams struct formatter<phosphor::network::InAddrAny> : 78689d734b9SPatrick Williams phosphor::network::detail::Format<phosphor::network::InAddrAny> 78789d734b9SPatrick Williams {}; 788b9d7cbacSWilliam A. Kennington III template <> 78989d734b9SPatrick Williams struct formatter<phosphor::network::IfAddr> : 79089d734b9SPatrick Williams phosphor::network::detail::Format<phosphor::network::IfAddr> 79189d734b9SPatrick Williams {}; 792bb0eaccbSWilliam A. Kennington III } // namespace fmt 793bb0eaccbSWilliam A. Kennington III 794bb0eaccbSWilliam A. Kennington III namespace std 795bb0eaccbSWilliam A. Kennington III { 796bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value); 797bb0eaccbSWilliam A. Kennington III string to_string(in_addr value); 798bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value); 799bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value); 800b9d7cbacSWilliam A. Kennington III string to_string(phosphor::network::IfAddr value); 801bb0eaccbSWilliam A. Kennington III } // namespace std 802bb0eaccbSWilliam A. Kennington III 803bb0eaccbSWilliam A. Kennington III template <typename T> 804bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>, 805bb0eaccbSWilliam A. Kennington III bool> 806bb0eaccbSWilliam A. Kennington III operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept 807bb0eaccbSWilliam A. Kennington III { 808bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::veq(rhs, lhs); 809bb0eaccbSWilliam A. Kennington III } 810bb0eaccbSWilliam A. Kennington III 81186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v) 812bb0eaccbSWilliam A. Kennington III { 81355bdc36cSWilliam A. Kennington III return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v); 814bb0eaccbSWilliam A. Kennington III } 815bb0eaccbSWilliam A. Kennington III 81686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v) 817bb0eaccbSWilliam A. Kennington III { 81855bdc36cSWilliam A. Kennington III return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v); 819bb0eaccbSWilliam A. Kennington III } 820bb0eaccbSWilliam A. Kennington III 82186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v) 822bb0eaccbSWilliam A. Kennington III { 82355bdc36cSWilliam A. Kennington III return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v); 824bb0eaccbSWilliam A. Kennington III } 825bb0eaccbSWilliam A. Kennington III 82686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v) 827bb0eaccbSWilliam A. Kennington III { 82855bdc36cSWilliam A. Kennington III phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb; 82955bdc36cSWilliam A. Kennington III return os << tsb(v); 830bb0eaccbSWilliam A. Kennington III } 831b9d7cbacSWilliam A. Kennington III 832b9d7cbacSWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::IfAddr v) 833b9d7cbacSWilliam A. Kennington III { 83455bdc36cSWilliam A. Kennington III phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb; 83555bdc36cSWilliam A. Kennington III return os << tsb(v); 836b9d7cbacSWilliam A. Kennington III } 83713d665caSWilliam A. Kennington III 83813d665caSWilliam A. Kennington III namespace phosphor::network 83913d665caSWilliam A. Kennington III { 84013d665caSWilliam A. Kennington III 84113d665caSWilliam A. Kennington III /** @brief Contains all of the object information about the interface */ 84213d665caSWilliam A. Kennington III struct AllIntfInfo 84313d665caSWilliam A. Kennington III { 84413d665caSWilliam A. Kennington III InterfaceInfo intf; 84513d665caSWilliam A. Kennington III std::optional<in_addr> defgw4 = std::nullopt; 84613d665caSWilliam A. Kennington III std::optional<in6_addr> defgw6 = std::nullopt; 84713d665caSWilliam A. Kennington III std::unordered_map<IfAddr, AddressInfo> addrs = {}; 84813d665caSWilliam A. Kennington III std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {}; 84913d665caSWilliam A. Kennington III }; 85013d665caSWilliam A. Kennington III 85113d665caSWilliam A. Kennington III } // namespace phosphor::network 852