OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/net_util.h" | 5 #include "net/base/net_util.h" |
6 | 6 |
7 #include <iphlpapi.h> | 7 #include <iphlpapi.h> |
8 #include <wlanapi.h> | 8 #include <wlanapi.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "net/base/escape.h" | 22 #include "net/base/escape.h" |
23 #include "net/base/ip_endpoint.h" | 23 #include "net/base/ip_endpoint.h" |
24 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
25 #include "url/gurl.h" | 25 #include "url/gurl.h" |
26 | 26 |
27 namespace net { | 27 namespace net { |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 struct WlanApi { | 31 struct WlanApi { |
32 typedef DWORD (WINAPI *WlanOpenHandleFunc)( | 32 typedef DWORD(WINAPI* WlanOpenHandleFunc)(DWORD, VOID*, DWORD*, HANDLE*); |
33 DWORD, VOID*, DWORD*, HANDLE*); | 33 typedef DWORD(WINAPI* WlanEnumInterfacesFunc)(HANDLE, |
34 typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( | 34 VOID*, |
35 HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); | 35 WLAN_INTERFACE_INFO_LIST**); |
36 typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( | 36 typedef DWORD(WINAPI* WlanQueryInterfaceFunc)(HANDLE, |
37 HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, | 37 const GUID*, |
38 WLAN_OPCODE_VALUE_TYPE*); | 38 WLAN_INTF_OPCODE, |
39 typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); | 39 VOID*, |
40 typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); | 40 DWORD*, |
| 41 VOID**, |
| 42 WLAN_OPCODE_VALUE_TYPE*); |
| 43 typedef VOID(WINAPI* WlanFreeMemoryFunc)(VOID*); |
| 44 typedef DWORD(WINAPI* WlanCloseHandleFunc)(HANDLE, VOID*); |
41 | 45 |
42 WlanApi() : initialized(false) { | 46 WlanApi() : initialized(false) { |
43 // Use an absolute path to load the DLL to avoid DLL preloading attacks. | 47 // Use an absolute path to load the DLL to avoid DLL preloading attacks. |
44 static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; | 48 static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; |
45 wchar_t path[MAX_PATH] = {0}; | 49 wchar_t path[MAX_PATH] = {0}; |
46 ExpandEnvironmentStrings(kDLL, path, arraysize(path)); | 50 ExpandEnvironmentStrings(kDLL, path, arraysize(path)); |
47 module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | 51 module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); |
48 if (!module) | 52 if (!module) |
49 return; | 53 return; |
50 | 54 |
51 open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( | 55 open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( |
52 ::GetProcAddress(module, "WlanOpenHandle")); | 56 ::GetProcAddress(module, "WlanOpenHandle")); |
53 enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( | 57 enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( |
54 ::GetProcAddress(module, "WlanEnumInterfaces")); | 58 ::GetProcAddress(module, "WlanEnumInterfaces")); |
55 query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( | 59 query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( |
56 ::GetProcAddress(module, "WlanQueryInterface")); | 60 ::GetProcAddress(module, "WlanQueryInterface")); |
57 free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( | 61 free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( |
58 ::GetProcAddress(module, "WlanFreeMemory")); | 62 ::GetProcAddress(module, "WlanFreeMemory")); |
59 close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( | 63 close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( |
60 ::GetProcAddress(module, "WlanCloseHandle")); | 64 ::GetProcAddress(module, "WlanCloseHandle")); |
61 initialized = open_handle_func && enum_interfaces_func && | 65 initialized = open_handle_func && enum_interfaces_func && |
62 query_interface_func && free_memory_func && | 66 query_interface_func && free_memory_func && close_handle_func; |
63 close_handle_func; | |
64 } | 67 } |
65 | 68 |
66 template <typename T> | 69 template <typename T> |
67 DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { | 70 DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { |
68 HANDLE temp_handle; | 71 HANDLE temp_handle; |
69 DWORD result = open_handle_func(client_version, NULL, cur_version, | 72 DWORD result = |
70 &temp_handle); | 73 open_handle_func(client_version, NULL, cur_version, &temp_handle); |
71 if (result != ERROR_SUCCESS) | 74 if (result != ERROR_SUCCESS) |
72 return result; | 75 return result; |
73 handle->Set(temp_handle); | 76 handle->Set(temp_handle); |
74 return ERROR_SUCCESS; | 77 return ERROR_SUCCESS; |
75 } | 78 } |
76 | 79 |
77 HMODULE module; | 80 HMODULE module; |
78 WlanOpenHandleFunc open_handle_func; | 81 WlanOpenHandleFunc open_handle_func; |
79 WlanEnumInterfacesFunc enum_interfaces_func; | 82 WlanEnumInterfacesFunc enum_interfaces_func; |
80 WlanQueryInterfaceFunc query_interface_func; | 83 WlanQueryInterfaceFunc query_interface_func; |
(...skipping 23 matching lines...) Expand all Loading... |
104 bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA; | 107 bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA; |
105 ULONG len = 0; | 108 ULONG len = 0; |
106 ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0; | 109 ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0; |
107 // First get number of networks. | 110 // First get number of networks. |
108 ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len); | 111 ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len); |
109 if (result != ERROR_BUFFER_OVERFLOW) { | 112 if (result != ERROR_BUFFER_OVERFLOW) { |
110 // There are 0 networks. | 113 // There are 0 networks. |
111 return true; | 114 return true; |
112 } | 115 } |
113 scoped_ptr<char[]> buf(new char[len]); | 116 scoped_ptr<char[]> buf(new char[len]); |
114 IP_ADAPTER_ADDRESSES *adapters = | 117 IP_ADAPTER_ADDRESSES* adapters = |
115 reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get()); | 118 reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get()); |
116 result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len); | 119 result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len); |
117 if (result != NO_ERROR) { | 120 if (result != NO_ERROR) { |
118 LOG(ERROR) << "GetAdaptersAddresses failed: " << result; | 121 LOG(ERROR) << "GetAdaptersAddresses failed: " << result; |
119 return false; | 122 return false; |
120 } | 123 } |
121 | 124 |
122 // These two variables are used below when this method is asked to pick a | 125 // These two variables are used below when this method is asked to pick a |
123 // IPv6 address which has the shortest lifetime. | 126 // IPv6 address which has the shortest lifetime. |
124 ULONG ipv6_valid_lifetime = 0; | 127 ULONG ipv6_valid_lifetime = 0; |
125 scoped_ptr<NetworkInterface> ipv6_address; | 128 scoped_ptr<NetworkInterface> ipv6_address; |
126 | 129 |
127 for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL; | 130 for (IP_ADAPTER_ADDRESSES* adapter = adapters; adapter != NULL; |
128 adapter = adapter->Next) { | 131 adapter = adapter->Next) { |
129 // Ignore the loopback device. | 132 // Ignore the loopback device. |
130 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { | 133 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { |
131 continue; | 134 continue; |
132 } | 135 } |
133 | 136 |
134 if (adapter->OperStatus != IfOperStatusUp) { | 137 if (adapter->OperStatus != IfOperStatusUp) { |
135 continue; | 138 continue; |
136 } | 139 } |
137 | 140 |
138 // Ignore any HOST side vmware adapters with a description like: | 141 // Ignore any HOST side vmware adapters with a description like: |
139 // VMware Virtual Ethernet Adapter for VMnet1 | 142 // VMware Virtual Ethernet Adapter for VMnet1 |
140 // but don't ignore any GUEST side adapters with a description like: | 143 // but don't ignore any GUEST side adapters with a description like: |
141 // VMware Accelerated AMD PCNet Adapter #2 | 144 // VMware Accelerated AMD PCNet Adapter #2 |
142 if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES && | 145 if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES && |
143 strstr(adapter->AdapterName, "VMnet") != NULL) { | 146 strstr(adapter->AdapterName, "VMnet") != NULL) { |
144 continue; | 147 continue; |
145 } | 148 } |
146 | 149 |
147 for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; | 150 for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; |
148 address; address = address->Next) { | 151 address; |
| 152 address = address->Next) { |
149 int family = address->Address.lpSockaddr->sa_family; | 153 int family = address->Address.lpSockaddr->sa_family; |
150 if (family == AF_INET || family == AF_INET6) { | 154 if (family == AF_INET || family == AF_INET6) { |
151 IPEndPoint endpoint; | 155 IPEndPoint endpoint; |
152 if (endpoint.FromSockAddr(address->Address.lpSockaddr, | 156 if (endpoint.FromSockAddr(address->Address.lpSockaddr, |
153 address->Address.iSockaddrLength)) { | 157 address->Address.iSockaddrLength)) { |
154 // XP has no OnLinkPrefixLength field. | 158 // XP has no OnLinkPrefixLength field. |
155 size_t net_prefix = is_xp ? 0 : address->OnLinkPrefixLength; | 159 size_t net_prefix = is_xp ? 0 : address->OnLinkPrefixLength; |
156 if (is_xp) { | 160 if (is_xp) { |
157 // Prior to Windows Vista the FirstPrefix pointed to the list with | 161 // Prior to Windows Vista the FirstPrefix pointed to the list with |
158 // single prefix for each IP address assigned to the adapter. | 162 // single prefix for each IP address assigned to the adapter. |
159 // Order of FirstPrefix does not match order of FirstUnicastAddress, | 163 // Order of FirstPrefix does not match order of FirstUnicastAddress, |
160 // so we need to find corresponding prefix. | 164 // so we need to find corresponding prefix. |
161 for (IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix; | 165 for (IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix; |
162 prefix = prefix->Next) { | 166 prefix = prefix->Next) { |
163 int prefix_family = prefix->Address.lpSockaddr->sa_family; | 167 int prefix_family = prefix->Address.lpSockaddr->sa_family; |
164 IPEndPoint network_endpoint; | 168 IPEndPoint network_endpoint; |
165 if (prefix_family == family && | 169 if (prefix_family == family && |
166 network_endpoint.FromSockAddr(prefix->Address.lpSockaddr, | 170 network_endpoint.FromSockAddr( |
| 171 prefix->Address.lpSockaddr, |
167 prefix->Address.iSockaddrLength) && | 172 prefix->Address.iSockaddrLength) && |
168 IPNumberMatchesPrefix(endpoint.address(), | 173 IPNumberMatchesPrefix(endpoint.address(), |
169 network_endpoint.address(), | 174 network_endpoint.address(), |
170 prefix->PrefixLength)) { | 175 prefix->PrefixLength)) { |
171 net_prefix = std::max<size_t>(net_prefix, prefix->PrefixLength); | 176 net_prefix = std::max<size_t>(net_prefix, prefix->PrefixLength); |
172 } | 177 } |
173 } | 178 } |
174 } | 179 } |
175 uint32 index = | 180 uint32 index = |
176 (family == AF_INET) ? adapter->IfIndex : adapter->Ipv6IfIndex; | 181 (family == AF_INET) ? adapter->IfIndex : adapter->Ipv6IfIndex; |
177 // Pick one IPv6 address with least valid lifetime. | 182 // Pick one IPv6 address with least valid lifetime. |
178 // The reason we are checking |ValidLifeftime| as there is no other | 183 // The reason we are checking |ValidLifeftime| as there is no other |
179 // way identifying the interface type. Usually (and most likely) temp | 184 // way identifying the interface type. Usually (and most likely) temp |
180 // IPv6 will have a shorter ValidLifetime value then the permanent | 185 // IPv6 will have a shorter ValidLifetime value then the permanent |
181 // interface. | 186 // interface. |
182 if (family == AF_INET6 && | 187 if (family == AF_INET6 && |
183 (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE)) { | 188 (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE)) { |
184 if (ipv6_valid_lifetime == 0 || | 189 if (ipv6_valid_lifetime == 0 || |
185 ipv6_valid_lifetime > address->ValidLifetime) { | 190 ipv6_valid_lifetime > address->ValidLifetime) { |
186 ipv6_valid_lifetime = address->ValidLifetime; | 191 ipv6_valid_lifetime = address->ValidLifetime; |
187 ipv6_address.reset(new NetworkInterface(adapter->AdapterName, | 192 ipv6_address.reset(new NetworkInterface( |
188 base::SysWideToNativeMB(adapter->FriendlyName), | 193 adapter->AdapterName, |
189 index, | 194 base::SysWideToNativeMB(adapter->FriendlyName), |
190 GetNetworkInterfaceType(adapter->IfType), | 195 index, |
191 endpoint.address(), | 196 GetNetworkInterfaceType(adapter->IfType), |
192 net_prefix)); | 197 endpoint.address(), |
| 198 net_prefix)); |
193 continue; | 199 continue; |
194 } | 200 } |
195 } | 201 } |
196 networks->push_back( | 202 networks->push_back( |
197 NetworkInterface(adapter->AdapterName, | 203 NetworkInterface(adapter->AdapterName, |
198 base::SysWideToNativeMB(adapter->FriendlyName), | 204 base::SysWideToNativeMB(adapter->FriendlyName), |
199 index, GetNetworkInterfaceType(adapter->IfType), | 205 index, |
200 endpoint.address(), net_prefix)); | 206 GetNetworkInterfaceType(adapter->IfType), |
| 207 endpoint.address(), |
| 208 net_prefix)); |
201 } | 209 } |
202 } | 210 } |
203 } | 211 } |
204 } | 212 } |
205 | 213 |
206 if (ipv6_address.get()) { | 214 if (ipv6_address.get()) { |
207 networks->push_back(*(ipv6_address.get())); | 215 networks->push_back(*(ipv6_address.get())); |
208 } | 216 } |
209 return true; | 217 return true; |
210 } | 218 } |
211 | 219 |
212 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { | 220 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { |
213 static base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = | 221 static base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = |
214 LAZY_INSTANCE_INITIALIZER; | 222 LAZY_INSTANCE_INITIALIZER; |
215 | 223 |
216 struct WlanApiHandleTraits { | 224 struct WlanApiHandleTraits { |
217 typedef HANDLE Handle; | 225 typedef HANDLE Handle; |
218 | 226 |
219 static bool CloseHandle(HANDLE handle) { | 227 static bool CloseHandle(HANDLE handle) { |
220 return lazy_wlanapi.Get().close_handle_func(handle, NULL) == | 228 return lazy_wlanapi.Get().close_handle_func(handle, NULL) == |
221 ERROR_SUCCESS; | 229 ERROR_SUCCESS; |
222 } | 230 } |
223 static bool IsHandleValid(HANDLE handle) { | 231 static bool IsHandleValid(HANDLE handle) { |
224 return base::win::HandleTraits::IsHandleValid(handle); | 232 return base::win::HandleTraits::IsHandleValid(handle); |
225 } | 233 } |
226 static HANDLE NullHandle() { | 234 static HANDLE NullHandle() { return base::win::HandleTraits::NullHandle(); } |
227 return base::win::HandleTraits::NullHandle(); | |
228 } | |
229 }; | 235 }; |
230 | 236 |
231 typedef base::win::GenericScopedHandle< | 237 typedef base::win::GenericScopedHandle<WlanApiHandleTraits, |
232 WlanApiHandleTraits, | 238 base::win::DummyVerifierTraits> |
233 base::win::DummyVerifierTraits> WlanHandle; | 239 WlanHandle; |
234 | 240 |
235 struct WlanApiDeleter { | 241 struct WlanApiDeleter { |
236 inline void operator()(void* ptr) const { | 242 inline void operator()(void* ptr) const { |
237 lazy_wlanapi.Get().free_memory_func(ptr); | 243 lazy_wlanapi.Get().free_memory_func(ptr); |
238 } | 244 } |
239 }; | 245 }; |
240 | 246 |
241 const WlanApi& wlanapi = lazy_wlanapi.Get(); | 247 const WlanApi& wlanapi = lazy_wlanapi.Get(); |
242 if (!wlanapi.initialized) | 248 if (!wlanapi.initialized) |
243 return WIFI_PHY_LAYER_PROTOCOL_NONE; | 249 return WIFI_PHY_LAYER_PROTOCOL_NONE; |
(...skipping 21 matching lines...) Expand all Loading... |
265 break; | 271 break; |
266 } | 272 } |
267 } | 273 } |
268 | 274 |
269 if (info == NULL) | 275 if (info == NULL) |
270 return WIFI_PHY_LAYER_PROTOCOL_NONE; | 276 return WIFI_PHY_LAYER_PROTOCOL_NONE; |
271 | 277 |
272 WLAN_CONNECTION_ATTRIBUTES* conn_info_ptr; | 278 WLAN_CONNECTION_ATTRIBUTES* conn_info_ptr; |
273 DWORD conn_info_size = 0; | 279 DWORD conn_info_size = 0; |
274 WLAN_OPCODE_VALUE_TYPE op_code; | 280 WLAN_OPCODE_VALUE_TYPE op_code; |
275 result = wlanapi.query_interface_func( | 281 result = |
276 client, &info->InterfaceGuid, wlan_intf_opcode_current_connection, NULL, | 282 wlanapi.query_interface_func(client, |
277 &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr), &op_code); | 283 &info->InterfaceGuid, |
| 284 wlan_intf_opcode_current_connection, |
| 285 NULL, |
| 286 &conn_info_size, |
| 287 reinterpret_cast<VOID**>(&conn_info_ptr), |
| 288 &op_code); |
278 if (result != ERROR_SUCCESS) | 289 if (result != ERROR_SUCCESS) |
279 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; | 290 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; |
280 scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, WlanApiDeleter> conn_info( | 291 scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, WlanApiDeleter> conn_info( |
281 conn_info_ptr); | 292 conn_info_ptr); |
282 | 293 |
283 switch (conn_info->wlanAssociationAttributes.dot11PhyType) { | 294 switch (conn_info->wlanAssociationAttributes.dot11PhyType) { |
284 case dot11_phy_type_fhss: | 295 case dot11_phy_type_fhss: |
285 return WIFI_PHY_LAYER_PROTOCOL_ANCIENT; | 296 return WIFI_PHY_LAYER_PROTOCOL_ANCIENT; |
286 case dot11_phy_type_dsss: | 297 case dot11_phy_type_dsss: |
287 return WIFI_PHY_LAYER_PROTOCOL_B; | 298 return WIFI_PHY_LAYER_PROTOCOL_B; |
288 case dot11_phy_type_irbaseband: | 299 case dot11_phy_type_irbaseband: |
289 return WIFI_PHY_LAYER_PROTOCOL_ANCIENT; | 300 return WIFI_PHY_LAYER_PROTOCOL_ANCIENT; |
290 case dot11_phy_type_ofdm: | 301 case dot11_phy_type_ofdm: |
291 return WIFI_PHY_LAYER_PROTOCOL_A; | 302 return WIFI_PHY_LAYER_PROTOCOL_A; |
292 case dot11_phy_type_hrdsss: | 303 case dot11_phy_type_hrdsss: |
293 return WIFI_PHY_LAYER_PROTOCOL_B; | 304 return WIFI_PHY_LAYER_PROTOCOL_B; |
294 case dot11_phy_type_erp: | 305 case dot11_phy_type_erp: |
295 return WIFI_PHY_LAYER_PROTOCOL_G; | 306 return WIFI_PHY_LAYER_PROTOCOL_G; |
296 case dot11_phy_type_ht: | 307 case dot11_phy_type_ht: |
297 return WIFI_PHY_LAYER_PROTOCOL_N; | 308 return WIFI_PHY_LAYER_PROTOCOL_N; |
298 default: | 309 default: |
299 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; | 310 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; |
300 } | 311 } |
301 } | 312 } |
302 | 313 |
303 } // namespace net | 314 } // namespace net |
OLD | NEW |