55 #include "../network-address.hpp"    56 #include "../../name.hpp"    57 #include "../../util/logger.hpp"    61 #include <net/if_dl.h>        62 #include <net/if_types.h>     63 #include <netinet/in.h>       65 #include <boost/asio/io_service.hpp>    66 #include <boost/asio/ip/address.hpp>    67 #include <boost/asio/ip/udp.hpp>    72 using util::CFReleaser;
    81     if (::getifaddrs(&m_ifaList) < 0) {
    89     if (m_ifaList != 
nullptr) {
    90       ::freeifaddrs(m_ifaList);
   101   ifaddrs* m_ifaList = 
nullptr;
   106   , m_cfLoopEvent(m_scheduler)
   107   , m_context{0, 
this, 
nullptr, 
nullptr, 
nullptr}
   108   , m_scStore(SCDynamicStoreCreate(
nullptr, CFSTR(
"net.named-data.ndn-cxx.NetworkMonitor"),
   109                                    &NetworkMonitorImplOsx::onConfigChanged, &m_context))
   110   , m_loopSource(SCDynamicStoreCreateRunLoopSource(
nullptr, m_scStore.
get(), 0))
   111   , m_ioctlSocket(io, boost::asio::ip::udp::v4())
   119   CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
   120                                   static_cast<void*>(
this),
   121                                   &NetworkMonitorImplOsx::afterNotificationCenterEvent,
   122                                   CFSTR(
"com.apple.system.config.network_change"),
   124                                   CFNotificationSuspensionBehaviorDeliverImmediately);
   126   CFRunLoopAddSource(CFRunLoopGetCurrent(), m_loopSource.
get(), kCFRunLoopDefaultMode);
   137   auto patterns = CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks);
   138   CFArrayAppendValue(patterns, CFSTR(
"State:/Network/Interface/.*/Link"));
   139   CFArrayAppendValue(patterns, CFSTR(
"State:/Network/Interface/.*/IPv4"));
   140   CFArrayAppendValue(patterns, CFSTR(
"State:/Network/Interface/.*/IPv6"));
   142   if (!SCDynamicStoreSetNotificationKeys(m_scStore.
get(), 
nullptr, patterns)) {
   143     BOOST_THROW_EXCEPTION(
Error(
"SCDynamicStoreSetNotificationKeys failed"));
   146   io.post([
this] { enumerateInterfaces(); });
   151   CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_loopSource.
get(), kCFRunLoopDefaultMode);
   153   CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(),
   154                                           static_cast<void*>(
this));
   157 shared_ptr<const NetworkInterface>
   160   auto it = m_interfaces.find(ifname);
   161   return it == m_interfaces.end() ? 
nullptr : it->second;
   164 std::vector<shared_ptr<const NetworkInterface>>
   167   std::vector<shared_ptr<const NetworkInterface>> v;
   168   v.reserve(m_interfaces.size());
   170   for (
const auto& e : m_interfaces) {
   171     v.push_back(e.second);
   177 NetworkMonitorImplOsx::afterNotificationCenterEvent(CFNotificationCenterRef center,
   181                                                     CFDictionaryRef userInfo)
   187 NetworkMonitorImplOsx::scheduleCfLoop()
   190   m_cfLoopEvent = m_scheduler.scheduleEvent(time::seconds(1), [
this] {
   192     CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 
true);
   198 NetworkMonitorImplOsx::enumerateInterfaces()
   201   for (
const auto& ifName : getInterfaceNames()) {
   202     addNewInterface(ifName, ifaList);
   210   const char* cStr = CFStringGetCStringPtr(cfStr, kCFStringEncodingASCII);
   211   if (cStr != 
nullptr) {
   217   std::string str(CFStringGetLength(cfStr) + 1, 
'\0');
   218   if (!CFStringGetCString(cfStr, &str.front(), str.size(), kCFStringEncodingASCII)) {
   227 std::set<std::string>
   228 NetworkMonitorImplOsx::getInterfaceNames()
 const   230   CFReleaser<CFDictionaryRef> dict =
   231     (CFDictionaryRef)SCDynamicStoreCopyValue(m_scStore.
get(), CFSTR(
"State:/Network/Interface"));
   232   if (dict.get() == 
nullptr) {
   236   CFArrayRef interfaces = (CFArrayRef)CFDictionaryGetValue(dict.get(), CFSTR(
"Interfaces"));
   237   if (interfaces == 
nullptr) {
   241   std::set<std::string> ifNames;
   242   size_t count = CFArrayGetCount(interfaces);
   243   for (
size_t i = 0; i != count; ++i) {
   244     auto ifName = (CFStringRef)CFArrayGetValueAtIndex(interfaces, i);
   251 NetworkMonitorImplOsx::addNewInterface(
const std::string& ifName, 
const IfAddrs& ifaList)
   254   interface->setName(ifName);
   255   interface->setState(getInterfaceState(*interface));
   256   updateInterfaceInfo(*interface, ifaList);
   259     NDN_LOG_DEBUG(
"ignoring " << ifName << 
" due to unhandled interface type");
   264   m_interfaces[interface->getName()] = interface;
   269 NetworkMonitorImplOsx::getInterfaceState(
const NetworkInterface& netif)
 const   271   CFReleaser<CFStringRef> linkName =
   272     CFStringCreateWithCString(kCFAllocatorDefault,
   273                               (
"State:/Network/Interface/" + netif.
getName() + 
"/Link").data(),
   274                               kCFStringEncodingASCII);
   276   CFReleaser<CFDictionaryRef> dict =
   277     (CFDictionaryRef)SCDynamicStoreCopyValue(m_scStore.
get(), linkName.get());
   278   if (dict.get() == 
nullptr) {
   282   CFBooleanRef isActive = (CFBooleanRef)CFDictionaryGetValue(dict.get(), CFSTR(
"Active"));
   283   if (isActive == 
nullptr) {
   294   std::strncpy(ifr.ifr_name, netif.
getName().data(), 
sizeof(ifr.ifr_name) - 1);
   296   if (::ioctl(m_ioctlSocket.native_handle(), SIOCGIFMTU, &ifr) == 0) {
   297     return static_cast<size_t>(ifr.ifr_mtu);
   304 template<
typename AddressBytes>
   308   uint8_t prefixLength = 0;
   309   for (
auto byte : mask) {
   321   BOOST_ASSERT(!netif.
getName().empty());
   323   netif.
setMtu(getInterfaceMtu(netif));
   325   for (ifaddrs* ifa = ifaList.
get(); ifa != 
nullptr; ifa = ifa->ifa_next) {
   326     if (ifa->ifa_name != netif.
getName())
   331     if (ifa->ifa_addr == 
nullptr)
   336     ip::address ipAddr, broadcastAddr;
   337     uint8_t prefixLength = 0;
   339     switch (ifa->ifa_addr->sa_family) {
   343         const sockaddr_in* sin = 
reinterpret_cast<sockaddr_in*
>(ifa->ifa_addr);
   344         ip::address_v4::bytes_type bytes;
   345         std::copy_n(reinterpret_cast<const unsigned char*>(&sin->sin_addr), bytes.size(), bytes.begin());
   346         ipAddr = ip::address_v4(bytes);
   348         const sockaddr_in* sinMask = 
reinterpret_cast<sockaddr_in*
>(ifa->ifa_netmask);
   349         std::copy_n(reinterpret_cast<const unsigned char*>(&sinMask->sin_addr), bytes.size(), bytes.begin());
   357         const sockaddr_in6* sin6 = 
reinterpret_cast<sockaddr_in6*
>(ifa->ifa_addr);
   358         ip::address_v6::bytes_type bytes;
   359         std::copy_n(reinterpret_cast<const unsigned char*>(&sin6->sin6_addr), bytes.size(), bytes.begin());
   360         ip::address_v6 v6Addr(bytes);
   361         if (v6Addr.is_link_local())
   362           v6Addr.scope_id(if_nametoindex(netif.
getName().data()));
   365         const sockaddr_in6* sinMask = 
reinterpret_cast<sockaddr_in6*
>(ifa->ifa_netmask);
   366         std::copy_n(reinterpret_cast<const unsigned char*>(&sinMask->sin6_addr), bytes.size(), bytes.begin());
   372         const sockaddr_dl* sdl = 
reinterpret_cast<sockaddr_dl*
>(ifa->ifa_addr);
   380         else if (sdl->sdl_type == IFT_LOOP) {
   394         const sockaddr_in* sin = 
reinterpret_cast<sockaddr_in*
>(ifa->ifa_broadaddr);
   395         ip::address_v4::bytes_type bytes;
   396         std::copy_n(reinterpret_cast<const unsigned char*>(&sin->sin_addr), bytes.size(), bytes.begin());
   397         broadcastAddr = ip::address_v4(bytes);
   405     if (ipAddr.is_loopback()) {
   408     else if ((ipAddr.is_v4() && (ipAddr.to_v4().to_ulong() & 0xFFFF0000) == 0xA9FE0000) ||
   409              (ipAddr.is_v6() && ipAddr.to_v6().is_link_local())) {
   418 NetworkMonitorImplOsx::onConfigChanged(SCDynamicStoreRef m_scStore, CFArrayRef changedKeys, 
void* context)
   424 NetworkMonitorImplOsx::onConfigChanged(CFArrayRef changedKeys)
   428   size_t count = CFArrayGetCount(changedKeys);
   429   for (
size_t i = 0; i != count; ++i) {
   431     std::string ifName = key.
at(-2).
toUri();
   433     auto ifIt = m_interfaces.find(ifName);
   434     if (ifIt == m_interfaces.end()) {
   435       addNewInterface(ifName, ifaList);
   439     auto removeInterface = [&] {
   441       shared_ptr<NetworkInterface> removedNetif = ifIt->second;
   442       m_interfaces.erase(ifIt);
   447     std::string changedItem = key.
at(-1).
toUri();
   448     if (changedItem == 
"Link") {
   449       auto newState = getInterfaceState(netif);
   452         if (getInterfaceNames().count(ifName) == 0) {
   460     else if (changedItem == 
"IPv4" || changedItem == 
"IPv6") {
   462       updatedNetif->setName(ifName);
   463       updateInterfaceInfo(*updatedNetif, ifaList);
   470       const auto& newAddrs = updatedNetif->getNetworkAddresses();
   472       std::set<NetworkAddress> added;
   473       std::set<NetworkAddress> removed;
   474       std::set_difference(newAddrs.begin(), newAddrs.end(),
   475                           oldAddrs.begin(), oldAddrs.end(), std::inserter(added, added.end()));
   476       std::set_difference(oldAddrs.begin(), oldAddrs.end(),
   477                           newAddrs.begin(), newAddrs.end(), std::inserter(removed, removed.end()));
   479       for (
const auto& addr : removed) {
   482       for (
const auto& addr : added) {
 interface is administratively down 
 
Copyright (c) 2011-2015 Regents of the University of California. 
 
interface is in an unknown state 
 
interface can be used to send and receive packets 
 
void setState(InterfaceState state)
 
static shared_ptr< NetworkInterface > makeNetworkInterface()
 
const size_t ADDR_LEN
Octets in one Ethernet address. 
 
void setMtu(uint32_t mtu)
 
NetworkMonitorImplOsx(boost::asio::io_service &io)
 
#define emitSignal(...)
(implementation detail) 
 
InterfaceState
Indicates the state of a network interface. 
 
NetworkMonitor::Error Error
 
void setEthernetAddress(const ethernet::Address &address)
 
void setEthernetBroadcastAddress(const ethernet::Address &address)
 
util::Signal< NetworkMonitorImpl > onEnumerationCompleted
 
Represents one network interface attached to the host. 
 
#define NDN_LOG_INIT(name)
declare a log module 
 
Stores one IP address supported by a network interface. 
 
Address getBroadcastAddress()
Returns the Ethernet broadcast address (ff:ff:ff:ff:ff:ff) 
 
#define NDN_LOG_DEBUG(expression)
 
std::vector< shared_ptr< const NetworkInterface > > listNetworkInterfaces() const final
 
bool removeNetworkAddress(const NetworkAddress &address)
 
util::Signal< NetworkMonitorImpl, shared_ptr< const NetworkInterface > > onInterfaceRemoved
 
static std::string convertToStdString(CFStringRef cfStr)
 
void toUri(std::ostream &os) const 
Write *this to the output stream, escaping characters according to the NDN URI Scheme. 
 
void setFlags(uint32_t flags)
 
Represents an absolute name. 
 
std::string getName() const 
Returns the name of the interface, unique on the system. 
 
const std::set< NetworkAddress > & getNetworkAddresses() const 
Returns a list of all network-layer addresses present on the interface. 
 
util::Signal< NetworkMonitorImpl, shared_ptr< const NetworkInterface > > onInterfaceAdded
 
const Component & at(ssize_t i) const 
Get the component at the given index. 
 
bool addNetworkAddress(const NetworkAddress &address)
 
shared_ptr< const NetworkInterface > getNetworkInterface(const std::string &ifname) const final
 
represents an Ethernet hardware address 
 
ifaddrs * get() const noexcept
 
ethernet::Address getEthernetAddress() const 
Returns the link-layer (Ethernet) address of the interface. 
 
#define NDN_LOG_WARN(expression)
 
util::Signal< NetworkMonitorImpl > onNetworkStateChanged
 
#define NDN_LOG_TRACE(expression)
 
void setType(InterfaceType type)
 
InterfaceState getState() const 
Returns the current state of the interface. 
 
const size_t MAX_DATA_LEN
Max octets in Ethernet payload. 
 
bool canBroadcast() const 
Returns true if the interface supports broadcast communication. 
 
static uint8_t computePrefixLength(const AddressBytes &mask)