rtnetlink: Separate out gateway parsing

This same logic will get re-used by other code in a future change.

Change-Id: I28218b9defb64c15f24df989f46db255e6ce4045
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/routing_table.cpp b/src/routing_table.cpp
index bed1f70..d6285a7 100644
--- a/src/routing_table.cpp
+++ b/src/routing_table.cpp
@@ -1,6 +1,7 @@
 #include "routing_table.hpp"
 
 #include "netlink.hpp"
+#include "rtnetlink.hpp"
 
 #include <optional>
 #include <phosphor-logging/elog-errors.hpp>
@@ -20,30 +21,6 @@
 using namespace phosphor::logging;
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
-template <typename Addr>
-static void parse(auto& gws, std::string_view msg)
-{
-    std::optional<unsigned> ifIdx;
-    std::optional<Addr> gw;
-    while (!msg.empty())
-    {
-        auto [hdr, data] = netlink::extractRtAttr(msg);
-        switch (hdr.rta_type)
-        {
-            case RTA_OIF:
-                ifIdx.emplace(stdplus::raw::copyFrom<int>(data));
-                break;
-            case RTA_GATEWAY:
-                gw.emplace(stdplus::raw::copyFrom<Addr>(data));
-                break;
-        }
-    }
-    if (ifIdx && gw)
-    {
-        gws.emplace(*ifIdx, *gw);
-    }
-}
-
 static void parseRoute(auto& gws4, auto& gws6, const nlmsghdr& hdr,
                        std::string_view msg)
 {
@@ -51,19 +28,25 @@
     {
         throw std::runtime_error("Not a route msg");
     }
-    const auto& rtm = netlink::extractRtData<rtmsg>(msg);
 
-    if (rtm.rtm_table != RT_TABLE_MAIN || rtm.rtm_dst_len != 0)
+    if (auto ret = netlink::gatewayFromRtm(msg); ret)
     {
-        return;
-    }
-
-    switch (rtm.rtm_family)
-    {
-        case AF_INET:
-            return parse<in_addr>(gws4, msg);
-        case AF_INET6:
-            return parse<in6_addr>(gws6, msg);
+        std::visit(
+            [&](auto addr) {
+                if constexpr (std::is_same_v<in_addr, decltype(addr)>)
+                {
+                    gws4.emplace(std::get<unsigned>(*ret), addr);
+                }
+                else if constexpr (std::is_same_v<in6_addr, decltype(addr)>)
+                {
+                    gws6.emplace(std::get<unsigned>(*ret), addr);
+                }
+                else
+                {
+                    static_assert(!std::is_same_v<void, decltype(addr)>);
+                }
+            },
+            std::get<InAddrAny>(*ret));
     }
 }