net: use the correct netlink message payload to request an address dump

RTM_GETADDR wants an ifaddrmsg structure as payload, not ifinfomsg

Change-Id: I441d07f873668fac296085547458ef6ea077945b
diff --git a/ndn-cxx/net/impl/netlink-socket.cpp b/ndn-cxx/net/impl/netlink-socket.cpp
index 1e795e0..20b777e 100644
--- a/ndn-cxx/net/impl/netlink-socket.cpp
+++ b/ndn-cxx/net/impl/netlink-socket.cpp
@@ -35,9 +35,6 @@
 #ifndef NETLINK_CAP_ACK
 #define NETLINK_CAP_ACK 10
 #endif
-#ifndef RTEXT_FILTER_SKIP_STATS
-#define RTEXT_FILTER_SKIP_STATS (1 << 3)
-#endif
 
 NDN_LOG_INIT(ndn.NetworkMonitor);
 
@@ -353,35 +350,34 @@
 }
 
 void
-RtnlSocket::sendDumpRequest(uint16_t nlmsgType, MessageCallback cb)
+RtnlSocket::sendDumpRequest(uint16_t nlmsgType, const void* payload, size_t payloadLen,
+                            MessageCallback cb)
 {
-  struct RtnlRequest
+  struct RtnlMessageHeader
   {
-    nlmsghdr nlh;
-    alignas(NLMSG_ALIGNTO) ifinfomsg ifi;
-    alignas(NLMSG_ALIGNTO) rtattr rta;
-    alignas(NLMSG_ALIGNTO) uint32_t rtext; // space for IFLA_EXT_MASK
+    alignas(NLMSG_ALIGNTO) nlmsghdr nlh;
   };
+  static_assert(sizeof(RtnlMessageHeader) == NLMSG_HDRLEN, "");
 
-  auto request = make_shared<RtnlRequest>();
-  request->nlh.nlmsg_type = nlmsgType;
-  request->nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
-  request->nlh.nlmsg_seq = ++m_seqNum;
-  request->nlh.nlmsg_pid = m_pid;
-  request->ifi.ifi_family = AF_UNSPEC;
-  request->rta.rta_type = IFLA_EXT_MASK;
-  request->rta.rta_len = RTA_LENGTH(sizeof(request->rtext));
-  request->rtext = RTEXT_FILTER_SKIP_STATS;
-  request->nlh.nlmsg_len = NLMSG_SPACE(sizeof(ifinfomsg)) + request->rta.rta_len;
+  auto hdr = make_shared<RtnlMessageHeader>();
+  hdr->nlh.nlmsg_len = sizeof(RtnlMessageHeader) + payloadLen;
+  hdr->nlh.nlmsg_type = nlmsgType;
+  hdr->nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+  hdr->nlh.nlmsg_seq = ++m_seqNum;
+  hdr->nlh.nlmsg_pid = m_pid;
 
-  registerRequestCallback(request->nlh.nlmsg_seq, std::move(cb));
+  registerRequestCallback(hdr->nlh.nlmsg_seq, std::move(cb));
 
-  m_sock->async_send(boost::asio::buffer(request.get(), request->nlh.nlmsg_len),
-    // capture 'request' to prevent its premature deallocation
-    [this, request] (const boost::system::error_code& ec, size_t) {
+  std::array<boost::asio::const_buffer, 2> bufs = {
+    boost::asio::buffer(hdr.get(), sizeof(RtnlMessageHeader)),
+    boost::asio::buffer(payload, payloadLen)
+  };
+  m_sock->async_send(bufs,
+    // capture 'hdr' to prevent its premature deallocation
+    [this, hdr] (const boost::system::error_code& ec, size_t) {
       if (!ec) {
-        NDN_LOG_TRACE("sent dump request type=" << nlmsgTypeToString(request->nlh.nlmsg_type)
-                      << " seq=" << request->nlh.nlmsg_seq);
+        NDN_LOG_TRACE("sent dump request type=" << nlmsgTypeToString(hdr->nlh.nlmsg_type)
+                      << " seq=" << hdr->nlh.nlmsg_seq);
       }
       else if (ec != boost::asio::error::operation_aborted) {
         NDN_LOG_ERROR("send failed: " << ec.message());
@@ -464,15 +460,15 @@
 GenlSocket::sendRequest(uint16_t familyId, uint8_t command,
                         const void* payload, size_t payloadLen, MessageCallback cb)
 {
-  struct GenlRequestHeader
+  struct GenlMessageHeader
   {
     alignas(NLMSG_ALIGNTO) nlmsghdr nlh;
     alignas(NLMSG_ALIGNTO) genlmsghdr genlh;
   };
-  static_assert(sizeof(GenlRequestHeader) == NLMSG_SPACE(GENL_HDRLEN), "");
+  static_assert(sizeof(GenlMessageHeader) == NLMSG_SPACE(GENL_HDRLEN), "");
 
-  auto hdr = make_shared<GenlRequestHeader>();
-  hdr->nlh.nlmsg_len = sizeof(GenlRequestHeader) + payloadLen;
+  auto hdr = make_shared<GenlMessageHeader>();
+  hdr->nlh.nlmsg_len = sizeof(GenlMessageHeader) + payloadLen;
   hdr->nlh.nlmsg_type = familyId;
   hdr->nlh.nlmsg_flags = NLM_F_REQUEST;
   hdr->nlh.nlmsg_seq = ++m_seqNum;
@@ -483,7 +479,7 @@
   registerRequestCallback(hdr->nlh.nlmsg_seq, std::move(cb));
 
   std::array<boost::asio::const_buffer, 2> bufs = {
-    boost::asio::buffer(hdr.get(), sizeof(GenlRequestHeader)),
+    boost::asio::buffer(hdr.get(), sizeof(GenlMessageHeader)),
     boost::asio::buffer(payload, payloadLen)
   };
   m_sock->async_send(bufs,
@@ -518,8 +514,8 @@
 {
   struct FamilyNameAttribute
   {
-    alignas(NLMSG_ALIGNTO) nlattr nla;
-    alignas(NLMSG_ALIGNTO) char name[GENL_NAMSIZ];
+    alignas(NLA_ALIGNTO) nlattr nla;
+    alignas(NLA_ALIGNTO) char name[GENL_NAMSIZ];
   };
 
   auto attr = make_shared<FamilyNameAttribute>();
diff --git a/ndn-cxx/net/impl/netlink-socket.hpp b/ndn-cxx/net/impl/netlink-socket.hpp
index d9a9635..46ff6bc 100644
--- a/ndn-cxx/net/impl/netlink-socket.hpp
+++ b/ndn-cxx/net/impl/netlink-socket.hpp
@@ -94,7 +94,9 @@
   open();
 
   void
-  sendDumpRequest(uint16_t nlmsgType, MessageCallback cb);
+  sendDumpRequest(uint16_t nlmsgType,
+                  const void* payload, size_t payloadLen,
+                  MessageCallback cb);
 
 protected:
   std::string
diff --git a/ndn-cxx/net/impl/network-monitor-impl-netlink.cpp b/ndn-cxx/net/impl/network-monitor-impl-netlink.cpp
index 4190717..39e6505 100644
--- a/ndn-cxx/net/impl/network-monitor-impl-netlink.cpp
+++ b/ndn-cxx/net/impl/network-monitor-impl-netlink.cpp
@@ -35,6 +35,10 @@
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm_ext/push_back.hpp>
 
+#ifndef RTEXT_FILTER_SKIP_STATS
+#define RTEXT_FILTER_SKIP_STATS (1 << 3)
+#endif
+
 NDN_LOG_INIT(ndn.NetworkMonitor);
 
 namespace ndn {
@@ -53,10 +57,7 @@
   }
   m_rtnlSocket.registerNotificationCallback([this] (const auto& msg) { this->parseRtnlMessage(msg); });
 
-  m_phase = ENUMERATING_LINKS;
-  NDN_LOG_TRACE("enumerating links");
-  m_rtnlSocket.sendDumpRequest(RTM_GETLINK,
-                               [this] (const auto& msg) { this->parseRtnlMessage(msg); });
+  enumerateLinks();
 }
 
 shared_ptr<const NetworkInterface>
@@ -79,6 +80,61 @@
 }
 
 void
+NetworkMonitorImplNetlink::enumerateLinks()
+{
+  NDN_LOG_TRACE("enumerating links");
+  m_phase = ENUMERATING_LINKS;
+
+  struct IfInfoMessage
+  {
+    alignas(NLMSG_ALIGNTO) ifinfomsg ifi;
+    alignas(RTA_ALIGNTO) rtattr rta;
+    alignas(RTA_ALIGNTO) uint32_t rtext; // space for IFLA_EXT_MASK
+  };
+
+  auto payload = make_shared<IfInfoMessage>();
+  payload->ifi.ifi_family = AF_UNSPEC;
+  payload->rta.rta_type = IFLA_EXT_MASK;
+  payload->rta.rta_len = RTA_LENGTH(sizeof(payload->rtext));
+  payload->rtext = RTEXT_FILTER_SKIP_STATS;
+
+  m_rtnlSocket.sendDumpRequest(RTM_GETLINK, payload.get(), sizeof(IfInfoMessage),
+                               // capture 'payload' to prevent its premature deallocation
+                               [this, payload] (const auto& msg) { this->parseRtnlMessage(msg); });
+}
+
+void
+NetworkMonitorImplNetlink::enumerateAddrs()
+{
+  NDN_LOG_TRACE("enumerating addresses");
+  m_phase = ENUMERATING_ADDRS;
+
+  struct IfAddrMessage
+  {
+    alignas(NLMSG_ALIGNTO) ifaddrmsg ifa;
+  };
+
+  auto payload = make_shared<IfAddrMessage>();
+  payload->ifa.ifa_family = AF_UNSPEC;
+
+  m_rtnlSocket.sendDumpRequest(RTM_GETADDR, payload.get(), sizeof(IfAddrMessage),
+                               // capture 'payload' to prevent its premature deallocation
+                               [this, payload] (const auto& msg) { this->parseRtnlMessage(msg); });
+}
+
+void
+NetworkMonitorImplNetlink::enumerateRoutes()
+{
+  // TODO: enumerate routes
+  //NDN_LOG_TRACE("enumerating routes");
+  //m_phase = ENUMERATING_ROUTES;
+
+  NDN_LOG_DEBUG("enumeration complete");
+  m_phase = ENUMERATION_COMPLETE;
+  this->emitSignal(onEnumerationCompleted);
+}
+
+void
 NetworkMonitorImplNetlink::parseRtnlMessage(const NetlinkMessage& nlmsg)
 {
   switch (nlmsg->nlmsg_type) {
@@ -348,16 +404,11 @@
   switch (m_phase) {
   case ENUMERATING_LINKS:
     // links enumeration complete, now request all the addresses
-    m_phase = ENUMERATING_ADDRS;
-    NDN_LOG_TRACE("enumerating addresses");
-    m_rtnlSocket.sendDumpRequest(RTM_GETADDR,
-                                 [this] (const auto& msg) { this->parseRtnlMessage(msg); });
+    enumerateAddrs();
     break;
   case ENUMERATING_ADDRS:
-    // links and addresses enumeration complete
-    m_phase = ENUMERATION_COMPLETE; // TODO: enumerate routes
-    NDN_LOG_DEBUG("enumeration complete");
-    this->emitSignal(onEnumerationCompleted);
+    // links and addresses enumeration complete, now request all the routes
+    enumerateRoutes();
     break;
   default:
     break;
diff --git a/ndn-cxx/net/impl/network-monitor-impl-netlink.hpp b/ndn-cxx/net/impl/network-monitor-impl-netlink.hpp
index c7388a4..4bcc755 100644
--- a/ndn-cxx/net/impl/network-monitor-impl-netlink.hpp
+++ b/ndn-cxx/net/impl/network-monitor-impl-netlink.hpp
@@ -64,6 +64,15 @@
 
 private:
   void
+  enumerateLinks();
+
+  void
+  enumerateAddrs();
+
+  void
+  enumerateRoutes();
+
+  void
   parseRtnlMessage(const NetlinkMessage& nlmsg);
 
   void