netlink: Add common function for extracting payload

Change-Id: I809bd17d50ccb8a8f624b6117c088193f55e79de
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ipaddress.cpp b/src/ipaddress.cpp
index 6aebc94..56bec97 100644
--- a/src/ipaddress.cpp
+++ b/src/ipaddress.cpp
@@ -98,7 +98,7 @@
     {
         throw std::runtime_error("Not an address msg");
     }
-    auto ifaddr = stdplus::raw::extract<ifaddrmsg>(msg);
+    const auto& ifaddr = netlink::extractRtData<ifaddrmsg>(msg);
 
     // Filter out addresses we don't care about
     unsigned ifindex = ifaddr.ifa_index;
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index cfa8e60..58e1a47 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -35,7 +35,7 @@
     {
         throw std::runtime_error("Not a neighbor msg");
     }
-    auto ndm = stdplus::raw::extract<ndmsg>(msg);
+    const auto& ndm = netlink::extractRtData<ndmsg>(msg);
 
     // Filter out neighbors we don't care about
     unsigned ifindex = ndm.ndm_ifindex;
diff --git a/src/netlink.hpp b/src/netlink.hpp
index 1260f8e..754b4b4 100644
--- a/src/netlink.hpp
+++ b/src/netlink.hpp
@@ -3,6 +3,7 @@
 #include <linux/rtnetlink.h>
 
 #include <function2/function2.hpp>
+#include <stdplus/raw.hpp>
 #include <string_view>
 #include <tuple>
 #include <type_traits>
@@ -35,6 +36,20 @@
  */
 void receive(int sock, ReceiveCallback cb);
 
+/* @brief Call on an rtnetlink payload
+ *        Updates the input to remove the attr parsed out.
+ *
+ * @param[in,out] data - The buffer holding rtpayload to parse
+ * @return The payload for the rt msg
+ */
+template <typename T>
+constexpr const T& extractRtData(std::string_view& data)
+{
+    const T& ret = stdplus::raw::refFrom<T, stdplus::raw::Aligned>(data);
+    data.remove_prefix(NLMSG_ALIGN(sizeof(T)));
+    return ret;
+}
+
 /* @brief Call on a block of rtattrs to parse a single one out
  *        Updates the input to remove the attr parsed out.
  *
diff --git a/src/routing_table.cpp b/src/routing_table.cpp
index 20535e5..39cdf2d 100644
--- a/src/routing_table.cpp
+++ b/src/routing_table.cpp
@@ -53,7 +53,7 @@
     {
         throw std::runtime_error("Not a route msg");
     }
-    auto rtm = stdplus::raw::extract<rtmsg>(msg);
+    const auto& rtm = netlink::extractRtData<rtmsg>(msg);
 
     if ((rtm.rtm_family != AF_INET && rtm.rtm_family != AF_INET6) ||
         rtm.rtm_table != RT_TABLE_MAIN)
diff --git a/src/system_queries.cpp b/src/system_queries.cpp
index aa8e46b..0152f4a 100644
--- a/src/system_queries.cpp
+++ b/src/system_queries.cpp
@@ -131,7 +131,7 @@
     {
         throw std::runtime_error("Not an interface msg");
     }
-    auto ifinfo = stdplus::raw::extract<ifinfomsg>(msg);
+    const auto& ifinfo = netlink::extractRtData<ifinfomsg>(msg);
     InterfaceInfo ret;
     ret.flags = ifinfo.ifi_flags;
     ret.idx = ifinfo.ifi_index;