1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifdef HAVE_CONFIG_H 29 #include "config.h" 30 #endif 31 32 #include "talk/base/network.h" 33 34 #ifdef POSIX 35 // linux/if.h can't be included at the same time as the posix sys/if.h, and 36 // it's transitively required by linux/route.h, so include that version on 37 // linux instead of the standard posix one. 38 #if defined(ANDROID) || defined(LINUX) 39 #include <linux/if.h> 40 #include <linux/route.h> 41 #else 42 #include <net/if.h> 43 #endif 44 #include <sys/socket.h> 45 #include <sys/utsname.h> 46 #include <sys/ioctl.h> 47 #include <unistd.h> 48 #include <errno.h> 49 #ifdef ANDROID 50 #include "talk/base/ifaddrs-android.h" 51 #else 52 #include <ifaddrs.h> 53 #endif 54 #endif // POSIX 55 56 #ifdef WIN32 57 #include "talk/base/win32.h" 58 #include <Iphlpapi.h> 59 #endif 60 61 #include <algorithm> 62 #include <cstdio> 63 64 #include "talk/base/logging.h" 65 #include "talk/base/scoped_ptr.h" 66 #include "talk/base/socket.h" // includes something that makes windows happy 67 #include "talk/base/stream.h" 68 #include "talk/base/stringencode.h" 69 #include "talk/base/thread.h" 70 71 namespace talk_base { 72 namespace { 73 74 const uint32 kUpdateNetworksMessage = 1; 75 const uint32 kSignalNetworksMessage = 2; 76 77 // Fetch list of networks every two seconds. 78 const int kNetworksUpdateIntervalMs = 2000; 79 80 81 // Makes a string key for this network. Used in the network manager's maps. 82 // Network objects are keyed on interface name, network prefix and the 83 // length of that prefix. 84 std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix, 85 int prefix_length) { 86 std::ostringstream ost; 87 ost << name << "%" << prefix.ToString() << "/" << prefix_length; 88 return ost.str(); 89 } 90 91 bool CompareNetworks(const Network* a, const Network* b) { 92 if (a->prefix_length() == b->prefix_length()) { 93 if (a->name() == b->name()) { 94 return a->prefix() < b->prefix(); 95 } 96 } 97 return a->name() < b->name(); 98 } 99 100 101 } // namespace 102 103 NetworkManager::NetworkManager() { 104 } 105 106 NetworkManager::~NetworkManager() { 107 } 108 109 NetworkManagerBase::NetworkManagerBase() : ipv6_enabled_(true) { 110 } 111 112 NetworkManagerBase::~NetworkManagerBase() { 113 for (NetworkMap::iterator i = networks_map_.begin(); 114 i != networks_map_.end(); ++i) { 115 delete i->second; 116 } 117 } 118 119 void NetworkManagerBase::GetNetworks(NetworkList* result) const { 120 *result = networks_; 121 } 122 123 void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks, 124 bool* changed) { 125 // Sort the list so that we can detect when it changes. 126 typedef std::pair<Network*, std::vector<IPAddress> > address_list; 127 std::map<std::string, address_list> address_map; 128 NetworkList list(new_networks); 129 NetworkList merged_list; 130 std::sort(list.begin(), list.end(), CompareNetworks); 131 132 *changed = false; 133 134 if (networks_.size() != list.size()) 135 *changed = true; 136 137 // First, build a set of network-keys to the ipaddresses. 138 for (uint32 i = 0; i < list.size(); ++i) { 139 bool might_add_to_merged_list = false; 140 std::string key = MakeNetworkKey(list[i]->name(), 141 list[i]->prefix(), 142 list[i]->prefix_length()); 143 if (address_map.find(key) == address_map.end()) { 144 address_map[key] = address_list(list[i], std::vector<IPAddress>()); 145 might_add_to_merged_list = true; 146 } 147 const std::vector<IPAddress>& addresses = list[i]->GetIPs(); 148 address_list& current_list = address_map[key]; 149 for (std::vector<IPAddress>::const_iterator it = addresses.begin(); 150 it != addresses.end(); 151 ++it) { 152 current_list.second.push_back(*it); 153 } 154 if (!might_add_to_merged_list) { 155 delete list[i]; 156 } 157 } 158 159 // Next, look for existing network objects to re-use. 160 for (std::map<std::string, address_list >::iterator it = address_map.begin(); 161 it != address_map.end(); 162 ++it) { 163 const std::string& key = it->first; 164 Network* net = it->second.first; 165 NetworkMap::iterator existing = networks_map_.find(key); 166 if (existing == networks_map_.end()) { 167 // This network is new. Place it in the network map. 168 merged_list.push_back(net); 169 networks_map_[key] = net; 170 *changed = true; 171 } else { 172 // This network exists in the map already. Reset its IP addresses. 173 *changed = existing->second->SetIPs(it->second.second, *changed); 174 merged_list.push_back(existing->second); 175 if (existing->second != net) { 176 delete net; 177 } 178 } 179 } 180 networks_ = merged_list; 181 } 182 183 BasicNetworkManager::BasicNetworkManager() 184 : thread_(NULL), sent_first_update_(false), start_count_(0), 185 ignore_non_default_routes_(false) { 186 } 187 188 BasicNetworkManager::~BasicNetworkManager() { 189 } 190 191 #if defined(POSIX) 192 void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces, 193 bool include_ignored, 194 NetworkList* networks) const { 195 NetworkMap current_networks; 196 for (struct ifaddrs* cursor = interfaces; 197 cursor != NULL; cursor = cursor->ifa_next) { 198 IPAddress prefix; 199 IPAddress mask; 200 IPAddress ip; 201 int scope_id = 0; 202 203 // Some interfaces may not have address assigned. 204 if (!cursor->ifa_addr || !cursor->ifa_netmask) 205 continue; 206 207 switch (cursor->ifa_addr->sa_family) { 208 case AF_INET: { 209 ip = IPAddress( 210 reinterpret_cast<sockaddr_in*>(cursor->ifa_addr)->sin_addr); 211 mask = IPAddress( 212 reinterpret_cast<sockaddr_in*>(cursor->ifa_netmask)->sin_addr); 213 break; 214 } 215 case AF_INET6: { 216 if (ipv6_enabled()) { 217 ip = IPAddress( 218 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_addr); 219 mask = IPAddress( 220 reinterpret_cast<sockaddr_in6*>(cursor->ifa_netmask)->sin6_addr); 221 scope_id = 222 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_scope_id; 223 break; 224 } else { 225 continue; 226 } 227 } 228 default: { 229 continue; 230 } 231 } 232 int prefix_length = CountIPMaskBits(mask); 233 prefix = TruncateIP(ip, prefix_length); 234 std::string key = MakeNetworkKey(std::string(cursor->ifa_name), 235 prefix, prefix_length); 236 NetworkMap::iterator existing_network = current_networks.find(key); 237 if (existing_network == current_networks.end()) { 238 scoped_ptr<Network> network(new Network(cursor->ifa_name, 239 cursor->ifa_name, 240 prefix, 241 prefix_length)); 242 network->set_scope_id(scope_id); 243 network->AddIP(ip); 244 bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) || 245 IsIgnoredNetwork(*network)); 246 network->set_ignored(ignored); 247 if (include_ignored || !network->ignored()) { 248 networks->push_back(network.release()); 249 } 250 } else { 251 (*existing_network).second->AddIP(ip); 252 } 253 } 254 } 255 256 bool BasicNetworkManager::CreateNetworks(bool include_ignored, 257 NetworkList* networks) const { 258 struct ifaddrs* interfaces; 259 int error = getifaddrs(&interfaces); 260 if (error != 0) { 261 LOG_ERR(LERROR) << "getifaddrs failed to gather interface data: " << error; 262 return false; 263 } 264 265 ConvertIfAddrs(interfaces, include_ignored, networks); 266 267 freeifaddrs(interfaces); 268 return true; 269 } 270 271 #elif defined(WIN32) 272 273 unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist, 274 const IPAddress& ip, IPAddress* prefix) { 275 IPAddress current_prefix; 276 IPAddress best_prefix; 277 unsigned int best_length = 0; 278 while (prefixlist) { 279 // Look for the longest matching prefix in the prefixlist. 280 if (prefixlist->Address.lpSockaddr == NULL || 281 prefixlist->Address.lpSockaddr->sa_family != ip.family()) { 282 prefixlist = prefixlist->Next; 283 continue; 284 } 285 switch (prefixlist->Address.lpSockaddr->sa_family) { 286 case AF_INET: { 287 sockaddr_in* v4_addr = 288 reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr); 289 current_prefix = IPAddress(v4_addr->sin_addr); 290 break; 291 } 292 case AF_INET6: { 293 sockaddr_in6* v6_addr = 294 reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr); 295 current_prefix = IPAddress(v6_addr->sin6_addr); 296 break; 297 } 298 default: { 299 prefixlist = prefixlist->Next; 300 continue; 301 } 302 } 303 if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix && 304 prefixlist->PrefixLength > best_length) { 305 best_prefix = current_prefix; 306 best_length = prefixlist->PrefixLength; 307 } 308 prefixlist = prefixlist->Next; 309 } 310 *prefix = best_prefix; 311 return best_length; 312 } 313 314 bool BasicNetworkManager::CreateNetworks(bool include_ignored, 315 NetworkList* networks) const { 316 NetworkMap current_networks; 317 // MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses. 318 size_t buffer_size = 16384; 319 scoped_ptr<char[]> adapter_info(new char[buffer_size]); 320 PIP_ADAPTER_ADDRESSES adapter_addrs = 321 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get()); 322 int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST | 323 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX); 324 int ret = 0; 325 do { 326 adapter_info.reset(new char[buffer_size]); 327 adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get()); 328 ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags, 329 0, adapter_addrs, 330 reinterpret_cast<PULONG>(&buffer_size)); 331 } while (ret == ERROR_BUFFER_OVERFLOW); 332 if (ret != ERROR_SUCCESS) { 333 return false; 334 } 335 int count = 0; 336 while (adapter_addrs) { 337 if (adapter_addrs->OperStatus == IfOperStatusUp) { 338 PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress; 339 PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix; 340 std::string name; 341 std::string description; 342 #ifdef _DEBUG 343 name = ToUtf8(adapter_addrs->FriendlyName, 344 wcslen(adapter_addrs->FriendlyName)); 345 #endif 346 description = ToUtf8(adapter_addrs->Description, 347 wcslen(adapter_addrs->Description)); 348 for (; address; address = address->Next) { 349 #ifndef _DEBUG 350 name = talk_base::ToString(count); 351 #endif 352 353 IPAddress ip; 354 int scope_id = 0; 355 scoped_ptr<Network> network; 356 switch (address->Address.lpSockaddr->sa_family) { 357 case AF_INET: { 358 sockaddr_in* v4_addr = 359 reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr); 360 ip = IPAddress(v4_addr->sin_addr); 361 break; 362 } 363 case AF_INET6: { 364 if (ipv6_enabled()) { 365 sockaddr_in6* v6_addr = 366 reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr); 367 scope_id = v6_addr->sin6_scope_id; 368 ip = IPAddress(v6_addr->sin6_addr); 369 break; 370 } else { 371 continue; 372 } 373 } 374 default: { 375 continue; 376 } 377 } 378 IPAddress prefix; 379 int prefix_length = GetPrefix(prefixlist, ip, &prefix); 380 std::string key = MakeNetworkKey(name, prefix, prefix_length); 381 NetworkMap::iterator existing_network = current_networks.find(key); 382 if (existing_network == current_networks.end()) { 383 scoped_ptr<Network> network(new Network(name, 384 description, 385 prefix, 386 prefix_length)); 387 network->set_scope_id(scope_id); 388 network->AddIP(ip); 389 bool ignore = ((adapter_addrs->IfType == IF_TYPE_SOFTWARE_LOOPBACK) || 390 IsIgnoredNetwork(*network)); 391 network->set_ignored(ignore); 392 if (include_ignored || !network->ignored()) { 393 networks->push_back(network.release()); 394 } 395 } else { 396 (*existing_network).second->AddIP(ip); 397 } 398 } 399 // Count is per-adapter - all 'Networks' created from the same 400 // adapter need to have the same name. 401 ++count; 402 } 403 adapter_addrs = adapter_addrs->Next; 404 } 405 return true; 406 } 407 #endif // WIN32 408 409 #if defined(ANDROID) || defined(LINUX) 410 bool IsDefaultRoute(const std::string& network_name) { 411 FileStream fs; 412 if (!fs.Open("/proc/net/route", "r", NULL)) { 413 LOG(LS_WARNING) << "Couldn't read /proc/net/route, skipping default " 414 << "route check (assuming everything is a default route)."; 415 return true; 416 } else { 417 std::string line; 418 while (fs.ReadLine(&line) == SR_SUCCESS) { 419 char iface_name[256]; 420 unsigned int iface_ip, iface_gw, iface_mask, iface_flags; 421 if (sscanf(line.c_str(), 422 "%255s %8X %8X %4X %*d %*u %*d %8X", 423 iface_name, &iface_ip, &iface_gw, 424 &iface_flags, &iface_mask) == 5 && 425 network_name == iface_name && 426 iface_mask == 0 && 427 (iface_flags & (RTF_UP | RTF_HOST)) == RTF_UP) { 428 return true; 429 } 430 } 431 } 432 return false; 433 } 434 #endif 435 436 bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const { 437 // Ignore networks on the explicit ignore list. 438 for (size_t i = 0; i < network_ignore_list_.size(); ++i) { 439 if (network.name() == network_ignore_list_[i]) { 440 return true; 441 } 442 } 443 #ifdef POSIX 444 // Filter out VMware interfaces, typically named vmnet1 and vmnet8 445 if (strncmp(network.name().c_str(), "vmnet", 5) == 0 || 446 strncmp(network.name().c_str(), "vnic", 4) == 0) { 447 return true; 448 } 449 #if defined(ANDROID) || defined(LINUX) 450 // Make sure this is a default route, if we're ignoring non-defaults. 451 if (ignore_non_default_routes_ && !IsDefaultRoute(network.name())) { 452 return true; 453 } 454 #endif 455 #elif defined(WIN32) 456 // Ignore any HOST side vmware adapters with a description like: 457 // VMware Virtual Ethernet Adapter for VMnet1 458 // but don't ignore any GUEST side adapters with a description like: 459 // VMware Accelerated AMD PCNet Adapter #2 460 if (strstr(network.description().c_str(), "VMnet") != NULL) { 461 return true; 462 } 463 #endif 464 465 // Ignore any networks with a 0.x.y.z IP 466 if (network.prefix().family() == AF_INET) { 467 return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000); 468 } 469 return false; 470 } 471 472 void BasicNetworkManager::StartUpdating() { 473 thread_ = Thread::Current(); 474 if (start_count_) { 475 // If network interfaces are already discovered and signal is sent, 476 // we should trigger network signal immediately for the new clients 477 // to start allocating ports. 478 if (sent_first_update_) 479 thread_->Post(this, kSignalNetworksMessage); 480 } else { 481 thread_->Post(this, kUpdateNetworksMessage); 482 } 483 ++start_count_; 484 } 485 486 void BasicNetworkManager::StopUpdating() { 487 ASSERT(Thread::Current() == thread_); 488 if (!start_count_) 489 return; 490 491 --start_count_; 492 if (!start_count_) { 493 thread_->Clear(this); 494 sent_first_update_ = false; 495 } 496 } 497 498 void BasicNetworkManager::OnMessage(Message* msg) { 499 switch (msg->message_id) { 500 case kUpdateNetworksMessage: { 501 DoUpdateNetworks(); 502 break; 503 } 504 case kSignalNetworksMessage: { 505 SignalNetworksChanged(); 506 break; 507 } 508 default: 509 ASSERT(false); 510 } 511 } 512 513 void BasicNetworkManager::DoUpdateNetworks() { 514 if (!start_count_) 515 return; 516 517 ASSERT(Thread::Current() == thread_); 518 519 NetworkList list; 520 if (!CreateNetworks(false, &list)) { 521 SignalError(); 522 } else { 523 bool changed; 524 MergeNetworkList(list, &changed); 525 if (changed || !sent_first_update_) { 526 SignalNetworksChanged(); 527 sent_first_update_ = true; 528 } 529 } 530 531 thread_->PostDelayed(kNetworksUpdateIntervalMs, this, kUpdateNetworksMessage); 532 } 533 534 void BasicNetworkManager::DumpNetworks(bool include_ignored) { 535 NetworkList list; 536 CreateNetworks(include_ignored, &list); 537 LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:"; 538 for (size_t i = 0; i < list.size(); ++i) { 539 const Network* network = list[i]; 540 if (!network->ignored() || include_ignored) { 541 LOG(LS_INFO) << network->ToString() << ": " 542 << network->description() 543 << ((network->ignored()) ? ", Ignored" : ""); 544 } 545 } 546 // Release the network list created previously. 547 // Do this in a seperated for loop for better readability. 548 for (size_t i = 0; i < list.size(); ++i) { 549 delete list[i]; 550 } 551 } 552 553 Network::Network(const std::string& name, const std::string& desc, 554 const IPAddress& prefix, int prefix_length) 555 : name_(name), description_(desc), prefix_(prefix), 556 prefix_length_(prefix_length), scope_id_(0), ignored_(false), 557 uniform_numerator_(0), uniform_denominator_(0), exponential_numerator_(0), 558 exponential_denominator_(0) { 559 } 560 561 std::string Network::ToString() const { 562 std::stringstream ss; 563 // Print out the first space-terminated token of the network desc, plus 564 // the IP address. 565 ss << "Net[" << description_.substr(0, description_.find(' ')) 566 << ":" << prefix_.ToSensitiveString() << "/" << prefix_length_ << "]"; 567 return ss.str(); 568 } 569 570 // Sets the addresses of this network. Returns true if the address set changed. 571 // Change detection is short circuited if the changed argument is true. 572 bool Network::SetIPs(const std::vector<IPAddress>& ips, bool changed) { 573 changed = changed || ips.size() != ips_.size(); 574 // Detect changes with a nested loop; n-squared but we expect on the order 575 // of 2-3 addresses per network. 576 for (std::vector<IPAddress>::const_iterator it = ips.begin(); 577 !changed && it != ips.end(); 578 ++it) { 579 bool found = false; 580 for (std::vector<IPAddress>::iterator inner_it = ips_.begin(); 581 !found && inner_it != ips_.end(); 582 ++inner_it) { 583 if (*it == *inner_it) { 584 found = true; 585 } 586 } 587 changed = !found; 588 } 589 ips_ = ips; 590 return changed; 591 } 592 } // namespace talk_base 593