blob: df47ac5c5171c9b0de9c201692807cd18bad3e3b [file] [log] [blame]
Davide Pesavento248d6bd2014-03-09 10:24:08 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Davide Pesavento248d6bd2014-03-09 10:24:08 +010024
25#include "network-interface.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060026#include "core/logger.hpp"
Davide Pesavento248d6bd2014-03-09 10:24:08 +010027
28#include <boost/foreach.hpp>
29
30#include <arpa/inet.h> // for inet_ntop()
31#include <netinet/in.h> // for struct sockaddr_in{,6}
32#include <ifaddrs.h> // for getifaddrs()
33
34#if defined(__linux__)
35#include <net/if_arp.h> // for ARPHRD_* constants
36#include <netpacket/packet.h> // for struct sockaddr_ll
Alexander Afanasyev500b2532014-03-31 12:29:25 -070037#elif defined(__APPLE__) || defined(__FreeBSD__)
Davide Pesavento248d6bd2014-03-09 10:24:08 +010038#include <net/if_dl.h> // for struct sockaddr_dl
39#else
40#error Platform not supported
41#endif
42
Davide Pesavento1bdef282014-04-08 20:59:50 +020043NFD_LOG_INIT("NetworkInterfaceInfo");
Davide Pesavento248d6bd2014-03-09 10:24:08 +010044
Davide Pesavento1bdef282014-04-08 20:59:50 +020045namespace nfd {
Davide Pesavento248d6bd2014-03-09 10:24:08 +010046
47std::list< shared_ptr<NetworkInterfaceInfo> >
48listNetworkInterfaces()
49{
50 typedef std::map< std::string, shared_ptr<NetworkInterfaceInfo> > InterfacesMap;
51 InterfacesMap ifmap;
52
53 ifaddrs* ifa_list;
54 if (::getifaddrs(&ifa_list) < 0)
55 throw std::runtime_error("getifaddrs() failed");
56
57 for (ifaddrs* ifa = ifa_list; ifa != 0; ifa = ifa->ifa_next)
58 {
59 shared_ptr<NetworkInterfaceInfo> netif;
60 std::string ifname(ifa->ifa_name);
61 InterfacesMap::iterator i = ifmap.find(ifname);
62 if (i == ifmap.end())
63 {
64 netif = make_shared<NetworkInterfaceInfo>();
65 netif->name = ifname;
66 netif->flags = ifa->ifa_flags;
67 ifmap[ifname] = netif;
68 }
69 else
70 {
71 netif = i->second;
72 }
73
74 if (!ifa->ifa_addr)
75 continue;
76
77 switch (ifa->ifa_addr->sa_family)
78 {
79 case AF_INET: {
80 const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
81 char address[INET_ADDRSTRLEN];
82 if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
83 netif->ipv4Addresses.push_back(boost::asio::ip::address_v4::from_string(address));
84 else
85 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
86 }
87 break;
88 case AF_INET6: {
89 const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
90 char address[INET6_ADDRSTRLEN];
91 if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address)))
92 netif->ipv6Addresses.push_back(boost::asio::ip::address_v6::from_string(address));
93 else
94 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
95 }
96 break;
97#if defined(__linux__)
98 case AF_PACKET: {
99 const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
100 netif->index = sll->sll_ifindex;
101 if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN)
102 netif->etherAddress = ethernet::Address(sll->sll_addr);
103 else if (sll->sll_hatype != ARPHRD_LOOPBACK)
104 NFD_LOG_WARN("Unrecognized hardware address on " << ifname);
105 }
106 break;
Alexander Afanasyev500b2532014-03-31 12:29:25 -0700107#elif defined(__APPLE__) || defined(__FreeBSD__)
Davide Pesavento248d6bd2014-03-09 10:24:08 +0100108 case AF_LINK: {
109 const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
110 netif->index = sdl->sdl_index;
111 netif->etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
112 }
113 break;
114#endif
115 }
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600116
117 if (netif->isBroadcastCapable() && ifa->ifa_broadaddr != 0)
118 {
119 const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
120
121 char address[INET_ADDRSTRLEN];
122 if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
123 netif->broadcastAddress = boost::asio::ip::address_v4::from_string(address);
124 else
125 NFD_LOG_WARN("inet_ntop() failed on " << ifname);
126 }
Davide Pesavento248d6bd2014-03-09 10:24:08 +0100127 }
128
129 ::freeifaddrs(ifa_list);
130
131 std::list< shared_ptr<NetworkInterfaceInfo> > list;
132 BOOST_FOREACH(InterfacesMap::value_type elem, ifmap) {
133 list.push_back(elem.second);
134 }
135
136 return list;
137}
138
139} // namespace nfd