core: ignore non-Ethernet AF_LINK addresses when enumerating NICs.
Also modernize the code with some C++11 features.
Change-Id: Ibd29b39c37fdce8f87f917ab0cf48750e631e76c
diff --git a/core/network-interface.cpp b/core/network-interface.cpp
index df47ac5..d7eebbd 100644
--- a/core/network-interface.cpp
+++ b/core/network-interface.cpp
@@ -1,11 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014 Regents of the University of California,
- * Arizona Board of Regents,
- * Colorado State University,
- * University Pierre & Marie Curie, Sorbonne University,
- * Washington University in St. Louis,
- * Beijing Institute of Technology
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
@@ -20,12 +21,15 @@
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
#include "network-interface.hpp"
#include "core/logger.hpp"
-#include <boost/foreach.hpp>
+#include <cerrno>
+#include <cstring>
+#include <type_traits>
+#include <unordered_map>
#include <arpa/inet.h> // for inet_ntop()
#include <netinet/in.h> // for struct sockaddr_in{,6}
@@ -36,104 +40,120 @@
#include <netpacket/packet.h> // for struct sockaddr_ll
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <net/if_dl.h> // for struct sockaddr_dl
-#else
-#error Platform not supported
+#include <net/if_types.h> // for IFT_* constants
#endif
NFD_LOG_INIT("NetworkInterfaceInfo");
namespace nfd {
-std::list< shared_ptr<NetworkInterfaceInfo> >
+static_assert(std::is_standard_layout<NetworkInterfaceInfo>::value,
+ "NetworkInterfaceInfo must be a standard layout type");
+#ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
+static_assert(std::is_default_constructible<NetworkInterfaceInfo>::value,
+ "NetworkInterfaceInfo must provide a default constructor");
+#endif
+
+std::vector<NetworkInterfaceInfo>
listNetworkInterfaces()
{
- typedef std::map< std::string, shared_ptr<NetworkInterfaceInfo> > InterfacesMap;
- InterfacesMap ifmap;
+ using namespace boost::asio::ip;
+ using std::strerror;
- ifaddrs* ifa_list;
+ std::unordered_map<std::string, NetworkInterfaceInfo> ifmap;
+ ifaddrs* ifa_list = nullptr;
+
if (::getifaddrs(&ifa_list) < 0)
- throw std::runtime_error("getifaddrs() failed");
+ throw std::runtime_error(std::string("getifaddrs() failed: ") + strerror(errno));
- for (ifaddrs* ifa = ifa_list; ifa != 0; ifa = ifa->ifa_next)
- {
- shared_ptr<NetworkInterfaceInfo> netif;
- std::string ifname(ifa->ifa_name);
- InterfacesMap::iterator i = ifmap.find(ifname);
- if (i == ifmap.end())
- {
- netif = make_shared<NetworkInterfaceInfo>();
- netif->name = ifname;
- netif->flags = ifa->ifa_flags;
- ifmap[ifname] = netif;
- }
+ for (ifaddrs* ifa = ifa_list; ifa != nullptr; ifa = ifa->ifa_next) {
+ std::string ifname(ifa->ifa_name);
+ NetworkInterfaceInfo& netif = ifmap[ifname];
+ netif.name = ifa->ifa_name;
+ netif.flags = ifa->ifa_flags;
+
+ if (ifa->ifa_addr == nullptr)
+ continue;
+
+ switch (ifa->ifa_addr->sa_family) {
+
+ case AF_INET: {
+ const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
+ char address[INET_ADDRSTRLEN];
+ if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
+ netif.ipv4Addresses.push_back(address_v4::from_string(address));
+ NFD_LOG_TRACE(ifname << ": added IPv4 address " << address);
+ }
else
- {
- netif = i->second;
- }
-
- if (!ifa->ifa_addr)
- continue;
-
- switch (ifa->ifa_addr->sa_family)
- {
- case AF_INET: {
- const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
- char address[INET_ADDRSTRLEN];
- if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
- netif->ipv4Addresses.push_back(boost::asio::ip::address_v4::from_string(address));
- else
- NFD_LOG_WARN("inet_ntop() failed on " << ifname);
- }
- break;
- case AF_INET6: {
- const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
- char address[INET6_ADDRSTRLEN];
- if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address)))
- netif->ipv6Addresses.push_back(boost::asio::ip::address_v6::from_string(address));
- else
- NFD_LOG_WARN("inet_ntop() failed on " << ifname);
- }
- break;
-#if defined(__linux__)
- case AF_PACKET: {
- const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
- netif->index = sll->sll_ifindex;
- if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN)
- netif->etherAddress = ethernet::Address(sll->sll_addr);
- else if (sll->sll_hatype != ARPHRD_LOOPBACK)
- NFD_LOG_WARN("Unrecognized hardware address on " << ifname);
- }
- break;
-#elif defined(__APPLE__) || defined(__FreeBSD__)
- case AF_LINK: {
- const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
- netif->index = sdl->sdl_index;
- netif->etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
- }
- break;
-#endif
- }
-
- if (netif->isBroadcastCapable() && ifa->ifa_broadaddr != 0)
- {
- const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
-
- char address[INET_ADDRSTRLEN];
- if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
- netif->broadcastAddress = boost::asio::ip::address_v4::from_string(address);
- else
- NFD_LOG_WARN("inet_ntop() failed on " << ifname);
- }
+ NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) failed: " << strerror(errno));
+ break;
}
+ case AF_INET6: {
+ const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
+ char address[INET6_ADDRSTRLEN];
+ if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address))) {
+ netif.ipv6Addresses.push_back(address_v6::from_string(address));
+ NFD_LOG_TRACE(ifname << ": added IPv6 address " << address);
+ }
+ else
+ NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET6) failed: " << strerror(errno));
+ break;
+ }
+
+#if defined(__linux__)
+ case AF_PACKET: {
+ const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
+ netif.index = sll->sll_ifindex;
+ if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN) {
+ netif.etherAddress = ethernet::Address(sll->sll_addr);
+ NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
+ }
+ else if (sll->sll_hatype != ARPHRD_LOOPBACK) {
+ NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled hardware type "
+ << sll->sll_hatype);
+ }
+ break;
+ }
+
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+ case AF_LINK: {
+ const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
+ netif.index = sdl->sdl_index;
+ if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ethernet::ADDR_LEN) {
+ netif.etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
+ NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
+ }
+ else if (sdl->sdl_type != IFT_LOOP) {
+ NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled interface type "
+ << sdl->sdl_type);
+ }
+ break;
+ }
+#endif
+ }
+
+ if (netif.isBroadcastCapable() && ifa->ifa_broadaddr != nullptr) {
+ const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
+ char address[INET_ADDRSTRLEN];
+ if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
+ netif.broadcastAddress = address_v4::from_string(address);
+ NFD_LOG_TRACE(ifname << ": added IPv4 broadcast address " << address);
+ }
+ else
+ NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) for broadaddr failed: " << strerror(errno));
+ }
+ }
+
::freeifaddrs(ifa_list);
- std::list< shared_ptr<NetworkInterfaceInfo> > list;
- BOOST_FOREACH(InterfacesMap::value_type elem, ifmap) {
- list.push_back(elem.second);
+ std::vector<NetworkInterfaceInfo> v;
+ v.reserve(ifmap.size());
+ for (auto&& element : ifmap) {
+ v.push_back(element.second);
}
- return list;
+ return v;
}
} // namespace nfd