blob: 67888ede8342310a0706cf13af824ae9b5f32992 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/network.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
13#if defined(WEBRTC_POSIX)
14// linux/if.h can't be included at the same time as the posix sys/if.h, and
15// it's transitively required by linux/route.h, so include that version on
16// linux instead of the standard posix one.
17#if defined(WEBRTC_LINUX)
18#include <linux/if.h>
19#include <linux/route.h>
20#elif !defined(__native_client__)
21#include <net/if.h>
22#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000023#endif // WEBRTC_POSIX
24
25#if defined(WEBRTC_WIN)
Mirko Bonadei01914412018-03-23 16:30:58 +010026#include <iphlpapi.h>
Yves Gerey665174f2018-06-19 15:03:05 +020027#include "rtc_base/win32.h"
Guo-wei Shieh9faf1542015-12-28 14:06:55 -080028#elif !defined(__native_client__)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "rtc_base/ifaddrs_converter.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030#endif
31
32#include <stdio.h>
33
34#include <algorithm>
jbauch555604a2016-04-26 03:13:22 -070035#include <memory>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000036
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020037#include "rtc_base/checks.h"
38#include "rtc_base/logging.h"
39#include "rtc_base/networkmonitor.h"
40#include "rtc_base/socket.h" // includes something that makes windows happy
41#include "rtc_base/stream.h"
42#include "rtc_base/stringencode.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020043#include "rtc_base/strings/string_builder.h"
Niels Möllerd7b91312018-05-24 11:21:34 +020044#include "rtc_base/stringutils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020045#include "rtc_base/thread.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046
47namespace rtc {
48namespace {
49
Peter Boström0c4e06b2015-10-07 12:23:21 +020050const uint32_t kUpdateNetworksMessage = 1;
51const uint32_t kSignalNetworksMessage = 2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000052
53// Fetch list of networks every two seconds.
54const int kNetworksUpdateIntervalMs = 2000;
55
56const int kHighestNetworkPreference = 127;
57
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +000058typedef struct {
59 Network* net;
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +000060 std::vector<InterfaceAddress> ips;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +000061} AddressList;
62
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000063bool CompareNetworks(const Network* a, const Network* b) {
64 if (a->prefix_length() == b->prefix_length()) {
65 if (a->name() == b->name()) {
66 return a->prefix() < b->prefix();
67 }
68 }
69 return a->name() < b->name();
70}
71
72bool SortNetworks(const Network* a, const Network* b) {
73 // Network types will be preferred above everything else while sorting
74 // Networks.
75
76 // Networks are sorted first by type.
77 if (a->type() != b->type()) {
78 return a->type() < b->type();
79 }
80
guoweis@webrtc.org369a6372014-09-17 22:37:29 +000081 IPAddress ip_a = a->GetBestIP();
82 IPAddress ip_b = b->GetBestIP();
83
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000084 // After type, networks are sorted by IP address precedence values
85 // from RFC 3484-bis
guoweis@webrtc.org369a6372014-09-17 22:37:29 +000086 if (IPAddressPrecedence(ip_a) != IPAddressPrecedence(ip_b)) {
87 return IPAddressPrecedence(ip_a) > IPAddressPrecedence(ip_b);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088 }
89
90 // TODO(mallinath) - Add VPN and Link speed conditions while sorting.
91
92 // Networks are sorted last by key.
deadbeef3427f532017-07-26 16:09:33 -070093 return a->key() < b->key();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000094}
95
96std::string AdapterTypeToString(AdapterType type) {
97 switch (type) {
Qingsi Wang9f1de692018-06-28 15:38:09 -070098 case ADAPTER_TYPE_ANY:
Qingsi Wang01560de2018-07-26 10:44:02 -070099 return "Wildcard";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000100 case ADAPTER_TYPE_UNKNOWN:
101 return "Unknown";
102 case ADAPTER_TYPE_ETHERNET:
103 return "Ethernet";
104 case ADAPTER_TYPE_WIFI:
105 return "Wifi";
106 case ADAPTER_TYPE_CELLULAR:
107 return "Cellular";
108 case ADAPTER_TYPE_VPN:
109 return "VPN";
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000110 case ADAPTER_TYPE_LOOPBACK:
111 return "Loopback";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000112 default:
nisseeb4ca4e2017-01-12 02:24:27 -0800113 RTC_NOTREACHED() << "Invalid type " << type;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000114 return std::string();
115 }
116}
117
Qingsi Wangde2ed7d2018-04-27 14:25:37 -0700118uint16_t ComputeNetworkCostByType(int type) {
119 switch (type) {
120 case rtc::ADAPTER_TYPE_ETHERNET:
121 case rtc::ADAPTER_TYPE_LOOPBACK:
122 return kNetworkCostMin;
123 case rtc::ADAPTER_TYPE_WIFI:
124 return kNetworkCostLow;
125 case rtc::ADAPTER_TYPE_CELLULAR:
126 return kNetworkCostHigh;
Qingsi Wang9f1de692018-06-28 15:38:09 -0700127 case rtc::ADAPTER_TYPE_ANY:
128 // Candidates gathered from the any-address/wildcard ports, as backups,
129 // are given the maximum cost so that if there are other candidates with
130 // known interface types, we would not select candidate pairs using these
131 // backup candidates if other selection criteria with higher precedence
132 // (network conditions over the route) are the same. Note that setting the
133 // cost to kNetworkCostUnknown would be problematic since
134 // ADAPTER_TYPE_CELLULAR would then have a higher cost. See
135 // P2PTransportChannel::SortConnectionsAndUpdateState for how we rank and
136 // select candidate pairs, where the network cost is among the criteria.
137 return kNetworkCostMax;
Qingsi Wangde2ed7d2018-04-27 14:25:37 -0700138 case rtc::ADAPTER_TYPE_VPN:
139 // The cost of a VPN should be computed using its underlying network type.
140 RTC_NOTREACHED();
141 return kNetworkCostUnknown;
142 default:
143 return kNetworkCostUnknown;
144 }
145}
146
thakis06689a12015-12-30 15:05:30 -0800147#if !defined(__native_client__)
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800148bool IsIgnoredIPv6(const InterfaceAddress& ip) {
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000149 if (ip.family() != AF_INET6) {
150 return false;
151 }
152
153 // Link-local addresses require scope id to be bound successfully.
154 // However, our IPAddress structure doesn't carry that so the
155 // information is lost and causes binding failure.
156 if (IPIsLinkLocal(ip)) {
157 return true;
158 }
159
160 // Any MAC based IPv6 should be avoided to prevent the MAC tracking.
161 if (IPIsMacBased(ip)) {
162 return true;
163 }
164
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800165 // Ignore deprecated IPv6.
166 if (ip.ipv6_flags() & IPV6_ADDRESS_FLAG_DEPRECATED) {
167 return true;
168 }
169
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000170 return false;
171}
thakis06689a12015-12-30 15:05:30 -0800172#endif // !defined(__native_client__)
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000173
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000174} // namespace
175
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800176// These addresses are used as the targets to find out the default local address
177// on a multi-homed endpoint. They are actually DNS servers.
178const char kPublicIPv4Host[] = "8.8.8.8";
179const char kPublicIPv6Host[] = "2001:4860:4860::8888";
180const int kPublicPort = 53; // DNS port.
181
Yves Gerey665174f2018-06-19 15:03:05 +0200182std::string MakeNetworkKey(const std::string& name,
183 const IPAddress& prefix,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000184 int prefix_length) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200185 rtc::StringBuilder ost;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000186 ost << name << "%" << prefix.ToString() << "/" << prefix_length;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200187 return ost.Release();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000188}
Qingsi Wange53ac042018-05-08 11:55:07 -0700189// Test if the network name matches the type<number> pattern, e.g. eth0. The
190// matching is case-sensitive.
191bool MatchTypeNameWithIndexPattern(const std::string& network_name,
192 const std::string& type_name) {
193 if (network_name.find(type_name) != 0) {
194 return false;
195 }
196 return std::find_if(network_name.begin() + type_name.size(),
197 network_name.end(),
198 [](char c) { return !isdigit(c); }) == network_name.end();
199}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000200
Qingsi Wange53ac042018-05-08 11:55:07 -0700201// A cautious note that this method may not provide an accurate adapter type
202// based on the string matching. Incorrect type of adapters can affect the
203// result of the downstream network filtering, see e.g.
204// BasicPortAllocatorSession::GetNetworks when
205// PORTALLOCATOR_DISABLE_COSTLY_NETWORKS is turned on.
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800206AdapterType GetAdapterTypeFromName(const char* network_name) {
Qingsi Wange53ac042018-05-08 11:55:07 -0700207 if (MatchTypeNameWithIndexPattern(network_name, "lo")) {
208 // Note that we have a more robust way to determine if a network interface
209 // is a loopback interface by checking the flag IFF_LOOPBACK in ifa_flags of
210 // an ifaddr struct. See ConvertIfAddrs in this file.
211 return ADAPTER_TYPE_LOOPBACK;
212 }
213 if (MatchTypeNameWithIndexPattern(network_name, "eth")) {
214 return ADAPTER_TYPE_ETHERNET;
215 }
216
217 if (MatchTypeNameWithIndexPattern(network_name, "ipsec") ||
218 MatchTypeNameWithIndexPattern(network_name, "tun") ||
219 MatchTypeNameWithIndexPattern(network_name, "utun") ||
220 MatchTypeNameWithIndexPattern(network_name, "tap")) {
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800221 return ADAPTER_TYPE_VPN;
222 }
223#if defined(WEBRTC_IOS)
224 // Cell networks are pdp_ipN on iOS.
Qingsi Wange53ac042018-05-08 11:55:07 -0700225 if (MatchTypeNameWithIndexPattern(network_name, "pdp_ip")) {
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800226 return ADAPTER_TYPE_CELLULAR;
227 }
Qingsi Wange53ac042018-05-08 11:55:07 -0700228 if (MatchTypeNameWithIndexPattern(network_name, "en")) {
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800229 // This may not be most accurate because sometimes Ethernet interface
230 // name also starts with "en" but it is better than showing it as
231 // "unknown" type.
232 // TODO(honghaiz): Write a proper IOS network manager.
233 return ADAPTER_TYPE_WIFI;
234 }
235#elif defined(WEBRTC_ANDROID)
Qingsi Wange53ac042018-05-08 11:55:07 -0700236 if (MatchTypeNameWithIndexPattern(network_name, "rmnet") ||
237 MatchTypeNameWithIndexPattern(network_name, "rmnet_data") ||
238 MatchTypeNameWithIndexPattern(network_name, "v4-rmnet") ||
239 MatchTypeNameWithIndexPattern(network_name, "v4-rmnet_data")) {
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800240 return ADAPTER_TYPE_CELLULAR;
241 }
Qingsi Wange53ac042018-05-08 11:55:07 -0700242 if (MatchTypeNameWithIndexPattern(network_name, "wlan")) {
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800243 return ADAPTER_TYPE_WIFI;
244 }
245#endif
246
247 return ADAPTER_TYPE_UNKNOWN;
248}
249
Yves Gerey665174f2018-06-19 15:03:05 +0200250NetworkManager::NetworkManager() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000251
Yves Gerey665174f2018-06-19 15:03:05 +0200252NetworkManager::~NetworkManager() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000253
Guo-wei Shieh86cb9232015-08-19 10:57:53 -0700254NetworkManager::EnumerationPermission NetworkManager::enumeration_permission()
255 const {
guoweisea1012b2015-08-21 09:06:28 -0700256 return ENUMERATION_ALLOWED;
Guo-wei Shieh86cb9232015-08-19 10:57:53 -0700257}
258
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800259bool NetworkManager::GetDefaultLocalAddress(int family, IPAddress* addr) const {
260 return false;
261}
262
Qingsi Wang09619332018-09-12 22:51:55 -0700263webrtc::MDnsResponderInterface* NetworkManager::GetMDnsResponder() const {
264 return nullptr;
265}
266
guoweis@webrtc.org2444d962015-01-30 00:09:28 +0000267NetworkManagerBase::NetworkManagerBase()
guoweisea1012b2015-08-21 09:06:28 -0700268 : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED),
Yves Gerey665174f2018-06-19 15:03:05 +0200269 ipv6_enabled_(true) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000270
271NetworkManagerBase::~NetworkManagerBase() {
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000272 for (const auto& kv : networks_map_) {
273 delete kv.second;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000274 }
275}
276
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700277NetworkManager::EnumerationPermission
278NetworkManagerBase::enumeration_permission() const {
279 return enumeration_permission_;
280}
281
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000282void NetworkManagerBase::GetAnyAddressNetworks(NetworkList* networks) {
283 if (!ipv4_any_address_network_) {
284 const rtc::IPAddress ipv4_any_address(INADDR_ANY);
285 ipv4_any_address_network_.reset(
Qingsi Wang9f1de692018-06-28 15:38:09 -0700286 new rtc::Network("any", "any", ipv4_any_address, 0, ADAPTER_TYPE_ANY));
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800287 ipv4_any_address_network_->set_default_local_address_provider(this);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000288 ipv4_any_address_network_->AddIP(ipv4_any_address);
Qingsi Wang09619332018-09-12 22:51:55 -0700289 ipv4_any_address_network_->SetMDnsResponder(GetMDnsResponder());
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000290 }
291 networks->push_back(ipv4_any_address_network_.get());
292
293 if (ipv6_enabled()) {
294 if (!ipv6_any_address_network_) {
295 const rtc::IPAddress ipv6_any_address(in6addr_any);
Qingsi Wang9f1de692018-06-28 15:38:09 -0700296 ipv6_any_address_network_.reset(new rtc::Network(
297 "any", "any", ipv6_any_address, 0, ADAPTER_TYPE_ANY));
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800298 ipv6_any_address_network_->set_default_local_address_provider(this);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000299 ipv6_any_address_network_->AddIP(ipv6_any_address);
Qingsi Wang09619332018-09-12 22:51:55 -0700300 ipv6_any_address_network_->SetMDnsResponder(GetMDnsResponder());
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000301 }
302 networks->push_back(ipv6_any_address_network_.get());
303 }
304}
305
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000306void NetworkManagerBase::GetNetworks(NetworkList* result) const {
guoweis@webrtc.org2444d962015-01-30 00:09:28 +0000307 result->clear();
deadbeef3427f532017-07-26 16:09:33 -0700308 result->insert(result->begin(), networks_.begin(), networks_.end());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000309}
310
311void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
312 bool* changed) {
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000313 NetworkManager::Stats stats;
314 MergeNetworkList(new_networks, changed, &stats);
315}
316
317void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
318 bool* changed,
319 NetworkManager::Stats* stats) {
honghaizdb8cf502015-12-21 13:08:46 -0800320 *changed = false;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000321 // AddressList in this map will track IP addresses for all Networks
322 // with the same key.
323 std::map<std::string, AddressList> consolidated_address_list;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000324 NetworkList list(new_networks);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000325 std::sort(list.begin(), list.end(), CompareNetworks);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000326 // First, build a set of network-keys to the ipaddresses.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000327 for (Network* network : list) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000328 bool might_add_to_merged_list = false;
Yves Gerey665174f2018-06-19 15:03:05 +0200329 std::string key = MakeNetworkKey(network->name(), network->prefix(),
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000330 network->prefix_length());
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000331 if (consolidated_address_list.find(key) ==
332 consolidated_address_list.end()) {
333 AddressList addrlist;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000334 addrlist.net = network;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000335 consolidated_address_list[key] = addrlist;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336 might_add_to_merged_list = true;
337 }
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000338 const std::vector<InterfaceAddress>& addresses = network->GetIPs();
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000339 AddressList& current_list = consolidated_address_list[key];
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000340 for (const InterfaceAddress& address : addresses) {
341 current_list.ips.push_back(address);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000342 }
343 if (!might_add_to_merged_list) {
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000344 delete network;
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000345 } else {
346 if (current_list.ips[0].family() == AF_INET) {
347 stats->ipv4_network_count++;
348 } else {
nisseede5da42017-01-12 05:15:36 -0800349 RTC_DCHECK(current_list.ips[0].family() == AF_INET6);
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000350 stats->ipv6_network_count++;
351 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000352 }
353 }
354
355 // Next, look for existing network objects to re-use.
honghaizdb8cf502015-12-21 13:08:46 -0800356 // Result of Network merge. Element in this list should have unique key.
357 NetworkList merged_list;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000358 for (const auto& kv : consolidated_address_list) {
359 const std::string& key = kv.first;
360 Network* net = kv.second.net;
361 auto existing = networks_map_.find(key);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000362 if (existing == networks_map_.end()) {
363 // This network is new. Place it in the network map.
364 merged_list.push_back(net);
365 networks_map_[key] = net;
honghaiza0c44ea2016-03-23 16:07:48 -0700366 net->set_id(next_available_network_id_++);
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000367 // Also, we might have accumulated IPAddresses from the first
368 // step, set it here.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000369 net->SetIPs(kv.second.ips, true);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000370 *changed = true;
371 } else {
372 // This network exists in the map already. Reset its IP addresses.
honghaizdb8cf502015-12-21 13:08:46 -0800373 Network* existing_net = existing->second;
374 *changed = existing_net->SetIPs(kv.second.ips, *changed);
375 merged_list.push_back(existing_net);
Honghai Zhang351d77b2016-05-20 15:08:29 -0700376 if (net->type() != ADAPTER_TYPE_UNKNOWN &&
377 net->type() != existing_net->type()) {
378 existing_net->set_type(net->type());
379 *changed = true;
380 }
honghaizdb8cf502015-12-21 13:08:46 -0800381 // If the existing network was not active, networks have changed.
382 if (!existing_net->active()) {
383 *changed = true;
384 }
nisseede5da42017-01-12 05:15:36 -0800385 RTC_DCHECK(net->active());
honghaizdb8cf502015-12-21 13:08:46 -0800386 if (existing_net != net) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000387 delete net;
388 }
389 }
Qingsi Wang09619332018-09-12 22:51:55 -0700390 networks_map_[key]->SetMDnsResponder(GetMDnsResponder());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000391 }
honghaizdb8cf502015-12-21 13:08:46 -0800392 // It may still happen that the merged list is a subset of |networks_|.
393 // To detect this change, we compare their sizes.
394 if (merged_list.size() != networks_.size()) {
395 *changed = true;
396 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000397
honghaizdb8cf502015-12-21 13:08:46 -0800398 // If the network list changes, we re-assign |networks_| to the merged list
399 // and re-sort it.
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000400 if (*changed) {
honghaizdb8cf502015-12-21 13:08:46 -0800401 networks_ = merged_list;
402 // Reset the active states of all networks.
403 for (const auto& kv : networks_map_) {
honghaize3c6c822016-02-17 13:00:28 -0800404 Network* network = kv.second;
405 // If |network| is in the newly generated |networks_|, it is active.
406 bool found = std::find(networks_.begin(), networks_.end(), network) !=
407 networks_.end();
408 network->set_active(found);
honghaizdb8cf502015-12-21 13:08:46 -0800409 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000410 std::sort(networks_.begin(), networks_.end(), SortNetworks);
411 // Now network interfaces are sorted, we should set the preference value
412 // for each of the interfaces we are planning to use.
413 // Preference order of network interfaces might have changed from previous
414 // sorting due to addition of higher preference network interface.
415 // Since we have already sorted the network interfaces based on our
416 // requirements, we will just assign a preference value starting with 127,
417 // in decreasing order.
418 int pref = kHighestNetworkPreference;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000419 for (Network* network : networks_) {
420 network->set_preference(pref);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000421 if (pref > 0) {
422 --pref;
423 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100424 RTC_LOG(LS_ERROR) << "Too many network interfaces to handle!";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000425 break;
426 }
427 }
428 }
429}
430
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800431void NetworkManagerBase::set_default_local_addresses(const IPAddress& ipv4,
432 const IPAddress& ipv6) {
433 if (ipv4.family() == AF_INET) {
434 default_local_ipv4_address_ = ipv4;
435 }
436 if (ipv6.family() == AF_INET6) {
437 default_local_ipv6_address_ = ipv6;
438 }
439}
440
441bool NetworkManagerBase::GetDefaultLocalAddress(int family,
442 IPAddress* ipaddr) const {
Guo-wei Shieha34c39e2015-11-25 13:12:26 -0800443 if (family == AF_INET && !default_local_ipv4_address_.IsNil()) {
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800444 *ipaddr = default_local_ipv4_address_;
445 return true;
Guo-wei Shieha34c39e2015-11-25 13:12:26 -0800446 } else if (family == AF_INET6 && !default_local_ipv6_address_.IsNil()) {
honghaizaf83fe62016-04-18 14:50:44 -0700447 Network* ipv6_network = GetNetworkFromAddress(default_local_ipv6_address_);
448 if (ipv6_network) {
449 // If the default ipv6 network's BestIP is different than
450 // default_local_ipv6_address_, use it instead.
451 // This is to prevent potential IP address leakage. See WebRTC bug 5376.
452 *ipaddr = ipv6_network->GetBestIP();
453 } else {
454 *ipaddr = default_local_ipv6_address_;
455 }
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800456 return true;
457 }
458 return false;
459}
460
honghaizaf83fe62016-04-18 14:50:44 -0700461Network* NetworkManagerBase::GetNetworkFromAddress(
462 const rtc::IPAddress& ip) const {
463 for (Network* network : networks_) {
464 const auto& ips = network->GetIPs();
465 if (std::find_if(ips.begin(), ips.end(),
466 [ip](const InterfaceAddress& existing_ip) {
467 return ip == static_cast<rtc::IPAddress>(existing_ip);
468 }) != ips.end()) {
469 return network;
470 }
471 }
472 return nullptr;
473}
474
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000475BasicNetworkManager::BasicNetworkManager()
deadbeef37f5ecf2017-02-27 14:06:41 -0800476 : thread_(nullptr),
477 sent_first_update_(false),
478 start_count_(0),
479 ignore_non_default_routes_(false) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000480
Yves Gerey665174f2018-06-19 15:03:05 +0200481BasicNetworkManager::~BasicNetworkManager() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000482
honghaiz023f3ef2015-10-19 09:39:32 -0700483void BasicNetworkManager::OnNetworksChanged() {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100484 RTC_LOG(LS_INFO) << "Network change was observed";
honghaiz023f3ef2015-10-19 09:39:32 -0700485 UpdateNetworksOnce();
486}
487
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000488#if defined(__native_client__)
489
490bool BasicNetworkManager::CreateNetworks(bool include_ignored,
491 NetworkList* networks) const {
nissec80e7412017-01-11 05:56:46 -0800492 RTC_NOTREACHED();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100493 RTC_LOG(LS_WARNING) << "BasicNetworkManager doesn't work on NaCl yet";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000494 return false;
495}
496
497#elif defined(WEBRTC_POSIX)
498void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800499 IfAddrsConverter* ifaddrs_converter,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000500 bool include_ignored,
501 NetworkList* networks) const {
502 NetworkMap current_networks;
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800503
deadbeef37f5ecf2017-02-27 14:06:41 -0800504 for (struct ifaddrs* cursor = interfaces; cursor != nullptr;
505 cursor = cursor->ifa_next) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000506 IPAddress prefix;
507 IPAddress mask;
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800508 InterfaceAddress ip;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000509 int scope_id = 0;
510
511 // Some interfaces may not have address assigned.
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800512 if (!cursor->ifa_addr || !cursor->ifa_netmask) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000513 continue;
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800514 }
515 // Skip ones which are down.
516 if (!(cursor->ifa_flags & IFF_RUNNING)) {
517 continue;
518 }
519 // Skip unknown family.
520 if (cursor->ifa_addr->sa_family != AF_INET &&
521 cursor->ifa_addr->sa_family != AF_INET6) {
522 continue;
523 }
524 // Skip IPv6 if not enabled.
525 if (cursor->ifa_addr->sa_family == AF_INET6 && !ipv6_enabled()) {
526 continue;
527 }
528 // Convert to InterfaceAddress.
529 if (!ifaddrs_converter->ConvertIfAddrsToIPAddress(cursor, &ip, &mask)) {
530 continue;
531 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000532
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800533 // Special case for IPv6 address.
534 if (cursor->ifa_addr->sa_family == AF_INET6) {
535 if (IsIgnoredIPv6(ip)) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000536 continue;
537 }
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800538 scope_id =
539 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_scope_id;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000540 }
541
Honghai Zhang351d77b2016-05-20 15:08:29 -0700542 AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN;
Qingsi Wangde2ed7d2018-04-27 14:25:37 -0700543 AdapterType vpn_underlying_adapter_type = ADAPTER_TYPE_UNKNOWN;
Honghai Zhang351d77b2016-05-20 15:08:29 -0700544 if (cursor->ifa_flags & IFF_LOOPBACK) {
545 adapter_type = ADAPTER_TYPE_LOOPBACK;
546 } else {
Taylor Brandstetter8bac1d92018-01-24 17:38:00 -0800547 // If there is a network_monitor, use it to get the adapter type.
548 // Otherwise, get the adapter type based on a few name matching rules.
549 if (network_monitor_) {
550 adapter_type = network_monitor_->GetAdapterType(cursor->ifa_name);
551 }
552 if (adapter_type == ADAPTER_TYPE_UNKNOWN) {
553 adapter_type = GetAdapterTypeFromName(cursor->ifa_name);
554 }
Honghai Zhang351d77b2016-05-20 15:08:29 -0700555 }
Qingsi Wangde2ed7d2018-04-27 14:25:37 -0700556
557 if (adapter_type == ADAPTER_TYPE_VPN && network_monitor_) {
558 vpn_underlying_adapter_type =
559 network_monitor_->GetVpnUnderlyingAdapterType(cursor->ifa_name);
560 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000561 int prefix_length = CountIPMaskBits(mask);
562 prefix = TruncateIP(ip, prefix_length);
Yves Gerey665174f2018-06-19 15:03:05 +0200563 std::string key =
564 MakeNetworkKey(std::string(cursor->ifa_name), prefix, prefix_length);
Honghai Zhang351d77b2016-05-20 15:08:29 -0700565 auto iter = current_networks.find(key);
566 if (iter == current_networks.end()) {
Noah Richards2e266e92015-04-07 11:51:56 -0700567 // TODO(phoglund): Need to recognize other types as well.
jbauch555604a2016-04-26 03:13:22 -0700568 std::unique_ptr<Network> network(
569 new Network(cursor->ifa_name, cursor->ifa_name, prefix, prefix_length,
570 adapter_type));
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800571 network->set_default_local_address_provider(this);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000572 network->set_scope_id(scope_id);
573 network->AddIP(ip);
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000574 network->set_ignored(IsIgnoredNetwork(*network));
Qingsi Wangde2ed7d2018-04-27 14:25:37 -0700575 network->set_underlying_type_for_vpn(vpn_underlying_adapter_type);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000576 if (include_ignored || !network->ignored()) {
honghaizdb8cf502015-12-21 13:08:46 -0800577 current_networks[key] = network.get();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000578 networks->push_back(network.release());
579 }
580 } else {
Honghai Zhang351d77b2016-05-20 15:08:29 -0700581 Network* existing_network = iter->second;
582 existing_network->AddIP(ip);
583 if (adapter_type != ADAPTER_TYPE_UNKNOWN) {
584 existing_network->set_type(adapter_type);
Qingsi Wangde2ed7d2018-04-27 14:25:37 -0700585 existing_network->set_underlying_type_for_vpn(
586 vpn_underlying_adapter_type);
Honghai Zhang351d77b2016-05-20 15:08:29 -0700587 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000588 }
589 }
590}
591
592bool BasicNetworkManager::CreateNetworks(bool include_ignored,
593 NetworkList* networks) const {
594 struct ifaddrs* interfaces;
595 int error = getifaddrs(&interfaces);
596 if (error != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100597 RTC_LOG_ERR(LERROR) << "getifaddrs failed to gather interface data: "
598 << error;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000599 return false;
600 }
601
jbauch555604a2016-04-26 03:13:22 -0700602 std::unique_ptr<IfAddrsConverter> ifaddrs_converter(CreateIfAddrsConverter());
Guo-wei Shieh9faf1542015-12-28 14:06:55 -0800603 ConvertIfAddrs(interfaces, ifaddrs_converter.get(), include_ignored,
604 networks);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000605
606 freeifaddrs(interfaces);
607 return true;
608}
609
610#elif defined(WEBRTC_WIN)
611
612unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist,
Yves Gerey665174f2018-06-19 15:03:05 +0200613 const IPAddress& ip,
614 IPAddress* prefix) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000615 IPAddress current_prefix;
616 IPAddress best_prefix;
617 unsigned int best_length = 0;
618 while (prefixlist) {
619 // Look for the longest matching prefix in the prefixlist.
deadbeef37f5ecf2017-02-27 14:06:41 -0800620 if (prefixlist->Address.lpSockaddr == nullptr ||
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000621 prefixlist->Address.lpSockaddr->sa_family != ip.family()) {
622 prefixlist = prefixlist->Next;
623 continue;
624 }
625 switch (prefixlist->Address.lpSockaddr->sa_family) {
626 case AF_INET: {
627 sockaddr_in* v4_addr =
628 reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr);
629 current_prefix = IPAddress(v4_addr->sin_addr);
630 break;
631 }
632 case AF_INET6: {
Yves Gerey665174f2018-06-19 15:03:05 +0200633 sockaddr_in6* v6_addr =
634 reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr);
635 current_prefix = IPAddress(v6_addr->sin6_addr);
636 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000637 }
638 default: {
639 prefixlist = prefixlist->Next;
640 continue;
641 }
642 }
643 if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix &&
644 prefixlist->PrefixLength > best_length) {
645 best_prefix = current_prefix;
646 best_length = prefixlist->PrefixLength;
647 }
648 prefixlist = prefixlist->Next;
649 }
650 *prefix = best_prefix;
651 return best_length;
652}
653
654bool BasicNetworkManager::CreateNetworks(bool include_ignored,
655 NetworkList* networks) const {
656 NetworkMap current_networks;
657 // MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
658 size_t buffer_size = 16384;
jbauch555604a2016-04-26 03:13:22 -0700659 std::unique_ptr<char[]> adapter_info(new char[buffer_size]);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000660 PIP_ADAPTER_ADDRESSES adapter_addrs =
661 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
662 int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
663 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX);
664 int ret = 0;
665 do {
666 adapter_info.reset(new char[buffer_size]);
667 adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
Yves Gerey665174f2018-06-19 15:03:05 +0200668 ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags, 0, adapter_addrs,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000669 reinterpret_cast<PULONG>(&buffer_size));
670 } while (ret == ERROR_BUFFER_OVERFLOW);
671 if (ret != ERROR_SUCCESS) {
672 return false;
673 }
674 int count = 0;
675 while (adapter_addrs) {
676 if (adapter_addrs->OperStatus == IfOperStatusUp) {
677 PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress;
678 PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix;
679 std::string name;
680 std::string description;
tfarinaa41ab932015-10-30 16:08:48 -0700681#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000682 name = ToUtf8(adapter_addrs->FriendlyName,
683 wcslen(adapter_addrs->FriendlyName));
684#endif
685 description = ToUtf8(adapter_addrs->Description,
686 wcslen(adapter_addrs->Description));
687 for (; address; address = address->Next) {
tfarinaa41ab932015-10-30 16:08:48 -0700688#if defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000689 name = rtc::ToString(count);
690#endif
691
692 IPAddress ip;
693 int scope_id = 0;
jbauch555604a2016-04-26 03:13:22 -0700694 std::unique_ptr<Network> network;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000695 switch (address->Address.lpSockaddr->sa_family) {
696 case AF_INET: {
697 sockaddr_in* v4_addr =
698 reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr);
699 ip = IPAddress(v4_addr->sin_addr);
700 break;
701 }
702 case AF_INET6: {
703 if (ipv6_enabled()) {
704 sockaddr_in6* v6_addr =
705 reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
706 scope_id = v6_addr->sin6_scope_id;
707 ip = IPAddress(v6_addr->sin6_addr);
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000708
Taylor Brandstetter01cb5f22018-03-07 15:49:32 -0800709 if (IsIgnoredIPv6(InterfaceAddress(ip))) {
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000710 continue;
711 }
712
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000713 break;
714 } else {
715 continue;
716 }
717 }
Yves Gerey665174f2018-06-19 15:03:05 +0200718 default: { continue; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000719 }
720
721 IPAddress prefix;
722 int prefix_length = GetPrefix(prefixlist, ip, &prefix);
723 std::string key = MakeNetworkKey(name, prefix, prefix_length);
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000724 auto existing_network = current_networks.find(key);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000725 if (existing_network == current_networks.end()) {
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000726 AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN;
Yura Yaroshevich0ce868c2018-05-15 11:15:32 +0300727 switch (adapter_addrs->IfType) {
728 case IF_TYPE_SOFTWARE_LOOPBACK:
729 adapter_type = ADAPTER_TYPE_LOOPBACK;
730 break;
731 case IF_TYPE_ETHERNET_CSMACD:
732 case IF_TYPE_ETHERNET_3MBIT:
733 case IF_TYPE_IEEE80212:
734 case IF_TYPE_FASTETHER:
735 case IF_TYPE_FASTETHER_FX:
736 case IF_TYPE_GIGABITETHERNET:
737 adapter_type = ADAPTER_TYPE_ETHERNET;
738 break;
739 case IF_TYPE_IEEE80211:
740 adapter_type = ADAPTER_TYPE_WIFI;
741 break;
742 case IF_TYPE_WWANPP:
743 case IF_TYPE_WWANPP2:
744 adapter_type = ADAPTER_TYPE_CELLULAR;
745 break;
746 default:
747 // TODO(phoglund): Need to recognize other types as well.
748 adapter_type = ADAPTER_TYPE_UNKNOWN;
749 break;
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000750 }
jbauch555604a2016-04-26 03:13:22 -0700751 std::unique_ptr<Network> network(new Network(
752 name, description, prefix, prefix_length, adapter_type));
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800753 network->set_default_local_address_provider(this);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000754 network->set_scope_id(scope_id);
755 network->AddIP(ip);
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000756 bool ignored = IsIgnoredNetwork(*network);
757 network->set_ignored(ignored);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000758 if (include_ignored || !network->ignored()) {
honghaizdb8cf502015-12-21 13:08:46 -0800759 current_networks[key] = network.get();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000760 networks->push_back(network.release());
761 }
762 } else {
763 (*existing_network).second->AddIP(ip);
764 }
765 }
766 // Count is per-adapter - all 'Networks' created from the same
767 // adapter need to have the same name.
768 ++count;
769 }
770 adapter_addrs = adapter_addrs->Next;
771 }
772 return true;
773}
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000774#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000775
776#if defined(WEBRTC_LINUX)
777bool IsDefaultRoute(const std::string& network_name) {
778 FileStream fs;
deadbeef37f5ecf2017-02-27 14:06:41 -0800779 if (!fs.Open("/proc/net/route", "r", nullptr)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100780 RTC_LOG(LS_WARNING)
781 << "Couldn't read /proc/net/route, skipping default "
782 << "route check (assuming everything is a default route).";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000783 return true;
784 } else {
785 std::string line;
786 while (fs.ReadLine(&line) == SR_SUCCESS) {
787 char iface_name[256];
788 unsigned int iface_ip, iface_gw, iface_mask, iface_flags;
Yves Gerey665174f2018-06-19 15:03:05 +0200789 if (sscanf(line.c_str(), "%255s %8X %8X %4X %*d %*u %*d %8X", iface_name,
790 &iface_ip, &iface_gw, &iface_flags, &iface_mask) == 5 &&
791 network_name == iface_name && iface_mask == 0 &&
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000792 (iface_flags & (RTF_UP | RTF_HOST)) == RTF_UP) {
793 return true;
794 }
795 }
796 }
797 return false;
798}
799#endif
800
801bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const {
802 // Ignore networks on the explicit ignore list.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000803 for (const std::string& ignored_name : network_ignore_list_) {
804 if (network.name() == ignored_name) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000805 return true;
806 }
807 }
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000808
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000809#if defined(WEBRTC_POSIX)
pthatcher@webrtc.orgdfef0282015-01-07 17:20:52 +0000810 // Filter out VMware/VirtualBox interfaces, typically named vmnet1,
811 // vmnet8, or vboxnet0.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000812 if (strncmp(network.name().c_str(), "vmnet", 5) == 0 ||
pthatcher@webrtc.orgdfef0282015-01-07 17:20:52 +0000813 strncmp(network.name().c_str(), "vnic", 4) == 0 ||
814 strncmp(network.name().c_str(), "vboxnet", 7) == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000815 return true;
816 }
817#if defined(WEBRTC_LINUX)
818 // Make sure this is a default route, if we're ignoring non-defaults.
819 if (ignore_non_default_routes_ && !IsDefaultRoute(network.name())) {
820 return true;
821 }
822#endif
823#elif defined(WEBRTC_WIN)
824 // Ignore any HOST side vmware adapters with a description like:
825 // VMware Virtual Ethernet Adapter for VMnet1
826 // but don't ignore any GUEST side adapters with a description like:
827 // VMware Accelerated AMD PCNet Adapter #2
deadbeef37f5ecf2017-02-27 14:06:41 -0800828 if (strstr(network.description().c_str(), "VMnet") != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000829 return true;
830 }
831#endif
832
833 // Ignore any networks with a 0.x.y.z IP
834 if (network.prefix().family() == AF_INET) {
835 return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000);
836 }
guoweis@webrtc.orgbbce5ef2015-03-05 04:38:29 +0000837
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000838 return false;
839}
840
841void BasicNetworkManager::StartUpdating() {
842 thread_ = Thread::Current();
843 if (start_count_) {
844 // If network interfaces are already discovered and signal is sent,
845 // we should trigger network signal immediately for the new clients
846 // to start allocating ports.
847 if (sent_first_update_)
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700848 thread_->Post(RTC_FROM_HERE, this, kSignalNetworksMessage);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000849 } else {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700850 thread_->Post(RTC_FROM_HERE, this, kUpdateNetworksMessage);
honghaiz023f3ef2015-10-19 09:39:32 -0700851 StartNetworkMonitor();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000852 }
853 ++start_count_;
854}
855
856void BasicNetworkManager::StopUpdating() {
nisseede5da42017-01-12 05:15:36 -0800857 RTC_DCHECK(Thread::Current() == thread_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000858 if (!start_count_)
859 return;
860
861 --start_count_;
862 if (!start_count_) {
863 thread_->Clear(this);
864 sent_first_update_ = false;
honghaiz023f3ef2015-10-19 09:39:32 -0700865 StopNetworkMonitor();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000866 }
867}
868
honghaiz023f3ef2015-10-19 09:39:32 -0700869void BasicNetworkManager::StartNetworkMonitor() {
870 NetworkMonitorFactory* factory = NetworkMonitorFactory::GetFactory();
871 if (factory == nullptr) {
872 return;
873 }
honghaiz023f3ef2015-10-19 09:39:32 -0700874 if (!network_monitor_) {
honghaizcec0a082016-01-15 14:49:09 -0800875 network_monitor_.reset(factory->CreateNetworkMonitor());
876 if (!network_monitor_) {
877 return;
878 }
skvlad979c2682016-06-10 15:24:13 -0700879 network_monitor_->SignalNetworksChanged.connect(
880 this, &BasicNetworkManager::OnNetworksChanged);
honghaiz023f3ef2015-10-19 09:39:32 -0700881 }
honghaiz023f3ef2015-10-19 09:39:32 -0700882 network_monitor_->Start();
883}
884
885void BasicNetworkManager::StopNetworkMonitor() {
886 if (!network_monitor_) {
887 return;
888 }
889 network_monitor_->Stop();
honghaiz023f3ef2015-10-19 09:39:32 -0700890}
891
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000892void BasicNetworkManager::OnMessage(Message* msg) {
893 switch (msg->message_id) {
honghaiz023f3ef2015-10-19 09:39:32 -0700894 case kUpdateNetworksMessage: {
895 UpdateNetworksContinually();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000896 break;
897 }
Yves Gerey665174f2018-06-19 15:03:05 +0200898 case kSignalNetworksMessage: {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000899 SignalNetworksChanged();
900 break;
901 }
902 default:
nissec80e7412017-01-11 05:56:46 -0800903 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000904 }
905}
906
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800907IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const {
nisseede5da42017-01-12 05:15:36 -0800908 RTC_DCHECK(thread_ == Thread::Current());
909 RTC_DCHECK(thread_->socketserver() != nullptr);
910 RTC_DCHECK(family == AF_INET || family == AF_INET6);
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800911
jbauch555604a2016-04-26 03:13:22 -0700912 std::unique_ptr<AsyncSocket> socket(
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800913 thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));
914 if (!socket) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100915 RTC_LOG_ERR(LERROR) << "Socket creation failed";
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800916 return IPAddress();
917 }
918
guoweis56271ed2016-01-15 14:45:06 -0800919 if (socket->Connect(SocketAddress(
920 family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host, kPublicPort)) <
921 0) {
Yves Gerey665174f2018-06-19 15:03:05 +0200922 if (socket->GetError() != ENETUNREACH &&
923 socket->GetError() != EHOSTUNREACH) {
skvlad75024012016-09-29 12:59:35 -0700924 // Ignore the expected case of "host/net unreachable" - which happens if
925 // the network is V4- or V6-only.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100926 RTC_LOG(LS_INFO) << "Connect failed with " << socket->GetError();
skvlad75024012016-09-29 12:59:35 -0700927 }
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800928 return IPAddress();
929 }
930 return socket->GetLocalAddress().ipaddr();
931}
932
honghaiz023f3ef2015-10-19 09:39:32 -0700933void BasicNetworkManager::UpdateNetworksOnce() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000934 if (!start_count_)
935 return;
936
nisseede5da42017-01-12 05:15:36 -0800937 RTC_DCHECK(Thread::Current() == thread_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000938
939 NetworkList list;
940 if (!CreateNetworks(false, &list)) {
941 SignalError();
942 } else {
943 bool changed;
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800944 NetworkManager::Stats stats;
945 MergeNetworkList(list, &changed, &stats);
946 set_default_local_addresses(QueryDefaultLocalAddress(AF_INET),
947 QueryDefaultLocalAddress(AF_INET6));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000948 if (changed || !sent_first_update_) {
949 SignalNetworksChanged();
950 sent_first_update_ = true;
951 }
952 }
honghaiz023f3ef2015-10-19 09:39:32 -0700953}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000954
honghaiz023f3ef2015-10-19 09:39:32 -0700955void BasicNetworkManager::UpdateNetworksContinually() {
956 UpdateNetworksOnce();
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700957 thread_->PostDelayed(RTC_FROM_HERE, kNetworksUpdateIntervalMs, this,
958 kUpdateNetworksMessage);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000959}
960
honghaizdb8cf502015-12-21 13:08:46 -0800961void BasicNetworkManager::DumpNetworks() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000962 NetworkList list;
honghaizdb8cf502015-12-21 13:08:46 -0800963 GetNetworks(&list);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100964 RTC_LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:";
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000965 for (const Network* network : list) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100966 RTC_LOG(LS_INFO) << network->ToString() << ": " << network->description()
967 << ", active ? " << network->active()
968 << ((network->ignored()) ? ", Ignored" : "");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000969 }
970}
971
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800972Network::Network(const std::string& name,
973 const std::string& desc,
974 const IPAddress& prefix,
975 int prefix_length)
976 : name_(name),
977 description_(desc),
978 prefix_(prefix),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000979 prefix_length_(prefix_length),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800980 key_(MakeNetworkKey(name, prefix, prefix_length)),
981 scope_id_(0),
982 ignored_(false),
983 type_(ADAPTER_TYPE_UNKNOWN),
984 preference_(0) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000985
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800986Network::Network(const std::string& name,
987 const std::string& desc,
988 const IPAddress& prefix,
989 int prefix_length,
990 AdapterType type)
991 : name_(name),
992 description_(desc),
993 prefix_(prefix),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000994 prefix_length_(prefix_length),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800995 key_(MakeNetworkKey(name, prefix, prefix_length)),
996 scope_id_(0),
997 ignored_(false),
998 type_(type),
999 preference_(0) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001000
Steve Anton9de3aac2017-10-24 10:08:26 -07001001Network::Network(const Network&) = default;
1002
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001003Network::~Network() = default;
1004
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001005// Sets the addresses of this network. Returns true if the address set changed.
1006// Change detection is short circuited if the changed argument is true.
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +00001007bool Network::SetIPs(const std::vector<InterfaceAddress>& ips, bool changed) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001008 // Detect changes with a nested loop; n-squared but we expect on the order
1009 // of 2-3 addresses per network.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +00001010 changed = changed || ips.size() != ips_.size();
1011 if (!changed) {
1012 for (const InterfaceAddress& ip : ips) {
1013 if (std::find(ips_.begin(), ips_.end(), ip) == ips_.end()) {
1014 changed = true;
1015 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001016 }
1017 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001018 }
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +00001019
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001020 ips_ = ips;
1021 return changed;
1022}
1023
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +00001024// Select the best IP address to use from this Network.
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001025IPAddress Network::GetBestIP() const {
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +00001026 if (ips_.size() == 0) {
1027 return IPAddress();
1028 }
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001029
1030 if (prefix_.family() == AF_INET) {
1031 return static_cast<IPAddress>(ips_.at(0));
1032 }
1033
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +00001034 InterfaceAddress selected_ip, ula_ip;
1035
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +00001036 for (const InterfaceAddress& ip : ips_) {
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +00001037 // Ignore any address which has been deprecated already.
1038 if (ip.ipv6_flags() & IPV6_ADDRESS_FLAG_DEPRECATED)
1039 continue;
1040
1041 // ULA address should only be returned when we have no other
1042 // global IP.
1043 if (IPIsULA(static_cast<const IPAddress&>(ip))) {
1044 ula_ip = ip;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001045 continue;
1046 }
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +00001047 selected_ip = ip;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001048
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +00001049 // Search could stop once a temporary non-deprecated one is found.
1050 if (ip.ipv6_flags() & IPV6_ADDRESS_FLAG_TEMPORARY)
1051 break;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001052 }
1053
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +00001054 // No proper global IPv6 address found, use ULA instead.
1055 if (IPIsUnspec(selected_ip) && !IPIsUnspec(ula_ip)) {
1056 selected_ip = ula_ip;
1057 }
1058
1059 return static_cast<IPAddress>(selected_ip);
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001060}
1061
Qingsi Wangde2ed7d2018-04-27 14:25:37 -07001062uint16_t Network::GetCost() const {
1063 AdapterType type = IsVpn() ? underlying_type_for_vpn_ : type_;
1064 return ComputeNetworkCostByType(type);
1065}
1066
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001067std::string Network::ToString() const {
Jonas Olsson366a50c2018-09-06 13:41:30 +02001068 rtc::StringBuilder ss;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +00001069 // Print out the first space-terminated token of the network desc, plus
1070 // the IP address.
Qingsi Wangde2ed7d2018-04-27 14:25:37 -07001071 ss << "Net[" << description_.substr(0, description_.find(' ')) << ":"
1072 << prefix_.ToSensitiveString() << "/" << prefix_length_ << ":"
1073 << AdapterTypeToString(type_);
1074 if (IsVpn()) {
1075 ss << "/" << AdapterTypeToString(underlying_type_for_vpn_);
1076 }
Qingsi Wang10a0e512018-05-16 13:37:03 -07001077 ss << ":id=" << id_ << "]";
Jonas Olsson84df1c72018-09-14 16:59:32 +02001078 return ss.Release();
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +00001079}
1080
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001081} // namespace rtc