NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
network-interface.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "network-interface.hpp"
27 #include "core/logger.hpp"
28 
29 #include <cerrno>
30 #include <cstring>
31 #include <type_traits>
32 #include <unordered_map>
33 
34 #ifdef HAVE_IFADDRS_H
35 #include <ifaddrs.h> // for getifaddrs()
36 
37 #include <arpa/inet.h> // for inet_ntop()
38 #include <netinet/in.h> // for struct sockaddr_in{,6}
39 
40 #if defined(__linux__)
41 #include <net/if_arp.h> // for ARPHRD_* constants
42 #include <netpacket/packet.h> // for struct sockaddr_ll
43 #elif defined(__APPLE__) || defined(__FreeBSD__)
44 #include <net/if_dl.h> // for struct sockaddr_dl
45 #include <net/if_types.h> // for IFT_* constants
46 #endif
47 
48 #endif // HAVE_IFADDRS_H
49 
50 
51 NFD_LOG_INIT("NetworkInterfaceInfo");
52 
53 namespace nfd {
54 
55 static_assert(std::is_standard_layout<NetworkInterfaceInfo>::value,
56  "NetworkInterfaceInfo must be a standard layout type");
57 #ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
58 static_assert(std::is_default_constructible<NetworkInterfaceInfo>::value,
59  "NetworkInterfaceInfo must provide a default constructor");
60 #endif
61 
62 #ifdef WITH_TESTS
63 static shared_ptr<std::vector<NetworkInterfaceInfo>> s_debugNetworkInterfaces = nullptr;
64 
65 void
66 setDebugNetworkInterfaces(shared_ptr<std::vector<NetworkInterfaceInfo>> interfaces)
67 {
68  s_debugNetworkInterfaces = interfaces;
69 }
70 #endif
71 
72 std::vector<NetworkInterfaceInfo>
74 {
75 #ifdef WITH_TESTS
76  if (s_debugNetworkInterfaces != nullptr) {
77  return *s_debugNetworkInterfaces;
78  }
79 #endif
80 
81 #ifdef HAVE_IFADDRS_H
82  using namespace boost::asio::ip;
83  using std::strerror;
84 
85  std::unordered_map<std::string, NetworkInterfaceInfo> ifmap;
86  ifaddrs* ifa_list = nullptr;
87 
88  if (::getifaddrs(&ifa_list) < 0)
89  BOOST_THROW_EXCEPTION(std::runtime_error(std::string("getifaddrs() failed: ") +
90  strerror(errno)));
91 
92  for (ifaddrs* ifa = ifa_list; ifa != nullptr; ifa = ifa->ifa_next) {
93  std::string ifname(ifa->ifa_name);
94  NetworkInterfaceInfo& netif = ifmap[ifname];
95  netif.name = ifa->ifa_name;
96  netif.flags = ifa->ifa_flags;
97 
98  if (ifa->ifa_addr == nullptr)
99  continue;
100 
101  switch (ifa->ifa_addr->sa_family) {
102 
103  case AF_INET: {
104  const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
105  char address[INET_ADDRSTRLEN];
106  if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
107  netif.ipv4Addresses.push_back(address_v4::from_string(address));
108  NFD_LOG_TRACE(ifname << ": added IPv4 address " << address);
109  }
110  else
111  NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) failed: " << strerror(errno));
112  break;
113  }
114 
115  case AF_INET6: {
116  const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
117  char address[INET6_ADDRSTRLEN];
118  if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address))) {
119  netif.ipv6Addresses.push_back(address_v6::from_string(address));
120  NFD_LOG_TRACE(ifname << ": added IPv6 address " << address);
121  }
122  else
123  NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET6) failed: " << strerror(errno));
124  break;
125  }
126 
127 #if defined(__linux__)
128  case AF_PACKET: {
129  const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
130  netif.index = sll->sll_ifindex;
131  if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN) {
132  netif.etherAddress = ethernet::Address(sll->sll_addr);
133  NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
134  }
135  else if (sll->sll_hatype != ARPHRD_LOOPBACK) {
136  NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled hardware type "
137  << sll->sll_hatype);
138  }
139  break;
140  }
141 
142 #elif defined(__APPLE__) || defined(__FreeBSD__)
143  case AF_LINK: {
144  const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
145  netif.index = sdl->sdl_index;
146  if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ethernet::ADDR_LEN) {
147  netif.etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
148  NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
149  }
150  else if (sdl->sdl_type != IFT_LOOP) {
151  NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled interface type "
152  << sdl->sdl_type);
153  }
154  break;
155  }
156 #endif
157  }
158 
159  if (netif.isBroadcastCapable() && ifa->ifa_broadaddr != nullptr) {
160  const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
161  char address[INET_ADDRSTRLEN];
162  if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
163  netif.broadcastAddress = address_v4::from_string(address);
164  NFD_LOG_TRACE(ifname << ": added IPv4 broadcast address " << address);
165  }
166  else
167  NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) for broadaddr failed: " << strerror(errno));
168  }
169  }
170 
171  ::freeifaddrs(ifa_list);
172 
173  std::vector<NetworkInterfaceInfo> v;
174  v.reserve(ifmap.size());
175  for (auto&& element : ifmap) {
176  v.push_back(element.second);
177  }
178 
179  return v;
180 #else
181  return {};
182 #endif // HAVE_IFADDRS_H
183 }
184 
185 } // namespace nfd
const size_t ADDR_LEN
Octets in one Ethernet address.
Definition: ethernet.hpp:42
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
represents an Ethernet hardware address
Definition: ethernet.hpp:53
contains information about a network interface
ethernet::Address etherAddress
std::vector< NetworkInterfaceInfo > listNetworkInterfaces()
List configured network interfaces on the system and their info.
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
boost::asio::ip::address_v4 broadcastAddress
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
std::vector< boost::asio::ip::address_v6 > ipv6Addresses
std::vector< boost::asio::ip::address_v4 > ipv4Addresses
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54