diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/base/net_util.cc | 3 | ||||
-rw-r--r-- | net/base/net_util.h | 22 | ||||
-rw-r--r-- | net/base/net_util_posix.cc | 6 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 109 | ||||
-rw-r--r-- | net/base/net_util_win.cc | 184 | ||||
-rw-r--r-- | net/base/net_util_win.h | 85 |
6 files changed, 322 insertions, 87 deletions
diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 559f887..704add2 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -1040,4 +1040,7 @@ unsigned MaskPrefixLength(const IPAddressNumber& mask) { return CommonPrefixLength(mask, all_ones); } +ScopedWifiOptions::~ScopedWifiOptions() { +} + } // namespace net diff --git a/net/base/net_util.h b/net/base/net_util.h index 5999ad2..49780e8 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -518,6 +518,28 @@ enum WifiPHYLayerProtocol { // Currently only available on OS_WIN. NET_EXPORT WifiPHYLayerProtocol GetWifiPHYLayerProtocol(); +enum WifiOptions { + // Disables background SSID scans. + WIFI_OPTIONS_DISABLE_SCAN = 1 << 0, + // Enables media streaming mode. + WIFI_OPTIONS_MEDIA_STREAMING_MODE = 1 << 1 +}; + +class NET_EXPORT ScopedWifiOptions { + public: + ScopedWifiOptions() {} + virtual ~ScopedWifiOptions(); + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedWifiOptions); +}; + +// Set temporary options on all wifi interfaces. +// |options| is an ORed bitfield of WifiOptions. +// Options are automatically disabled when the scoped pointer +// is freed. Currently only available on OS_WIN. +NET_EXPORT scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options); + // Returns number of matching initial bits between the addresses |a1| and |a2|. unsigned CommonPrefixLength(const IPAddressNumber& a1, const IPAddressNumber& a2); diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc index 7f88ef6..73704cd 100644 --- a/net/base/net_util_posix.cc +++ b/net/base/net_util_posix.cc @@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" @@ -284,4 +285,9 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; } +scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) { + return scoped_ptr<ScopedWifiOptions>(); +} + + } // namespace net diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 8306db5..3bb518f 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -24,6 +24,7 @@ #include <iphlpapi.h> #include <objbase.h> #include "base/win/windows_version.h" +#include "net/base/net_util_win.h" #elif !defined(OS_ANDROID) #include <net/if.h> #endif // OS_WIN @@ -790,6 +791,114 @@ TEST(NetUtilTest, GetNetworkList) { } } +namespace { + +#if defined(OS_WIN) +bool read_int_or_bool(DWORD data_size, + PVOID data) { + switch (data_size) { + case 1: + return !!*reinterpret_cast<uint8*>(data); + case 4: + return !!*reinterpret_cast<uint32*>(data); + default: + LOG(FATAL) << "That is not a type I know!"; + return false; + } +} + +int GetWifiOptions() { + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); + if (!wlanapi.initialized) + return -1; + + internal::WlanHandle client; + DWORD cur_version = 0; + const DWORD kMaxClientVersion = 2; + DWORD result = wlanapi.OpenHandle( + kMaxClientVersion, &cur_version, &client); + if (result != ERROR_SUCCESS) + return -1; + + WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; + result = wlanapi.enum_interfaces_func(client, NULL, &interface_list_ptr); + if (result != ERROR_SUCCESS) + return -1; + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list( + interface_list_ptr); + + for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i]; + DWORD data_size; + PVOID data; + int options = 0; + result = wlanapi.query_interface_func( + client, + &info->InterfaceGuid, + wlan_intf_opcode_background_scan_enabled, + NULL, + &data_size, + &data, + NULL); + if (result != ERROR_SUCCESS) + continue; + if (!read_int_or_bool(data_size, data)) { + options |= WIFI_OPTIONS_DISABLE_SCAN; + } + internal::WlanApi::GetInstance().free_memory_func(data); + + result = wlanapi.query_interface_func( + client, + &info->InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, + NULL, + &data_size, + &data, + NULL); + if (result != ERROR_SUCCESS) + continue; + if (read_int_or_bool(data_size, data)) { + options |= WIFI_OPTIONS_MEDIA_STREAMING_MODE; + } + internal::WlanApi::GetInstance().free_memory_func(data); + + // Just the the options from the first succesful + // interface. + return options; + } + + // No wifi interface found. + return -1; +} + +#else // OS_WIN + +int GetWifiOptions() { + // Not supported. + return -1; +} + +#endif // OS_WIN + +void TryChangeWifiOptions(int options) { + int previous_options = GetWifiOptions(); + scoped_ptr<ScopedWifiOptions> scoped_options = SetWifiOptions(options); + EXPECT_EQ(previous_options | options, GetWifiOptions()); + scoped_options.reset(); + EXPECT_EQ(previous_options, GetWifiOptions()); +} + +}; // namespace + +// Test SetWifiOptions(). +TEST(NetUtilTest, SetWifiOptionsTest) { + TryChangeWifiOptions(0); + TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN); + TryChangeWifiOptions(WIFI_OPTIONS_MEDIA_STREAMING_MODE); + TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN | + WIFI_OPTIONS_MEDIA_STREAMING_MODE); +} + struct NonUniqueNameTestData { bool is_unique; const char* hostname; diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc index 6f331ec..4f59d6d 100644 --- a/net/base/net_util_win.cc +++ b/net/base/net_util_win.cc @@ -22,67 +22,13 @@ #include "net/base/escape.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/net_util_win.h" #include "url/gurl.h" namespace net { namespace { -struct WlanApi { - typedef DWORD (WINAPI *WlanOpenHandleFunc)( - DWORD, VOID*, DWORD*, HANDLE*); - typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( - HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); - typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( - HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, - WLAN_OPCODE_VALUE_TYPE*); - typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); - typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); - - WlanApi() : initialized(false) { - // Use an absolute path to load the DLL to avoid DLL preloading attacks. - static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; - wchar_t path[MAX_PATH] = {0}; - ExpandEnvironmentStrings(kDLL, path, arraysize(path)); - module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!module) - return; - - open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( - ::GetProcAddress(module, "WlanOpenHandle")); - enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( - ::GetProcAddress(module, "WlanEnumInterfaces")); - query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( - ::GetProcAddress(module, "WlanQueryInterface")); - free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( - ::GetProcAddress(module, "WlanFreeMemory")); - close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( - ::GetProcAddress(module, "WlanCloseHandle")); - initialized = open_handle_func && enum_interfaces_func && - query_interface_func && free_memory_func && - close_handle_func; - } - - template <typename T> - DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { - HANDLE temp_handle; - DWORD result = open_handle_func(client_version, NULL, cur_version, - &temp_handle); - if (result != ERROR_SUCCESS) - return result; - handle->Set(temp_handle); - return ERROR_SUCCESS; - } - - HMODULE module; - WlanOpenHandleFunc open_handle_func; - WlanEnumInterfacesFunc enum_interfaces_func; - WlanQueryInterfaceFunc query_interface_func; - WlanFreeMemoryFunc free_memory_func; - WlanCloseHandleFunc close_handle_func; - bool initialized; -}; - // Converts Windows defined types to NetworkInterfaceType. NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) { // Bail out for pre-Vista versions of Windows which are documented to give @@ -104,6 +50,43 @@ NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) { } // namespace +namespace internal { + +base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = + LAZY_INSTANCE_INITIALIZER; + +WlanApi& WlanApi::GetInstance() { + return lazy_wlanapi.Get(); +} + +WlanApi::WlanApi() : initialized(false) { + // Use an absolute path to load the DLL to avoid DLL preloading attacks. + static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; + wchar_t path[MAX_PATH] = {0}; + ExpandEnvironmentStrings(kDLL, path, arraysize(path)); + module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!module) + return; + + open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( + ::GetProcAddress(module, "WlanOpenHandle")); + enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( + ::GetProcAddress(module, "WlanEnumInterfaces")); + query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( + ::GetProcAddress(module, "WlanQueryInterface")); + set_interface_func = reinterpret_cast<WlanSetInterfaceFunc>( + ::GetProcAddress(module, "WlanSetInterface")); + free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( + ::GetProcAddress(module, "WlanFreeMemory")); + close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( + ::GetProcAddress(module, "WlanCloseHandle")); + initialized = open_handle_func && enum_interfaces_func && + query_interface_func && set_interface_func && + free_memory_func && close_handle_func; +} + +} // namespace internal + bool GetNetworkList(NetworkInterfaceList* networks, int policy) { // GetAdaptersAddresses() may require IO operations. base::ThreadRestrictions::AssertIOAllowed(); @@ -221,39 +204,11 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { } WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { - static base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = - LAZY_INSTANCE_INITIALIZER; - - struct WlanApiHandleTraits { - typedef HANDLE Handle; - - static bool CloseHandle(HANDLE handle) { - return lazy_wlanapi.Get().close_handle_func(handle, NULL) == - ERROR_SUCCESS; - } - static bool IsHandleValid(HANDLE handle) { - return base::win::HandleTraits::IsHandleValid(handle); - } - static HANDLE NullHandle() { - return base::win::HandleTraits::NullHandle(); - } - }; - - typedef base::win::GenericScopedHandle< - WlanApiHandleTraits, - base::win::DummyVerifierTraits> WlanHandle; - - struct WlanApiDeleter { - inline void operator()(void* ptr) const { - lazy_wlanapi.Get().free_memory_func(ptr); - } - }; - - const WlanApi& wlanapi = lazy_wlanapi.Get(); + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); if (!wlanapi.initialized) return WIFI_PHY_LAYER_PROTOCOL_NONE; - WlanHandle client; + internal::WlanHandle client; DWORD cur_version = 0; const DWORD kMaxClientVersion = 2; DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client); @@ -264,7 +219,7 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { result = wlanapi.enum_interfaces_func(client, NULL, &interface_list_ptr); if (result != ERROR_SUCCESS) return WIFI_PHY_LAYER_PROTOCOL_NONE; - scoped_ptr<WLAN_INTERFACE_INFO_LIST, WlanApiDeleter> interface_list( + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list( interface_list_ptr); // Assume at most one connected wifi interface. @@ -288,7 +243,7 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr), &op_code); if (result != ERROR_SUCCESS) return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; - scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, WlanApiDeleter> conn_info( + scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, internal::WlanApiDeleter> conn_info( conn_info_ptr); switch (conn_info->wlanAssociationAttributes.dot11PhyType) { @@ -311,4 +266,59 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { } } +// Note: There is no need to explicitly set the options back +// as the OS will automatically set them back when the WlanHandle +// is closed. +class WifiOptionSetter : public ScopedWifiOptions { + public: + WifiOptionSetter(int options) { + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); + if (!wlanapi.initialized) + return; + + DWORD cur_version = 0; + const DWORD kMaxClientVersion = 2; + DWORD result = wlanapi.OpenHandle( + kMaxClientVersion, &cur_version, &client_); + if (result != ERROR_SUCCESS) + return; + + WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; + result = wlanapi.enum_interfaces_func(client_, NULL, &interface_list_ptr); + if (result != ERROR_SUCCESS) + return; + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> + interface_list(interface_list_ptr); + + for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i]; + if (options & WIFI_OPTIONS_DISABLE_SCAN) { + BOOL data = false; + wlanapi.set_interface_func(client_, + &info->InterfaceGuid, + wlan_intf_opcode_background_scan_enabled, + sizeof(data), + &data, + NULL); + } + if (options & WIFI_OPTIONS_MEDIA_STREAMING_MODE) { + BOOL data = true; + wlanapi.set_interface_func(client_, + &info->InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, + sizeof(data), + &data, + NULL); + } + } + } + + private: + internal::WlanHandle client_; +}; + +scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) { + return scoped_ptr<ScopedWifiOptions>(new WifiOptionSetter(options)); +} + } // namespace net diff --git a/net/base/net_util_win.h b/net/base/net_util_win.h new file mode 100644 index 0000000..afa888b --- /dev/null +++ b/net/base/net_util_win.h @@ -0,0 +1,85 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_NET_UTIL_WIN_H_ +#define NET_BASE_NET_UTIL_WIN_H_ + +// This file is only used to expose some of the internals +// of net_util_win.cc to tests. + +#include <wlanapi.h> + +#include "base/win/scoped_handle.h" +#include "net/base/net_export.h" + +namespace net { +namespace internal { + +struct NET_EXPORT WlanApi { + typedef DWORD (WINAPI *WlanOpenHandleFunc)( + DWORD, VOID*, DWORD*, HANDLE*); + typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( + HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); + typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( + HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, + WLAN_OPCODE_VALUE_TYPE*); + typedef DWORD (WINAPI *WlanSetInterfaceFunc)( + HANDLE, const GUID*, WLAN_INTF_OPCODE, DWORD, const VOID*, VOID*); + typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); + typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); + + WlanApi(); + static WlanApi& GetInstance(); + + template <typename T> + DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { + HANDLE temp_handle; + DWORD result = open_handle_func(client_version, NULL, cur_version, + &temp_handle); + if (result != ERROR_SUCCESS) + return result; + handle->Set(temp_handle); + return ERROR_SUCCESS; + } + + HMODULE module; + WlanOpenHandleFunc open_handle_func; + WlanEnumInterfacesFunc enum_interfaces_func; + WlanQueryInterfaceFunc query_interface_func; + WlanSetInterfaceFunc set_interface_func; + WlanFreeMemoryFunc free_memory_func; + WlanCloseHandleFunc close_handle_func; + bool initialized; +}; + +struct WlanApiHandleTraits { + typedef HANDLE Handle; + + static bool CloseHandle(HANDLE handle) { + return WlanApi::GetInstance().close_handle_func(handle, NULL) == + ERROR_SUCCESS; + } + static bool IsHandleValid(HANDLE handle) { + return base::win::HandleTraits::IsHandleValid(handle); + } + static HANDLE NullHandle() { + return base::win::HandleTraits::NullHandle(); + } +}; + +typedef base::win::GenericScopedHandle< + WlanApiHandleTraits, + base::win::DummyVerifierTraits> WlanHandle; + +struct WlanApiDeleter { + inline void operator()(void* ptr) const { + WlanApi::GetInstance().free_memory_func(ptr); + } +}; + +} // namespace internal + +} // namespace net + +#endif // NET_BASE_NET_UTIL_WIN_H_ |