31 #include <linux/if_addr.h> 32 #include <linux/if_link.h> 33 #include <net/if_arp.h> 35 #include <boost/range/adaptor/map.hpp> 36 #include <boost/range/algorithm_ext/push_back.hpp> 46 , m_isEnumeratingLinks(false)
47 , m_isEnumeratingAddresses(false)
51 for (
auto group : {RTNLGRP_LINK,
52 RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV4_ROUTE,
53 RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_ROUTE}) {
60 [
this] (
const auto& msg) { this->parseRtnlMessage(msg); });
61 m_isEnumeratingLinks =
true;
64 shared_ptr<const NetworkInterface>
67 for (
const auto& interface : m_interfaces | boost::adaptors::map_values) {
68 if (interface->getName() == ifname)
74 std::vector<shared_ptr<const NetworkInterface>>
77 std::vector<shared_ptr<const NetworkInterface>> v;
78 v.reserve(m_interfaces.size());
79 boost::push_back(v, m_interfaces | boost::adaptors::map_values);
84 NetworkMonitorImplNetlink::isEnumerating()
const 86 return m_isEnumeratingLinks || m_isEnumeratingAddresses;
90 NetworkMonitorImplNetlink::parseRtnlMessage(
const NetlinkMessage& nlmsg)
92 switch (nlmsg->nlmsg_type) {
95 parseLinkMessage(nlmsg);
102 parseAddressMessage(nlmsg);
103 if (!isEnumerating())
109 parseRouteMessage(nlmsg);
110 if (!isEnumerating())
115 if (m_isEnumeratingLinks) {
117 m_isEnumeratingLinks =
false;
120 [
this] (
const auto& msg) { this->parseRtnlMessage(msg); });
121 m_isEnumeratingAddresses =
true;
123 else if (m_isEnumeratingAddresses) {
125 m_isEnumeratingAddresses =
false;
133 parseErrorMessage(nlmsg);
144 case ARPHRD_LOOPBACK:
168 case RT_SCOPE_NOWHERE:
182 if (operState == linux_if::OPER_STATE_UP) {
185 else if (operState == linux_if::OPER_STATE_DORMANT) {
191 if ((flags & linux_if::FLAG_LOWER_UP) && !(flags & linux_if::FLAG_DORMANT))
193 else if (flags & IFF_UP)
201 NetworkMonitorImplNetlink::parseLinkMessage(
const NetlinkMessage& nlmsg)
203 const ifinfomsg* ifi = nlmsg.getPayload<ifinfomsg>();
204 if (ifi ==
nullptr) {
214 shared_ptr<NetworkInterface> interface;
215 auto it = m_interfaces.find(ifi->ifi_index);
216 if (it != m_interfaces.end()) {
217 interface = it->second;
218 BOOST_ASSERT(interface !=
nullptr);
219 BOOST_ASSERT(interface->getIndex() == ifi->ifi_index);
222 if (nlmsg->nlmsg_type == RTM_DELLINK) {
223 if (interface !=
nullptr) {
224 NDN_LOG_DEBUG(
"removing interface " << interface->getName());
225 m_interfaces.erase(it);
231 if (interface ==
nullptr) {
233 interface->setIndex(ifi->ifi_index);
236 interface->setFlags(ifi->ifi_flags);
238 auto attrs = nlmsg.getAttributes<rtattr>(ifi);
239 NDN_LOG_TRACE(
"message contains " << attrs.size() <<
" attributes");
241 auto address = attrs.getAttributeByType<ethernet::Address>(IFLA_ADDRESS);
243 interface->setEthernetAddress(*address);
245 auto broadcast = attrs.getAttributeByType<ethernet::Address>(IFLA_BROADCAST);
247 interface->setEthernetBroadcastAddress(*broadcast);
249 auto name = attrs.getAttributeByType<std::string>(IFLA_IFNAME);
251 interface->setName(*
name);
253 auto mtu = attrs.getAttributeByType<uint32_t>(IFLA_MTU);
255 interface->setMtu(*mtu);
257 auto state = attrs.getAttributeByType<uint8_t>(IFLA_OPERSTATE);
260 if (it == m_interfaces.end()) {
262 m_interfaces[interface->getIndex()] = interface;
268 NetworkMonitorImplNetlink::parseAddressMessage(
const NetlinkMessage& nlmsg)
270 const ifaddrmsg* ifa = nlmsg.getPayload<ifaddrmsg>();
271 if (ifa ==
nullptr) {
276 auto it = m_interfaces.find(ifa->ifa_index);
277 if (it == m_interfaces.end()) {
282 auto interface = it->second;
283 BOOST_ASSERT(interface !=
nullptr);
285 auto attrs = nlmsg.getAttributes<rtattr>(ifa);
286 NDN_LOG_TRACE(
"message contains " << attrs.size() <<
" attributes");
288 namespace ip = boost::asio::ip;
289 ip::address ipAddr, broadcastAddr;
290 if (ifa->ifa_family == AF_INET) {
291 auto v4 = attrs.getAttributeByType<ip::address_v4>(IFA_LOCAL);
295 v4 = attrs.getAttributeByType<ip::address_v4>(IFA_BROADCAST);
299 else if (ifa->ifa_family == AF_INET6) {
300 auto v6 = attrs.getAttributeByType<ip::address_v6>(IFA_ADDRESS);
302 if (v6->is_link_local())
303 v6->scope_id(ifa->ifa_index);
309 uint32_t flags = ifa->ifa_flags;
310 #ifdef NDN_CXX_HAVE_IFA_FLAGS 311 auto extFlags = attrs.getAttributeByType<uint32_t>(IFA_FLAGS);
314 #endif // NDN_CXX_HAVE_IFA_FLAGS 324 if (nlmsg->nlmsg_type == RTM_NEWADDR)
325 interface->addNetworkAddress(address);
326 else if (nlmsg->nlmsg_type == RTM_DELADDR)
327 interface->removeNetworkAddress(address);
331 NetworkMonitorImplNetlink::parseRouteMessage(
const NetlinkMessage& nlmsg)
337 NetworkMonitorImplNetlink::parseErrorMessage(
const NetlinkMessage& nlmsg)
339 const nlmsgerr* err = nlmsg.getPayload<nlmsgerr>();
340 if (err ==
nullptr) {
345 if (err->error == 0) {
353 #ifdef NDN_CXX_HAVE_NETLINK_EXT_ACK 354 if (!(nlmsg->nlmsg_flags & NLM_F_ACK_TLVS))
357 size_t errLen = NLMSG_LENGTH(
sizeof(nlmsgerr));
358 if (!(nlmsg->nlmsg_flags & NLM_F_CAPPED))
359 errLen += err->msg.nlmsg_len - NLMSG_HDRLEN;
361 if (nlmsg->nlmsg_len <= errLen)
364 auto nla = reinterpret_cast<const nlattr*>(reinterpret_cast<const uint8_t*>(&*nlmsg) + errLen);
365 auto attrs = NetlinkMessageAttributes<nlattr>(nla, nlmsg->nlmsg_len - errLen);
366 auto msg = attrs.getAttributeByType<std::string>(NLMSGERR_ATTR_MSG);
367 if (msg && !msg->empty())
369 #endif // NDN_CXX_HAVE_NETLINK_EXT_ACK interface is administratively down
static AddressScope ifaScopeToAddressScope(uint8_t scope)
Copyright (c) 2011-2015 Regents of the University of California.
interface can be used to send and receive packets
interface is administratively up but has no carrier
void setState(InterfaceState state)
static shared_ptr< NetworkInterface > makeNetworkInterface()
static void updateInterfaceState(NetworkInterface &interface, uint8_t operState)
#define NDN_LOG_WARN(expression)
static AddressFamily ifaFamilyToAddressFamily(uint8_t family)
#define NDN_LOG_DEBUG(expression)
#define emitSignal(...)
(implementation detail)
InterfaceType
Indicates the hardware type of a network interface.
constexpr duration< Rep, Period > abs(duration< Rep, Period > d)
static InterfaceType ifiTypeToInterfaceType(uint16_t type)
util::Signal< NetworkMonitorImpl > onEnumerationCompleted
#define NDN_LOG_ERROR(expression)
Represents one network interface attached to the host.
util::Signal< NetworkMonitorImpl, shared_ptr< const NetworkInterface > > onInterfaceRemoved
void sendDumpRequest(uint16_t nlmsgType, MessageCallback cb)
shared_ptr< const NetworkInterface > getNetworkInterface(const std::string &ifname) const final
#define NDN_LOG_TRACE(expression)
util::Signal< NetworkMonitorImpl, shared_ptr< const NetworkInterface > > onInterfaceAdded
interface has a carrier but it cannot send or receive normal user traffic yet
std::vector< shared_ptr< const NetworkInterface > > listNetworkInterfaces() const final
void registerNotificationCallback(MessageCallback cb)
uint32_t getFlags() const
Returns a bitset of platform-specific flags enabled on the interface.
void joinGroup(int group)
#define NDN_LOG_INIT(name)
declare a log module
NetworkMonitorImplNetlink(boost::asio::io_service &io)
initialize netlink socket and start enumerating interfaces
util::Signal< NetworkMonitorImpl > onNetworkStateChanged