network_interfaces_win_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/base/network_interfaces_win.h"
  5. #include <iphlpapi.h>
  6. #include <objbase.h>
  7. #include <ostream>
  8. #include <string>
  9. #include <unordered_set>
  10. #include "base/logging.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "build/build_config.h"
  13. #include "net/base/ip_endpoint.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. namespace net {
  16. namespace {
  17. static const char kIfnameEm1[] = "em1";
  18. static const char kIfnameVmnet[] = "VMnet";
  19. static const unsigned char kIPv6LocalAddr[] = {0, 0, 0, 0, 0, 0, 0, 0,
  20. 0, 0, 0, 0, 0, 0, 0, 1};
  21. static const unsigned char kIPv6Addr[] = {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04,
  22. 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
  23. 0xfe, 0xe5, 0x00, 0xc3};
  24. static const unsigned char kIPv6AddrPrefix[] = {
  25. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  26. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  27. // Helper function to create a valid IP_ADAPTER_ADDRESSES with reasonable
  28. // default value. The output is the |adapter_address|. All the rests are input
  29. // to fill the |adapter_address|. |sock_addrs| are temporary storage used by
  30. // |adapter_address| once the function is returned.
  31. bool FillAdapterAddress(IP_ADAPTER_ADDRESSES* adapter_address,
  32. const char* ifname,
  33. const IPAddress& ip_address,
  34. const IPAddress& ip_netmask,
  35. sockaddr_storage sock_addrs[2]) {
  36. adapter_address->AdapterName = const_cast<char*>(ifname);
  37. adapter_address->FriendlyName = const_cast<PWCHAR>(L"interface");
  38. adapter_address->IfType = IF_TYPE_ETHERNET_CSMACD;
  39. adapter_address->OperStatus = IfOperStatusUp;
  40. adapter_address->FirstUnicastAddress->DadState = IpDadStatePreferred;
  41. adapter_address->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther;
  42. adapter_address->FirstUnicastAddress->SuffixOrigin = IpSuffixOriginOther;
  43. adapter_address->FirstUnicastAddress->PreferredLifetime = 100;
  44. adapter_address->FirstUnicastAddress->ValidLifetime = 1000;
  45. socklen_t sock_len = sizeof(sockaddr_storage);
  46. // Convert to sockaddr for next check.
  47. if (!IPEndPoint(ip_address, 0)
  48. .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[0]),
  49. &sock_len)) {
  50. return false;
  51. }
  52. adapter_address->FirstUnicastAddress->Address.lpSockaddr =
  53. reinterpret_cast<sockaddr*>(&sock_addrs[0]);
  54. adapter_address->FirstUnicastAddress->Address.iSockaddrLength = sock_len;
  55. adapter_address->FirstUnicastAddress->OnLinkPrefixLength = 1;
  56. sock_len = sizeof(sockaddr_storage);
  57. if (!IPEndPoint(ip_netmask, 0)
  58. .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[1]),
  59. &sock_len)) {
  60. return false;
  61. }
  62. adapter_address->FirstPrefix->Address.lpSockaddr =
  63. reinterpret_cast<sockaddr*>(&sock_addrs[1]);
  64. adapter_address->FirstPrefix->Address.iSockaddrLength = sock_len;
  65. adapter_address->FirstPrefix->PrefixLength = 1;
  66. DCHECK_EQ(sock_addrs[0].ss_family, sock_addrs[1].ss_family);
  67. if (sock_addrs[0].ss_family == AF_INET6) {
  68. adapter_address->Ipv6IfIndex = 0;
  69. } else {
  70. DCHECK_EQ(sock_addrs[0].ss_family, AF_INET);
  71. adapter_address->IfIndex = 0;
  72. }
  73. return true;
  74. }
  75. TEST(NetworkInterfacesTest, NetworkListTrimmingWindows) {
  76. IPAddress ipv6_local_address(kIPv6LocalAddr);
  77. IPAddress ipv6_address(kIPv6Addr);
  78. IPAddress ipv6_prefix(kIPv6AddrPrefix);
  79. NetworkInterfaceList results;
  80. sockaddr_storage addresses[2];
  81. IP_ADAPTER_ADDRESSES adapter_address = {};
  82. IP_ADAPTER_UNICAST_ADDRESS address = {};
  83. IP_ADAPTER_PREFIX adapter_prefix = {};
  84. adapter_address.FirstUnicastAddress = &address;
  85. adapter_address.FirstPrefix = &adapter_prefix;
  86. // Address of offline links should be ignored.
  87. ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
  88. ipv6_prefix, addresses));
  89. adapter_address.OperStatus = IfOperStatusDown;
  90. EXPECT_TRUE(internal::GetNetworkListImpl(
  91. &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  92. EXPECT_EQ(results.size(), 0ul);
  93. // Address on loopback interface should be trimmed out.
  94. ASSERT_TRUE(FillAdapterAddress(
  95. &adapter_address /* adapter_address */, kIfnameEm1 /* ifname */,
  96. ipv6_local_address /* ip_address */, ipv6_prefix /* ip_netmask */,
  97. addresses /* sock_addrs */));
  98. adapter_address.IfType = IF_TYPE_SOFTWARE_LOOPBACK;
  99. EXPECT_TRUE(internal::GetNetworkListImpl(
  100. &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  101. EXPECT_EQ(results.size(), 0ul);
  102. // vmware address should return by default.
  103. ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameVmnet, ipv6_address,
  104. ipv6_prefix, addresses));
  105. EXPECT_TRUE(internal::GetNetworkListImpl(
  106. &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  107. EXPECT_EQ(results.size(), 1ul);
  108. EXPECT_EQ(results[0].name, kIfnameVmnet);
  109. EXPECT_EQ(results[0].prefix_length, 1ul);
  110. EXPECT_EQ(results[0].address, ipv6_address);
  111. EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_NONE);
  112. results.clear();
  113. // vmware address should be trimmed out if policy specified so.
  114. ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameVmnet, ipv6_address,
  115. ipv6_prefix, addresses));
  116. EXPECT_TRUE(internal::GetNetworkListImpl(
  117. &results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  118. EXPECT_EQ(results.size(), 0ul);
  119. results.clear();
  120. // Addresses with incomplete DAD should be ignored.
  121. ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
  122. ipv6_prefix, addresses));
  123. adapter_address.FirstUnicastAddress->DadState = IpDadStateTentative;
  124. EXPECT_TRUE(internal::GetNetworkListImpl(
  125. &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  126. EXPECT_EQ(results.size(), 0ul);
  127. results.clear();
  128. // Addresses with allowed attribute IpSuffixOriginRandom should be returned
  129. // and attributes should be translated correctly to
  130. // IP_ADDRESS_ATTRIBUTE_TEMPORARY.
  131. ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
  132. ipv6_prefix, addresses));
  133. adapter_address.FirstUnicastAddress->PrefixOrigin =
  134. IpPrefixOriginRouterAdvertisement;
  135. adapter_address.FirstUnicastAddress->SuffixOrigin = IpSuffixOriginRandom;
  136. EXPECT_TRUE(internal::GetNetworkListImpl(
  137. &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  138. EXPECT_EQ(results.size(), 1ul);
  139. EXPECT_EQ(results[0].name, kIfnameEm1);
  140. EXPECT_EQ(results[0].prefix_length, 1ul);
  141. EXPECT_EQ(results[0].address, ipv6_address);
  142. EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
  143. results.clear();
  144. // Addresses with preferred lifetime 0 should be returned and
  145. // attributes should be translated correctly to
  146. // IP_ADDRESS_ATTRIBUTE_DEPRECATED.
  147. ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
  148. ipv6_prefix, addresses));
  149. adapter_address.FirstUnicastAddress->PreferredLifetime = 0;
  150. adapter_address.FriendlyName = const_cast<PWCHAR>(L"FriendlyInterfaceName");
  151. EXPECT_TRUE(internal::GetNetworkListImpl(
  152. &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
  153. EXPECT_EQ(results.size(), 1ul);
  154. EXPECT_EQ(results[0].friendly_name, "FriendlyInterfaceName");
  155. EXPECT_EQ(results[0].name, kIfnameEm1);
  156. EXPECT_EQ(results[0].prefix_length, 1ul);
  157. EXPECT_EQ(results[0].address, ipv6_address);
  158. EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
  159. results.clear();
  160. }
  161. bool read_int_or_bool(DWORD data_size, PVOID data) {
  162. switch (data_size) {
  163. case 1:
  164. return !!*reinterpret_cast<uint8_t*>(data);
  165. case 4:
  166. return !!*reinterpret_cast<uint32_t*>(data);
  167. default:
  168. LOG(FATAL) << "That is not a type I know!";
  169. return false;
  170. }
  171. }
  172. int GetWifiOptions() {
  173. const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance();
  174. if (!wlanapi.initialized)
  175. return -1;
  176. internal::WlanHandle client;
  177. DWORD cur_version = 0;
  178. const DWORD kMaxClientVersion = 2;
  179. DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client);
  180. if (result != ERROR_SUCCESS)
  181. return -1;
  182. WLAN_INTERFACE_INFO_LIST* interface_list_ptr = nullptr;
  183. result =
  184. wlanapi.enum_interfaces_func(client.Get(), nullptr, &interface_list_ptr);
  185. if (result != ERROR_SUCCESS)
  186. return -1;
  187. std::unique_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter>
  188. interface_list(interface_list_ptr);
  189. for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) {
  190. WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i];
  191. DWORD data_size;
  192. PVOID data;
  193. int options = 0;
  194. result =
  195. wlanapi.query_interface_func(client.Get(), &info->InterfaceGuid,
  196. wlan_intf_opcode_background_scan_enabled,
  197. nullptr, &data_size, &data, nullptr);
  198. if (result != ERROR_SUCCESS)
  199. continue;
  200. if (!read_int_or_bool(data_size, data)) {
  201. options |= WIFI_OPTIONS_DISABLE_SCAN;
  202. }
  203. internal::WlanApi::GetInstance().free_memory_func(data);
  204. result = wlanapi.query_interface_func(client.Get(), &info->InterfaceGuid,
  205. wlan_intf_opcode_media_streaming_mode,
  206. nullptr, &data_size, &data, nullptr);
  207. if (result != ERROR_SUCCESS)
  208. continue;
  209. if (read_int_or_bool(data_size, data)) {
  210. options |= WIFI_OPTIONS_MEDIA_STREAMING_MODE;
  211. }
  212. internal::WlanApi::GetInstance().free_memory_func(data);
  213. // Just the the options from the first succesful
  214. // interface.
  215. return options;
  216. }
  217. // No wifi interface found.
  218. return -1;
  219. }
  220. void TryChangeWifiOptions(int options) {
  221. int previous_options = GetWifiOptions();
  222. std::unique_ptr<ScopedWifiOptions> scoped_options = SetWifiOptions(options);
  223. EXPECT_EQ(previous_options | options, GetWifiOptions());
  224. scoped_options.reset();
  225. EXPECT_EQ(previous_options, GetWifiOptions());
  226. }
  227. // Test SetWifiOptions().
  228. TEST(NetworkInterfacesTest, SetWifiOptions) {
  229. TryChangeWifiOptions(0);
  230. TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN);
  231. TryChangeWifiOptions(WIFI_OPTIONS_MEDIA_STREAMING_MODE);
  232. TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN |
  233. WIFI_OPTIONS_MEDIA_STREAMING_MODE);
  234. }
  235. } // namespace
  236. } // namespace net