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> 81bbe3d1eSWilliam A. Kennington III #include <chrono> 971de63a2SWilliam A. Kennington III #include <numeric> 101bbe3d1eSWilliam A. Kennington III #include <sdeventplus/clock.hpp> 111bbe3d1eSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 121bbe3d1eSWilliam A. Kennington III #include <string> 13bb0eaccbSWilliam A. Kennington III #include <string_view> 14bb0eaccbSWilliam A. Kennington III #include <type_traits> 15dd9ef815SWilliam A. Kennington III #include <unordered_map> 16f7dce2e8SWilly Tu #include <unordered_set> 171bbe3d1eSWilliam A. Kennington III #include <variant> 181bbe3d1eSWilliam A. Kennington III 191bbe3d1eSWilliam A. Kennington III namespace phosphor 201bbe3d1eSWilliam A. Kennington III { 211bbe3d1eSWilliam A. Kennington III namespace network 221bbe3d1eSWilliam A. Kennington III { 231bbe3d1eSWilliam A. Kennington III 241bbe3d1eSWilliam A. Kennington III using namespace std::chrono_literals; 251bbe3d1eSWilliam A. Kennington III 26c7cf25f7SWilliam A. Kennington III // wait for three seconds before reloading systemd-networkd 27c7cf25f7SWilliam A. Kennington III constexpr auto reloadTimeout = 3s; 281bbe3d1eSWilliam A. Kennington III 29d41db383SWilliam A. Kennington III // refresh the objets after four seconds as network 30d41db383SWilliam A. Kennington III // configuration takes 3-4 sec to reconfigure at most. 31d41db383SWilliam A. Kennington III constexpr auto refreshTimeout = 4s; 321bbe3d1eSWilliam A. Kennington III 331bbe3d1eSWilliam A. Kennington III // Byte representations for common address types in network byte order 34bb0eaccbSWilliam A. Kennington III using InAddrAny = std::variant<in_addr, in6_addr>; 35b9d7cbacSWilliam A. Kennington III class IfAddr 36b9d7cbacSWilliam A. Kennington III { 37b9d7cbacSWilliam A. Kennington III private: 38b9d7cbacSWilliam A. Kennington III InAddrAny addr; 39b9d7cbacSWilliam A. Kennington III uint8_t pfx; 40b9d7cbacSWilliam A. Kennington III 41b9d7cbacSWilliam A. Kennington III static void invalidPfx(uint8_t pfx); 42b9d7cbacSWilliam A. Kennington III 43b9d7cbacSWilliam A. Kennington III public: 44b9d7cbacSWilliam A. Kennington III constexpr IfAddr() : addr({}), pfx(0) 45b9d7cbacSWilliam A. Kennington III { 46b9d7cbacSWilliam A. Kennington III } 47b9d7cbacSWilliam A. Kennington III 48b9d7cbacSWilliam A. Kennington III constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx) 49b9d7cbacSWilliam A. Kennington III { 50b9d7cbacSWilliam A. Kennington III std::visit( 51b9d7cbacSWilliam A. Kennington III [pfx](auto v) { 52b9d7cbacSWilliam A. Kennington III if (sizeof(v) * 8 < pfx) 53b9d7cbacSWilliam A. Kennington III { 54b9d7cbacSWilliam A. Kennington III invalidPfx(pfx); 55b9d7cbacSWilliam A. Kennington III } 56b9d7cbacSWilliam A. Kennington III }, 57b9d7cbacSWilliam A. Kennington III addr); 58b9d7cbacSWilliam A. Kennington III } 59b9d7cbacSWilliam A. Kennington III 60b9d7cbacSWilliam A. Kennington III constexpr auto getAddr() const 61b9d7cbacSWilliam A. Kennington III { 62b9d7cbacSWilliam A. Kennington III return addr; 63b9d7cbacSWilliam A. Kennington III } 64b9d7cbacSWilliam A. Kennington III 65b9d7cbacSWilliam A. Kennington III constexpr auto getPfx() const 66b9d7cbacSWilliam A. Kennington III { 67b9d7cbacSWilliam A. Kennington III return pfx; 68b9d7cbacSWilliam A. Kennington III } 69b9d7cbacSWilliam A. Kennington III 70b9d7cbacSWilliam A. Kennington III constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept 71b9d7cbacSWilliam A. Kennington III { 72b9d7cbacSWilliam A. Kennington III return addr == rhs.addr && pfx == rhs.pfx; 73b9d7cbacSWilliam A. Kennington III } 74b9d7cbacSWilliam A. Kennington III }; 751bbe3d1eSWilliam A. Kennington III 761bbe3d1eSWilliam A. Kennington III using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>; 771bbe3d1eSWilliam A. Kennington III 78dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view> 79dd9ef815SWilliam A. Kennington III { 80dd9ef815SWilliam A. Kennington III using is_transparent = void; 81dd9ef815SWilliam A. Kennington III }; 82dd9ef815SWilliam A. Kennington III template <typename V> 83dd9ef815SWilliam A. Kennington III using string_umap = 84dd9ef815SWilliam A. Kennington III std::unordered_map<std::string, V, string_hash, std::equal_to<>>; 8596444795SWilliam A. Kennington III using string_uset = 8696444795SWilliam A. Kennington III std::unordered_set<std::string, string_hash, std::equal_to<>>; 87dd9ef815SWilliam A. Kennington III 883e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept 89991a8e81SWilliam A. Kennington III { 90991a8e81SWilliam A. Kennington III return 0; 91991a8e81SWilliam A. Kennington III } 92991a8e81SWilliam A. Kennington III 93991a8e81SWilliam A. Kennington III template <typename T, typename... Args> 94becda1aaSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept 95991a8e81SWilliam A. Kennington III { 96991a8e81SWilliam A. Kennington III const std::size_t seed = hash_multi(args...); 97991a8e81SWilliam A. Kennington III return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 98991a8e81SWilliam A. Kennington III } 99991a8e81SWilliam A. Kennington III 100bb0eaccbSWilliam A. Kennington III namespace detail 101bb0eaccbSWilliam A. Kennington III { 102bb0eaccbSWilliam A. Kennington III 10371de63a2SWilliam A. Kennington III template <typename T, uint8_t size = sizeof(T)> 10471de63a2SWilliam A. Kennington III struct BswapAlign 10571de63a2SWilliam A. Kennington III { 10671de63a2SWilliam A. Kennington III using type = T; 10771de63a2SWilliam A. Kennington III }; 10871de63a2SWilliam A. Kennington III 10971de63a2SWilliam A. Kennington III template <typename T> 11071de63a2SWilliam A. Kennington III struct BswapAlign<T, 2> 11171de63a2SWilliam A. Kennington III { 11271de63a2SWilliam A. Kennington III using type alignas(uint16_t) = T; 11371de63a2SWilliam A. Kennington III }; 11471de63a2SWilliam A. Kennington III 11571de63a2SWilliam A. Kennington III template <typename T> 11671de63a2SWilliam A. Kennington III struct BswapAlign<T, 4> 11771de63a2SWilliam A. Kennington III { 11871de63a2SWilliam A. Kennington III using type alignas(uint32_t) = T; 11971de63a2SWilliam A. Kennington III }; 12071de63a2SWilliam A. Kennington III 12171de63a2SWilliam A. Kennington III template <typename T> 12271de63a2SWilliam A. Kennington III struct BswapAlign<T, 8> 12371de63a2SWilliam A. Kennington III { 12471de63a2SWilliam A. Kennington III using type alignas(uint64_t) = T; 12571de63a2SWilliam A. Kennington III }; 12671de63a2SWilliam A. Kennington III 12771de63a2SWilliam A. Kennington III template <typename T> 12871de63a2SWilliam A. Kennington III constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept 12971de63a2SWilliam A. Kennington III { 13071de63a2SWilliam A. Kennington III static_assert(std::is_trivially_copyable_v<T>); 13171de63a2SWilliam A. Kennington III if constexpr (sizeof(T) == 2) 13271de63a2SWilliam A. Kennington III { 13371de63a2SWilliam A. Kennington III reinterpret_cast<uint16_t&>(n) = 13471de63a2SWilliam A. Kennington III __builtin_bswap16(reinterpret_cast<uint16_t&>(n)); 13571de63a2SWilliam A. Kennington III } 13671de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 4) 13771de63a2SWilliam A. Kennington III { 13871de63a2SWilliam A. Kennington III reinterpret_cast<uint32_t&>(n) = 13971de63a2SWilliam A. Kennington III __builtin_bswap32(reinterpret_cast<uint32_t&>(n)); 14071de63a2SWilliam A. Kennington III } 14171de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 8) 14271de63a2SWilliam A. Kennington III { 14371de63a2SWilliam A. Kennington III reinterpret_cast<uint64_t&>(n) = 14471de63a2SWilliam A. Kennington III __builtin_bswap64(reinterpret_cast<uint64_t&>(n)); 14571de63a2SWilliam A. Kennington III } 14671de63a2SWilliam A. Kennington III else 14771de63a2SWilliam A. Kennington III { 14871de63a2SWilliam A. Kennington III auto b = reinterpret_cast<std::byte*>(&n); 14971de63a2SWilliam A. Kennington III std::reverse(b, b + sizeof(n)); 15071de63a2SWilliam A. Kennington III } 15171de63a2SWilliam A. Kennington III return n; 15271de63a2SWilliam A. Kennington III } 15371de63a2SWilliam A. Kennington III 15471de63a2SWilliam A. Kennington III } // namespace detail 15571de63a2SWilliam A. Kennington III 15671de63a2SWilliam A. Kennington III template <typename T> 15771de63a2SWilliam A. Kennington III constexpr T bswap(T n) noexcept 15871de63a2SWilliam A. Kennington III { 15971de63a2SWilliam A. Kennington III return detail::bswapInt<T>(n); 16071de63a2SWilliam A. Kennington III } 16171de63a2SWilliam A. Kennington III 16271de63a2SWilliam A. Kennington III template <typename T> 16371de63a2SWilliam A. Kennington III constexpr T hton(T n) noexcept 16471de63a2SWilliam A. Kennington III { 16571de63a2SWilliam A. Kennington III if constexpr (std::endian::native == std::endian::big) 16671de63a2SWilliam A. Kennington III { 16771de63a2SWilliam A. Kennington III return n; 16871de63a2SWilliam A. Kennington III } 16971de63a2SWilliam A. Kennington III else if constexpr (std::endian::native == std::endian::little) 17071de63a2SWilliam A. Kennington III { 17171de63a2SWilliam A. Kennington III return bswap(n); 17271de63a2SWilliam A. Kennington III } 17371de63a2SWilliam A. Kennington III else 17471de63a2SWilliam A. Kennington III { 17571de63a2SWilliam A. Kennington III static_assert(std::is_same_v<T, void>); 17671de63a2SWilliam A. Kennington III } 17771de63a2SWilliam A. Kennington III } 17871de63a2SWilliam A. Kennington III 17971de63a2SWilliam A. Kennington III template <typename T> 18071de63a2SWilliam A. Kennington III constexpr T ntoh(T n) noexcept 18171de63a2SWilliam A. Kennington III { 18271de63a2SWilliam A. Kennington III return hton(n); 18371de63a2SWilliam A. Kennington III } 18471de63a2SWilliam A. Kennington III 18571de63a2SWilliam A. Kennington III namespace detail 18671de63a2SWilliam A. Kennington III { 187238ef992SWilliam A. Kennington III inline constexpr auto charLookup = []() { 188238ef992SWilliam A. Kennington III std::array<int8_t, 256> ret; 189238ef992SWilliam A. Kennington III std::fill(ret.begin(), ret.end(), -1); 190238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 10; ++i) 191238ef992SWilliam A. Kennington III { 192238ef992SWilliam A. Kennington III ret[i + '0'] = i; 193238ef992SWilliam A. Kennington III } 194238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 26; ++i) 195238ef992SWilliam A. Kennington III { 196238ef992SWilliam A. Kennington III ret[i + 'A'] = i + 10; 197238ef992SWilliam A. Kennington III ret[i + 'a'] = i + 10; 198238ef992SWilliam A. Kennington III } 199238ef992SWilliam A. Kennington III return ret; 200238ef992SWilliam A. Kennington III }(); 201238ef992SWilliam A. Kennington III } 202238ef992SWilliam A. Kennington III 203238ef992SWilliam A. Kennington III template <typename T, uint8_t base> 204238ef992SWilliam A. Kennington III struct DecodeInt 205238ef992SWilliam A. Kennington III { 206238ef992SWilliam A. Kennington III static_assert(base > 1 && base <= 36); 207238ef992SWilliam A. Kennington III static_assert(std::is_unsigned_v<T>); 208238ef992SWilliam A. Kennington III 209238ef992SWilliam A. Kennington III constexpr T operator()(std::string_view str) const 210238ef992SWilliam A. Kennington III { 211238ef992SWilliam A. Kennington III if (str.empty()) 212238ef992SWilliam A. Kennington III { 213238ef992SWilliam A. Kennington III throw std::invalid_argument("Empty Str"); 214238ef992SWilliam A. Kennington III } 215238ef992SWilliam A. Kennington III constexpr auto max = std::numeric_limits<T>::max(); 216238ef992SWilliam A. Kennington III auto ret = 217238ef992SWilliam A. Kennington III std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) { 218238ef992SWilliam A. Kennington III auto v = detail::charLookup[c]; 219238ef992SWilliam A. Kennington III if (v < 0 || v >= base) 220238ef992SWilliam A. Kennington III { 221238ef992SWilliam A. Kennington III throw std::invalid_argument("Invalid numeral"); 222238ef992SWilliam A. Kennington III } 223238ef992SWilliam A. Kennington III if constexpr (std::popcount(base) == 1) 224238ef992SWilliam A. Kennington III { 225238ef992SWilliam A. Kennington III constexpr auto shift = std::countr_zero(base); 226238ef992SWilliam A. Kennington III constexpr auto maxshift = max >> shift; 227238ef992SWilliam A. Kennington III if (r > maxshift) 228238ef992SWilliam A. Kennington III { 229238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 230238ef992SWilliam A. Kennington III } 231238ef992SWilliam A. Kennington III return (r << shift) | v; 232238ef992SWilliam A. Kennington III } 233238ef992SWilliam A. Kennington III else 234238ef992SWilliam A. Kennington III { 235238ef992SWilliam A. Kennington III constexpr auto maxbase = max / base; 236238ef992SWilliam A. Kennington III if (r > maxbase) 237238ef992SWilliam A. Kennington III { 238238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 239238ef992SWilliam A. Kennington III } 240238ef992SWilliam A. Kennington III r *= base; 241238ef992SWilliam A. Kennington III if (max - v < r) 242238ef992SWilliam A. Kennington III { 243238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 244238ef992SWilliam A. Kennington III } 245238ef992SWilliam A. Kennington III return r + v; 246238ef992SWilliam A. Kennington III } 247238ef992SWilliam A. Kennington III }); 248238ef992SWilliam A. Kennington III return ret; 249238ef992SWilliam A. Kennington III } 250238ef992SWilliam A. Kennington III }; 251238ef992SWilliam A. Kennington III 252b01d08fdSWilliam A. Kennington III template <typename T> 253b01d08fdSWilliam A. Kennington III struct ToAddr 254b01d08fdSWilliam A. Kennington III { 255b01d08fdSWilliam A. Kennington III }; 256b01d08fdSWilliam A. Kennington III 257b01d08fdSWilliam A. Kennington III template <> 258b01d08fdSWilliam A. Kennington III struct ToAddr<ether_addr> 259b01d08fdSWilliam A. Kennington III { 260b01d08fdSWilliam A. Kennington III constexpr ether_addr operator()(std::string_view str) const 261b01d08fdSWilliam A. Kennington III { 262b01d08fdSWilliam A. Kennington III constexpr DecodeInt<uint8_t, 16> di; 263b01d08fdSWilliam A. Kennington III ether_addr ret; 264b01d08fdSWilliam A. Kennington III if (str.size() == 12 && str.find(":") == str.npos) 265b01d08fdSWilliam A. Kennington III { 266b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 6; ++i) 267b01d08fdSWilliam A. Kennington III { 268b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(i * 2, 2)); 269b01d08fdSWilliam A. Kennington III } 270b01d08fdSWilliam A. Kennington III } 271b01d08fdSWilliam A. Kennington III else 272b01d08fdSWilliam A. Kennington III { 273b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 5; ++i) 274b01d08fdSWilliam A. Kennington III { 275b01d08fdSWilliam A. Kennington III auto loc = str.find(":"); 276b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(0, loc)); 277b01d08fdSWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 278b01d08fdSWilliam A. Kennington III if (str.empty()) 279b01d08fdSWilliam A. Kennington III { 280b01d08fdSWilliam A. Kennington III throw std::invalid_argument("Missing mac data"); 281b01d08fdSWilliam A. Kennington III } 282b01d08fdSWilliam A. Kennington III } 283b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[5] = di(str); 284b01d08fdSWilliam A. Kennington III } 285b01d08fdSWilliam A. Kennington III return ret; 286b01d08fdSWilliam A. Kennington III } 287b01d08fdSWilliam A. Kennington III }; 288b01d08fdSWilliam A. Kennington III 289df1178e0SWilliam A. Kennington III template <> 290df1178e0SWilliam A. Kennington III struct ToAddr<in_addr> 291df1178e0SWilliam A. Kennington III { 292df1178e0SWilliam A. Kennington III constexpr in_addr operator()(std::string_view str) const 293df1178e0SWilliam A. Kennington III { 294df1178e0SWilliam A. Kennington III constexpr DecodeInt<uint8_t, 10> di; 295df1178e0SWilliam A. Kennington III uint32_t addr = {}; 296df1178e0SWilliam A. Kennington III for (size_t i = 0; i < 3; ++i) 297df1178e0SWilliam A. Kennington III { 298df1178e0SWilliam A. Kennington III auto loc = str.find("."); 299df1178e0SWilliam A. Kennington III addr |= di(str.substr(0, loc)); 300df1178e0SWilliam A. Kennington III addr <<= 8; 301df1178e0SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 302df1178e0SWilliam A. Kennington III if (str.empty()) 303df1178e0SWilliam A. Kennington III { 304df1178e0SWilliam A. Kennington III throw std::invalid_argument("Missing addr data"); 305df1178e0SWilliam A. Kennington III } 306df1178e0SWilliam A. Kennington III } 307df1178e0SWilliam A. Kennington III addr |= di(str); 308df1178e0SWilliam A. Kennington III return {hton(addr)}; 309df1178e0SWilliam A. Kennington III } 310df1178e0SWilliam A. Kennington III }; 311df1178e0SWilliam A. Kennington III 312*ec496a86SWilliam A. Kennington III template <> 313*ec496a86SWilliam A. Kennington III struct ToAddr<in6_addr> 314*ec496a86SWilliam A. Kennington III { 315*ec496a86SWilliam A. Kennington III constexpr in6_addr operator()(std::string_view str) const 316*ec496a86SWilliam A. Kennington III { 317*ec496a86SWilliam A. Kennington III constexpr DecodeInt<uint16_t, 16> di; 318*ec496a86SWilliam A. Kennington III in6_addr ret = {}; 319*ec496a86SWilliam A. Kennington III size_t i = 0; 320*ec496a86SWilliam A. Kennington III while (i < 8) 321*ec496a86SWilliam A. Kennington III { 322*ec496a86SWilliam A. Kennington III auto loc = str.find(':'); 323*ec496a86SWilliam A. Kennington III if (i == 6 && loc == str.npos) 324*ec496a86SWilliam A. Kennington III { 325*ec496a86SWilliam A. Kennington III ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr; 326*ec496a86SWilliam A. Kennington III return ret; 327*ec496a86SWilliam A. Kennington III } 328*ec496a86SWilliam A. Kennington III if (loc != 0 && !str.empty()) 329*ec496a86SWilliam A. Kennington III { 330*ec496a86SWilliam A. Kennington III ret.s6_addr16[i++] = hton(di(str.substr(0, loc))); 331*ec496a86SWilliam A. Kennington III } 332*ec496a86SWilliam A. Kennington III if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':') 333*ec496a86SWilliam A. Kennington III { 334*ec496a86SWilliam A. Kennington III str.remove_prefix(loc + 2); 335*ec496a86SWilliam A. Kennington III break; 336*ec496a86SWilliam A. Kennington III } 337*ec496a86SWilliam A. Kennington III else if (str.empty()) 338*ec496a86SWilliam A. Kennington III { 339*ec496a86SWilliam A. Kennington III throw std::invalid_argument("IPv6 Data"); 340*ec496a86SWilliam A. Kennington III } 341*ec496a86SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 342*ec496a86SWilliam A. Kennington III } 343*ec496a86SWilliam A. Kennington III if (str.starts_with(':')) 344*ec496a86SWilliam A. Kennington III { 345*ec496a86SWilliam A. Kennington III throw std::invalid_argument("Extra separator"); 346*ec496a86SWilliam A. Kennington III } 347*ec496a86SWilliam A. Kennington III size_t j = 7; 348*ec496a86SWilliam A. Kennington III if (!str.empty() && i < 6 && str.find('.') != str.npos) 349*ec496a86SWilliam A. Kennington III { 350*ec496a86SWilliam A. Kennington III auto loc = str.rfind(':'); 351*ec496a86SWilliam A. Kennington III ret.s6_addr32[3] = 352*ec496a86SWilliam A. Kennington III ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1)) 353*ec496a86SWilliam A. Kennington III .s_addr; 354*ec496a86SWilliam A. Kennington III str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc); 355*ec496a86SWilliam A. Kennington III j -= 2; 356*ec496a86SWilliam A. Kennington III } 357*ec496a86SWilliam A. Kennington III while (!str.empty() && j > i) 358*ec496a86SWilliam A. Kennington III { 359*ec496a86SWilliam A. Kennington III auto loc = str.rfind(':'); 360*ec496a86SWilliam A. Kennington III ret.s6_addr16[j--] = 361*ec496a86SWilliam A. Kennington III hton(di(str.substr(loc == str.npos ? 0 : loc + 1))); 362*ec496a86SWilliam A. Kennington III str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc); 363*ec496a86SWilliam A. Kennington III } 364*ec496a86SWilliam A. Kennington III if (!str.empty()) 365*ec496a86SWilliam A. Kennington III { 366*ec496a86SWilliam A. Kennington III throw std::invalid_argument("Too much data"); 367*ec496a86SWilliam A. Kennington III } 368*ec496a86SWilliam A. Kennington III return ret; 369*ec496a86SWilliam A. Kennington III } 370*ec496a86SWilliam A. Kennington III }; 371*ec496a86SWilliam A. Kennington III 372238ef992SWilliam A. Kennington III namespace detail 373238ef992SWilliam A. Kennington III { 37471de63a2SWilliam A. Kennington III 375bb0eaccbSWilliam A. Kennington III template <typename T> 376bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 377bb0eaccbSWilliam A. Kennington III { 378bb0eaccbSWilliam A. Kennington III return false; 379bb0eaccbSWilliam A. Kennington III } 380bb0eaccbSWilliam A. Kennington III 381bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs> 382bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 383bb0eaccbSWilliam A. Kennington III { 384bb0eaccbSWilliam A. Kennington III return vcontains<T, Vs...>() || std::is_same_v<T, V>; 385bb0eaccbSWilliam A. Kennington III } 386bb0eaccbSWilliam A. Kennington III 387bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types> 388bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool> 389bb0eaccbSWilliam A. Kennington III veq(T t, std::variant<Types...> v) noexcept 390bb0eaccbSWilliam A. Kennington III { 391bb0eaccbSWilliam A. Kennington III return std::visit( 392bb0eaccbSWilliam A. Kennington III [t](auto v) { 393bb0eaccbSWilliam A. Kennington III if constexpr (std::is_same_v<T, decltype(v)>) 394bb0eaccbSWilliam A. Kennington III { 395bb0eaccbSWilliam A. Kennington III return v == t; 396bb0eaccbSWilliam A. Kennington III } 397bb0eaccbSWilliam A. Kennington III else 398bb0eaccbSWilliam A. Kennington III { 399bb0eaccbSWilliam A. Kennington III return false; 400bb0eaccbSWilliam A. Kennington III } 401bb0eaccbSWilliam A. Kennington III }, 402bb0eaccbSWilliam A. Kennington III v); 403bb0eaccbSWilliam A. Kennington III } 404bb0eaccbSWilliam A. Kennington III 405bb0eaccbSWilliam A. Kennington III template <typename T> 406bb0eaccbSWilliam A. Kennington III struct AddrBufMaker 407bb0eaccbSWilliam A. Kennington III { 408bb0eaccbSWilliam A. Kennington III }; 409bb0eaccbSWilliam A. Kennington III 410bb0eaccbSWilliam A. Kennington III template <> 411bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<ether_addr> 412bb0eaccbSWilliam A. Kennington III { 413bb0eaccbSWilliam A. Kennington III public: 414bb0eaccbSWilliam A. Kennington III std::string_view operator()(ether_addr val) noexcept; 415bb0eaccbSWilliam A. Kennington III 416bb0eaccbSWilliam A. Kennington III private: 417bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 2 * /*octets*/ 6 + /*seps*/ 5> buf; 418bb0eaccbSWilliam A. Kennington III }; 419bb0eaccbSWilliam A. Kennington III 420bb0eaccbSWilliam A. Kennington III template <> 421bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in_addr> 422bb0eaccbSWilliam A. Kennington III { 423bb0eaccbSWilliam A. Kennington III public: 424bb0eaccbSWilliam A. Kennington III std::string_view operator()(in_addr val) noexcept; 425bb0eaccbSWilliam A. Kennington III 426bb0eaccbSWilliam A. Kennington III private: 427bb0eaccbSWilliam A. Kennington III std::array<char, /*octet*/ 3 * /*octets*/ 4 + /*seps*/ 3> buf; 428bb0eaccbSWilliam A. Kennington III }; 429bb0eaccbSWilliam A. Kennington III 430bb0eaccbSWilliam A. Kennington III template <> 431bb0eaccbSWilliam A. Kennington III struct AddrBufMaker<in6_addr> 432bb0eaccbSWilliam A. Kennington III { 433bb0eaccbSWilliam A. Kennington III public: 434bb0eaccbSWilliam A. Kennington III std::string_view operator()(in6_addr val) noexcept; 435bb0eaccbSWilliam A. Kennington III 436bb0eaccbSWilliam A. Kennington III private: 437bb0eaccbSWilliam A. Kennington III std::array<char, /*hextet*/ 4 * /*hextets*/ 8 + /*seps*/ 7> buf; 438bb0eaccbSWilliam A. Kennington III }; 439bb0eaccbSWilliam A. Kennington III 440bb0eaccbSWilliam A. Kennington III template <typename BufMaker> 441bb0eaccbSWilliam A. Kennington III struct FormatFromBuf 442bb0eaccbSWilliam A. Kennington III { 443bb0eaccbSWilliam A. Kennington III private: 444bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 445bb0eaccbSWilliam A. Kennington III 446bb0eaccbSWilliam A. Kennington III public: 447bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 448bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 449bb0eaccbSWilliam A. Kennington III { 450bb0eaccbSWilliam A. Kennington III return ctx.begin(); 451bb0eaccbSWilliam A. Kennington III } 452bb0eaccbSWilliam A. Kennington III 453bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 454bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 455bb0eaccbSWilliam A. Kennington III { 456bb0eaccbSWilliam A. Kennington III return formatter.format(BufMaker{}(v), ctx); 457bb0eaccbSWilliam A. Kennington III } 458bb0eaccbSWilliam A. Kennington III }; 459bb0eaccbSWilliam A. Kennington III } // namespace detail 4601bbe3d1eSWilliam A. Kennington III } // namespace network 4611bbe3d1eSWilliam A. Kennington III } // namespace phosphor 4623e471c5fSWilliam A. Kennington III 4633e471c5fSWilliam A. Kennington III template <typename... Ts> 4643e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>> 4653e471c5fSWilliam A. Kennington III { 4663e471c5fSWilliam A. Kennington III constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept 4673e471c5fSWilliam A. Kennington III { 4683e471c5fSWilliam A. Kennington III return std::apply(phosphor::network::hash_multi<Ts...>, t); 4693e471c5fSWilliam A. Kennington III } 4703e471c5fSWilliam A. Kennington III }; 471bb0eaccbSWilliam A. Kennington III 472653114fcSWilliam A. Kennington III template <> 473653114fcSWilliam A. Kennington III struct std::hash<in_addr> 474653114fcSWilliam A. Kennington III { 475653114fcSWilliam A. Kennington III std::size_t operator()(in_addr addr) const noexcept; 476653114fcSWilliam A. Kennington III }; 477653114fcSWilliam A. Kennington III 478653114fcSWilliam A. Kennington III template <> 479653114fcSWilliam A. Kennington III struct std::hash<in6_addr> 480653114fcSWilliam A. Kennington III { 481653114fcSWilliam A. Kennington III std::size_t operator()(in6_addr addr) const noexcept; 482653114fcSWilliam A. Kennington III }; 483653114fcSWilliam A. Kennington III 484b9d7cbacSWilliam A. Kennington III template <> 485b9d7cbacSWilliam A. Kennington III struct std::hash<phosphor::network::IfAddr> 486b9d7cbacSWilliam A. Kennington III { 487b9d7cbacSWilliam A. Kennington III std::size_t operator()(phosphor::network::IfAddr addr) const noexcept; 488b9d7cbacSWilliam A. Kennington III }; 489b9d7cbacSWilliam A. Kennington III 490bb0eaccbSWilliam A. Kennington III namespace fmt 491bb0eaccbSWilliam A. Kennington III { 492bb0eaccbSWilliam A. Kennington III template <> 493bb0eaccbSWilliam A. Kennington III struct formatter<ether_addr> 494bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 495bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<ether_addr>> 496bb0eaccbSWilliam A. Kennington III { 497bb0eaccbSWilliam A. Kennington III }; 498bb0eaccbSWilliam A. Kennington III template <> 499bb0eaccbSWilliam A. Kennington III struct formatter<in_addr> 500bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 501bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in_addr>> 502bb0eaccbSWilliam A. Kennington III { 503bb0eaccbSWilliam A. Kennington III }; 504bb0eaccbSWilliam A. Kennington III template <> 505bb0eaccbSWilliam A. Kennington III struct formatter<in6_addr> 506bb0eaccbSWilliam A. Kennington III : phosphor::network::detail::FormatFromBuf< 507bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<in6_addr>> 508bb0eaccbSWilliam A. Kennington III { 509bb0eaccbSWilliam A. Kennington III }; 510bb0eaccbSWilliam A. Kennington III template <> 511bb0eaccbSWilliam A. Kennington III struct formatter<phosphor::network::InAddrAny> 512bb0eaccbSWilliam A. Kennington III { 513bb0eaccbSWilliam A. Kennington III private: 514bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 515bb0eaccbSWilliam A. Kennington III 516bb0eaccbSWilliam A. Kennington III public: 517bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 518bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 519bb0eaccbSWilliam A. Kennington III { 520bb0eaccbSWilliam A. Kennington III return ctx.begin(); 521bb0eaccbSWilliam A. Kennington III } 522bb0eaccbSWilliam A. Kennington III 523bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 524bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 525bb0eaccbSWilliam A. Kennington III { 526bb0eaccbSWilliam A. Kennington III return std::visit( 527bb0eaccbSWilliam A. Kennington III [&](auto v) { 528bb0eaccbSWilliam A. Kennington III auto abm = 529bb0eaccbSWilliam A. Kennington III phosphor::network::detail::AddrBufMaker<decltype(v)>{}; 530bb0eaccbSWilliam A. Kennington III return formatter.format(abm(v), ctx); 531bb0eaccbSWilliam A. Kennington III }, 532bb0eaccbSWilliam A. Kennington III v); 533bb0eaccbSWilliam A. Kennington III } 534bb0eaccbSWilliam A. Kennington III }; 535b9d7cbacSWilliam A. Kennington III template <> 536b9d7cbacSWilliam A. Kennington III struct formatter<phosphor::network::IfAddr> 537b9d7cbacSWilliam A. Kennington III { 538b9d7cbacSWilliam A. Kennington III private: 539b9d7cbacSWilliam A. Kennington III fmt::formatter<phosphor::network::InAddrAny> addrF; 540b9d7cbacSWilliam A. Kennington III fmt::formatter<char> strF; 541b9d7cbacSWilliam A. Kennington III fmt::formatter<uint8_t> numF; 542b9d7cbacSWilliam A. Kennington III 543b9d7cbacSWilliam A. Kennington III public: 544b9d7cbacSWilliam A. Kennington III template <typename ParseContext> 545b9d7cbacSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 546b9d7cbacSWilliam A. Kennington III { 547b9d7cbacSWilliam A. Kennington III return ctx.begin(); 548b9d7cbacSWilliam A. Kennington III } 549b9d7cbacSWilliam A. Kennington III 550b9d7cbacSWilliam A. Kennington III template <typename FormatContext> 551b9d7cbacSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 552b9d7cbacSWilliam A. Kennington III { 553b9d7cbacSWilliam A. Kennington III addrF.format(v.getAddr(), ctx); 554b9d7cbacSWilliam A. Kennington III strF.format('/', ctx); 555b9d7cbacSWilliam A. Kennington III return numF.format(v.getPfx(), ctx); 556b9d7cbacSWilliam A. Kennington III } 557b9d7cbacSWilliam A. Kennington III }; 558bb0eaccbSWilliam A. Kennington III } // namespace fmt 559bb0eaccbSWilliam A. Kennington III 560bb0eaccbSWilliam A. Kennington III namespace std 561bb0eaccbSWilliam A. Kennington III { 562bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value); 563bb0eaccbSWilliam A. Kennington III string to_string(in_addr value); 564bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value); 565bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value); 566b9d7cbacSWilliam A. Kennington III string to_string(phosphor::network::IfAddr value); 567bb0eaccbSWilliam A. Kennington III } // namespace std 568bb0eaccbSWilliam A. Kennington III 569bb0eaccbSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept 570bb0eaccbSWilliam A. Kennington III { 571bb0eaccbSWilliam A. Kennington III return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6, 572bb0eaccbSWilliam A. Kennington III rhs.ether_addr_octet); 573bb0eaccbSWilliam A. Kennington III } 574bb0eaccbSWilliam A. Kennington III 575bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept 576bb0eaccbSWilliam A. Kennington III { 577bb0eaccbSWilliam A. Kennington III return lhs.s_addr == rhs.s_addr; 578bb0eaccbSWilliam A. Kennington III } 579bb0eaccbSWilliam A. Kennington III 580bb0eaccbSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept 581bb0eaccbSWilliam A. Kennington III { 582bb0eaccbSWilliam A. Kennington III return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32); 583bb0eaccbSWilliam A. Kennington III } 584bb0eaccbSWilliam A. Kennington III 585bb0eaccbSWilliam A. Kennington III template <typename T> 586bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>, 587bb0eaccbSWilliam A. Kennington III bool> 588bb0eaccbSWilliam A. Kennington III operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept 589bb0eaccbSWilliam A. Kennington III { 590bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::veq(rhs, lhs); 591bb0eaccbSWilliam A. Kennington III } 592bb0eaccbSWilliam A. Kennington III 59386eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v) 594bb0eaccbSWilliam A. Kennington III { 595bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<ether_addr>{}(v); 596bb0eaccbSWilliam A. Kennington III } 597bb0eaccbSWilliam A. Kennington III 59886eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v) 599bb0eaccbSWilliam A. Kennington III { 600bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in_addr>{}(v); 601bb0eaccbSWilliam A. Kennington III } 602bb0eaccbSWilliam A. Kennington III 60386eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v) 604bb0eaccbSWilliam A. Kennington III { 605bb0eaccbSWilliam A. Kennington III return os << phosphor::network::detail::AddrBufMaker<in6_addr>{}(v); 606bb0eaccbSWilliam A. Kennington III } 607bb0eaccbSWilliam A. Kennington III 60886eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v) 609bb0eaccbSWilliam A. Kennington III { 610bb0eaccbSWilliam A. Kennington III return os << std::visit( 611bb0eaccbSWilliam A. Kennington III [](auto v) { 612bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::AddrBufMaker< 613bb0eaccbSWilliam A. Kennington III decltype(v)>{}(v); 614bb0eaccbSWilliam A. Kennington III }, 615bb0eaccbSWilliam A. Kennington III v); 616bb0eaccbSWilliam A. Kennington III } 617b9d7cbacSWilliam A. Kennington III 618b9d7cbacSWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::IfAddr v) 619b9d7cbacSWilliam A. Kennington III { 620b9d7cbacSWilliam A. Kennington III return os << v.getAddr() << "/" << std::dec << int{v.getPfx()}; 621b9d7cbacSWilliam A. Kennington III } 622