rtnetlink: Migrate IP functions

Change-Id: I4c87b59306911df4c5a73e441b2b962fbaab072c
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index c2e3e63..a0c6193 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -176,19 +176,14 @@
 void EthernetInterface::createIPAddressObjects()
 {
     addrs.clear();
-
-    AddressFilter filter;
-    filter.interface = ifIdx;
-    auto currentAddrs = getCurrentAddresses(filter);
-    for (const auto& addr : currentAddrs)
+    for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
     {
         if (addr.flags & IFA_F_DEPRECATED)
         {
             continue;
         }
-        auto ifaddr = IfAddr(addr.address, addr.prefix);
         IP::AddressOrigin origin = IP::AddressOrigin::Static;
-        if (dhcpIsEnabled(addr.address))
+        if (dhcpIsEnabled(addr.ifaddr.getAddr()))
         {
             origin = IP::AddressOrigin::DHCP;
         }
@@ -200,8 +195,9 @@
 #endif
 
         this->addrs.insert_or_assign(
-            ifaddr, std::make_unique<IPAddress>(bus, std::string_view(objPath),
-                                                *this, ifaddr, origin));
+            addr.ifaddr,
+            std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
+                                        addr.ifaddr, origin));
     }
 }
 
diff --git a/src/ipaddress.cpp b/src/ipaddress.cpp
index 647c37e..560129d 100644
--- a/src/ipaddress.cpp
+++ b/src/ipaddress.cpp
@@ -1,20 +1,14 @@
 #include "ipaddress.hpp"
 
 #include "ethernet_interface.hpp"
-#include "netlink.hpp"
 #include "network_manager.hpp"
 #include "util.hpp"
 
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
 #include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/log.hpp>
 #include <stdexcept>
-#include <stdplus/raw.hpp>
 #include <string>
 #include <string_view>
-#include <vector>
 #include <xyz/openbmc_project/Common/error.hpp>
 
 namespace phosphor
@@ -22,18 +16,6 @@
 namespace network
 {
 
-std::vector<AddressInfo> getCurrentAddresses(const AddressFilter& filter)
-{
-    std::vector<AddressInfo> addresses;
-    auto cb = [&filter, &addresses](const nlmsghdr& hdr, std::string_view msg) {
-        detail::parseAddress(filter, hdr, msg, addresses);
-    };
-    ifaddrmsg msg{};
-    msg.ifa_index = filter.interface;
-    netlink::performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, msg, cb);
-    return addresses;
-}
-
 using namespace phosphor::logging;
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
@@ -132,56 +114,5 @@
     parent.manager.reloadConfigs();
 }
 
-namespace detail
-{
-
-void parseAddress(const AddressFilter& filter, const nlmsghdr& hdr,
-                  std::string_view msg, std::vector<AddressInfo>& addresses)
-{
-    if (hdr.nlmsg_type != RTM_NEWADDR)
-    {
-        throw std::runtime_error("Not an address msg");
-    }
-    const auto& ifaddr = netlink::extractRtData<ifaddrmsg>(msg);
-
-    // Filter out addresses we don't care about
-    unsigned ifindex = ifaddr.ifa_index;
-    if (filter.interface != 0 && filter.interface != ifindex)
-    {
-        return;
-    }
-    if (filter.scope && *filter.scope != ifaddr.ifa_scope)
-    {
-        return;
-    }
-
-    // Build the info about the address we found
-    AddressInfo address;
-    address.interface = ifindex;
-    address.prefix = ifaddr.ifa_prefixlen;
-    address.flags = ifaddr.ifa_flags;
-    address.scope = ifaddr.ifa_scope;
-    bool set_addr = false;
-    while (!msg.empty())
-    {
-        auto [hdr, data] = netlink::extractRtAttr(msg);
-        if (hdr.rta_type == IFA_ADDRESS)
-        {
-            address.address = addrFromBuf(ifaddr.ifa_family, data);
-            set_addr = true;
-        }
-        else if (hdr.rta_type == IFA_FLAGS)
-        {
-            address.flags = stdplus::raw::extract<uint32_t>(data);
-        }
-    }
-    if (!set_addr)
-    {
-        throw std::runtime_error("Missing address");
-    }
-    addresses.push_back(std::move(address));
-}
-
-} // namespace detail
 } // namespace network
 } // namespace phosphor
diff --git a/src/ipaddress.hpp b/src/ipaddress.hpp
index 94bdfdb..05aafbd 100644
--- a/src/ipaddress.hpp
+++ b/src/ipaddress.hpp
@@ -1,16 +1,10 @@
 #pragma once
 #include "types.hpp"
 
-#include <linux/netlink.h>
-
-#include <cstdint>
-#include <optional>
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/message/native_types.hpp>
 #include <sdbusplus/server/object.hpp>
-#include <string>
 #include <string_view>
-#include <vector>
 #include <xyz/openbmc_project/Network/IP/server.hpp>
 #include <xyz/openbmc_project/Object/Delete/server.hpp>
 
@@ -27,30 +21,6 @@
 
 class EthernetInterface;
 
-/* @class AddressFilter
- */
-struct AddressFilter
-{
-    unsigned interface = 0;
-    std::optional<uint8_t> scope;
-};
-
-/** @class AddressInfo
- *  @brief Information about a addresses from the kernel
- */
-struct AddressInfo
-{
-    unsigned interface;
-    InAddrAny address;
-    uint8_t prefix;
-    uint8_t scope;
-    uint32_t flags;
-};
-
-/** @brief Returns a list of the current system neighbor table
- */
-std::vector<AddressInfo> getCurrentAddresses(const AddressFilter& filter);
-
 /** @class IPAddress
  *  @brief OpenBMC IPAddress implementation.
  *  @details A concrete implementation for the
@@ -109,12 +79,5 @@
               EthernetInterface& parent, IfAddr addr, IP::AddressOrigin origin);
 };
 
-namespace detail
-{
-
-void parseAddress(const AddressFilter& filter, const nlmsghdr& hdr,
-                  std::string_view msg, std::vector<AddressInfo>& addresses);
-
-} // namespace detail
 } // namespace network
 } // namespace phosphor
diff --git a/src/rtnetlink.cpp b/src/rtnetlink.cpp
index 6e0946f..5d6e660 100644
--- a/src/rtnetlink.cpp
+++ b/src/rtnetlink.cpp
@@ -1,6 +1,7 @@
 #include "rtnetlink.hpp"
 
 #include "netlink.hpp"
+#include "util.hpp"
 
 #include <linux/rtnetlink.h>
 
@@ -19,10 +20,10 @@
         switch (hdr.rta_type)
         {
             case RTA_OIF:
-                ifIdx.emplace(stdplus::raw::copyFrom<int>(data));
+                ifIdx.emplace(stdplus::raw::copyFromStrict<int>(data));
                 break;
             case RTA_GATEWAY:
-                gw.emplace(stdplus::raw::copyFrom<Addr>(data));
+                gw.emplace(stdplus::raw::copyFromStrict<Addr>(data));
                 break;
         }
     }
@@ -51,4 +52,33 @@
     return std::nullopt;
 }
 
+AddressInfo addrFromRtm(std::string_view msg)
+{
+    const auto& ifa = extractRtData<ifaddrmsg>(msg);
+
+    AddressInfo ret;
+    ret.ifidx = ifa.ifa_index;
+    ret.flags = ifa.ifa_flags;
+    ret.scope = ifa.ifa_scope;
+    std::optional<InAddrAny> addr;
+    while (!msg.empty())
+    {
+        auto [hdr, data] = extractRtAttr(msg);
+        if (hdr.rta_type == IFA_ADDRESS)
+        {
+            addr.emplace(addrFromBuf(ifa.ifa_family, data));
+        }
+        else if (hdr.rta_type == IFA_FLAGS)
+        {
+            ret.flags = stdplus::raw::copyFromStrict<uint32_t>(data);
+        }
+    }
+    if (!addr)
+    {
+        throw std::runtime_error("Missing address");
+    }
+    ret.ifaddr = {*addr, ifa.ifa_prefixlen};
+    return ret;
+}
+
 } // namespace phosphor::network::netlink
diff --git a/src/rtnetlink.hpp b/src/rtnetlink.hpp
index 41df902..48f3820 100644
--- a/src/rtnetlink.hpp
+++ b/src/rtnetlink.hpp
@@ -7,6 +7,10 @@
 
 namespace phosphor::network::netlink
 {
+
 std::optional<std::tuple<unsigned, InAddrAny>>
     gatewayFromRtm(std::string_view msg);
-}
+
+AddressInfo addrFromRtm(std::string_view msg);
+
+} // namespace phosphor::network::netlink
diff --git a/src/system_queries.cpp b/src/system_queries.cpp
index f0222ec..5aba1d2 100644
--- a/src/system_queries.cpp
+++ b/src/system_queries.cpp
@@ -1,6 +1,7 @@
 #include "system_queries.hpp"
 
 #include "netlink.hpp"
+#include "rtnetlink.hpp"
 #include "util.hpp"
 
 #include <fmt/format.h>
@@ -224,6 +225,16 @@
     return true;
 }
 
+bool detail::validateNewAddr(const AddressInfo& info,
+                             const AddressFilter& filter) noexcept
+{
+    if (filter.ifidx != 0 && filter.ifidx != info.ifidx)
+    {
+        return false;
+    }
+    return true;
+}
+
 std::vector<InterfaceInfo> getInterfaces()
 {
     std::vector<InterfaceInfo> ret;
@@ -239,4 +250,20 @@
     return ret;
 }
 
+std::vector<AddressInfo> getAddresses(const AddressFilter& filter)
+{
+    std::vector<AddressInfo> ret;
+    auto cb = [&](const nlmsghdr&, std::string_view msg) {
+        auto info = netlink::addrFromRtm(msg);
+        if (detail::validateNewAddr(info, filter))
+        {
+            ret.emplace_back(std::move(info));
+        }
+    };
+    ifaddrmsg msg{};
+    msg.ifa_index = filter.ifidx;
+    netlink::performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, msg, cb);
+    return ret;
+}
+
 } // namespace phosphor::network::system
diff --git a/src/system_queries.hpp b/src/system_queries.hpp
index 32d54cf..97a5faa 100644
--- a/src/system_queries.hpp
+++ b/src/system_queries.hpp
@@ -53,10 +53,17 @@
     }
 };
 
+struct AddressFilter
+{
+    unsigned ifidx = 0;
+};
+
 namespace detail
 {
 InterfaceInfo parseInterface(const nlmsghdr& hdr, std::string_view msg);
 bool validateNewInterface(const InterfaceInfo& info);
+bool validateNewAddr(const AddressInfo& info,
+                     const AddressFilter& filter) noexcept;
 } // namespace detail
 
 /** @brief Get all the interfaces from the system.
@@ -64,4 +71,9 @@
  */
 std::vector<InterfaceInfo> getInterfaces();
 
+/** @brief Get all the addreses from the system.
+ *  @returns list of addresses
+ */
+std::vector<AddressInfo> getAddresses(const AddressFilter& filter);
+
 } // namespace phosphor::network::system
diff --git a/src/types.hpp b/src/types.hpp
index 4515211..8755068 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -75,6 +75,17 @@
 
 using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
 
+/** @class AddressInfo
+ *  @brief Information about a addresses from the kernel
+ */
+struct AddressInfo
+{
+    unsigned ifidx;
+    IfAddr ifaddr;
+    uint8_t scope;
+    uint32_t flags;
+};
+
 struct string_hash : public std::hash<std::string_view>
 {
     using is_transparent = void;