blob: c1cfaa67cdaa784aa0943703ff26e1ddf2c212b2 [file] [log] [blame]
Davide Pesavento248d6bd2014-03-09 10:24:08 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "network-interface.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -06008#include "core/logger.hpp"
Davide Pesavento248d6bd2014-03-09 10:24:08 +01009
10#include <boost/foreach.hpp>
11
12#include <arpa/inet.h> // for inet_ntop()
13#include <netinet/in.h> // for struct sockaddr_in{,6}
14#include <ifaddrs.h> // for getifaddrs()
15
16#if defined(__linux__)
17#include <net/if_arp.h> // for ARPHRD_* constants
18#include <netpacket/packet.h> // for struct sockaddr_ll
Alexander Afanasyev500b2532014-03-31 12:29:25 -070019#elif defined(__APPLE__) || defined(__FreeBSD__)
Davide Pesavento248d6bd2014-03-09 10:24:08 +010020#include <net/if_dl.h> // for struct sockaddr_dl
21#else
22#error Platform not supported
23#endif
24
25namespace nfd {
26
27NFD_LOG_INIT("NetworkInterfaceInfo")
28
29std::list< shared_ptr<NetworkInterfaceInfo> >
30listNetworkInterfaces()
31{
32 typedef std::map< std::string, shared_ptr<NetworkInterfaceInfo> > InterfacesMap;
33 InterfacesMap ifmap;
34
35 ifaddrs* ifa_list;
36 if (::getifaddrs(&ifa_list) < 0)
37 throw std::runtime_error("getifaddrs() failed");
38
39 for (ifaddrs* ifa = ifa_list; ifa != 0; ifa = ifa->ifa_next)
40 {
41 shared_ptr<NetworkInterfaceInfo> netif;
42 std::string ifname(ifa->ifa_name);
43 InterfacesMap::iterator i = ifmap.find(ifname);
44 if (i == ifmap.end())
45 {
46 netif = make_shared<NetworkInterfaceInfo>();
47 netif->name = ifname;
48 netif->flags = ifa->ifa_flags;
49 ifmap[ifname] = netif;
50 }
51 else
52 {
53 netif = i->second;
54 }
55
56 if (!ifa->ifa_addr)
57 continue;
58
59 switch (ifa->ifa_addr->sa_family)
60 {
61 case AF_INET: {
62 const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
63 char address[INET_ADDRSTRLEN];
64 if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
65 netif->ipv4Addresses.push_back(boost::asio::ip::address_v4::from_string(address));
66 else
67 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
68 }
69 break;
70 case AF_INET6: {
71 const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
72 char address[INET6_ADDRSTRLEN];
73 if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address)))
74 netif->ipv6Addresses.push_back(boost::asio::ip::address_v6::from_string(address));
75 else
76 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
77 }
78 break;
79#if defined(__linux__)
80 case AF_PACKET: {
81 const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
82 netif->index = sll->sll_ifindex;
83 if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN)
84 netif->etherAddress = ethernet::Address(sll->sll_addr);
85 else if (sll->sll_hatype != ARPHRD_LOOPBACK)
86 NFD_LOG_WARN("Unrecognized hardware address on " << ifname);
87 }
88 break;
Alexander Afanasyev500b2532014-03-31 12:29:25 -070089#elif defined(__APPLE__) || defined(__FreeBSD__)
Davide Pesavento248d6bd2014-03-09 10:24:08 +010090 case AF_LINK: {
91 const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
92 netif->index = sdl->sdl_index;
93 netif->etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
94 }
95 break;
96#endif
97 }
Steve DiBenedettoca53ac62014-03-27 19:58:40 -060098
99 if (netif->isBroadcastCapable() && ifa->ifa_broadaddr != 0)
100 {
101 const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
102
103 char address[INET_ADDRSTRLEN];
104 if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
105 netif->broadcastAddress = boost::asio::ip::address_v4::from_string(address);
106 else
107 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
108 }
Davide Pesavento248d6bd2014-03-09 10:24:08 +0100109 }
110
111 ::freeifaddrs(ifa_list);
112
113 std::list< shared_ptr<NetworkInterfaceInfo> > list;
114 BOOST_FOREACH(InterfacesMap::value_type elem, ifmap) {
115 list.push_back(elem.second);
116 }
117
118 return list;
119}
120
121} // namespace nfd