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