types: Better IPv6 RFC5952 support
This makes sure our text output better conforms to standards.
Change-Id: I6d9ed5490d11b5e59c3c1bccabe0520fddeb6b56
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/types.cpp b/src/types.cpp
index 37eb69e..ff49313 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -34,23 +34,36 @@
return {buf.begin(), buf.size()};
}
-std::string_view AddrBufMaker<in_addr>::operator()(in_addr val) noexcept
+static char* makeInAddr(char* ptr, char* end, in_addr val) noexcept
{
auto v = bswap(ntoh(val.s_addr));
- char* ptr = buf.begin();
for (size_t i = 0; i < 3; ++i)
{
- const auto res = std::to_chars(ptr, buf.end(), v & 0xff, 10);
+ const auto res = std::to_chars(ptr, end, v & 0xff, 10);
*res.ptr = '.';
ptr = res.ptr + 1;
v >>= 8;
}
- const auto res = std::to_chars(ptr, buf.end(), v & 0xff, 10);
- return {buf.data(), res.ptr};
+ return std::to_chars(ptr, end, v & 0xff, 10).ptr;
+}
+
+std::string_view AddrBufMaker<in_addr>::operator()(in_addr val) noexcept
+{
+ return {buf.data(), makeInAddr(buf.data(), buf.end(), val)};
}
std::string_view AddrBufMaker<in6_addr>::operator()(in6_addr val) noexcept
{
+ // IPv4 in IPv6 Addr
+ if (val.s6_addr32[0] == 0 && val.s6_addr32[1] == 0 &&
+ val.s6_addr32[2] == hton(uint32_t(0xffff)))
+ {
+ constexpr auto prefix = std::string_view("::ffff:");
+ return {buf.data(),
+ makeInAddr(std::copy(prefix.begin(), prefix.end(), buf.begin()),
+ buf.end(), {val.s6_addr32[3]})};
+ }
+
size_t skip_start = 0;
size_t skip_size = 0;
{
@@ -80,7 +93,7 @@
char* ptr = buf.begin();
for (size_t i = 0; i < 8; ++i)
{
- if (i == skip_start && skip_size > 0)
+ if (i == skip_start && skip_size > 1)
{
if (i == 0)
{
diff --git a/test/test_types.cpp b/test/test_types.cpp
index fc4a998..09a9666 100644
--- a/test/test_types.cpp
+++ b/test/test_types.cpp
@@ -172,6 +172,16 @@
EXPECT_EQ("ff00::"sv, abm(in6_addr{0xff}));
EXPECT_EQ("1:2:3:4:5:6:7:8"sv,
abm(in6_addr{0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}));
+ // rfc5952 4.2.2
+ EXPECT_EQ("1:2:3:4:0:6:7:8"sv,
+ abm(in6_addr{0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 0, 6, 0, 7, 0, 8}));
+ // rfc5952 4.2.3
+ EXPECT_EQ("1::4:0:0:7:8"sv,
+ abm(in6_addr{0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 7, 0, 8}));
+ // rfc5952 5
+ EXPECT_EQ("::ffff:192.168.0.1"sv,
+ abm(in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168,
+ 0, 1}));
}
TEST(BasicOps, AllAddrs)