From a00b1c3f74d329c1ca65826e430efa9105a72465 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Fri, 1 Feb 2019 18:57:17 -0800 Subject: util: Add InAddrAny population function We commonly want to be able to turn netlink network order address data into the corresponding InAddrAny when parsing netlink data. This makes it trivial given the address family and data buffer. Tested: Ran throgh unit tests and builds fine in a BMC image. Change-Id: I4ebe1dbd284f150ea03ee091cddda5a06806c01f Signed-off-by: William A. Kennington III --- test/test_util.cpp | 24 ++++++++++++++++++++++++ util.cpp | 26 ++++++++++++++++++++++++++ util.hpp | 8 ++++++++ 3 files changed, 58 insertions(+) diff --git a/test/test_util.cpp b/test/test_util.cpp index 25953a1..0e58081 100644 --- a/test/test_util.cpp +++ b/test/test_util.cpp @@ -45,6 +45,30 @@ TEST_F(TestUtil, MacToString) EXPECT_EQ("70:FF:84:09:35:09", mac_address::toString(mac2)); } +TEST_F(TestUtil, AddrFromBuf) +{ + std::string tooSmall(1, 'a'); + std::string tooLarge(24, 'a'); + + struct in_addr ip1; + EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); + std::string_view buf1(reinterpret_cast(&ip1), sizeof(ip1)); + InAddrAny res1 = addrFromBuf(AF_INET, buf1); + EXPECT_EQ(0, memcmp(&ip1, &std::get(res1), sizeof(ip1))); + EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error); + EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error); + EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::runtime_error); + + struct in6_addr ip2; + EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); + std::string_view buf2(reinterpret_cast(&ip2), sizeof(ip2)); + InAddrAny res2 = addrFromBuf(AF_INET6, buf2); + EXPECT_EQ(0, memcmp(&ip2, &std::get(res2), sizeof(ip2))); + EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error); + EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error); + EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::runtime_error); +} + TEST_F(TestUtil, IpToString) { struct in_addr ip1; diff --git a/util.cpp b/util.cpp index db164e6..b1300fb 100644 --- a/util.cpp +++ b/util.cpp @@ -204,6 +204,32 @@ std::string getNetworkID(int addressFamily, const std::string& ipaddress, return networkString; } +InAddrAny addrFromBuf(int addressFamily, std::string_view buf) +{ + if (addressFamily == AF_INET) + { + struct in_addr ret; + if (buf.size() != sizeof(ret)) + { + throw std::runtime_error("Buf not in_addr sized"); + } + memcpy(&ret, buf.data(), sizeof(ret)); + return ret; + } + else if (addressFamily == AF_INET6) + { + struct in6_addr ret; + if (buf.size() != sizeof(ret)) + { + throw std::runtime_error("Buf not in6_addr sized"); + } + memcpy(&ret, buf.data(), sizeof(ret)); + return ret; + } + + throw std::runtime_error("Unsupported address family"); +} + std::string toString(const InAddrAny& addr) { std::string ip; diff --git a/util.hpp b/util.hpp index 537c6a0..a07fa49 100644 --- a/util.hpp +++ b/util.hpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace phosphor { @@ -93,6 +94,13 @@ constexpr auto timeSynchdService = "systemd-timesyncd.service"; */ uint8_t toCidr(int addressFamily, const std::string& mask); +/* @brief converts a sockaddr for the specified address family into + * a type_safe InAddrAny. + * @param[in] addressFamily - The address family of the buf + * @param[in] buf - The network byte order address + */ +InAddrAny addrFromBuf(int addressFamily, std::string_view buf); + /* @brief converts the ip bytes into a string representation * @param[in] addr - input ip address to convert. * @returns String representation of the ip. -- cgit v1.2.1