blob: 65a690c1730f6a9b16ce557216adeb2a4f3937ae [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"
8
9#include <boost/foreach.hpp>
10
11#include <arpa/inet.h> // for inet_ntop()
12#include <netinet/in.h> // for struct sockaddr_in{,6}
13#include <ifaddrs.h> // for getifaddrs()
14
15#if defined(__linux__)
16#include <net/if_arp.h> // for ARPHRD_* constants
17#include <netpacket/packet.h> // for struct sockaddr_ll
18#elif defined(__APPLE__)
19#include <net/if_dl.h> // for struct sockaddr_dl
20#else
21#error Platform not supported
22#endif
23
24namespace nfd {
25
26NFD_LOG_INIT("NetworkInterfaceInfo")
27
28std::list< shared_ptr<NetworkInterfaceInfo> >
29listNetworkInterfaces()
30{
31 typedef std::map< std::string, shared_ptr<NetworkInterfaceInfo> > InterfacesMap;
32 InterfacesMap ifmap;
33
34 ifaddrs* ifa_list;
35 if (::getifaddrs(&ifa_list) < 0)
36 throw std::runtime_error("getifaddrs() failed");
37
38 for (ifaddrs* ifa = ifa_list; ifa != 0; ifa = ifa->ifa_next)
39 {
40 shared_ptr<NetworkInterfaceInfo> netif;
41 std::string ifname(ifa->ifa_name);
42 InterfacesMap::iterator i = ifmap.find(ifname);
43 if (i == ifmap.end())
44 {
45 netif = make_shared<NetworkInterfaceInfo>();
46 netif->name = ifname;
47 netif->flags = ifa->ifa_flags;
48 ifmap[ifname] = netif;
49 }
50 else
51 {
52 netif = i->second;
53 }
54
55 if (!ifa->ifa_addr)
56 continue;
57
58 switch (ifa->ifa_addr->sa_family)
59 {
60 case AF_INET: {
61 const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
62 char address[INET_ADDRSTRLEN];
63 if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
64 netif->ipv4Addresses.push_back(boost::asio::ip::address_v4::from_string(address));
65 else
66 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
67 }
68 break;
69 case AF_INET6: {
70 const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
71 char address[INET6_ADDRSTRLEN];
72 if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address)))
73 netif->ipv6Addresses.push_back(boost::asio::ip::address_v6::from_string(address));
74 else
75 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
76 }
77 break;
78#if defined(__linux__)
79 case AF_PACKET: {
80 const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
81 netif->index = sll->sll_ifindex;
82 if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN)
83 netif->etherAddress = ethernet::Address(sll->sll_addr);
84 else if (sll->sll_hatype != ARPHRD_LOOPBACK)
85 NFD_LOG_WARN("Unrecognized hardware address on " << ifname);
86 }
87 break;
88#elif defined(__APPLE__)
89 case AF_LINK: {
90 const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
91 netif->index = sdl->sdl_index;
92 netif->etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
93 }
94 break;
95#endif
96 }
97 }
98
99 ::freeifaddrs(ifa_list);
100
101 std::list< shared_ptr<NetworkInterfaceInfo> > list;
102 BOOST_FOREACH(InterfacesMap::value_type elem, ifmap) {
103 list.push_back(elem.second);
104 }
105
106 return list;
107}
108
109} // namespace nfd