rtnetlink: Add public interface parser

This will be used by the rtnetlink server to parse new links.

Change-Id: Ibc0abc12ca58b78ffc22ac6f75822853d4b7bdc8
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/system_queries.cpp b/src/system_queries.cpp
index 19c37ba..894fc09 100644
--- a/src/system_queries.cpp
+++ b/src/system_queries.cpp
@@ -125,87 +125,6 @@
     getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
 }
 
-static void parseVlanInfo(InterfaceInfo& info, std::string_view msg)
-{
-    if (msg.data() == nullptr)
-    {
-        throw std::runtime_error("Missing VLAN data");
-    }
-    while (!msg.empty())
-    {
-        auto [hdr, data] = netlink::extractRtAttr(msg);
-        switch (hdr.rta_type)
-        {
-            case IFLA_VLAN_ID:
-                info.vlan_id.emplace(stdplus::raw::copyFrom<uint16_t>(data));
-                break;
-        }
-    }
-}
-
-static void parseLinkInfo(InterfaceInfo& info, std::string_view msg)
-{
-    std::string_view submsg;
-    while (!msg.empty())
-    {
-        auto [hdr, data] = netlink::extractRtAttr(msg);
-        switch (hdr.rta_type)
-        {
-            case IFLA_INFO_KIND:
-                data.remove_suffix(1);
-                info.kind.emplace(data);
-                break;
-            case IFLA_INFO_DATA:
-                submsg = data;
-                break;
-        }
-    }
-    if (info.kind == "vlan"sv)
-    {
-        parseVlanInfo(info, submsg);
-    }
-}
-
-InterfaceInfo detail::parseInterface(const nlmsghdr& hdr, std::string_view msg)
-{
-    if (hdr.nlmsg_type != RTM_NEWLINK)
-    {
-        throw std::runtime_error("Not an interface msg");
-    }
-    const auto& ifinfo = netlink::extractRtData<ifinfomsg>(msg);
-    InterfaceInfo ret;
-    ret.flags = ifinfo.ifi_flags;
-    ret.idx = ifinfo.ifi_index;
-    while (!msg.empty())
-    {
-        auto [hdr, data] = netlink::extractRtAttr(msg);
-        switch (hdr.rta_type)
-        {
-            case IFLA_IFNAME:
-                ret.name.emplace(data.begin(), data.end() - 1);
-                break;
-            case IFLA_ADDRESS:
-                if (data.size() != sizeof(ether_addr))
-                {
-                    // Some interfaces have IP addresses for their LLADDR
-                    break;
-                }
-                ret.mac.emplace(stdplus::raw::copyFrom<ether_addr>(data));
-                break;
-            case IFLA_MTU:
-                ret.mtu.emplace(stdplus::raw::copyFrom<unsigned>(data));
-                break;
-            case IFLA_LINK:
-                ret.parent_idx.emplace(stdplus::raw::copyFrom<unsigned>(data));
-                break;
-            case IFLA_LINKINFO:
-                parseLinkInfo(ret, data);
-                break;
-        }
-    }
-    return ret;
-}
-
 bool detail::validateNewAddr(const AddressInfo& info,
                              const AddressFilter& filter) noexcept
 {
@@ -229,10 +148,10 @@
 std::vector<InterfaceInfo> getInterfaces()
 {
     std::vector<InterfaceInfo> ret;
-    auto cb = [&](const nlmsghdr& hdr, std::string_view msg) {
+    auto cb = [&](const nlmsghdr&, std::string_view msg) {
         try
         {
-            ret.emplace_back(detail::parseInterface(hdr, msg));
+            ret.emplace_back(netlink::intfFromRtm(msg));
         }
         catch (const std::exception& e)
         {