blob: 2dcfa1762375f96654e9be8130ebdd2a38c319ac [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
11#ifdef HAVE_CONFIG_H
12#include "config.h"
13#endif
14
15#include "webrtc/base/network.h"
16
17#if defined(WEBRTC_POSIX)
18// linux/if.h can't be included at the same time as the posix sys/if.h, and
19// it's transitively required by linux/route.h, so include that version on
20// linux instead of the standard posix one.
21#if defined(WEBRTC_LINUX)
22#include <linux/if.h>
23#include <linux/route.h>
24#elif !defined(__native_client__)
25#include <net/if.h>
26#endif
Guo-wei Shieha6c86b22015-12-22 20:17:30 -080027#include <sys/socket.h>
28#include <sys/utsname.h>
29#include <sys/ioctl.h>
30#include <unistd.h>
31#include <errno.h>
32
33#if defined(WEBRTC_ANDROID)
34#include "webrtc/base/ifaddrs-android.h"
35#elif !defined(__native_client__)
36#include <ifaddrs.h>
37#endif
38
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000039#endif // WEBRTC_POSIX
40
41#if defined(WEBRTC_WIN)
42#include "webrtc/base/win32.h"
43#include <Iphlpapi.h>
44#endif
45
46#include <stdio.h>
47
48#include <algorithm>
49
50#include "webrtc/base/logging.h"
honghaiz023f3ef2015-10-19 09:39:32 -070051#include "webrtc/base/networkmonitor.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000052#include "webrtc/base/scoped_ptr.h"
53#include "webrtc/base/socket.h" // includes something that makes windows happy
54#include "webrtc/base/stream.h"
55#include "webrtc/base/stringencode.h"
56#include "webrtc/base/thread.h"
57
58namespace rtc {
59namespace {
60
guoweis@webrtc.org2444d962015-01-30 00:09:28 +000061// Turning on IPv6 could make many IPv6 interfaces available for connectivity
62// check and delay the call setup time. kMaxIPv6Networks is the default upper
63// limit of IPv6 networks but could be changed by set_max_ipv6_networks().
64const int kMaxIPv6Networks = 5;
65
Peter Boström0c4e06b2015-10-07 12:23:21 +020066const uint32_t kUpdateNetworksMessage = 1;
67const uint32_t kSignalNetworksMessage = 2;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000068
69// Fetch list of networks every two seconds.
70const int kNetworksUpdateIntervalMs = 2000;
71
72const int kHighestNetworkPreference = 127;
73
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +000074typedef struct {
75 Network* net;
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +000076 std::vector<InterfaceAddress> ips;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +000077} AddressList;
78
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000079bool CompareNetworks(const Network* a, const Network* b) {
80 if (a->prefix_length() == b->prefix_length()) {
81 if (a->name() == b->name()) {
82 return a->prefix() < b->prefix();
83 }
84 }
85 return a->name() < b->name();
86}
87
88bool SortNetworks(const Network* a, const Network* b) {
89 // Network types will be preferred above everything else while sorting
90 // Networks.
91
92 // Networks are sorted first by type.
93 if (a->type() != b->type()) {
94 return a->type() < b->type();
95 }
96
guoweis@webrtc.org369a6372014-09-17 22:37:29 +000097 IPAddress ip_a = a->GetBestIP();
98 IPAddress ip_b = b->GetBestIP();
99
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000100 // After type, networks are sorted by IP address precedence values
101 // from RFC 3484-bis
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000102 if (IPAddressPrecedence(ip_a) != IPAddressPrecedence(ip_b)) {
103 return IPAddressPrecedence(ip_a) > IPAddressPrecedence(ip_b);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000104 }
105
106 // TODO(mallinath) - Add VPN and Link speed conditions while sorting.
107
108 // Networks are sorted last by key.
109 return a->key() > b->key();
110}
111
112std::string AdapterTypeToString(AdapterType type) {
113 switch (type) {
114 case ADAPTER_TYPE_UNKNOWN:
115 return "Unknown";
116 case ADAPTER_TYPE_ETHERNET:
117 return "Ethernet";
118 case ADAPTER_TYPE_WIFI:
119 return "Wifi";
120 case ADAPTER_TYPE_CELLULAR:
121 return "Cellular";
122 case ADAPTER_TYPE_VPN:
123 return "VPN";
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000124 case ADAPTER_TYPE_LOOPBACK:
125 return "Loopback";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000126 default:
henrikg91d6ede2015-09-17 00:24:34 -0700127 RTC_DCHECK(false) << "Invalid type " << type;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000128 return std::string();
129 }
130}
131
Guo-wei Shieha6c86b22015-12-22 20:17:30 -0800132bool IsIgnoredIPv6(const IPAddress& ip) {
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000133 if (ip.family() != AF_INET6) {
134 return false;
135 }
136
137 // Link-local addresses require scope id to be bound successfully.
138 // However, our IPAddress structure doesn't carry that so the
139 // information is lost and causes binding failure.
140 if (IPIsLinkLocal(ip)) {
141 return true;
142 }
143
144 // Any MAC based IPv6 should be avoided to prevent the MAC tracking.
145 if (IPIsMacBased(ip)) {
146 return true;
147 }
148
149 return false;
150}
151
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000152} // namespace
153
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800154// These addresses are used as the targets to find out the default local address
155// on a multi-homed endpoint. They are actually DNS servers.
156const char kPublicIPv4Host[] = "8.8.8.8";
157const char kPublicIPv6Host[] = "2001:4860:4860::8888";
158const int kPublicPort = 53; // DNS port.
159
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000160std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
161 int prefix_length) {
162 std::ostringstream ost;
163 ost << name << "%" << prefix.ToString() << "/" << prefix_length;
164 return ost.str();
165}
166
167NetworkManager::NetworkManager() {
168}
169
170NetworkManager::~NetworkManager() {
171}
172
Guo-wei Shieh86cb9232015-08-19 10:57:53 -0700173NetworkManager::EnumerationPermission NetworkManager::enumeration_permission()
174 const {
guoweisea1012b2015-08-21 09:06:28 -0700175 return ENUMERATION_ALLOWED;
Guo-wei Shieh86cb9232015-08-19 10:57:53 -0700176}
177
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800178bool NetworkManager::GetDefaultLocalAddress(int family, IPAddress* addr) const {
179 return false;
180}
181
guoweis@webrtc.org2444d962015-01-30 00:09:28 +0000182NetworkManagerBase::NetworkManagerBase()
guoweisea1012b2015-08-21 09:06:28 -0700183 : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED),
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700184 max_ipv6_networks_(kMaxIPv6Networks),
185 ipv6_enabled_(true) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000186}
187
188NetworkManagerBase::~NetworkManagerBase() {
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000189 for (const auto& kv : networks_map_) {
190 delete kv.second;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000191 }
192}
193
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700194NetworkManager::EnumerationPermission
195NetworkManagerBase::enumeration_permission() const {
196 return enumeration_permission_;
197}
198
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000199void NetworkManagerBase::GetAnyAddressNetworks(NetworkList* networks) {
200 if (!ipv4_any_address_network_) {
201 const rtc::IPAddress ipv4_any_address(INADDR_ANY);
202 ipv4_any_address_network_.reset(
203 new rtc::Network("any", "any", ipv4_any_address, 0));
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800204 ipv4_any_address_network_->set_default_local_address_provider(this);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000205 ipv4_any_address_network_->AddIP(ipv4_any_address);
206 }
207 networks->push_back(ipv4_any_address_network_.get());
208
209 if (ipv6_enabled()) {
210 if (!ipv6_any_address_network_) {
211 const rtc::IPAddress ipv6_any_address(in6addr_any);
212 ipv6_any_address_network_.reset(
213 new rtc::Network("any", "any", ipv6_any_address, 0));
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800214 ipv6_any_address_network_->set_default_local_address_provider(this);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000215 ipv6_any_address_network_->AddIP(ipv6_any_address);
216 }
217 networks->push_back(ipv6_any_address_network_.get());
218 }
219}
220
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000221void NetworkManagerBase::GetNetworks(NetworkList* result) const {
guoweis@webrtc.org2444d962015-01-30 00:09:28 +0000222 int ipv6_networks = 0;
223 result->clear();
224 for (Network* network : networks_) {
225 // Keep the number of IPv6 networks under |max_ipv6_networks_|.
226 if (network->prefix().family() == AF_INET6) {
227 if (ipv6_networks >= max_ipv6_networks_) {
228 continue;
229 }
230 ++ipv6_networks;
231 }
232 result->push_back(network);
233 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000234}
235
236void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
237 bool* changed) {
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000238 NetworkManager::Stats stats;
239 MergeNetworkList(new_networks, changed, &stats);
240}
241
242void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
243 bool* changed,
244 NetworkManager::Stats* stats) {
honghaizdb8cf502015-12-21 13:08:46 -0800245 *changed = false;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000246 // AddressList in this map will track IP addresses for all Networks
247 // with the same key.
248 std::map<std::string, AddressList> consolidated_address_list;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000249 NetworkList list(new_networks);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000250 std::sort(list.begin(), list.end(), CompareNetworks);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000251 // First, build a set of network-keys to the ipaddresses.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000252 for (Network* network : list) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000253 bool might_add_to_merged_list = false;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000254 std::string key = MakeNetworkKey(network->name(),
255 network->prefix(),
256 network->prefix_length());
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000257 if (consolidated_address_list.find(key) ==
258 consolidated_address_list.end()) {
259 AddressList addrlist;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000260 addrlist.net = network;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000261 consolidated_address_list[key] = addrlist;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000262 might_add_to_merged_list = true;
263 }
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000264 const std::vector<InterfaceAddress>& addresses = network->GetIPs();
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000265 AddressList& current_list = consolidated_address_list[key];
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000266 for (const InterfaceAddress& address : addresses) {
267 current_list.ips.push_back(address);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000268 }
269 if (!might_add_to_merged_list) {
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000270 delete network;
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000271 } else {
272 if (current_list.ips[0].family() == AF_INET) {
273 stats->ipv4_network_count++;
274 } else {
275 ASSERT(current_list.ips[0].family() == AF_INET6);
276 stats->ipv6_network_count++;
277 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000278 }
279 }
280
281 // Next, look for existing network objects to re-use.
honghaizdb8cf502015-12-21 13:08:46 -0800282 // Result of Network merge. Element in this list should have unique key.
283 NetworkList merged_list;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000284 for (const auto& kv : consolidated_address_list) {
285 const std::string& key = kv.first;
286 Network* net = kv.second.net;
287 auto existing = networks_map_.find(key);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000288 if (existing == networks_map_.end()) {
289 // This network is new. Place it in the network map.
290 merged_list.push_back(net);
291 networks_map_[key] = net;
guoweis@webrtc.org4bbd3c82014-09-09 13:54:45 +0000292 // Also, we might have accumulated IPAddresses from the first
293 // step, set it here.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000294 net->SetIPs(kv.second.ips, true);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000295 *changed = true;
296 } else {
297 // This network exists in the map already. Reset its IP addresses.
honghaizdb8cf502015-12-21 13:08:46 -0800298 Network* existing_net = existing->second;
299 *changed = existing_net->SetIPs(kv.second.ips, *changed);
300 merged_list.push_back(existing_net);
301 // If the existing network was not active, networks have changed.
302 if (!existing_net->active()) {
303 *changed = true;
304 }
305 ASSERT(net->active());
306 if (existing_net != net) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000307 delete net;
308 }
309 }
310 }
honghaizdb8cf502015-12-21 13:08:46 -0800311 // It may still happen that the merged list is a subset of |networks_|.
312 // To detect this change, we compare their sizes.
313 if (merged_list.size() != networks_.size()) {
314 *changed = true;
315 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000316
honghaizdb8cf502015-12-21 13:08:46 -0800317 // If the network list changes, we re-assign |networks_| to the merged list
318 // and re-sort it.
guoweis@webrtc.orga094cac2015-01-28 19:34:05 +0000319 if (*changed) {
honghaizdb8cf502015-12-21 13:08:46 -0800320 networks_ = merged_list;
321 // Reset the active states of all networks.
322 for (const auto& kv : networks_map_) {
323 kv.second->set_active(false);
324 }
325 for (Network* network : networks_) {
326 network->set_active(true);
327 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000328 std::sort(networks_.begin(), networks_.end(), SortNetworks);
329 // Now network interfaces are sorted, we should set the preference value
330 // for each of the interfaces we are planning to use.
331 // Preference order of network interfaces might have changed from previous
332 // sorting due to addition of higher preference network interface.
333 // Since we have already sorted the network interfaces based on our
334 // requirements, we will just assign a preference value starting with 127,
335 // in decreasing order.
336 int pref = kHighestNetworkPreference;
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000337 for (Network* network : networks_) {
338 network->set_preference(pref);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000339 if (pref > 0) {
340 --pref;
341 } else {
342 LOG(LS_ERROR) << "Too many network interfaces to handle!";
343 break;
344 }
345 }
346 }
347}
348
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800349void NetworkManagerBase::set_default_local_addresses(const IPAddress& ipv4,
350 const IPAddress& ipv6) {
351 if (ipv4.family() == AF_INET) {
352 default_local_ipv4_address_ = ipv4;
353 }
354 if (ipv6.family() == AF_INET6) {
355 default_local_ipv6_address_ = ipv6;
356 }
357}
358
359bool NetworkManagerBase::GetDefaultLocalAddress(int family,
360 IPAddress* ipaddr) const {
Guo-wei Shieha34c39e2015-11-25 13:12:26 -0800361 if (family == AF_INET && !default_local_ipv4_address_.IsNil()) {
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800362 *ipaddr = default_local_ipv4_address_;
363 return true;
Guo-wei Shieha34c39e2015-11-25 13:12:26 -0800364 } else if (family == AF_INET6 && !default_local_ipv6_address_.IsNil()) {
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800365 *ipaddr = default_local_ipv6_address_;
366 return true;
367 }
368 return false;
369}
370
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000371BasicNetworkManager::BasicNetworkManager()
372 : thread_(NULL), sent_first_update_(false), start_count_(0),
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000373 network_ignore_mask_(kDefaultNetworkIgnoreMask),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000374 ignore_non_default_routes_(false) {
375}
376
377BasicNetworkManager::~BasicNetworkManager() {
378}
379
honghaiz023f3ef2015-10-19 09:39:32 -0700380void BasicNetworkManager::OnNetworksChanged() {
381 LOG(LS_VERBOSE) << "Network change was observed at the network manager";
382 UpdateNetworksOnce();
383}
384
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000385#if defined(__native_client__)
386
387bool BasicNetworkManager::CreateNetworks(bool include_ignored,
388 NetworkList* networks) const {
389 ASSERT(false);
390 LOG(LS_WARNING) << "BasicNetworkManager doesn't work on NaCl yet";
391 return false;
392}
393
394#elif defined(WEBRTC_POSIX)
395void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
396 bool include_ignored,
397 NetworkList* networks) const {
398 NetworkMap current_networks;
399 for (struct ifaddrs* cursor = interfaces;
400 cursor != NULL; cursor = cursor->ifa_next) {
401 IPAddress prefix;
402 IPAddress mask;
Guo-wei Shieha6c86b22015-12-22 20:17:30 -0800403 IPAddress ip;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000404 int scope_id = 0;
405
406 // Some interfaces may not have address assigned.
Guo-wei Shieha6c86b22015-12-22 20:17:30 -0800407 if (!cursor->ifa_addr || !cursor->ifa_netmask)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000408 continue;
409
Guo-wei Shieha6c86b22015-12-22 20:17:30 -0800410 switch (cursor->ifa_addr->sa_family) {
411 case AF_INET: {
412 ip = IPAddress(
413 reinterpret_cast<sockaddr_in*>(cursor->ifa_addr)->sin_addr);
414 mask = IPAddress(
415 reinterpret_cast<sockaddr_in*>(cursor->ifa_netmask)->sin_addr);
416 break;
417 }
418 case AF_INET6: {
419 if (ipv6_enabled()) {
420 ip = IPAddress(
421 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_addr);
422
423 if (IsIgnoredIPv6(ip)) {
424 continue;
425 }
426
427 mask = IPAddress(
428 reinterpret_cast<sockaddr_in6*>(cursor->ifa_netmask)->sin6_addr);
429 scope_id =
430 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_scope_id;
431 break;
432 } else {
433 continue;
434 }
435 }
436 default: {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000437 continue;
438 }
439 }
440
441 int prefix_length = CountIPMaskBits(mask);
442 prefix = TruncateIP(ip, prefix_length);
443 std::string key = MakeNetworkKey(std::string(cursor->ifa_name),
444 prefix, prefix_length);
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000445 auto existing_network = current_networks.find(key);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000446 if (existing_network == current_networks.end()) {
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000447 AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN;
448 if (cursor->ifa_flags & IFF_LOOPBACK) {
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000449 adapter_type = ADAPTER_TYPE_LOOPBACK;
450 }
Noah Richards2e266e92015-04-07 11:51:56 -0700451#if defined(WEBRTC_IOS)
452 // Cell networks are pdp_ipN on iOS.
453 if (strncmp(cursor->ifa_name, "pdp_ip", 6) == 0) {
454 adapter_type = ADAPTER_TYPE_CELLULAR;
455 }
456#endif
457 // TODO(phoglund): Need to recognize other types as well.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000458 scoped_ptr<Network> network(new Network(cursor->ifa_name,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800459 cursor->ifa_name, prefix,
460 prefix_length, adapter_type));
461 network->set_default_local_address_provider(this);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000462 network->set_scope_id(scope_id);
463 network->AddIP(ip);
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000464 network->set_ignored(IsIgnoredNetwork(*network));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000465 if (include_ignored || !network->ignored()) {
honghaizdb8cf502015-12-21 13:08:46 -0800466 current_networks[key] = network.get();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000467 networks->push_back(network.release());
468 }
469 } else {
470 (*existing_network).second->AddIP(ip);
471 }
472 }
473}
474
475bool BasicNetworkManager::CreateNetworks(bool include_ignored,
476 NetworkList* networks) const {
477 struct ifaddrs* interfaces;
478 int error = getifaddrs(&interfaces);
479 if (error != 0) {
480 LOG_ERR(LERROR) << "getifaddrs failed to gather interface data: " << error;
481 return false;
482 }
483
Guo-wei Shieha6c86b22015-12-22 20:17:30 -0800484 ConvertIfAddrs(interfaces, include_ignored, networks);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000485
486 freeifaddrs(interfaces);
487 return true;
488}
489
490#elif defined(WEBRTC_WIN)
491
492unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist,
493 const IPAddress& ip, IPAddress* prefix) {
494 IPAddress current_prefix;
495 IPAddress best_prefix;
496 unsigned int best_length = 0;
497 while (prefixlist) {
498 // Look for the longest matching prefix in the prefixlist.
499 if (prefixlist->Address.lpSockaddr == NULL ||
500 prefixlist->Address.lpSockaddr->sa_family != ip.family()) {
501 prefixlist = prefixlist->Next;
502 continue;
503 }
504 switch (prefixlist->Address.lpSockaddr->sa_family) {
505 case AF_INET: {
506 sockaddr_in* v4_addr =
507 reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr);
508 current_prefix = IPAddress(v4_addr->sin_addr);
509 break;
510 }
511 case AF_INET6: {
512 sockaddr_in6* v6_addr =
513 reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr);
514 current_prefix = IPAddress(v6_addr->sin6_addr);
515 break;
516 }
517 default: {
518 prefixlist = prefixlist->Next;
519 continue;
520 }
521 }
522 if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix &&
523 prefixlist->PrefixLength > best_length) {
524 best_prefix = current_prefix;
525 best_length = prefixlist->PrefixLength;
526 }
527 prefixlist = prefixlist->Next;
528 }
529 *prefix = best_prefix;
530 return best_length;
531}
532
533bool BasicNetworkManager::CreateNetworks(bool include_ignored,
534 NetworkList* networks) const {
535 NetworkMap current_networks;
536 // MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
537 size_t buffer_size = 16384;
538 scoped_ptr<char[]> adapter_info(new char[buffer_size]);
539 PIP_ADAPTER_ADDRESSES adapter_addrs =
540 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
541 int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
542 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX);
543 int ret = 0;
544 do {
545 adapter_info.reset(new char[buffer_size]);
546 adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
547 ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags,
548 0, adapter_addrs,
549 reinterpret_cast<PULONG>(&buffer_size));
550 } while (ret == ERROR_BUFFER_OVERFLOW);
551 if (ret != ERROR_SUCCESS) {
552 return false;
553 }
554 int count = 0;
555 while (adapter_addrs) {
556 if (adapter_addrs->OperStatus == IfOperStatusUp) {
557 PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress;
558 PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix;
559 std::string name;
560 std::string description;
tfarinaa41ab932015-10-30 16:08:48 -0700561#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000562 name = ToUtf8(adapter_addrs->FriendlyName,
563 wcslen(adapter_addrs->FriendlyName));
564#endif
565 description = ToUtf8(adapter_addrs->Description,
566 wcslen(adapter_addrs->Description));
567 for (; address; address = address->Next) {
tfarinaa41ab932015-10-30 16:08:48 -0700568#if defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000569 name = rtc::ToString(count);
570#endif
571
572 IPAddress ip;
573 int scope_id = 0;
574 scoped_ptr<Network> network;
575 switch (address->Address.lpSockaddr->sa_family) {
576 case AF_INET: {
577 sockaddr_in* v4_addr =
578 reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr);
579 ip = IPAddress(v4_addr->sin_addr);
580 break;
581 }
582 case AF_INET6: {
583 if (ipv6_enabled()) {
584 sockaddr_in6* v6_addr =
585 reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
586 scope_id = v6_addr->sin6_scope_id;
587 ip = IPAddress(v6_addr->sin6_addr);
guoweis@webrtc.orgb91d0f52015-03-17 14:43:20 +0000588
589 if (IsIgnoredIPv6(ip)) {
590 continue;
591 }
592
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000593 break;
594 } else {
595 continue;
596 }
597 }
598 default: {
599 continue;
600 }
601 }
602
603 IPAddress prefix;
604 int prefix_length = GetPrefix(prefixlist, ip, &prefix);
605 std::string key = MakeNetworkKey(name, prefix, prefix_length);
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000606 auto existing_network = current_networks.find(key);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000607 if (existing_network == current_networks.end()) {
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000608 AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN;
609 if (adapter_addrs->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
610 // TODO(phoglund): Need to recognize other types as well.
611 adapter_type = ADAPTER_TYPE_LOOPBACK;
612 }
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800613 scoped_ptr<Network> network(new Network(name, description, prefix,
614 prefix_length, adapter_type));
615 network->set_default_local_address_provider(this);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000616 network->set_scope_id(scope_id);
617 network->AddIP(ip);
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000618 bool ignored = IsIgnoredNetwork(*network);
619 network->set_ignored(ignored);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000620 if (include_ignored || !network->ignored()) {
honghaizdb8cf502015-12-21 13:08:46 -0800621 current_networks[key] = network.get();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000622 networks->push_back(network.release());
623 }
624 } else {
625 (*existing_network).second->AddIP(ip);
626 }
627 }
628 // Count is per-adapter - all 'Networks' created from the same
629 // adapter need to have the same name.
630 ++count;
631 }
632 adapter_addrs = adapter_addrs->Next;
633 }
634 return true;
635}
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000636#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000637
638#if defined(WEBRTC_LINUX)
639bool IsDefaultRoute(const std::string& network_name) {
640 FileStream fs;
641 if (!fs.Open("/proc/net/route", "r", NULL)) {
642 LOG(LS_WARNING) << "Couldn't read /proc/net/route, skipping default "
643 << "route check (assuming everything is a default route).";
644 return true;
645 } else {
646 std::string line;
647 while (fs.ReadLine(&line) == SR_SUCCESS) {
648 char iface_name[256];
649 unsigned int iface_ip, iface_gw, iface_mask, iface_flags;
650 if (sscanf(line.c_str(),
651 "%255s %8X %8X %4X %*d %*u %*d %8X",
652 iface_name, &iface_ip, &iface_gw,
653 &iface_flags, &iface_mask) == 5 &&
654 network_name == iface_name &&
655 iface_mask == 0 &&
656 (iface_flags & (RTF_UP | RTF_HOST)) == RTF_UP) {
657 return true;
658 }
659 }
660 }
661 return false;
662}
663#endif
664
665bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const {
666 // Ignore networks on the explicit ignore list.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000667 for (const std::string& ignored_name : network_ignore_list_) {
668 if (network.name() == ignored_name) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000669 return true;
670 }
671 }
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000672
673 if (network_ignore_mask_ & network.type()) {
674 return true;
675 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000676#if defined(WEBRTC_POSIX)
pthatcher@webrtc.orgdfef0282015-01-07 17:20:52 +0000677 // Filter out VMware/VirtualBox interfaces, typically named vmnet1,
678 // vmnet8, or vboxnet0.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000679 if (strncmp(network.name().c_str(), "vmnet", 5) == 0 ||
pthatcher@webrtc.orgdfef0282015-01-07 17:20:52 +0000680 strncmp(network.name().c_str(), "vnic", 4) == 0 ||
681 strncmp(network.name().c_str(), "vboxnet", 7) == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000682 return true;
683 }
684#if defined(WEBRTC_LINUX)
685 // Make sure this is a default route, if we're ignoring non-defaults.
686 if (ignore_non_default_routes_ && !IsDefaultRoute(network.name())) {
687 return true;
688 }
689#endif
690#elif defined(WEBRTC_WIN)
691 // Ignore any HOST side vmware adapters with a description like:
692 // VMware Virtual Ethernet Adapter for VMnet1
693 // but don't ignore any GUEST side adapters with a description like:
694 // VMware Accelerated AMD PCNet Adapter #2
695 if (strstr(network.description().c_str(), "VMnet") != NULL) {
696 return true;
697 }
698#endif
699
700 // Ignore any networks with a 0.x.y.z IP
701 if (network.prefix().family() == AF_INET) {
702 return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000);
703 }
guoweis@webrtc.orgbbce5ef2015-03-05 04:38:29 +0000704
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000705 return false;
706}
707
708void BasicNetworkManager::StartUpdating() {
709 thread_ = Thread::Current();
710 if (start_count_) {
711 // If network interfaces are already discovered and signal is sent,
712 // we should trigger network signal immediately for the new clients
713 // to start allocating ports.
714 if (sent_first_update_)
715 thread_->Post(this, kSignalNetworksMessage);
716 } else {
717 thread_->Post(this, kUpdateNetworksMessage);
honghaiz023f3ef2015-10-19 09:39:32 -0700718 StartNetworkMonitor();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000719 }
720 ++start_count_;
721}
722
723void BasicNetworkManager::StopUpdating() {
724 ASSERT(Thread::Current() == thread_);
725 if (!start_count_)
726 return;
727
728 --start_count_;
729 if (!start_count_) {
730 thread_->Clear(this);
731 sent_first_update_ = false;
honghaiz023f3ef2015-10-19 09:39:32 -0700732 StopNetworkMonitor();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000733 }
734}
735
honghaiz023f3ef2015-10-19 09:39:32 -0700736void BasicNetworkManager::StartNetworkMonitor() {
737 NetworkMonitorFactory* factory = NetworkMonitorFactory::GetFactory();
738 if (factory == nullptr) {
739 return;
740 }
741 network_monitor_.reset(factory->CreateNetworkMonitor());
742 if (!network_monitor_) {
743 return;
744 }
745 network_monitor_->SignalNetworksChanged.connect(
746 this, &BasicNetworkManager::OnNetworksChanged);
747 network_monitor_->Start();
748}
749
750void BasicNetworkManager::StopNetworkMonitor() {
751 if (!network_monitor_) {
752 return;
753 }
754 network_monitor_->Stop();
755 network_monitor_.reset();
756}
757
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000758void BasicNetworkManager::OnMessage(Message* msg) {
759 switch (msg->message_id) {
honghaiz023f3ef2015-10-19 09:39:32 -0700760 case kUpdateNetworksMessage: {
761 UpdateNetworksContinually();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000762 break;
763 }
764 case kSignalNetworksMessage: {
765 SignalNetworksChanged();
766 break;
767 }
768 default:
769 ASSERT(false);
770 }
771}
772
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800773IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const {
774 ASSERT(thread_ == Thread::Current());
775 ASSERT(thread_->socketserver() != nullptr);
776 ASSERT(family == AF_INET || family == AF_INET6);
777
778 scoped_ptr<AsyncSocket> socket(
779 thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));
780 if (!socket) {
781 return IPAddress();
782 }
783
784 if (!socket->Connect(
785 SocketAddress(family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host,
786 kPublicPort))) {
787 return IPAddress();
788 }
789 return socket->GetLocalAddress().ipaddr();
790}
791
honghaiz023f3ef2015-10-19 09:39:32 -0700792void BasicNetworkManager::UpdateNetworksOnce() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000793 if (!start_count_)
794 return;
795
796 ASSERT(Thread::Current() == thread_);
797
798 NetworkList list;
799 if (!CreateNetworks(false, &list)) {
800 SignalError();
801 } else {
802 bool changed;
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800803 NetworkManager::Stats stats;
804 MergeNetworkList(list, &changed, &stats);
805 set_default_local_addresses(QueryDefaultLocalAddress(AF_INET),
806 QueryDefaultLocalAddress(AF_INET6));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000807 if (changed || !sent_first_update_) {
808 SignalNetworksChanged();
809 sent_first_update_ = true;
810 }
811 }
honghaiz023f3ef2015-10-19 09:39:32 -0700812}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000813
honghaiz023f3ef2015-10-19 09:39:32 -0700814void BasicNetworkManager::UpdateNetworksContinually() {
815 UpdateNetworksOnce();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000816 thread_->PostDelayed(kNetworksUpdateIntervalMs, this, kUpdateNetworksMessage);
817}
818
honghaizdb8cf502015-12-21 13:08:46 -0800819void BasicNetworkManager::DumpNetworks() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000820 NetworkList list;
honghaizdb8cf502015-12-21 13:08:46 -0800821 GetNetworks(&list);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000822 LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:";
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000823 for (const Network* network : list) {
honghaizdb8cf502015-12-21 13:08:46 -0800824 LOG(LS_INFO) << network->ToString() << ": " << network->description()
825 << ", active ? " << network->active()
826 << ((network->ignored()) ? ", Ignored" : "");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000827 }
828}
829
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800830Network::Network(const std::string& name,
831 const std::string& desc,
832 const IPAddress& prefix,
833 int prefix_length)
834 : name_(name),
835 description_(desc),
836 prefix_(prefix),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000837 prefix_length_(prefix_length),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800838 key_(MakeNetworkKey(name, prefix, prefix_length)),
839 scope_id_(0),
840 ignored_(false),
841 type_(ADAPTER_TYPE_UNKNOWN),
842 preference_(0) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000843
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800844Network::Network(const std::string& name,
845 const std::string& desc,
846 const IPAddress& prefix,
847 int prefix_length,
848 AdapterType type)
849 : name_(name),
850 description_(desc),
851 prefix_(prefix),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000852 prefix_length_(prefix_length),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800853 key_(MakeNetworkKey(name, prefix, prefix_length)),
854 scope_id_(0),
855 ignored_(false),
856 type_(type),
857 preference_(0) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000858
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000859Network::~Network() = default;
860
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000861// Sets the addresses of this network. Returns true if the address set changed.
862// Change detection is short circuited if the changed argument is true.
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000863bool Network::SetIPs(const std::vector<InterfaceAddress>& ips, bool changed) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000864 // Detect changes with a nested loop; n-squared but we expect on the order
865 // of 2-3 addresses per network.
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000866 changed = changed || ips.size() != ips_.size();
867 if (!changed) {
868 for (const InterfaceAddress& ip : ips) {
869 if (std::find(ips_.begin(), ips_.end(), ip) == ips_.end()) {
870 changed = true;
871 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000872 }
873 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000874 }
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000875
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000876 ips_ = ips;
877 return changed;
878}
879
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +0000880// Select the best IP address to use from this Network.
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000881IPAddress Network::GetBestIP() const {
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000882 if (ips_.size() == 0) {
883 return IPAddress();
884 }
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000885
886 if (prefix_.family() == AF_INET) {
887 return static_cast<IPAddress>(ips_.at(0));
888 }
889
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +0000890 InterfaceAddress selected_ip, ula_ip;
891
pthatcher@webrtc.org5950b642014-12-01 23:18:27 +0000892 for (const InterfaceAddress& ip : ips_) {
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +0000893 // Ignore any address which has been deprecated already.
894 if (ip.ipv6_flags() & IPV6_ADDRESS_FLAG_DEPRECATED)
895 continue;
896
897 // ULA address should only be returned when we have no other
898 // global IP.
899 if (IPIsULA(static_cast<const IPAddress&>(ip))) {
900 ula_ip = ip;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000901 continue;
902 }
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +0000903 selected_ip = ip;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000904
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +0000905 // Search could stop once a temporary non-deprecated one is found.
906 if (ip.ipv6_flags() & IPV6_ADDRESS_FLAG_TEMPORARY)
907 break;
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000908 }
909
aluebs@webrtc.org07dcf602015-02-27 18:42:22 +0000910 // No proper global IPv6 address found, use ULA instead.
911 if (IPIsUnspec(selected_ip) && !IPIsUnspec(ula_ip)) {
912 selected_ip = ula_ip;
913 }
914
915 return static_cast<IPAddress>(selected_ip);
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000916}
917
918std::string Network::ToString() const {
919 std::stringstream ss;
920 // Print out the first space-terminated token of the network desc, plus
921 // the IP address.
922 ss << "Net[" << description_.substr(0, description_.find(' '))
923 << ":" << prefix_.ToSensitiveString() << "/" << prefix_length_
924 << ":" << AdapterTypeToString(type_) << "]";
925 return ss.str();
guoweis@webrtc.orgfa603982014-09-09 23:42:40 +0000926}
927
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000928} // namespace rtc