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 #include <sys/socket.h> 36 #include <sys/utsname.h> 37 #include <sys/ioctl.h> 38 #include <net/if.h> 39 #include <unistd.h> 40 #include <errno.h> 41 #ifdef ANDROID 42 #include "talk/base/ifaddrs-android.h" 43 #else 44 #include <ifaddrs.h> 45 #endif 46 #endif // POSIX 47 48 #ifdef WIN32 49 #include "talk/base/win32.h" 50 #include <Iphlpapi.h> 51 #endif 52 53 #include <algorithm> 54 #include <cstdio> 55 56 #include "talk/base/logging.h" 57 #include "talk/base/scoped_ptr.h" 58 #include "talk/base/socket.h" // includes something that makes windows happy 59 #include "talk/base/stream.h" 60 #include "talk/base/stringencode.h" 61 #include "talk/base/thread.h" 62 63 namespace talk_base { 64 namespace { 65 66 const uint32 kUpdateNetworksMessage = 1; 67 const uint32 kSignalNetworksMessage = 2; 68 69 // Fetch list of networks every two seconds. 70 const int kNetworksUpdateIntervalMs = 2000; 71 72 73 // Makes a string key for this network. Used in the network manager's maps. 74 // Network objects are keyed on interface name, network prefix and the 75 // length of that prefix. 76 std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix, 77 int prefix_length) { 78 std::ostringstream ost; 79 ost << name << "%" << prefix.ToString() << "/" << prefix_length; 80 return ost.str(); 81 } 82 83 bool CompareNetworks(const Network* a, const Network* b) { 84 if (a->prefix_length() == b->prefix_length()) { 85 if (a->name() == b->name()) { 86 return a->prefix() < b->prefix(); 87 } 88 } 89 return a->name() < b->name(); 90 } 91 92 93 } // namespace 94 95 NetworkManager::NetworkManager() { 96 } 97 98 NetworkManager::~NetworkManager() { 99 } 100 101 NetworkManagerBase::NetworkManagerBase() : ipv6_enabled_(true) { 102 } 103 104 NetworkManagerBase::~NetworkManagerBase() { 105 for (NetworkMap::iterator i = networks_map_.begin(); 106 i != networks_map_.end(); ++i) { 107 delete i->second; 108 } 109 } 110 111 void NetworkManagerBase::GetNetworks(NetworkList* result) const { 112 *result = networks_; 113 } 114 115 void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks, 116 bool* changed) { 117 // Sort the list so that we can detect when it changes. 118 typedef std::pair<Network*, std::vector<IPAddress> > address_list; 119 std::map<std::string, address_list> address_map; 120 NetworkList list(new_networks); 121 NetworkList merged_list; 122 std::sort(list.begin(), list.end(), CompareNetworks); 123 124 *changed = false; 125 126 if (networks_.size() != list.size()) 127 *changed = true; 128 129 // First, build a set of network-keys to the ipaddresses. 130 for (uint32 i = 0; i < list.size(); ++i) { 131 bool might_add_to_merged_list = false; 132 std::string key = MakeNetworkKey(list[i]->name(), 133 list[i]->prefix(), 134 list[i]->prefix_length()); 135 if (address_map.find(key) == address_map.end()) { 136 address_map[key] = address_list(list[i], std::vector<IPAddress>()); 137 might_add_to_merged_list = true; 138 } 139 const std::vector<IPAddress>& addresses = list[i]->GetIPs(); 140 address_list& current_list = address_map[key]; 141 for (std::vector<IPAddress>::const_iterator it = addresses.begin(); 142 it != addresses.end(); 143 ++it) { 144 current_list.second.push_back(*it); 145 } 146 if (!might_add_to_merged_list) { 147 delete list[i]; 148 } 149 } 150 151 // Next, look for existing network objects to re-use. 152 for (std::map<std::string, address_list >::iterator it = address_map.begin(); 153 it != address_map.end(); 154 ++it) { 155 const std::string& key = it->first; 156 Network* net = it->second.first; 157 NetworkMap::iterator existing = networks_map_.find(key); 158 if (existing == networks_map_.end()) { 159 // This network is new. Place it in the network map. 160 merged_list.push_back(net); 161 networks_map_[key] = net; 162 *changed = true; 163 } else { 164 // This network exists in the map already. Reset its IP addresses. 165 *changed = existing->second->SetIPs(it->second.second, *changed); 166 merged_list.push_back(existing->second); 167 if (existing->second != net) { 168 delete net; 169 } 170 } 171 } 172 networks_ = merged_list; 173 } 174 175 BasicNetworkManager::BasicNetworkManager() 176 : thread_(NULL), sent_first_update_(false), start_count_(0) { 177 } 178 179 BasicNetworkManager::~BasicNetworkManager() { 180 } 181 182 #if defined(POSIX) 183 void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces, 184 bool include_ignored, 185 NetworkList* networks) const { 186 NetworkMap current_networks; 187 for (struct ifaddrs* cursor = interfaces; 188 cursor != NULL; cursor = cursor->ifa_next) { 189 IPAddress prefix; 190 IPAddress mask; 191 IPAddress ip; 192 int scope_id = 0; 193 194 // Some interfaces may not have address assigned. 195 if (!cursor->ifa_addr || !cursor->ifa_netmask) 196 continue; 197 198 switch (cursor->ifa_addr->sa_family) { 199 case AF_INET: { 200 ip = IPAddress( 201 reinterpret_cast<sockaddr_in*>(cursor->ifa_addr)->sin_addr); 202 mask = IPAddress( 203 reinterpret_cast<sockaddr_in*>(cursor->ifa_netmask)->sin_addr); 204 break; 205 } 206 case AF_INET6: { 207 if (ipv6_enabled()) { 208 ip = IPAddress( 209 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_addr); 210 mask = IPAddress( 211 reinterpret_cast<sockaddr_in6*>(cursor->ifa_netmask)->sin6_addr); 212 scope_id = 213 reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_scope_id; 214 break; 215 } else { 216 continue; 217 } 218 } 219 default: { 220 continue; 221 } 222 } 223 int prefix_length = CountIPMaskBits(mask); 224 prefix = TruncateIP(ip, prefix_length); 225 std::string key = MakeNetworkKey(std::string(cursor->ifa_name), 226 prefix, prefix_length); 227 NetworkMap::iterator existing_network = current_networks.find(key); 228 if (existing_network == current_networks.end()) { 229 scoped_ptr<Network> network(new Network(cursor->ifa_name, 230 cursor->ifa_name, 231 prefix, 232 prefix_length)); 233 network->set_scope_id(scope_id); 234 network->AddIP(ip); 235 bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) || 236 IsIgnoredNetwork(*network)); 237 network->set_ignored(ignored); 238 if (include_ignored || !network->ignored()) { 239 networks->push_back(network.release()); 240 } 241 } else { 242 (*existing_network).second->AddIP(ip); 243 } 244 } 245 } 246 247 bool BasicNetworkManager::CreateNetworks(bool include_ignored, 248 NetworkList* networks) const { 249 struct ifaddrs* interfaces; 250 int error = getifaddrs(&interfaces); 251 if (error != 0) { 252 LOG_ERR(LERROR) << "getifaddrs failed to gather interface data: " << error; 253 return false; 254 } 255 256 ConvertIfAddrs(interfaces, include_ignored, networks); 257 258 freeifaddrs(interfaces); 259 return true; 260 } 261 262 #elif defined(WIN32) 263 264 unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist, 265 const IPAddress& ip, IPAddress* prefix) { 266 IPAddress current_prefix; 267 IPAddress best_prefix; 268 unsigned int best_length = 0; 269 while (prefixlist) { 270 // Look for the longest matching prefix in the prefixlist. 271 if (prefixlist->Address.lpSockaddr == NULL || 272 prefixlist->Address.lpSockaddr->sa_family != ip.family()) { 273 prefixlist = prefixlist->Next; 274 continue; 275 } 276 switch (prefixlist->Address.lpSockaddr->sa_family) { 277 case AF_INET: { 278 sockaddr_in* v4_addr = 279 reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr); 280 current_prefix = IPAddress(v4_addr->sin_addr); 281 break; 282 } 283 case AF_INET6: { 284 sockaddr_in6* v6_addr = 285 reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr); 286 current_prefix = IPAddress(v6_addr->sin6_addr); 287 break; 288 } 289 default: { 290 prefixlist = prefixlist->Next; 291 continue; 292 } 293 } 294 if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix && 295 prefixlist->PrefixLength > best_length) { 296 best_prefix = current_prefix; 297 best_length = prefixlist->PrefixLength; 298 } 299 prefixlist = prefixlist->Next; 300 } 301 *prefix = best_prefix; 302 return best_length; 303 } 304 305 bool BasicNetworkManager::CreateNetworks(bool include_ignored, 306 NetworkList* networks) const { 307 NetworkMap current_networks; 308 // MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses. 309 size_t buffer_size = 16384; 310 scoped_array<char> adapter_info(new char[buffer_size]); 311 PIP_ADAPTER_ADDRESSES adapter_addrs = 312 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get()); 313 int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST | 314 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX); 315 int ret = 0; 316 do { 317 adapter_info.reset(new char[buffer_size]); 318 adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get()); 319 ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags, 320 0, adapter_addrs, 321 reinterpret_cast<PULONG>(&buffer_size)); 322 } while (ret == ERROR_BUFFER_OVERFLOW); 323 if (ret != ERROR_SUCCESS) { 324 return false; 325 } 326 int count = 0; 327 while (adapter_addrs) { 328 if (adapter_addrs->OperStatus == IfOperStatusUp) { 329 PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress; 330 PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix; 331 std::string name; 332 std::string description; 333 #ifdef _DEBUG 334 name = ToUtf8(adapter_addrs->FriendlyName, 335 wcslen(adapter_addrs->FriendlyName)); 336 #endif 337 description = ToUtf8(adapter_addrs->Description, 338 wcslen(adapter_addrs->Description)); 339 for (; address; address = address->Next) { 340 #ifndef _DEBUG 341 name = talk_base::ToString(count); 342 #endif 343 344 IPAddress ip; 345 int scope_id = 0; 346 scoped_ptr<Network> network; 347 switch (address->Address.lpSockaddr->sa_family) { 348 case AF_INET: { 349 sockaddr_in* v4_addr = 350 reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr); 351 ip = IPAddress(v4_addr->sin_addr); 352 break; 353 } 354 case AF_INET6: { 355 if (ipv6_enabled()) { 356 sockaddr_in6* v6_addr = 357 reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr); 358 scope_id = v6_addr->sin6_scope_id; 359 ip = IPAddress(v6_addr->sin6_addr); 360 break; 361 } else { 362 continue; 363 } 364 } 365 default: { 366 continue; 367 } 368 } 369 IPAddress prefix; 370 int prefix_length = GetPrefix(prefixlist, ip, &prefix); 371 std::string key = MakeNetworkKey(name, prefix, prefix_length); 372 NetworkMap::iterator existing_network = current_networks.find(key); 373 if (existing_network == current_networks.end()) { 374 scoped_ptr<Network> network(new Network(name, 375 description, 376 prefix, 377 prefix_length)); 378 network->set_scope_id(scope_id); 379 network->AddIP(ip); 380 bool ignore = ((adapter_addrs->IfType == IF_TYPE_SOFTWARE_LOOPBACK) || 381 IsIgnoredNetwork(*network)); 382 network->set_ignored(ignore); 383 if (include_ignored || !network->ignored()) { 384 networks->push_back(network.release()); 385 } 386 } else { 387 (*existing_network).second->AddIP(ip); 388 } 389 } 390 // Count is per-adapter - all 'Networks' created from the same 391 // adapter need to have the same name. 392 ++count; 393 } 394 adapter_addrs = adapter_addrs->Next; 395 } 396 return true; 397 } 398 #endif // WIN32 399 400 bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) { 401 #ifdef POSIX 402 // Ignore local networks (lo, lo0, etc) 403 // Also filter out VMware interfaces, typically named vmnet1 and vmnet8 404 if (strncmp(network.name().c_str(), "vmnet", 5) == 0 || 405 strncmp(network.name().c_str(), "vnic", 4) == 0) { 406 return true; 407 } 408 #elif defined(WIN32) 409 // Ignore any HOST side vmware adapters with a description like: 410 // VMware Virtual Ethernet Adapter for VMnet1 411 // but don't ignore any GUEST side adapters with a description like: 412 // VMware Accelerated AMD PCNet Adapter #2 413 if (strstr(network.description().c_str(), "VMnet") != NULL) { 414 return true; 415 } 416 #endif 417 418 // Ignore any networks with a 0.x.y.z IP 419 if (network.prefix().family() == AF_INET) { 420 return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000); 421 } 422 return false; 423 } 424 425 void BasicNetworkManager::StartUpdating() { 426 thread_ = Thread::Current(); 427 if (start_count_) { 428 // If network interfaces are already discovered and signal is sent, 429 // we should trigger network signal immediately for the new clients 430 // to start allocating ports. 431 if (sent_first_update_) 432 thread_->Post(this, kSignalNetworksMessage); 433 } else { 434 thread_->Post(this, kUpdateNetworksMessage); 435 } 436 ++start_count_; 437 } 438 439 void BasicNetworkManager::StopUpdating() { 440 ASSERT(Thread::Current() == thread_); 441 if (!start_count_) 442 return; 443 444 --start_count_; 445 if (!start_count_) { 446 thread_->Clear(this); 447 sent_first_update_ = false; 448 } 449 } 450 451 void BasicNetworkManager::OnMessage(Message* msg) { 452 switch (msg->message_id) { 453 case kUpdateNetworksMessage: { 454 DoUpdateNetworks(); 455 break; 456 } 457 case kSignalNetworksMessage: { 458 SignalNetworksChanged(); 459 break; 460 } 461 default: 462 ASSERT(false); 463 } 464 } 465 466 void BasicNetworkManager::DoUpdateNetworks() { 467 if (!start_count_) 468 return; 469 470 ASSERT(Thread::Current() == thread_); 471 472 NetworkList list; 473 if (!CreateNetworks(false, &list)) { 474 SignalError(); 475 } else { 476 bool changed; 477 MergeNetworkList(list, &changed); 478 if (changed || !sent_first_update_) { 479 SignalNetworksChanged(); 480 sent_first_update_ = true; 481 } 482 } 483 484 thread_->PostDelayed(kNetworksUpdateIntervalMs, this, kUpdateNetworksMessage); 485 } 486 487 void BasicNetworkManager::DumpNetworks(bool include_ignored) { 488 NetworkList list; 489 CreateNetworks(include_ignored, &list); 490 LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:"; 491 for (size_t i = 0; i < list.size(); ++i) { 492 const Network* network = list[i]; 493 if (!network->ignored() || include_ignored) { 494 LOG(LS_INFO) << network->ToString() << ": " 495 << network->description() 496 << ((network->ignored()) ? ", Ignored" : ""); 497 } 498 } 499 // Release the network list created previously. 500 // Do this in a seperated for loop for better readability. 501 for (size_t i = 0; i < list.size(); ++i) { 502 delete list[i]; 503 } 504 } 505 506 Network::Network(const std::string& name, const std::string& desc, 507 const IPAddress& prefix, int prefix_length) 508 : name_(name), description_(desc), prefix_(prefix), 509 prefix_length_(prefix_length), scope_id_(0), ignored_(false), 510 uniform_numerator_(0), uniform_denominator_(0), exponential_numerator_(0), 511 exponential_denominator_(0) { 512 } 513 514 std::string Network::ToString() const { 515 std::stringstream ss; 516 // Print out the first space-terminated token of the network desc, plus 517 // the IP address. 518 ss << "Net[" << description_.substr(0, description_.find(' ')) 519 << ":" << prefix_.ToSensitiveString() << "/" << prefix_length_ << "]"; 520 return ss.str(); 521 } 522 523 // Sets the addresses of this network. Returns true if the address set changed. 524 // Change detection is short circuited if the changed argument is true. 525 bool Network::SetIPs(const std::vector<IPAddress>& ips, bool changed) { 526 changed = changed || ips.size() != ips_.size(); 527 // Detect changes with a nested loop; n-squared but we expect on the order 528 // of 2-3 addresses per network. 529 for (std::vector<IPAddress>::const_iterator it = ips.begin(); 530 !changed && it != ips.end(); 531 ++it) { 532 bool found = false; 533 for (std::vector<IPAddress>::iterator inner_it = ips_.begin(); 534 !found && inner_it != ips_.end(); 535 ++inner_it) { 536 if (*it == *inner_it) { 537 found = true; 538 } 539 } 540 changed = !found; 541 } 542 ips_ = ips; 543 return changed; 544 } 545 } // namespace talk_base 546