blob: ff493132294f8a51768abef846aa9b9549d02a4a [file] [log] [blame]
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -07001#include "types.hpp"
2
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -08003#include <fmt/format.h>
4
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -07005#include <charconv>
6
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -08007namespace phosphor::network
8{
9
10void IfAddr::invalidPfx(uint8_t pfx)
11{
12 throw std::invalid_argument(fmt::format("Invalid prefix {}", pfx));
13}
14
15namespace detail
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070016{
17
18std::string_view AddrBufMaker<ether_addr>::operator()(ether_addr val) noexcept
19{
20 for (char* ptr = buf.data() + 2; ptr < buf.end(); ptr += 3)
21 {
22 *ptr = ':';
23 }
24 for (size_t i = 0; i < 6; ++i)
25 {
26 char* tmp = buf.data() + i * 3;
27 uint8_t byte = val.ether_addr_octet[i];
28 if (byte < 16)
29 {
30 *(tmp++) = '0';
31 }
32 std::to_chars(tmp, buf.end(), byte, 16);
33 }
34 return {buf.begin(), buf.size()};
35}
36
William A. Kennington III4f077982022-11-04 02:10:48 -070037static char* makeInAddr(char* ptr, char* end, in_addr val) noexcept
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070038{
William A. Kennington III71de63a2022-11-08 10:50:54 -080039 auto v = bswap(ntoh(val.s_addr));
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070040 for (size_t i = 0; i < 3; ++i)
41 {
William A. Kennington III4f077982022-11-04 02:10:48 -070042 const auto res = std::to_chars(ptr, end, v & 0xff, 10);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070043 *res.ptr = '.';
44 ptr = res.ptr + 1;
45 v >>= 8;
46 }
William A. Kennington III4f077982022-11-04 02:10:48 -070047 return std::to_chars(ptr, end, v & 0xff, 10).ptr;
48}
49
50std::string_view AddrBufMaker<in_addr>::operator()(in_addr val) noexcept
51{
52 return {buf.data(), makeInAddr(buf.data(), buf.end(), val)};
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070053}
54
55std::string_view AddrBufMaker<in6_addr>::operator()(in6_addr val) noexcept
56{
William A. Kennington III4f077982022-11-04 02:10:48 -070057 // IPv4 in IPv6 Addr
58 if (val.s6_addr32[0] == 0 && val.s6_addr32[1] == 0 &&
59 val.s6_addr32[2] == hton(uint32_t(0xffff)))
60 {
61 constexpr auto prefix = std::string_view("::ffff:");
62 return {buf.data(),
63 makeInAddr(std::copy(prefix.begin(), prefix.end(), buf.begin()),
64 buf.end(), {val.s6_addr32[3]})};
65 }
66
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070067 size_t skip_start = 0;
68 size_t skip_size = 0;
69 {
70 size_t new_start = 0;
71 size_t new_size = 0;
72 for (size_t i = 0; i < 9; ++i)
73 {
74 if (i < 8 && val.s6_addr16[i] == 0)
75 {
76 if (new_start + new_size == i)
77 {
78 new_size++;
79 }
80 else
81 {
82 new_start = i;
83 new_size = 1;
84 }
85 }
86 else if (new_start + new_size == i && new_size > skip_size)
87 {
88 skip_start = new_start;
89 skip_size = new_size;
90 }
91 }
92 }
93 char* ptr = buf.begin();
94 for (size_t i = 0; i < 8; ++i)
95 {
William A. Kennington III4f077982022-11-04 02:10:48 -070096 if (i == skip_start && skip_size > 1)
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070097 {
98 if (i == 0)
99 {
100 *(ptr++) = ':';
101 }
102 *(ptr++) = ':';
103 i += skip_size - 1;
104 continue;
105 }
106 const auto res =
William A. Kennington III71de63a2022-11-08 10:50:54 -0800107 std::to_chars(ptr, buf.end(), ntoh(val.s6_addr16[i]), 16);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700108 ptr = res.ptr;
109 if (i < 7)
110 {
111 *(ptr++) = ':';
112 }
113 }
114 return {buf.data(), ptr};
115}
116
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800117} // namespace detail
118} // namespace phosphor::network
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700119
William A. Kennington III653114f2022-11-01 22:34:04 -0700120std::size_t std::hash<in_addr>::operator()(in_addr addr) const noexcept
121{
122 return std::hash<decltype(addr.s_addr)>{}(addr.s_addr);
123}
124
125std::size_t std::hash<in6_addr>::operator()(in6_addr addr) const noexcept
126{
127 return phosphor::network::hash_multi(addr.s6_addr32[0], addr.s6_addr32[1],
128 addr.s6_addr32[2], addr.s6_addr32[3]);
129}
130
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800131std::size_t std::hash<phosphor::network::IfAddr>::operator()(
132 phosphor::network::IfAddr addr) const noexcept
133{
134 return phosphor::network::hash_multi(addr.getAddr(), addr.getPfx());
135}
136
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700137std::string std::to_string(ether_addr value)
138{
139 return string(phosphor::network::detail::AddrBufMaker<ether_addr>{}(value));
140}
141std::string std::to_string(in_addr value)
142{
143 return string(phosphor::network::detail::AddrBufMaker<in_addr>{}(value));
144}
145std::string std::to_string(in6_addr value)
146{
147 return string(phosphor::network::detail::AddrBufMaker<in6_addr>{}(value));
148}
149std::string std::to_string(phosphor::network::InAddrAny value)
150{
151 return std::visit([](auto v) { return std::to_string(v); }, value);
152}
William A. Kennington IIIb9d7cba2022-11-08 10:54:11 -0800153
154std::string std::to_string(phosphor::network::IfAddr value)
155{
156 return fmt::to_string(value);
157}