net/addr/ip: Add unicast / loopback queries
Change-Id: Ife21163dc87a3f2219cd1f0f7e5ca1b16093b7a8
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/net/addr/ip.hpp b/include/stdplus/net/addr/ip.hpp
index b2c5350..601c217 100644
--- a/include/stdplus/net/addr/ip.hpp
+++ b/include/stdplus/net/addr/ip.hpp
@@ -96,6 +96,18 @@
{
return word() == rhs.word();
}
+
+ constexpr bool isLoopback() const noexcept
+ {
+ return byte(0) == 127; // 127.0.0.0/8
+ }
+
+ constexpr bool isUnicast() const noexcept
+ {
+ return byte(0) != 0 && // 0.0.0.0/8
+ (byte(0) & uint8_t{0xf0u}) != 224 && // 224.0.0.0/4
+ word() != 0xffffffffu; // 255.255.255.255/32
+ }
};
template <>
@@ -229,6 +241,9 @@
{
return *this == static_cast<in6_addr&>(rhs);
}
+
+ constexpr bool isLoopback() noexcept;
+ constexpr bool isUnicast() noexcept;
};
template <>
@@ -509,6 +524,17 @@
} // namespace in_addr_literals
+constexpr bool In6Addr::isLoopback() noexcept
+{
+ return *this == "::1"_ip6; // ::1/128
+}
+
+constexpr bool In6Addr::isUnicast() noexcept
+{
+ return *this != "::"_ip6 && // ::/128
+ byte(0) != 0xff; // ff00::/8
+}
+
} // namespace stdplus
template <>
diff --git a/test/net/addr/ip.cpp b/test/net/addr/ip.cpp
index acb88c1..2133d3e 100644
--- a/test/net/addr/ip.cpp
+++ b/test/net/addr/ip.cpp
@@ -223,4 +223,77 @@
EXPECT_EQ("a ff00:: b", fmt::format("a {} b", InAnyAddr{In6Addr{0xff}}));
}
+TEST(Loopback, In4Addr)
+{
+ constexpr bool t = "127.0.0.0"_ip4.isLoopback();
+ EXPECT_TRUE(t);
+ EXPECT_TRUE("127.0.0.1"_ip4.isLoopback());
+ EXPECT_TRUE("127.0.0.83"_ip4.isLoopback());
+ EXPECT_TRUE("127.253.0.0"_ip4.isLoopback());
+ EXPECT_TRUE("127.255.255.255"_ip4.isLoopback());
+
+ EXPECT_FALSE("0.0.0.0"_ip4.isLoopback());
+ EXPECT_FALSE("0.255.255.255"_ip4.isLoopback());
+ EXPECT_FALSE("126.255.255.255"_ip4.isLoopback());
+ EXPECT_FALSE("128.0.0.0"_ip4.isLoopback());
+ EXPECT_FALSE("224.0.0.0"_ip4.isLoopback());
+ EXPECT_FALSE("227.30.10.50"_ip4.isLoopback());
+ EXPECT_FALSE("239.255.255.255"_ip4.isLoopback());
+ EXPECT_FALSE("255.255.255.255"_ip4.isLoopback());
+}
+
+TEST(Loopback, In6Addr)
+{
+ constexpr bool t = "::1"_ip6.isLoopback();
+ EXPECT_TRUE(t);
+
+ EXPECT_FALSE("::2"_ip6.isLoopback());
+ EXPECT_FALSE("1::"_ip6.isLoopback());
+ EXPECT_FALSE("2001:5938::fd98"_ip6.isLoopback());
+ EXPECT_FALSE("fe80::1"_ip6.isLoopback());
+ EXPECT_FALSE("feff:ffff:ffff:ffff::"_ip6.isLoopback());
+}
+
+TEST(Unicast, In4Addr)
+{
+ constexpr bool t = "1.1.1.1"_ip4.isUnicast();
+ EXPECT_TRUE(t);
+ EXPECT_TRUE("8.8.4.4"_ip4.isUnicast());
+ EXPECT_TRUE("10.30.0.1"_ip4.isUnicast());
+ EXPECT_TRUE("127.0.0.0"_ip4.isUnicast());
+ EXPECT_TRUE("127.0.0.1"_ip4.isUnicast());
+ EXPECT_TRUE("127.0.0.83"_ip4.isUnicast());
+ EXPECT_TRUE("127.253.0.0"_ip4.isUnicast());
+ EXPECT_TRUE("127.255.255.255"_ip4.isUnicast());
+ EXPECT_TRUE("169.253.255.255"_ip4.isUnicast());
+ EXPECT_TRUE("169.254.0.1"_ip4.isUnicast());
+ EXPECT_TRUE("169.254.255.255"_ip4.isUnicast());
+ EXPECT_TRUE("169.255.0.0"_ip4.isUnicast());
+ EXPECT_TRUE("192.168.1.0"_ip4.isUnicast());
+ EXPECT_TRUE("240.0.0.0"_ip4.isUnicast());
+ EXPECT_TRUE("255.255.255.1"_ip4.isUnicast());
+
+ EXPECT_FALSE("0.0.0.0"_ip4.isUnicast());
+ EXPECT_FALSE("0.255.255.255"_ip4.isUnicast());
+ EXPECT_FALSE("224.0.0.0"_ip4.isUnicast());
+ EXPECT_FALSE("227.30.10.50"_ip4.isUnicast());
+ EXPECT_FALSE("239.255.255.255"_ip4.isUnicast());
+ EXPECT_FALSE("255.255.255.255"_ip4.isUnicast());
+}
+
+TEST(Unicast, In6Addr)
+{
+ constexpr bool t = "::2"_ip6.isUnicast();
+ EXPECT_TRUE(t);
+ EXPECT_TRUE("::1"_ip6.isUnicast());
+ EXPECT_TRUE("1::"_ip6.isUnicast());
+ EXPECT_TRUE("2001:5938::fd98"_ip6.isUnicast());
+ EXPECT_TRUE("fe80::1"_ip6.isUnicast());
+ EXPECT_TRUE("feff:ffff:ffff:ffff::"_ip6.isUnicast());
+
+ EXPECT_FALSE("::"_ip6.isUnicast());
+ EXPECT_FALSE("ff00::"_ip6.isUnicast());
+ EXPECT_FALSE("ffff:ffff:ffff:ffff:ffff::"_ip6.isUnicast());
+}
+
} // namespace stdplus