1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/network_interfaces_win.h"
6
7 #include <objbase.h>
8
9 #include <iphlpapi.h>
10
11 #include <ostream>
12 #include <string>
13 #include <unordered_set>
14
15 #include "base/logging.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "build/build_config.h"
18 #include "net/base/ip_endpoint.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace net {
22
23 namespace {
24
25 static const char kIfnameEm1[] = "em1";
26 static const char kIfnameVmnet[] = "VMnet";
27
28 static const unsigned char kIPv6LocalAddr[] = {0, 0, 0, 0, 0, 0, 0, 0,
29 0, 0, 0, 0, 0, 0, 0, 1};
30
31 static const unsigned char kIPv6Addr[] = {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04,
32 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
33 0xfe, 0xe5, 0x00, 0xc3};
34 static const unsigned char kIPv6AddrPrefix[] = {
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
37
38 // Helper function to create a valid IP_ADAPTER_ADDRESSES with reasonable
39 // default value. The output is the |adapter_address|. All the rests are input
40 // to fill the |adapter_address|. |sock_addrs| are temporary storage used by
41 // |adapter_address| once the function is returned.
FillAdapterAddress(IP_ADAPTER_ADDRESSES * adapter_address,const char * ifname,const IPAddress & ip_address,const IPAddress & ip_netmask,sockaddr_storage sock_addrs[2])42 bool FillAdapterAddress(IP_ADAPTER_ADDRESSES* adapter_address,
43 const char* ifname,
44 const IPAddress& ip_address,
45 const IPAddress& ip_netmask,
46 sockaddr_storage sock_addrs[2]) {
47 adapter_address->AdapterName = const_cast<char*>(ifname);
48 adapter_address->FriendlyName = const_cast<PWCHAR>(L"interface");
49 adapter_address->IfType = IF_TYPE_ETHERNET_CSMACD;
50 adapter_address->OperStatus = IfOperStatusUp;
51 adapter_address->FirstUnicastAddress->DadState = IpDadStatePreferred;
52 adapter_address->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther;
53 adapter_address->FirstUnicastAddress->SuffixOrigin = IpSuffixOriginOther;
54 adapter_address->FirstUnicastAddress->PreferredLifetime = 100;
55 adapter_address->FirstUnicastAddress->ValidLifetime = 1000;
56
57 DCHECK(sizeof(adapter_address->PhysicalAddress) > 5);
58 // Generate 06:05:04:03:02:01
59 adapter_address->PhysicalAddressLength = 6;
60 for (unsigned long i = 0; i < adapter_address->PhysicalAddressLength; i++) {
61 adapter_address->PhysicalAddress[i] =
62 adapter_address->PhysicalAddressLength - i;
63 }
64
65 socklen_t sock_len = sizeof(sockaddr_storage);
66
67 // Convert to sockaddr for next check.
68 if (!IPEndPoint(ip_address, 0)
69 .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[0]),
70 &sock_len)) {
71 return false;
72 }
73 adapter_address->FirstUnicastAddress->Address.lpSockaddr =
74 reinterpret_cast<sockaddr*>(&sock_addrs[0]);
75 adapter_address->FirstUnicastAddress->Address.iSockaddrLength = sock_len;
76 adapter_address->FirstUnicastAddress->OnLinkPrefixLength = 1;
77
78 sock_len = sizeof(sockaddr_storage);
79 if (!IPEndPoint(ip_netmask, 0)
80 .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[1]),
81 &sock_len)) {
82 return false;
83 }
84 adapter_address->FirstPrefix->Address.lpSockaddr =
85 reinterpret_cast<sockaddr*>(&sock_addrs[1]);
86 adapter_address->FirstPrefix->Address.iSockaddrLength = sock_len;
87 adapter_address->FirstPrefix->PrefixLength = 1;
88
89 DCHECK_EQ(sock_addrs[0].ss_family, sock_addrs[1].ss_family);
90 if (sock_addrs[0].ss_family == AF_INET6) {
91 adapter_address->Ipv6IfIndex = 0;
92 } else {
93 DCHECK_EQ(sock_addrs[0].ss_family, AF_INET);
94 adapter_address->IfIndex = 0;
95 }
96
97 return true;
98 }
99
TEST(NetworkInterfacesTest,NetworkListTrimmingWindows)100 TEST(NetworkInterfacesTest, NetworkListTrimmingWindows) {
101 IPAddress ipv6_local_address(kIPv6LocalAddr);
102 IPAddress ipv6_address(kIPv6Addr);
103 IPAddress ipv6_prefix(kIPv6AddrPrefix);
104
105 NetworkInterfaceList results;
106 sockaddr_storage addresses[2];
107 IP_ADAPTER_ADDRESSES adapter_address = {};
108 IP_ADAPTER_UNICAST_ADDRESS address = {};
109 IP_ADAPTER_PREFIX adapter_prefix = {};
110 adapter_address.FirstUnicastAddress = &address;
111 adapter_address.FirstPrefix = &adapter_prefix;
112
113 // Address of offline links should be ignored.
114 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
115 ipv6_prefix, addresses));
116 adapter_address.OperStatus = IfOperStatusDown;
117
118 EXPECT_TRUE(internal::GetNetworkListImpl(
119 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
120
121 EXPECT_EQ(results.size(), 0ul);
122
123 // Address on loopback interface should be trimmed out.
124 ASSERT_TRUE(FillAdapterAddress(
125 &adapter_address /* adapter_address */, kIfnameEm1 /* ifname */,
126 ipv6_local_address /* ip_address */, ipv6_prefix /* ip_netmask */,
127 addresses /* sock_addrs */));
128 adapter_address.IfType = IF_TYPE_SOFTWARE_LOOPBACK;
129
130 EXPECT_TRUE(internal::GetNetworkListImpl(
131 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
132 EXPECT_EQ(results.size(), 0ul);
133
134 // vmware address should return by default.
135 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameVmnet, ipv6_address,
136 ipv6_prefix, addresses));
137 EXPECT_TRUE(internal::GetNetworkListImpl(
138 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
139 EXPECT_EQ(results.size(), 1ul);
140 EXPECT_EQ(results[0].name, kIfnameVmnet);
141 EXPECT_EQ(results[0].prefix_length, 1ul);
142 EXPECT_EQ(results[0].address, ipv6_address);
143 EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_NONE);
144 results.clear();
145
146 // vmware address should be trimmed out if policy specified so.
147 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameVmnet, ipv6_address,
148 ipv6_prefix, addresses));
149 EXPECT_TRUE(internal::GetNetworkListImpl(
150 &results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
151 EXPECT_EQ(results.size(), 0ul);
152 results.clear();
153
154 // Addresses with incomplete DAD should be ignored.
155 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
156 ipv6_prefix, addresses));
157 adapter_address.FirstUnicastAddress->DadState = IpDadStateTentative;
158
159 EXPECT_TRUE(internal::GetNetworkListImpl(
160 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
161 EXPECT_EQ(results.size(), 0ul);
162 results.clear();
163
164 // Addresses with allowed attribute IpSuffixOriginRandom should be returned
165 // and attributes should be translated correctly to
166 // IP_ADDRESS_ATTRIBUTE_TEMPORARY.
167 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
168 ipv6_prefix, addresses));
169 adapter_address.FirstUnicastAddress->PrefixOrigin =
170 IpPrefixOriginRouterAdvertisement;
171 adapter_address.FirstUnicastAddress->SuffixOrigin = IpSuffixOriginRandom;
172
173 EXPECT_TRUE(internal::GetNetworkListImpl(
174 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
175 EXPECT_EQ(results.size(), 1ul);
176 EXPECT_EQ(results[0].name, kIfnameEm1);
177 EXPECT_EQ(results[0].prefix_length, 1ul);
178 EXPECT_EQ(results[0].address, ipv6_address);
179 EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
180 results.clear();
181
182 // Addresses with preferred lifetime 0 should be returned and
183 // attributes should be translated correctly to
184 // IP_ADDRESS_ATTRIBUTE_DEPRECATED.
185 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
186 ipv6_prefix, addresses));
187 adapter_address.FirstUnicastAddress->PreferredLifetime = 0;
188 adapter_address.FriendlyName = const_cast<PWCHAR>(L"FriendlyInterfaceName");
189 EXPECT_TRUE(internal::GetNetworkListImpl(
190 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
191 EXPECT_EQ(results.size(), 1ul);
192 EXPECT_EQ(results[0].friendly_name, "FriendlyInterfaceName");
193 EXPECT_EQ(results[0].name, kIfnameEm1);
194 EXPECT_EQ(results[0].prefix_length, 1ul);
195 EXPECT_EQ(results[0].address, ipv6_address);
196 EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
197 results.clear();
198 }
199
TEST(NetworkInterfacesTest,NetworkListExtractMacAddress)200 TEST(NetworkInterfacesTest, NetworkListExtractMacAddress) {
201 IPAddress ipv6_local_address(kIPv6LocalAddr);
202 IPAddress ipv6_address(kIPv6Addr);
203 IPAddress ipv6_prefix(kIPv6AddrPrefix);
204
205 NetworkInterfaceList results;
206 sockaddr_storage addresses[2];
207 IP_ADAPTER_ADDRESSES adapter_address = {};
208 IP_ADAPTER_UNICAST_ADDRESS address = {};
209 IP_ADAPTER_PREFIX adapter_prefix = {};
210 adapter_address.FirstUnicastAddress = &address;
211 adapter_address.FirstPrefix = &adapter_prefix;
212
213 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
214 ipv6_prefix, addresses));
215
216 Eui48MacAddress expected_mac_address = {0x6, 0x5, 0x4, 0x3, 0x2, 0x1};
217
218 EXPECT_TRUE(internal::GetNetworkListImpl(
219 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
220 ASSERT_EQ(results.size(), 1ul);
221 ASSERT_EQ(results[0].mac_address, expected_mac_address);
222 }
223
TEST(NetworkInterfacesTest,NetworkListExtractMacAddressInvalidLength)224 TEST(NetworkInterfacesTest, NetworkListExtractMacAddressInvalidLength) {
225 IPAddress ipv6_local_address(kIPv6LocalAddr);
226 IPAddress ipv6_address(kIPv6Addr);
227 IPAddress ipv6_prefix(kIPv6AddrPrefix);
228
229 NetworkInterfaceList results;
230 sockaddr_storage addresses[2];
231 IP_ADAPTER_ADDRESSES adapter_address = {};
232 IP_ADAPTER_UNICAST_ADDRESS address = {};
233 IP_ADAPTER_PREFIX adapter_prefix = {};
234 adapter_address.FirstUnicastAddress = &address;
235 adapter_address.FirstPrefix = &adapter_prefix;
236
237 ASSERT_TRUE(FillAdapterAddress(&adapter_address, kIfnameEm1, ipv6_address,
238 ipv6_prefix, addresses));
239 // Not EUI-48 Mac address, so it is not extracted.
240 adapter_address.PhysicalAddressLength = 8;
241
242 EXPECT_TRUE(internal::GetNetworkListImpl(
243 &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &adapter_address));
244 ASSERT_EQ(results.size(), 1ul);
245 EXPECT_FALSE(results[0].mac_address.has_value());
246 }
247
read_int_or_bool(DWORD data_size,PVOID data)248 bool read_int_or_bool(DWORD data_size, PVOID data) {
249 switch (data_size) {
250 case 1:
251 return !!*reinterpret_cast<uint8_t*>(data);
252 case 4:
253 return !!*reinterpret_cast<uint32_t*>(data);
254 default:
255 LOG(FATAL) << "That is not a type I know!";
256 }
257 }
258
GetWifiOptions()259 int GetWifiOptions() {
260 const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance();
261 if (!wlanapi.initialized)
262 return -1;
263
264 internal::WlanHandle client;
265 DWORD cur_version = 0;
266 const DWORD kMaxClientVersion = 2;
267 DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client);
268 if (result != ERROR_SUCCESS)
269 return -1;
270
271 WLAN_INTERFACE_INFO_LIST* interface_list_ptr = nullptr;
272 result =
273 wlanapi.enum_interfaces_func(client.Get(), nullptr, &interface_list_ptr);
274 if (result != ERROR_SUCCESS)
275 return -1;
276 std::unique_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter>
277 interface_list(interface_list_ptr);
278
279 for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) {
280 WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i];
281 DWORD data_size;
282 PVOID data;
283 int options = 0;
284 result =
285 wlanapi.query_interface_func(client.Get(), &info->InterfaceGuid,
286 wlan_intf_opcode_background_scan_enabled,
287 nullptr, &data_size, &data, nullptr);
288 if (result != ERROR_SUCCESS)
289 continue;
290 if (!read_int_or_bool(data_size, data)) {
291 options |= WIFI_OPTIONS_DISABLE_SCAN;
292 }
293 internal::WlanApi::GetInstance().free_memory_func(data);
294
295 result = wlanapi.query_interface_func(client.Get(), &info->InterfaceGuid,
296 wlan_intf_opcode_media_streaming_mode,
297 nullptr, &data_size, &data, nullptr);
298 if (result != ERROR_SUCCESS)
299 continue;
300 if (read_int_or_bool(data_size, data)) {
301 options |= WIFI_OPTIONS_MEDIA_STREAMING_MODE;
302 }
303 internal::WlanApi::GetInstance().free_memory_func(data);
304
305 // Just the the options from the first succesful
306 // interface.
307 return options;
308 }
309
310 // No wifi interface found.
311 return -1;
312 }
313
TryChangeWifiOptions(int options)314 void TryChangeWifiOptions(int options) {
315 int previous_options = GetWifiOptions();
316 std::unique_ptr<ScopedWifiOptions> scoped_options = SetWifiOptions(options);
317 EXPECT_EQ(previous_options | options, GetWifiOptions());
318 scoped_options.reset();
319 EXPECT_EQ(previous_options, GetWifiOptions());
320 }
321
322 // Test fails on Win Arm64 bots. TODO(https://crbug.com/1425465): Fix on bot.
323 #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
324 #define MAYBE_SetWifiOptions DISABLED_SetWifiOptions
325 #else
326 #define MAYBE_SetWifiOptions SetWifiOptions
327 #endif
328 // Test SetWifiOptions().
TEST(NetworkInterfacesTest,MAYBE_SetWifiOptions)329 TEST(NetworkInterfacesTest, MAYBE_SetWifiOptions) {
330 TryChangeWifiOptions(0);
331 TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN);
332 TryChangeWifiOptions(WIFI_OPTIONS_MEDIA_STREAMING_MODE);
333 TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN |
334 WIFI_OPTIONS_MEDIA_STREAMING_MODE);
335 }
336
337 } // namespace
338
339 } // namespace net
340