diff --git a/rtc_base/network.cc b/rtc_base/network.cc index b485077129..a9352d809a 100644 --- a/rtc_base/network.cc +++ b/rtc_base/network.cc @@ -40,6 +40,14 @@ namespace rtc { namespace { +// List of MAC addresses of known VPN (for windows). +constexpr uint8_t kVpns[2][6] = { + // Cisco AnyConnect. + {0x0, 0x5, 0x9A, 0x3C, 0x7A, 0x0}, + // GlobalProtect Virtual Ethernet. + {0x2, 0x50, 0x41, 0x0, 0x0, 0x1}, +}; + const uint32_t kUpdateNetworksMessage = 1; const uint32_t kSignalNetworksMessage = 2; @@ -486,6 +494,20 @@ Network* NetworkManagerBase::GetNetworkFromAddress( return nullptr; } +bool NetworkManagerBase::IsVpnMacAddress( + rtc::ArrayView address) { + if (address.data() == nullptr && address.size() == 0) { + return false; + } + for (const auto& vpn : kVpns) { + if (sizeof(vpn) == address.size() && + memcmp(vpn, address.data(), address.size()) == 0) { + return true; + } + } + return false; +} + BasicNetworkManager::BasicNetworkManager() : BasicNetworkManager(nullptr) {} BasicNetworkManager::BasicNetworkManager( @@ -781,6 +803,15 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored, vpn_underlying_adapter_type = adapter_type; adapter_type = ADAPTER_TYPE_VPN; } + if (adapter_type != ADAPTER_TYPE_VPN && + IsVpnMacAddress(rtc::ArrayView( + reinterpret_cast( + adapter_addrs->PhysicalAddress), + adapter_addrs->PhysicalAddressLength))) { + vpn_underlying_adapter_type = adapter_type; + adapter_type = ADAPTER_TYPE_VPN; + } + std::unique_ptr network(new Network( name, description, prefix, prefix_length, adapter_type)); network->set_underlying_type_for_vpn(vpn_underlying_adapter_type); diff --git a/rtc_base/network.h b/rtc_base/network.h index 94350e0e4d..d97b07fd4e 100644 --- a/rtc_base/network.h +++ b/rtc_base/network.h @@ -19,6 +19,7 @@ #include #include +#include "api/array_view.h" #include "api/sequence_checker.h" #include "rtc_base/ip_address.h" #include "rtc_base/mdns_responder_interface.h" @@ -194,6 +195,10 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager { bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const override; + // Check if MAC address in |bytes| is one of the pre-defined + // MAC addresses for know VPNs. + static bool IsVpnMacAddress(rtc::ArrayView address); + protected: typedef std::map NetworkMap; // Updates `networks_` with the networks listed in `list`. If diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc index e7b9982cc6..b4f1f31b99 100644 --- a/rtc_base/network_unittest.cc +++ b/rtc_base/network_unittest.cc @@ -1434,4 +1434,19 @@ TEST_F(NetworkTest, VpnListOverrideAdapterType) { } #endif // defined(WEBRTC_POSIX) +TEST_F(NetworkTest, HardcodedVpn) { + const uint8_t cisco[] = {0x0, 0x5, 0x9A, 0x3C, 0x7A, 0x0}; + const uint8_t global[] = {0x2, 0x50, 0x41, 0x0, 0x0, 0x1}; + const uint8_t unknown[] = {0x2, 0x50, 0x41, 0x0, 0x0, 0x0}; + const uint8_t five_bytes[] = {0x2, 0x50, 0x41, 0x0, 0x0}; + EXPECT_TRUE(NetworkManagerBase::IsVpnMacAddress(cisco)); + EXPECT_TRUE(NetworkManagerBase::IsVpnMacAddress(global)); + + EXPECT_FALSE(NetworkManagerBase::IsVpnMacAddress( + rtc::ArrayView(cisco, 5))); + EXPECT_FALSE(NetworkManagerBase::IsVpnMacAddress(five_bytes)); + EXPECT_FALSE(NetworkManagerBase::IsVpnMacAddress(unknown)); + EXPECT_FALSE(NetworkManagerBase::IsVpnMacAddress(nullptr)); +} + } // namespace rtc