blob: d94c69eae7a881411c25d5536e8dd6249467c593 [file] [log] [blame]
henrike@webrtc.orgf7795df2014-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
27#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
39#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"
51#include "webrtc/base/scoped_ptr.h"
52#include "webrtc/base/socket.h" // includes something that makes windows happy
53#include "webrtc/base/stream.h"
54#include "webrtc/base/stringencode.h"
55#include "webrtc/base/thread.h"
56
57namespace rtc {
58namespace {
59
60const uint32 kUpdateNetworksMessage = 1;
61const uint32 kSignalNetworksMessage = 2;
62
63// Fetch list of networks every two seconds.
64const int kNetworksUpdateIntervalMs = 2000;
65
66const int kHighestNetworkPreference = 127;
67
68bool CompareNetworks(const Network* a, const Network* b) {
69 if (a->prefix_length() == b->prefix_length()) {
70 if (a->name() == b->name()) {
71 return a->prefix() < b->prefix();
72 }
73 }
74 return a->name() < b->name();
75}
76
77bool SortNetworks(const Network* a, const Network* b) {
78 // Network types will be preferred above everything else while sorting
79 // Networks.
80
81 // Networks are sorted first by type.
82 if (a->type() != b->type()) {
83 return a->type() < b->type();
84 }
85
86 // After type, networks are sorted by IP address precedence values
87 // from RFC 3484-bis
88 if (IPAddressPrecedence(a->ip()) != IPAddressPrecedence(b->ip())) {
89 return IPAddressPrecedence(a->ip()) > IPAddressPrecedence(b->ip());
90 }
91
92 // TODO(mallinath) - Add VPN and Link speed conditions while sorting.
93
94 // Networks are sorted last by key.
95 return a->key() > b->key();
96}
97
98std::string AdapterTypeToString(AdapterType type) {
99 switch (type) {
100 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";
110 default:
111 ASSERT(false);
112 return std::string();
113 }
114}
115
116} // namespace
117
118std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
119 int prefix_length) {
120 std::ostringstream ost;
121 ost << name << "%" << prefix.ToString() << "/" << prefix_length;
122 return ost.str();
123}
124
125NetworkManager::NetworkManager() {
126}
127
128NetworkManager::~NetworkManager() {
129}
130
131NetworkManagerBase::NetworkManagerBase() : ipv6_enabled_(true) {
132}
133
134NetworkManagerBase::~NetworkManagerBase() {
135 for (NetworkMap::iterator i = networks_map_.begin();
136 i != networks_map_.end(); ++i) {
137 delete i->second;
138 }
139}
140
141void NetworkManagerBase::GetNetworks(NetworkList* result) const {
142 *result = networks_;
143}
144
145void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
146 bool* changed) {
147 // Sort the list so that we can detect when it changes.
148 typedef std::pair<Network*, std::vector<IPAddress> > address_list;
149 std::map<std::string, address_list> address_map;
150 NetworkList list(new_networks);
151 NetworkList merged_list;
152 std::sort(list.begin(), list.end(), CompareNetworks);
153
154 *changed = false;
155
156 if (networks_.size() != list.size())
157 *changed = true;
158
159 // First, build a set of network-keys to the ipaddresses.
160 for (uint32 i = 0; i < list.size(); ++i) {
161 bool might_add_to_merged_list = false;
162 std::string key = MakeNetworkKey(list[i]->name(),
163 list[i]->prefix(),
164 list[i]->prefix_length());
165 if (address_map.find(key) == address_map.end()) {
166 address_map[key] = address_list(list[i], std::vector<IPAddress>());
167 might_add_to_merged_list = true;
168 }
169 const std::vector<IPAddress>& addresses = list[i]->GetIPs();
170 address_list& current_list = address_map[key];
171 for (std::vector<IPAddress>::const_iterator it = addresses.begin();
172 it != addresses.end();
173 ++it) {
174 current_list.second.push_back(*it);
175 }
176 if (!might_add_to_merged_list) {
177 delete list[i];
178 }
179 }
180
181 // Next, look for existing network objects to re-use.
182 for (std::map<std::string, address_list >::iterator it = address_map.begin();
183 it != address_map.end();
184 ++it) {
185 const std::string& key = it->first;
186 Network* net = it->second.first;
187 NetworkMap::iterator existing = networks_map_.find(key);
188 if (existing == networks_map_.end()) {
189 // This network is new. Place it in the network map.
190 merged_list.push_back(net);
191 networks_map_[key] = net;
192 *changed = true;
193 } else {
194 // This network exists in the map already. Reset its IP addresses.
195 *changed = existing->second->SetIPs(it->second.second, *changed);
196 merged_list.push_back(existing->second);
197 if (existing->second != net) {
198 delete net;
199 }
200 }
201 }
202 networks_ = merged_list;
203
204 // If the network lists changes, we resort it.
205 if (changed) {
206 std::sort(networks_.begin(), networks_.end(), SortNetworks);
207 // Now network interfaces are sorted, we should set the preference value
208 // for each of the interfaces we are planning to use.
209 // Preference order of network interfaces might have changed from previous
210 // sorting due to addition of higher preference network interface.
211 // Since we have already sorted the network interfaces based on our
212 // requirements, we will just assign a preference value starting with 127,
213 // in decreasing order.
214 int pref = kHighestNetworkPreference;
215 for (NetworkList::const_iterator iter = networks_.begin();
216 iter != networks_.end(); ++iter) {
217 (*iter)->set_preference(pref);
218 if (pref > 0) {
219 --pref;
220 } else {
221 LOG(LS_ERROR) << "Too many network interfaces to handle!";
222 break;
223 }
224 }
225 }
226}
227
228BasicNetworkManager::BasicNetworkManager()
229 : thread_(NULL), sent_first_update_(false), start_count_(0),
230 ignore_non_default_routes_(false) {
231}
232
233BasicNetworkManager::~BasicNetworkManager() {
234}
235
236#if defined(__native_client__)
237
238bool BasicNetworkManager::CreateNetworks(bool include_ignored,
239 NetworkList* networks) const {
240 ASSERT(false);
241 LOG(LS_WARNING) << "BasicNetworkManager doesn't work on NaCl yet";
242 return false;
243}
244
245#elif defined(WEBRTC_POSIX)
246void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
247 bool include_ignored,
248 NetworkList* networks) const {
249 NetworkMap current_networks;
250 for (struct ifaddrs* cursor = interfaces;
251 cursor != NULL; cursor = cursor->ifa_next) {
252 IPAddress prefix;
253 IPAddress mask;
254 IPAddress ip;
255 int scope_id = 0;
256
257 // Some interfaces may not have address assigned.
258 if (!cursor->ifa_addr || !cursor->ifa_netmask)
259 continue;
260
261 switch (cursor->ifa_addr->sa_family) {
262 case AF_INET: {
263 ip = IPAddress(
264 reinterpret_cast<sockaddr_in*>(cursor->ifa_addr)->sin_addr);
265 mask = IPAddress(
266 reinterpret_cast<sockaddr_in*>(cursor->ifa_netmask)->sin_addr);
267 break;
268 }
269 case AF_INET6: {
270 if (ipv6_enabled()) {
271 ip = IPAddress(
272 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_addr);
273 mask = IPAddress(
274 reinterpret_cast<sockaddr_in6*>(cursor->ifa_netmask)->sin6_addr);
275 scope_id =
276 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_scope_id;
277 break;
278 } else {
279 continue;
280 }
281 }
282 default: {
283 continue;
284 }
285 }
286
287 int prefix_length = CountIPMaskBits(mask);
288 prefix = TruncateIP(ip, prefix_length);
289 std::string key = MakeNetworkKey(std::string(cursor->ifa_name),
290 prefix, prefix_length);
291 NetworkMap::iterator existing_network = current_networks.find(key);
292 if (existing_network == current_networks.end()) {
293 scoped_ptr<Network> network(new Network(cursor->ifa_name,
294 cursor->ifa_name,
295 prefix,
296 prefix_length));
297 network->set_scope_id(scope_id);
298 network->AddIP(ip);
299 bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) ||
300 IsIgnoredNetwork(*network));
301 network->set_ignored(ignored);
302 if (include_ignored || !network->ignored()) {
303 networks->push_back(network.release());
304 }
305 } else {
306 (*existing_network).second->AddIP(ip);
307 }
308 }
309}
310
311bool BasicNetworkManager::CreateNetworks(bool include_ignored,
312 NetworkList* networks) const {
313 struct ifaddrs* interfaces;
314 int error = getifaddrs(&interfaces);
315 if (error != 0) {
316 LOG_ERR(LERROR) << "getifaddrs failed to gather interface data: " << error;
317 return false;
318 }
319
320 ConvertIfAddrs(interfaces, include_ignored, networks);
321
322 freeifaddrs(interfaces);
323 return true;
324}
325
326#elif defined(WEBRTC_WIN)
327
328unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist,
329 const IPAddress& ip, IPAddress* prefix) {
330 IPAddress current_prefix;
331 IPAddress best_prefix;
332 unsigned int best_length = 0;
333 while (prefixlist) {
334 // Look for the longest matching prefix in the prefixlist.
335 if (prefixlist->Address.lpSockaddr == NULL ||
336 prefixlist->Address.lpSockaddr->sa_family != ip.family()) {
337 prefixlist = prefixlist->Next;
338 continue;
339 }
340 switch (prefixlist->Address.lpSockaddr->sa_family) {
341 case AF_INET: {
342 sockaddr_in* v4_addr =
343 reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr);
344 current_prefix = IPAddress(v4_addr->sin_addr);
345 break;
346 }
347 case AF_INET6: {
348 sockaddr_in6* v6_addr =
349 reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr);
350 current_prefix = IPAddress(v6_addr->sin6_addr);
351 break;
352 }
353 default: {
354 prefixlist = prefixlist->Next;
355 continue;
356 }
357 }
358 if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix &&
359 prefixlist->PrefixLength > best_length) {
360 best_prefix = current_prefix;
361 best_length = prefixlist->PrefixLength;
362 }
363 prefixlist = prefixlist->Next;
364 }
365 *prefix = best_prefix;
366 return best_length;
367}
368
369bool BasicNetworkManager::CreateNetworks(bool include_ignored,
370 NetworkList* networks) const {
371 NetworkMap current_networks;
372 // MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
373 size_t buffer_size = 16384;
374 scoped_ptr<char[]> adapter_info(new char[buffer_size]);
375 PIP_ADAPTER_ADDRESSES adapter_addrs =
376 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
377 int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
378 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX);
379 int ret = 0;
380 do {
381 adapter_info.reset(new char[buffer_size]);
382 adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
383 ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags,
384 0, adapter_addrs,
385 reinterpret_cast<PULONG>(&buffer_size));
386 } while (ret == ERROR_BUFFER_OVERFLOW);
387 if (ret != ERROR_SUCCESS) {
388 return false;
389 }
390 int count = 0;
391 while (adapter_addrs) {
392 if (adapter_addrs->OperStatus == IfOperStatusUp) {
393 PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress;
394 PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix;
395 std::string name;
396 std::string description;
397#ifdef _DEBUG
398 name = ToUtf8(adapter_addrs->FriendlyName,
399 wcslen(adapter_addrs->FriendlyName));
400#endif
401 description = ToUtf8(adapter_addrs->Description,
402 wcslen(adapter_addrs->Description));
403 for (; address; address = address->Next) {
404#ifndef _DEBUG
405 name = rtc::ToString(count);
406#endif
407
408 IPAddress ip;
409 int scope_id = 0;
410 scoped_ptr<Network> network;
411 switch (address->Address.lpSockaddr->sa_family) {
412 case AF_INET: {
413 sockaddr_in* v4_addr =
414 reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr);
415 ip = IPAddress(v4_addr->sin_addr);
416 break;
417 }
418 case AF_INET6: {
419 if (ipv6_enabled()) {
420 sockaddr_in6* v6_addr =
421 reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
422 scope_id = v6_addr->sin6_scope_id;
423 ip = IPAddress(v6_addr->sin6_addr);
424 break;
425 } else {
426 continue;
427 }
428 }
429 default: {
430 continue;
431 }
432 }
433
434 IPAddress prefix;
435 int prefix_length = GetPrefix(prefixlist, ip, &prefix);
436 std::string key = MakeNetworkKey(name, prefix, prefix_length);
437 NetworkMap::iterator existing_network = current_networks.find(key);
438 if (existing_network == current_networks.end()) {
439 scoped_ptr<Network> network(new Network(name,
440 description,
441 prefix,
442 prefix_length));
443 network->set_scope_id(scope_id);
444 network->AddIP(ip);
445 bool ignore = ((adapter_addrs->IfType == IF_TYPE_SOFTWARE_LOOPBACK) ||
446 IsIgnoredNetwork(*network));
447 network->set_ignored(ignore);
448 if (include_ignored || !network->ignored()) {
449 networks->push_back(network.release());
450 }
451 } else {
452 (*existing_network).second->AddIP(ip);
453 }
454 }
455 // Count is per-adapter - all 'Networks' created from the same
456 // adapter need to have the same name.
457 ++count;
458 }
459 adapter_addrs = adapter_addrs->Next;
460 }
461 return true;
462}
463#endif // WEBRTC_WIN
464
465#if defined(WEBRTC_LINUX)
466bool IsDefaultRoute(const std::string& network_name) {
467 FileStream fs;
468 if (!fs.Open("/proc/net/route", "r", NULL)) {
469 LOG(LS_WARNING) << "Couldn't read /proc/net/route, skipping default "
470 << "route check (assuming everything is a default route).";
471 return true;
472 } else {
473 std::string line;
474 while (fs.ReadLine(&line) == SR_SUCCESS) {
475 char iface_name[256];
476 unsigned int iface_ip, iface_gw, iface_mask, iface_flags;
477 if (sscanf(line.c_str(),
478 "%255s %8X %8X %4X %*d %*u %*d %8X",
479 iface_name, &iface_ip, &iface_gw,
480 &iface_flags, &iface_mask) == 5 &&
481 network_name == iface_name &&
482 iface_mask == 0 &&
483 (iface_flags & (RTF_UP | RTF_HOST)) == RTF_UP) {
484 return true;
485 }
486 }
487 }
488 return false;
489}
490#endif
491
492bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const {
493 // Ignore networks on the explicit ignore list.
494 for (size_t i = 0; i < network_ignore_list_.size(); ++i) {
495 if (network.name() == network_ignore_list_[i]) {
496 return true;
497 }
498 }
499#if defined(WEBRTC_POSIX)
500 // Filter out VMware interfaces, typically named vmnet1 and vmnet8
501 if (strncmp(network.name().c_str(), "vmnet", 5) == 0 ||
502 strncmp(network.name().c_str(), "vnic", 4) == 0) {
503 return true;
504 }
505#if defined(WEBRTC_LINUX)
506 // Make sure this is a default route, if we're ignoring non-defaults.
507 if (ignore_non_default_routes_ && !IsDefaultRoute(network.name())) {
508 return true;
509 }
510#endif
511#elif defined(WEBRTC_WIN)
512 // Ignore any HOST side vmware adapters with a description like:
513 // VMware Virtual Ethernet Adapter for VMnet1
514 // but don't ignore any GUEST side adapters with a description like:
515 // VMware Accelerated AMD PCNet Adapter #2
516 if (strstr(network.description().c_str(), "VMnet") != NULL) {
517 return true;
518 }
519#endif
520
521 // Ignore any networks with a 0.x.y.z IP
522 if (network.prefix().family() == AF_INET) {
523 return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000);
524 }
525 return false;
526}
527
528void BasicNetworkManager::StartUpdating() {
529 thread_ = Thread::Current();
530 if (start_count_) {
531 // If network interfaces are already discovered and signal is sent,
532 // we should trigger network signal immediately for the new clients
533 // to start allocating ports.
534 if (sent_first_update_)
535 thread_->Post(this, kSignalNetworksMessage);
536 } else {
537 thread_->Post(this, kUpdateNetworksMessage);
538 }
539 ++start_count_;
540}
541
542void BasicNetworkManager::StopUpdating() {
543 ASSERT(Thread::Current() == thread_);
544 if (!start_count_)
545 return;
546
547 --start_count_;
548 if (!start_count_) {
549 thread_->Clear(this);
550 sent_first_update_ = false;
551 }
552}
553
554void BasicNetworkManager::OnMessage(Message* msg) {
555 switch (msg->message_id) {
556 case kUpdateNetworksMessage: {
557 DoUpdateNetworks();
558 break;
559 }
560 case kSignalNetworksMessage: {
561 SignalNetworksChanged();
562 break;
563 }
564 default:
565 ASSERT(false);
566 }
567}
568
569void BasicNetworkManager::DoUpdateNetworks() {
570 if (!start_count_)
571 return;
572
573 ASSERT(Thread::Current() == thread_);
574
575 NetworkList list;
576 if (!CreateNetworks(false, &list)) {
577 SignalError();
578 } else {
579 bool changed;
580 MergeNetworkList(list, &changed);
581 if (changed || !sent_first_update_) {
582 SignalNetworksChanged();
583 sent_first_update_ = true;
584 }
585 }
586
587 thread_->PostDelayed(kNetworksUpdateIntervalMs, this, kUpdateNetworksMessage);
588}
589
590void BasicNetworkManager::DumpNetworks(bool include_ignored) {
591 NetworkList list;
592 CreateNetworks(include_ignored, &list);
593 LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:";
594 for (size_t i = 0; i < list.size(); ++i) {
595 const Network* network = list[i];
596 if (!network->ignored() || include_ignored) {
597 LOG(LS_INFO) << network->ToString() << ": "
598 << network->description()
599 << ((network->ignored()) ? ", Ignored" : "");
600 }
601 }
602 // Release the network list created previously.
603 // Do this in a seperated for loop for better readability.
604 for (size_t i = 0; i < list.size(); ++i) {
605 delete list[i];
606 }
607}
608
609Network::Network(const std::string& name, const std::string& desc,
610 const IPAddress& prefix, int prefix_length)
611 : name_(name), description_(desc), prefix_(prefix),
612 prefix_length_(prefix_length),
613 key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
614 ignored_(false), type_(ADAPTER_TYPE_UNKNOWN), preference_(0) {
615}
616
617Network::Network(const std::string& name, const std::string& desc,
618 const IPAddress& prefix, int prefix_length, AdapterType type)
619 : name_(name), description_(desc), prefix_(prefix),
620 prefix_length_(prefix_length),
621 key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
622 ignored_(false), type_(type), preference_(0) {
623}
624
625std::string Network::ToString() const {
626 std::stringstream ss;
627 // Print out the first space-terminated token of the network desc, plus
628 // the IP address.
629 ss << "Net[" << description_.substr(0, description_.find(' '))
630 << ":" << prefix_.ToSensitiveString() << "/" << prefix_length_
631 << ":" << AdapterTypeToString(type_) << "]";
632 return ss.str();
633}
634
635// Sets the addresses of this network. Returns true if the address set changed.
636// Change detection is short circuited if the changed argument is true.
637bool Network::SetIPs(const std::vector<IPAddress>& ips, bool changed) {
638 changed = changed || ips.size() != ips_.size();
639 // Detect changes with a nested loop; n-squared but we expect on the order
640 // of 2-3 addresses per network.
641 for (std::vector<IPAddress>::const_iterator it = ips.begin();
642 !changed && it != ips.end();
643 ++it) {
644 bool found = false;
645 for (std::vector<IPAddress>::iterator inner_it = ips_.begin();
646 !found && inner_it != ips_.end();
647 ++inner_it) {
648 if (*it == *inner_it) {
649 found = true;
650 }
651 }
652 changed = !found;
653 }
654 ips_ = ips;
655 return changed;
656}
657
658} // namespace rtc