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/meson.build b/src/meson.build
index 79fa0b7..ce1c142 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -52,6 +52,7 @@
'ipaddress.cpp',
'netlink.cpp',
'network_manager.cpp',
+ 'rtnetlink.cpp',
'system_configuration.cpp',
'system_queries.cpp',
'types.cpp',
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));
}
}
diff --git a/src/rtnetlink.cpp b/src/rtnetlink.cpp
new file mode 100644
index 0000000..6e0946f
--- /dev/null
+++ b/src/rtnetlink.cpp
@@ -0,0 +1,54 @@
+#include "rtnetlink.hpp"
+
+#include "netlink.hpp"
+
+#include <linux/rtnetlink.h>
+
+namespace phosphor::network::netlink
+{
+
+template <typename Addr>
+static std::optional<std::tuple<unsigned, InAddrAny>>
+ parse(std::string_view msg)
+{
+ std::optional<unsigned> ifIdx;
+ std::optional<InAddrAny> gw;
+ while (!msg.empty())
+ {
+ auto [hdr, data] = 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)
+ {
+ return std::make_tuple(*ifIdx, *gw);
+ }
+ return std::nullopt;
+}
+
+std::optional<std::tuple<unsigned, InAddrAny>>
+ gatewayFromRtm(std::string_view msg)
+{
+ const auto& rtm = extractRtData<rtmsg>(msg);
+ if (rtm.rtm_table != RT_TABLE_MAIN || rtm.rtm_dst_len != 0)
+ {
+ return std::nullopt;
+ }
+ switch (rtm.rtm_family)
+ {
+ case AF_INET:
+ return parse<in_addr>(msg);
+ case AF_INET6:
+ return parse<in6_addr>(msg);
+ }
+ return std::nullopt;
+}
+
+} // namespace phosphor::network::netlink
diff --git a/src/rtnetlink.hpp b/src/rtnetlink.hpp
new file mode 100644
index 0000000..41df902
--- /dev/null
+++ b/src/rtnetlink.hpp
@@ -0,0 +1,12 @@
+#pragma once
+#include "types.hpp"
+
+#include <optional>
+#include <string_view>
+#include <tuple>
+
+namespace phosphor::network::netlink
+{
+std::optional<std::tuple<unsigned, InAddrAny>>
+ gatewayFromRtm(std::string_view msg);
+}