#include "rtc_base/network.h"
#include "absl/strings/string_view.h"
#include "rtc_base/experiments/field_trial_parser.h"
#if defined(WEBRTC_POSIX)
#include <net/if.h>
#endif
#if defined(WEBRTC_WIN)
#include <iphlpapi.h>
#include "rtc_base/win32.h"
#elif !defined(__native_client__)
#include "rtc_base/ifaddrs_converter.h"
#endif
#include <memory>
#include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/network_monitor.h"
#include "rtc_base/socket.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/thread.h"
namespace rtc {
namespace {
SafeTask;
TimeDelta;
constexpr uint8_t kVpns[3][6] = …;
const int kNetworksUpdateIntervalMs = …;
const int kHighestNetworkPreference = …;
struct AddressList { … };
bool SortNetworks(const Network* a, const Network* b) { … }
uint16_t ComputeNetworkCostByType(int type,
bool is_vpn,
bool use_differentiated_cellular_costs,
bool add_network_cost_to_vpn) { … }
#if !defined(__native_client__)
bool IsIgnoredIPv6(bool allow_mac_based_ipv6, const InterfaceAddress& ip) { … }
#endif
bool ShouldAdapterChangeTriggerNetworkChange(rtc::AdapterType old_type,
rtc::AdapterType new_type) { … }
#if defined(WEBRTC_WIN)
bool IpAddressAttributesEnabled(const webrtc::FieldTrialsView* field_trials) {
if (field_trials &&
field_trials->IsEnabled("WebRTC-IPv6NetworkResolutionFixes")) {
webrtc::FieldTrialParameter<bool> ip_address_attributes_enabled(
"IpAddressAttributesEnabled", false);
webrtc::ParseFieldTrial(
{&ip_address_attributes_enabled},
field_trials->Lookup("WebRTC-IPv6NetworkResolutionFixes"));
return ip_address_attributes_enabled;
}
return false;
}
#endif
}
const char kPublicIPv4Host[] = …;
const char kPublicIPv6Host[] = …;
const int kPublicPort = …;
namespace webrtc_network_internal {
bool CompareNetworks(const std::unique_ptr<Network>& a,
const std::unique_ptr<Network>& b) { … }
}
std::string MakeNetworkKey(absl::string_view name,
const IPAddress& prefix,
int prefix_length) { … }
bool MatchTypeNameWithIndexPattern(absl::string_view network_name,
absl::string_view type_name) { … }
AdapterType GetAdapterTypeFromName(absl::string_view network_name) { … }
NetworkManager::EnumerationPermission NetworkManager::enumeration_permission()
const { … }
bool NetworkManager::GetDefaultLocalAddress(int family, IPAddress* addr) const { … }
webrtc::MdnsResponderInterface* NetworkManager::GetMdnsResponder() const { … }
NetworkManagerBase::NetworkManagerBase()
: … { … }
NetworkManager::EnumerationPermission
NetworkManagerBase::enumeration_permission() const { … }
std::unique_ptr<Network> NetworkManagerBase::CreateNetwork(
absl::string_view name,
absl::string_view description,
const IPAddress& prefix,
int prefix_length,
AdapterType type) const { … }
std::vector<const Network*> NetworkManagerBase::GetAnyAddressNetworks() { … }
std::vector<const Network*> NetworkManagerBase::GetNetworks() const { … }
void NetworkManagerBase::MergeNetworkList(
std::vector<std::unique_ptr<Network>> new_networks,
bool* changed) { … }
void NetworkManagerBase::MergeNetworkList(
std::vector<std::unique_ptr<Network>> new_networks,
bool* changed,
NetworkManager::Stats* stats) { … }
void NetworkManagerBase::set_default_local_addresses(const IPAddress& ipv4,
const IPAddress& ipv6) { … }
bool NetworkManagerBase::GetDefaultLocalAddress(int family,
IPAddress* ipaddr) const { … }
Network* NetworkManagerBase::GetNetworkFromAddress(
const rtc::IPAddress& ip) const { … }
bool NetworkManagerBase::IsVpnMacAddress(
rtc::ArrayView<const uint8_t> address) { … }
BasicNetworkManager::BasicNetworkManager(
NetworkMonitorFactory* network_monitor_factory,
SocketFactory* socket_factory,
const webrtc::FieldTrialsView* field_trials_view)
: … { … }
BasicNetworkManager::~BasicNetworkManager() { … }
void BasicNetworkManager::OnNetworksChanged() { … }
#if defined(__native_client__)
bool BasicNetworkManager::CreateNetworks(
bool include_ignored,
std::vector<std::unique_ptr<Network>>* networks) const {
RTC_DCHECK_NOTREACHED();
RTC_LOG(LS_WARNING) << "BasicNetworkManager doesn't work on NaCl yet";
return false;
}
#elif defined(WEBRTC_POSIX)
NetworkMonitorInterface::InterfaceInfo BasicNetworkManager::GetInterfaceInfo(
struct ifaddrs* cursor) const { … }
void BasicNetworkManager::ConvertIfAddrs(
struct ifaddrs* interfaces,
IfAddrsConverter* ifaddrs_converter,
bool include_ignored,
std::vector<std::unique_ptr<Network>>* networks) const { … }
bool BasicNetworkManager::CreateNetworks(
bool include_ignored,
std::vector<std::unique_ptr<Network>>* networks) const { … }
#elif defined(WEBRTC_WIN)
unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist,
const IPAddress& ip,
IPAddress* prefix) {
IPAddress current_prefix;
IPAddress best_prefix;
unsigned int best_length = 0;
while (prefixlist) {
if (prefixlist->Address.lpSockaddr == nullptr ||
prefixlist->Address.lpSockaddr->sa_family != ip.family()) {
prefixlist = prefixlist->Next;
continue;
}
switch (prefixlist->Address.lpSockaddr->sa_family) {
case AF_INET: {
sockaddr_in* v4_addr =
reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr);
current_prefix = IPAddress(v4_addr->sin_addr);
break;
}
case AF_INET6: {
sockaddr_in6* v6_addr =
reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr);
current_prefix = IPAddress(v6_addr->sin6_addr);
break;
}
default: {
prefixlist = prefixlist->Next;
continue;
}
}
if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix &&
prefixlist->PrefixLength > best_length) {
best_prefix = current_prefix;
best_length = prefixlist->PrefixLength;
}
prefixlist = prefixlist->Next;
}
*prefix = best_prefix;
return best_length;
}
bool BasicNetworkManager::CreateNetworks(
bool include_ignored,
std::vector<std::unique_ptr<Network>>* networks) const {
std::map<std::string, Network*> current_networks;
size_t buffer_size = 16384;
std::unique_ptr<char[]> adapter_info(new char[buffer_size]);
PIP_ADAPTER_ADDRESSES adapter_addrs =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX);
int ret = 0;
do {
adapter_info.reset(new char[buffer_size]);
adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags, 0, adapter_addrs,
reinterpret_cast<PULONG>(&buffer_size));
} while (ret == ERROR_BUFFER_OVERFLOW);
if (ret != ERROR_SUCCESS) {
return false;
}
int count = 0;
while (adapter_addrs) {
if (adapter_addrs->OperStatus == IfOperStatusUp) {
PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress;
PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix;
std::string description = ToUtf8(adapter_addrs->Description,
wcslen(adapter_addrs->Description));
for (; address; address = address->Next) {
std::string name = rtc::ToString(count);
#if !defined(NDEBUG)
name = ToUtf8(adapter_addrs->FriendlyName,
wcslen(adapter_addrs->FriendlyName));
#endif
IPAddress ip;
int scope_id = 0;
std::unique_ptr<Network> network;
switch (address->Address.lpSockaddr->sa_family) {
case AF_INET: {
sockaddr_in* v4_addr =
reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr);
ip = IPAddress(v4_addr->sin_addr);
break;
}
case AF_INET6: {
sockaddr_in6* v6_addr =
reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
scope_id = v6_addr->sin6_scope_id;
int ip_address_attributes = IPV6_ADDRESS_FLAG_NONE;
if (IpAddressAttributesEnabled(field_trials_.get())) {
if (address->PrefixOrigin == IpPrefixOriginRouterAdvertisement &&
address->SuffixOrigin == IpSuffixOriginRandom) {
ip_address_attributes |= IPV6_ADDRESS_FLAG_TEMPORARY;
}
if (address->PreferredLifetime == 0) {
ip_address_attributes |= IPV6_ADDRESS_FLAG_DEPRECATED;
}
}
if (IsIgnoredIPv6(allow_mac_based_ipv6_,
InterfaceAddress(v6_addr->sin6_addr,
ip_address_attributes))) {
continue;
}
ip = InterfaceAddress(v6_addr->sin6_addr, ip_address_attributes);
break;
}
default: {
continue;
}
}
IPAddress prefix;
int prefix_length = GetPrefix(prefixlist, ip, &prefix);
std::string key = MakeNetworkKey(name, prefix, prefix_length);
auto existing_network = current_networks.find(key);
if (existing_network == current_networks.end()) {
AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN;
switch (adapter_addrs->IfType) {
case IF_TYPE_SOFTWARE_LOOPBACK:
adapter_type = ADAPTER_TYPE_LOOPBACK;
break;
case IF_TYPE_ETHERNET_CSMACD:
case IF_TYPE_ETHERNET_3MBIT:
case IF_TYPE_IEEE80212:
case IF_TYPE_FASTETHER:
case IF_TYPE_FASTETHER_FX:
case IF_TYPE_GIGABITETHERNET:
adapter_type = ADAPTER_TYPE_ETHERNET;
break;
case IF_TYPE_IEEE80211:
adapter_type = ADAPTER_TYPE_WIFI;
break;
case IF_TYPE_WWANPP:
case IF_TYPE_WWANPP2:
adapter_type = ADAPTER_TYPE_CELLULAR;
break;
default:
adapter_type = ADAPTER_TYPE_UNKNOWN;
break;
}
auto underlying_type_for_vpn = ADAPTER_TYPE_UNKNOWN;
if (adapter_type != ADAPTER_TYPE_VPN &&
IsConfiguredVpn(prefix, prefix_length)) {
underlying_type_for_vpn = adapter_type;
adapter_type = ADAPTER_TYPE_VPN;
}
if (adapter_type != ADAPTER_TYPE_VPN &&
IsVpnMacAddress(rtc::ArrayView<const uint8_t>(
reinterpret_cast<const uint8_t*>(
adapter_addrs->PhysicalAddress),
adapter_addrs->PhysicalAddressLength))) {
underlying_type_for_vpn = ADAPTER_TYPE_UNKNOWN;
adapter_type = ADAPTER_TYPE_VPN;
}
auto network = CreateNetwork(name, description, prefix, prefix_length,
adapter_type);
network->set_underlying_type_for_vpn(underlying_type_for_vpn);
network->set_default_local_address_provider(this);
network->set_mdns_responder_provider(this);
network->set_scope_id(scope_id);
network->AddIP(ip);
bool ignored = IsIgnoredNetwork(*network);
network->set_ignored(ignored);
if (include_ignored || !network->ignored()) {
current_networks[key] = network.get();
networks->push_back(std::move(network));
}
} else {
(*existing_network).second->AddIP(ip);
}
}
++count;
}
adapter_addrs = adapter_addrs->Next;
}
return true;
}
#endif
bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const { … }
void BasicNetworkManager::StartUpdating() { … }
void BasicNetworkManager::StopUpdating() { … }
void BasicNetworkManager::StartNetworkMonitor() { … }
void BasicNetworkManager::StopNetworkMonitor() { … }
IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const { … }
void BasicNetworkManager::UpdateNetworksOnce() { … }
void BasicNetworkManager::UpdateNetworksContinually() { … }
void BasicNetworkManager::DumpNetworks() { … }
NetworkBindingResult BasicNetworkManager::BindSocketToNetwork(
int socket_fd,
const IPAddress& address) { … }
Network::Network(absl::string_view name,
absl::string_view desc,
const IPAddress& prefix,
int prefix_length,
AdapterType type)
: … { … }
Network::Network(const Network&) = default;
Network::~Network() = default;
bool Network::SetIPs(const std::vector<InterfaceAddress>& ips, bool changed) { … }
IPAddress Network::GetBestIP() const { … }
webrtc::MdnsResponderInterface* Network::GetMdnsResponder() const { … }
uint16_t Network::GetCost(const webrtc::FieldTrialsView& field_trials) const { … }
std::pair<rtc::AdapterType, bool >
Network::GuessAdapterFromNetworkCost(int network_cost) { … }
std::string Network::ToString() const { … }
void BasicNetworkManager::set_vpn_list(const std::vector<NetworkMask>& vpn) { … }
bool BasicNetworkManager::IsConfiguredVpn(IPAddress prefix,
int prefix_length) const { … }
}