blob: e192947961a23ed8243552487322d538553e127a [file] [log] [blame]
Davide Pesavento2bf35a62017-04-02 00:41:06 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 *
21 * @author Davide Pesavento <davide.pesavento@lip6.fr>
22 */
23
24#include "network-interface.hpp"
25#include "detail/linux-if-constants.hpp"
26#include "logger.hpp"
27#include "string-helper.hpp"
28
29#include <net/if.h>
30
31NDN_LOG_INIT(ndn.NetworkMonitor);
32
33namespace ndn {
34namespace util {
35
36NetworkInterface::NetworkInterface()
37 : m_index(0)
38 , m_type(InterfaceType::UNKNOWN)
39 , m_flags(0)
40 , m_state(InterfaceState::UNKNOWN)
41 , m_mtu(0)
42{
43}
44
45bool
46NetworkInterface::addNetworkAddress(const NetworkAddress& address)
47{
48 if (!address.getIp().is_unspecified()) {
49 // need to erase the existing address before inserting
50 // because the address flags may have changed
51 bool isNew = m_netAddresses.erase(address) == 0;
52 m_netAddresses.insert(address);
53 if (isNew) {
54 NDN_LOG_DEBUG("added address " << address << " to " << m_name);
55 onAddressAdded(address);
56 return true;
57 }
58 }
59 return false;
60}
61
62bool
63NetworkInterface::removeNetworkAddress(const NetworkAddress& address)
64{
65 if (m_netAddresses.erase(address) > 0) {
66 NDN_LOG_DEBUG("removed address " << address << " from " << m_name);
67 onAddressRemoved(address);
68 return true;
69 }
70 return false;
71}
72
73void
74NetworkInterface::setIndex(int index)
75{
76 m_index = index;
77}
78
79void
80NetworkInterface::setName(const std::string& name)
81{
82 BOOST_ASSERT(!name.empty());
83 m_name = name;
84}
85
86void
87NetworkInterface::setType(InterfaceType type)
88{
89 m_type = type;
90}
91
92void
93NetworkInterface::setFlags(uint32_t flags)
94{
95 m_flags = flags;
96}
97
98void
99NetworkInterface::setState(InterfaceState state)
100{
101 if (m_state != state) {
102 std::swap(m_state, state);
103 onStateChanged(state, m_state);
104 }
105}
106
107void
108NetworkInterface::setMtu(uint32_t mtu)
109{
110 if (m_mtu != mtu) {
111 std::swap(m_mtu, mtu);
112 onMtuChanged(mtu, m_mtu);
113 }
114}
115
116void
117NetworkInterface::setEthernetAddress(const ethernet::Address& address)
118{
119 m_etherAddress = address;
120}
121
122void
123NetworkInterface::setEthernetBroadcastAddress(const ethernet::Address& address)
124{
125 m_etherBrdAddress = address;
126}
127
128std::ostream&
129operator<<(std::ostream& os, InterfaceType type)
130{
131 switch (type) {
132 case InterfaceType::UNKNOWN:
133 return os << "unknown";
134 case InterfaceType::LOOPBACK:
135 return os << "loopback";
136 case InterfaceType::ETHERNET:
137 return os << "ether";
138 }
139 return os;
140}
141
142std::ostream&
143operator<<(std::ostream& os, InterfaceState state)
144{
145 switch (state) {
146 case InterfaceState::UNKNOWN:
147 return os << "unknown";
148 case InterfaceState::DOWN:
149 return os << "down";
150 case InterfaceState::NO_CARRIER:
151 return os << "no-carrier";
152 case InterfaceState::DORMANT:
153 return os << "dormant";
154 case InterfaceState::RUNNING:
155 return os << "running";
156 }
157 return os;
158}
159
160static void
161printFlag(std::ostream& os, uint32_t& flags, uint32_t flagVal, const char* flagStr)
162{
163 if (flags & flagVal) {
164 flags &= ~flagVal;
165 os << flagStr << (flags ? "," : "");
166 }
167}
168
169std::ostream&
170operator<<(std::ostream& os, const NetworkInterface& netif)
171{
172 os << netif.getIndex() << ": " << netif.getName() << ": ";
173
174 auto flags = netif.getFlags();
175 os << "<";
176#define PRINT_IFF(flag) printFlag(os, flags, IFF_##flag, #flag)
177 PRINT_IFF(UP);
Davide Pesavento2ea07932017-05-19 23:12:08 -0400178 PRINT_IFF(BROADCAST);
Davide Pesavento2bf35a62017-04-02 00:41:06 -0400179 PRINT_IFF(DEBUG);
180 PRINT_IFF(LOOPBACK);
181 PRINT_IFF(POINTOPOINT);
Davide Pesavento2ea07932017-05-19 23:12:08 -0400182#if defined(IFF_NOTRAILERS)
Davide Pesavento2bf35a62017-04-02 00:41:06 -0400183 PRINT_IFF(NOTRAILERS);
Davide Pesavento2ea07932017-05-19 23:12:08 -0400184#endif
Davide Pesavento2bf35a62017-04-02 00:41:06 -0400185 PRINT_IFF(RUNNING);
186 PRINT_IFF(NOARP);
187 PRINT_IFF(PROMISC);
188 PRINT_IFF(ALLMULTI);
Davide Pesavento2ea07932017-05-19 23:12:08 -0400189 PRINT_IFF(MULTICAST);
Davide Pesavento2bf35a62017-04-02 00:41:06 -0400190#if defined(__linux__)
191 PRINT_IFF(MASTER);
192 PRINT_IFF(SLAVE);
193 PRINT_IFF(PORTSEL);
194 PRINT_IFF(AUTOMEDIA);
195 PRINT_IFF(DYNAMIC);
196#elif defined(__APPLE__) || defined(__FreeBSD__)
197 PRINT_IFF(OACTIVE);
198 PRINT_IFF(SIMPLEX);
Davide Pesavento2ea07932017-05-19 23:12:08 -0400199 PRINT_IFF(LINK0);
200 PRINT_IFF(LINK1);
201 PRINT_IFF(LINK2);
202#endif
203#if defined(__FreeBSD__)
204 PRINT_IFF(CANTCONFIG);
205 PRINT_IFF(PPROMISC);
206 PRINT_IFF(MONITOR);
207 PRINT_IFF(STATICARP);
208 PRINT_IFF(DYING);
209 PRINT_IFF(RENAMING);
Davide Pesavento2bf35a62017-04-02 00:41:06 -0400210#endif
211#undef PRINT_IFF
212#if defined(__linux__)
213#define PRINT_IF_FLAG(flag) printFlag(os, flags, linux_if::FLAG_##flag, #flag)
214 PRINT_IF_FLAG(LOWER_UP);
215 PRINT_IF_FLAG(DORMANT);
216 PRINT_IF_FLAG(ECHO);
217#undef PRINT_IF_FLAG
218#endif
219 if (flags) {
220 // print unknown flags in hex
221 os << AsHex{flags};
222 }
223 os << ">";
224
225 os << " state " << netif.getState() << " mtu " << netif.getMtu() << "\n"
226 << " link/" << netif.getType() << " " << netif.getEthernetAddress()
227 << " brd " << netif.getEthernetBroadcastAddress() << "\n";
228
229 for (const auto& addr : netif.getNetworkAddresses()) {
230 os << " " << (addr.getFamily() == AddressFamily::V4 ? "inet " : "inet6 ") << addr;
231 if (netif.canBroadcast() && !addr.getBroadcast().is_unspecified())
232 os << " brd " << addr.getBroadcast();
233 os << " scope " << addr.getScope() << "\n";
234 }
235
236 return os;
237}
238
239} // namespace util
240} // namespace ndn