rtnetlink: Migrate neighbor functions

Change-Id: I697f3d70f327f5d1d5e104dc7e4a2af528bf2b6e
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/test_rtnetlink.cpp b/test/test_rtnetlink.cpp
index 9518cdc..8bf2a1e 100644
--- a/test/test_rtnetlink.cpp
+++ b/test/test_rtnetlink.cpp
@@ -63,4 +63,54 @@
     EXPECT_EQ(0xff00ff00, ret.flags);
 }
 
+TEST(NeighFromRtm, MissingAddr)
+{
+    struct
+    {
+        alignas(NLMSG_ALIGNTO) ndmsg ndm = {};
+    } msg;
+    EXPECT_THROW(neighFromRtm(stdplus::raw::asView<char>(msg)),
+                 std::runtime_error);
+}
+
+TEST(NeighFromRtm, NoMac)
+{
+    struct
+    {
+        alignas(NLMSG_ALIGNTO) ndmsg ndm;
+        alignas(NLMSG_ALIGNTO) rtattr addr_hdr;
+        alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20};
+    } msg;
+    msg.ndm.ndm_family = AF_INET;
+    msg.ndm.ndm_state = 4;
+    msg.addr_hdr.rta_type = NDA_DST;
+    msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
+
+    auto ret = neighFromRtm(stdplus::raw::asView<char>(msg));
+    EXPECT_EQ(msg.ndm.ndm_state, ret.state);
+    EXPECT_EQ((in_addr{hton(0xc0a80114)}), ret.addr);
+    EXPECT_FALSE(ret.mac);
+}
+
+TEST(NeighFromRtm, Full)
+{
+    struct
+    {
+        alignas(NLMSG_ALIGNTO) ndmsg ndm;
+        alignas(NLMSG_ALIGNTO) rtattr addr_hdr;
+        alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20};
+        alignas(NLMSG_ALIGNTO) rtattr mac_hdr;
+        alignas(NLMSG_ALIGNTO) uint8_t mac[6] = {1, 2, 3, 4, 5, 6};
+    } msg;
+    msg.ndm.ndm_family = AF_INET;
+    msg.addr_hdr.rta_type = NDA_DST;
+    msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr));
+    msg.mac_hdr.rta_type = NDA_LLADDR;
+    msg.mac_hdr.rta_len = RTA_LENGTH(sizeof(msg.mac));
+
+    auto ret = neighFromRtm(stdplus::raw::asView<char>(msg));
+    EXPECT_EQ((in_addr{hton(0xc0a80114)}), ret.addr);
+    EXPECT_EQ((ether_addr{1, 2, 3, 4, 5, 6}), ret.mac);
+}
+
 } // namespace phosphor::network::netlink