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> 38 #ifndef RTEXT_FILTER_SKIP_STATS 39 #define RTEXT_FILTER_SKIP_STATS (1 << 3) 53 for (
auto group : {RTNLGRP_LINK,
54 RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV4_ROUTE,
55 RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_ROUTE}) {
63 shared_ptr<const NetworkInterface>
66 for (
const auto& interface : m_interfaces | boost::adaptors::map_values) {
67 if (interface->getName() == ifname)
73 std::vector<shared_ptr<const NetworkInterface>>
76 std::vector<shared_ptr<const NetworkInterface>> v;
77 v.reserve(m_interfaces.size());
78 boost::push_back(v, m_interfaces | boost::adaptors::map_values);
83 NetworkMonitorImplNetlink::enumerateLinks()
86 m_phase = ENUMERATING_LINKS;
90 alignas(NLMSG_ALIGNTO) ifinfomsg ifi;
91 alignas(RTA_ALIGNTO) rtattr rta;
92 alignas(RTA_ALIGNTO) uint32_t rtext;
95 auto payload = make_shared<IfInfoMessage>();
96 payload->ifi.ifi_family = AF_UNSPEC;
97 payload->rta.rta_type = IFLA_EXT_MASK;
98 payload->rta.rta_len = RTA_LENGTH(
sizeof(payload->rtext));
101 m_rtnlSocket.sendDumpRequest(RTM_GETLINK, payload.get(),
sizeof(IfInfoMessage),
103 [
this, payload] (
const auto& msg) { this->parseRtnlMessage(msg); });
107 NetworkMonitorImplNetlink::enumerateAddrs()
110 m_phase = ENUMERATING_ADDRS;
114 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa;
117 auto payload = make_shared<IfAddrMessage>();
118 payload->ifa.ifa_family = AF_UNSPEC;
120 m_rtnlSocket.sendDumpRequest(RTM_GETADDR, payload.get(),
sizeof(IfAddrMessage),
122 [
this, payload] (
const auto& msg) { this->parseRtnlMessage(msg); });
126 NetworkMonitorImplNetlink::enumerateRoutes()
133 m_phase = ENUMERATION_COMPLETE;
138 NetworkMonitorImplNetlink::parseRtnlMessage(
const NetlinkMessage& nlmsg)
140 switch (nlmsg->nlmsg_type) {
143 parseLinkMessage(nlmsg);
144 if (m_phase == ENUMERATION_COMPLETE)
150 parseAddressMessage(nlmsg);
151 if (m_phase == ENUMERATION_COMPLETE)
157 parseRouteMessage(nlmsg);
158 if (m_phase == ENUMERATION_COMPLETE)
163 parseDoneMessage(nlmsg);
167 parseErrorMessage(nlmsg);
178 case ARPHRD_LOOPBACK:
202 case RT_SCOPE_NOWHERE:
216 if (operState == linux_if::OPER_STATE_UP) {
219 else if (operState == linux_if::OPER_STATE_DORMANT) {
225 if ((flags & linux_if::FLAG_LOWER_UP) && !(flags & linux_if::FLAG_DORMANT))
227 else if (flags & IFF_UP)
234 #ifdef NDN_CXX_HAVE_NETLINK_EXT_ACK 241 if (msg && !msg->empty()) {
248 #endif // NDN_CXX_HAVE_NETLINK_EXT_ACK 251 NetworkMonitorImplNetlink::parseLinkMessage(
const NetlinkMessage& nlmsg)
253 const ifinfomsg* ifi = nlmsg.
getPayload<ifinfomsg>();
254 if (ifi ==
nullptr) {
260 NDN_LOG_DEBUG(
" unhandled interface type " << ifi->ifi_type);
264 shared_ptr<NetworkInterface> interface;
265 auto it = m_interfaces.find(ifi->ifi_index);
266 if (it != m_interfaces.end()) {
267 interface = it->second;
268 BOOST_ASSERT(interface !=
nullptr);
269 BOOST_ASSERT(interface->getIndex() == ifi->ifi_index);
272 if (nlmsg->nlmsg_type == RTM_DELLINK) {
273 if (interface !=
nullptr) {
274 NDN_LOG_DEBUG(
" removing interface " << interface->getName());
275 m_interfaces.erase(it);
281 if (interface ==
nullptr) {
283 interface->setIndex(ifi->ifi_index);
286 interface->setFlags(ifi->ifi_flags);
293 interface->setEthernetAddress(*address);
297 interface->setEthernetBroadcastAddress(*broadcast);
301 interface->setName(*
name);
305 interface->setMtu(*mtu);
310 if (it == m_interfaces.end()) {
312 m_interfaces[interface->getIndex()] = interface;
318 NetworkMonitorImplNetlink::parseAddressMessage(
const NetlinkMessage& nlmsg)
320 const ifaddrmsg* ifa = nlmsg.
getPayload<ifaddrmsg>();
321 if (ifa ==
nullptr) {
326 auto it = m_interfaces.find(ifa->ifa_index);
327 if (it == m_interfaces.end()) {
329 NDN_LOG_TRACE(
" unknown interface index " << ifa->ifa_index);
332 auto interface = it->second;
333 BOOST_ASSERT(interface !=
nullptr);
338 namespace ip = boost::asio::ip;
339 ip::address ipAddr, broadcastAddr;
340 if (ifa->ifa_family == AF_INET) {
349 else if (ifa->ifa_family == AF_INET6) {
352 if (v6->is_link_local())
353 v6->scope_id(ifa->ifa_index);
359 uint32_t flags = ifa->ifa_flags;
360 #ifdef NDN_CXX_HAVE_IFA_FLAGS 364 #endif // NDN_CXX_HAVE_IFA_FLAGS 366 if ((flags & IFA_F_TENTATIVE) && nlmsg->nlmsg_type == RTM_NEWADDR) {
380 if (nlmsg->nlmsg_type == RTM_NEWADDR)
381 interface->addNetworkAddress(address);
382 else if (nlmsg->nlmsg_type == RTM_DELADDR)
383 interface->removeNetworkAddress(address);
387 NetworkMonitorImplNetlink::parseRouteMessage(
const NetlinkMessage& nlmsg)
393 NetworkMonitorImplNetlink::parseDoneMessage(
const NetlinkMessage& nlmsg)
396 if (errcode ==
nullptr) {
403 #ifdef NDN_CXX_HAVE_NETLINK_EXT_ACK 404 if (nlmsg->nlmsg_flags & NLM_F_ACK_TLVS) {
405 parseExtAckAttributes(nlmsg.
getAttributes<nlattr>(errcode), *errcode != 0);
407 #endif // NDN_CXX_HAVE_NETLINK_EXT_ACK 411 case ENUMERATING_LINKS:
415 case ENUMERATING_ADDRS:
425 NetworkMonitorImplNetlink::parseErrorMessage(
const NetlinkMessage& nlmsg)
427 const nlmsgerr* err = nlmsg.
getPayload<nlmsgerr>();
428 if (err ==
nullptr) {
435 <<
" err=" << err->error <<
" " << std::strerror(
std::abs(err->error)));
437 #ifdef NDN_CXX_HAVE_NETLINK_EXT_ACK 438 if (!(nlmsg->nlmsg_flags & NLM_F_ACK_TLVS))
441 size_t errLen = NLMSG_LENGTH(
sizeof(nlmsgerr));
442 if (!(nlmsg->nlmsg_flags & NLM_F_CAPPED))
443 errLen += err->msg.nlmsg_len - NLMSG_HDRLEN;
445 if (nlmsg->nlmsg_len <= errLen)
448 auto nla =
reinterpret_cast<const nlattr*
>(
reinterpret_cast<const uint8_t*
>(&*nlmsg) + errLen);
450 parseExtAckAttributes(attrs, err->error != 0);
451 #endif // NDN_CXX_HAVE_NETLINK_EXT_ACK interface is administratively down
const T * getPayload() const noexcept
static AddressScope ifaScopeToAddressScope(uint8_t scope)
#define RTEXT_FILTER_SKIP_STATS
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.
size_t size() const noexcept
AddressFamily getFamily() const
Returns the address family.
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.
Stores one IP address supported by a network interface.
util::Signal< NetworkMonitorImpl, shared_ptr< const NetworkInterface > > onInterfaceRemoved
optional< U > getAttributeByType(uint16_t attrType) const
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
represents an Ethernet hardware address
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
NetlinkMessageAttributes< AttributeT > getAttributes(const PayloadT *p) const noexcept