blob: 3363a980d9c537a39bdb9182229be21caef93d7c [file] [log] [blame]
mukesh agrawal8a3188d2011-12-01 20:56:44 +00001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartb50f0b92011-05-16 16:31:42 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_WIFI_
6#define SHILL_WIFI_
7
Gary Morain22601da2012-03-16 10:48:39 -07008// A WiFi device represents a wireless network interface implemented as an IEEE
9// 802.11 station. An Access Point (AP) (or, more correctly, a Basic Service
10// Set(BSS)) is represented by a WiFiEndpoint. An AP provides a WiFiService,
11// which is the same concept as Extended Service Set (ESS) in 802.11,
12// identified by an SSID. A WiFiService includes zero or more WiFiEndpoints
13// that provide that service.
14//
15// A WiFi device interacts with a real device through WPA Supplicant.
16// Wifi::Start() creates a connection to WPA Supplicant, represented by
17// |supplicant_interface_proxy_|. [1]
18//
19// A WiFi device becomes aware of WiFiEndpoints through BSSAdded signals from
20// WPA Supplicant, which identifies them by a "path". The WiFi object maintains
21// an EndpointMap in |endpoint_by_rpcid_|, in which the key is the "path" and
22// the value is a pointer to a WiFiEndpoint object. When a WiFiEndpoint is
23// added, it is associated with a WiFiService.
24//
25// A WiFi device becomes aware of a WiFiService in three different ways. 1)
26// When a WiFiEndpoint is added through the BSSAdded signal, the WiFiEndpoint is
27// providing a service, and if that service is unknown to the WiFi device, it is
28// added at that point. 2) The Manager can add a WiFiService by calling
29// WiFi::GetService(). 3) Services are loaded from the profile through a call
30// to WiFi::Load().
31//
32// The WiFi device connects to a WiFiService, not a WiFiEndpoint, through WPA
33// Supplicant. It is the job of WPA Supplicant to select a BSS (aka
34// WiFiEndpoint) to connect to. The protocol for establishing a connection is
35// as follows:
36//
37// 1. The WiFi device sends AddNetwork to WPA Supplicant, which returns a
38// "network path" when done.
39//
40// 2. The WiFi device sends SelectNetwork, indicating the network path
41// received in 1, to WPA Supplicant, which begins the process of associating
42// with an AP in the ESS. At this point the WiFiService which is being
43// connected is called the |pending_service_|.
44//
45// 3. When association is complete, WPA Supplicant sends a PropertiesChanged
46// signal to the WiFi device, indicating a change in the CurrentBSS. The
47// WiFiService indicated by the new value of CurrentBSS is set as the
48// |current_service_|, and |pending_service_| is (normally) cleared.
49//
50// Some key things to notice are 1) WPA Supplicant does the work of selecting
51// the AP (aka WiFiEndpoint) and it tells the WiFi device which AP it selected.
52// 2) The process of connecting is asynchronous. There is a |current_service_|
53// to which the WiFi device is presently using and a |pending_service_| to which
54// the WiFi device has initiated a connection.
55//
56// A WiFi device is notified that an AP has gone away via the BSSRemoved signal.
57// When the last WiFiEndpoint of a WiFiService is removed, the WiFiService
58// itself is deleted.
59//
60// TODO(gmorain): Add explanation of hidden SSIDs.
61//
62// WPA Supplicant's PropertiesChanged signal communicates changes in the state
63// of WPA Supplicant's current service. This state is stored in
64// |supplicant_state_| and reflects WPA Supplicant's view of the state of the
65// connection to an AP. Changes in this state sometimes cause state changes in
66// the WiFiService to which a WiFi device is connected. For example, when WPA
67// Supplicant signals the new state to be "completed", then the WiFiService
68// state gets changed to "configuring". State change notifications are not
69// reliable because WPA Supplicant may coalesce state changes in quick
70// succession so that only the last of the changes is signaled.
71//
72// Notes:
73//
74// 1. Shill's definition of the interface is described in
75// shill/dbus_bindings/supplicant-interface.xml, and the WPA Supplicant's
76// description of the same interface is in
77// third_party/wpa_supplicant/doc/dbus.doxygen.
78
mukesh agrawal5c05b292012-03-07 10:12:52 -080079#include <time.h>
80
mukesh agrawalab87ea42011-05-18 11:44:49 -070081#include <map>
Chris Masone46eaaf52011-05-24 13:08:30 -070082#include <string>
mukesh agrawalab87ea42011-05-18 11:44:49 -070083#include <vector>
Chris Masone46eaaf52011-05-24 13:08:30 -070084
mukesh agrawalaf571952011-07-14 14:31:12 -070085#include <dbus-c++/dbus.h>
Paul Stewart6ab23a92011-11-09 17:17:47 -080086#include <gtest/gtest_prod.h> // for FRIEND_TEST
mukesh agrawalaf571952011-07-14 14:31:12 -070087
Paul Stewartb50f0b92011-05-16 16:31:42 -070088#include "shill/device.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070089#include "shill/event_dispatcher.h"
Gary Morainac1bdb42012-02-16 17:42:29 -080090#include "shill/power_manager.h"
Chris Masone2b105542011-06-22 10:58:09 -070091#include "shill/refptr_types.h"
Paul Stewartb50f0b92011-05-16 16:31:42 -070092
93namespace shill {
94
mukesh agrawal7a4e4002011-09-06 11:26:05 -070095class Error;
96class KeyValueStore;
Darin Petkovab565bb2011-10-06 02:55:51 -070097class ProxyFactory;
mukesh agrawalaf571952011-07-14 14:31:12 -070098class SupplicantInterfaceProxyInterface;
99class SupplicantProcessProxyInterface;
mukesh agrawal445e72c2011-06-22 11:13:50 -0700100class WiFiService;
mukesh agrawalb54601c2011-06-07 17:39:22 -0700101
mukesh agrawalab87ea42011-05-18 11:44:49 -0700102// WiFi class. Specialization of Device for WiFi.
Paul Stewartb50f0b92011-05-16 16:31:42 -0700103class WiFi : public Device {
104 public:
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700105 WiFi(ControlInterface *control_interface,
106 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -0800107 Metrics *metrics,
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700108 Manager *manager,
Chris Masone626719f2011-08-18 16:58:48 -0700109 const std::string &link,
110 const std::string &address,
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700111 int interface_index);
mukesh agrawalab87ea42011-05-18 11:44:49 -0700112 virtual ~WiFi();
Darin Petkovc0865312011-09-16 15:31:20 -0700113
mukesh agrawalab87ea42011-05-18 11:44:49 -0700114 virtual void Start();
115 virtual void Stop();
Paul Stewarta41e38d2011-11-11 07:47:29 -0800116 virtual bool Load(StoreInterface *storage);
Darin Petkovc0865312011-09-16 15:31:20 -0700117 virtual void Scan(Error *error);
Paul Stewartfdd16072011-09-16 12:41:35 -0700118 virtual bool TechnologyIs(const Technology::Identifier type) const;
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000119 virtual bool IsConnectingTo(const WiFiService &service) const;
mukesh agrawalab87ea42011-05-18 11:44:49 -0700120
mukesh agrawal15908392011-11-16 18:29:25 +0000121 // Called by SupplicantInterfaceProxy, in response to events from
mukesh agrawalab87ea42011-05-18 11:44:49 -0700122 // wpa_supplicant.
123 void BSSAdded(const ::DBus::Path &BSS,
Chris Masonea82b7112011-05-25 15:16:29 -0700124 const std::map<std::string, ::DBus::Variant> &properties);
mukesh agrawal261daca2011-12-02 18:56:56 +0000125 void BSSRemoved(const ::DBus::Path &BSS);
mukesh agrawal7ec71312011-11-10 02:08:26 +0000126 void PropertiesChanged(
127 const std::map<std::string, ::DBus::Variant> &properties);
mukesh agrawalab87ea42011-05-18 11:44:49 -0700128 void ScanDone();
129
mukesh agrawal15908392011-11-16 18:29:25 +0000130 // Called by WiFiService.
mukesh agrawal6e277772011-09-29 15:04:23 -0700131 virtual void ConnectTo(
132 WiFiService *service,
mukesh agrawal64896322011-12-01 01:13:10 +0000133 std::map<std::string, ::DBus::Variant> service_params);
mukesh agrawal0ed0f2e2011-12-05 20:36:17 +0000134 virtual void DisconnectFrom(WiFiService *service);
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000135 virtual bool IsIdle() const;
Paul Stewart66c86002012-01-30 18:00:52 -0800136 virtual void ClearCachedCredentials();
mukesh agrawalb54601c2011-06-07 17:39:22 -0700137
mukesh agrawalb20776f2012-02-10 16:00:36 -0800138 // Called by WiFiEndpoint.
139 virtual void NotifyEndpointChanged(const WiFiEndpoint &endpoint);
140
mukesh agrawal15908392011-11-16 18:29:25 +0000141 // Called by Manager.
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700142 virtual WiFiServiceRefPtr GetService(const KeyValueStore &args, Error *error);
143
mukesh agrawal16bc1b82012-02-09 18:38:26 -0800144 // Utility, used by WiFiService and WiFiEndpoint.
145 // Replace non-ASCII characters with '?'. Return true if one or more
146 // characters were changed.
147 static bool SanitizeSSID(std::string *ssid);
148
Paul Stewartb50f0b92011-05-16 16:31:42 -0700149 private:
mukesh agrawal7ec71312011-11-10 02:08:26 +0000150 friend class WiFiMainTest; // access to supplicant_*_proxy_, link_up_
mukesh agrawal7ec71312011-11-10 02:08:26 +0000151 FRIEND_TEST(WiFiMainTest, InitialSupplicantState); // kInterfaceStateUnknown
Thieu Lee41a72d2012-02-06 20:46:51 +0000152 FRIEND_TEST(WiFiMainTest, ScanResults); // EndpointMap
mukesh agrawal165e6142011-11-22 02:22:56 +0000153 FRIEND_TEST(WiFiMainTest, ScanResultsWithUpdates); // EndpointMap
mukesh agrawal5c05b292012-03-07 10:12:52 -0800154 FRIEND_TEST(WiFiMainTest, FlushBSSOnResume); // kMaxBSSResumeAgeSeconds
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800155 FRIEND_TEST(WiFiPropertyTest, ClearDerivedProperty); // bgscan_method_
Paul Stewart6ab23a92011-11-09 17:17:47 -0800156
mukesh agrawalb54601c2011-06-07 17:39:22 -0700157 typedef std::map<const std::string, WiFiEndpointRefPtr> EndpointMap;
mukesh agrawal15908392011-11-16 18:29:25 +0000158 typedef std::map<WiFiService *, std::string> ReverseServiceMap;
mukesh agrawalb54601c2011-06-07 17:39:22 -0700159
mukesh agrawal4d0401c2012-01-06 16:05:31 -0800160 static const char *kDefaultBgscanMethod;
161 static const uint16 kDefaultBgscanShortIntervalSeconds;
162 static const int32 kDefaultBgscanSignalThresholdDbm;
163 static const uint16 kDefaultScanIntervalSeconds;
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700164 static const char kManagerErrorPassphraseRequired[];
165 static const char kManagerErrorSSIDTooLong[];
166 static const char kManagerErrorSSIDTooShort[];
167 static const char kManagerErrorSSIDRequired[];
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700168 static const char kManagerErrorUnsupportedSecurityMode[];
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700169 static const char kManagerErrorUnsupportedServiceMode[];
mukesh agrawal5c05b292012-03-07 10:12:52 -0800170 static const time_t kMaxBSSResumeAgeSeconds;
mukesh agrawal7ec71312011-11-10 02:08:26 +0000171 static const char kInterfaceStateUnknown[];
mukesh agrawalf2028172012-03-13 14:20:22 -0700172 // Delay between scans when supplicant finds "No suitable network".
173 static const time_t kRescanIntervalSeconds;
mukesh agrawalab87ea42011-05-18 11:44:49 -0700174
mukesh agrawal4d0401c2012-01-06 16:05:31 -0800175 std::string CreateBgscanConfigString();
176 std::string GetBgscanMethod(Error */* error */) { return bgscan_method_; }
177 uint16 GetBgscanShortInterval(Error */* error */) {
178 return bgscan_short_interval_seconds_;
179 }
180 int32 GetBgscanSignalThreshold(Error */* error */) {
181 return bgscan_signal_threshold_dbm_;
182 }
183 uint16 GetScanInterval(Error */* error */) { return scan_interval_seconds_; }
184 void SetBgscanMethod(const std::string &method, Error *error);
185 void SetBgscanShortInterval(const uint16 &seconds, Error *error);
186 void SetBgscanSignalThreshold(const int32 &dbm, Error *error);
187 void SetScanInterval(const uint16 &seconds, Error *error);
188
mukesh agrawal15908392011-11-16 18:29:25 +0000189 WiFiServiceRefPtr CreateServiceForEndpoint(
190 const WiFiEndpoint &endpoint, bool hidden_ssid);
191 void CurrentBSSChanged(const ::DBus::Path &new_bss);
Paul Stewart6ab23a92011-11-09 17:17:47 -0800192 WiFiServiceRefPtr FindService(const std::vector<uint8_t> &ssid,
193 const std::string &mode,
194 const std::string &security) const;
mukesh agrawal165e6142011-11-22 02:22:56 +0000195 WiFiServiceRefPtr FindServiceForEndpoint(const WiFiEndpoint &endpoint);
Paul Stewartced6a0b2011-11-08 15:32:04 -0800196 ByteArrays GetHiddenSSIDList();
mukesh agrawal15908392011-11-16 18:29:25 +0000197 void HandleDisconnect();
198 void HandleRoam(const ::DBus::Path &new_bssid);
Paul Stewarta41e38d2011-11-11 07:47:29 -0800199 // Create services for hidden networks stored in |storage|. Returns true
200 // if any were found, otherwise returns false.
201 bool LoadHiddenServices(StoreInterface *storage);
mukesh agrawalb4bc57d2011-12-07 01:07:47 +0000202 void BSSAddedTask(const ::DBus::Path &BSS,
203 const std::map<std::string, ::DBus::Variant> &properties);
204 void BSSRemovedTask(const ::DBus::Path &BSS);
Paul Stewart66c86002012-01-30 18:00:52 -0800205 void ClearCachedCredentialsTask();
mukesh agrawal15908392011-11-16 18:29:25 +0000206 void PropertiesChangedTask(
207 const std::map<std::string, ::DBus::Variant> &properties);
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700208 void ScanDoneTask();
mukesh agrawal32399322011-09-01 10:53:43 -0700209 void ScanTask();
mukesh agrawal7ec71312011-11-10 02:08:26 +0000210 void StateChanged(const std::string &new_state);
mukesh agrawalb54601c2011-06-07 17:39:22 -0700211
mukesh agrawal4d0401c2012-01-06 16:05:31 -0800212 void HelpRegisterDerivedInt32(
213 PropertyStore *store,
214 const std::string &name,
215 int32(WiFi::*get)(Error *error),
216 void(WiFi::*set)(const int32 &value, Error *error));
217 void HelpRegisterDerivedString(
218 PropertyStore *store,
219 const std::string &name,
220 std::string(WiFi::*get)(Error *error),
221 void(WiFi::*set)(const std::string &value, Error *error));
222 void HelpRegisterDerivedUint16(
223 PropertyStore *store,
224 const std::string &name,
225 uint16(WiFi::*get)(Error *error),
226 void(WiFi::*set)(const uint16 &value, Error *error));
227
Gary Morainac1bdb42012-02-16 17:42:29 -0800228 // If this WiFi device is idle and |new_state| indicates a resume event, a
229 // scan is initiated.
230 void HandlePowerStateChange(PowerManager::SuspendState new_state);
231
Darin Petkovab565bb2011-10-06 02:55:51 -0700232 // Store cached copies of singletons for speed/ease of testing.
233 ProxyFactory *proxy_factory_;
mukesh agrawal5c05b292012-03-07 10:12:52 -0800234 Time *time_;
Darin Petkovab565bb2011-10-06 02:55:51 -0700235
mukesh agrawalaf571952011-07-14 14:31:12 -0700236 scoped_ptr<SupplicantProcessProxyInterface> supplicant_process_proxy_;
237 scoped_ptr<SupplicantInterfaceProxyInterface> supplicant_interface_proxy_;
mukesh agrawal15908392011-11-16 18:29:25 +0000238 // The rpcid used as the key is wpa_supplicant's D-Bus path for the
239 // Endpoint (BSS, in supplicant parlance).
240 EndpointMap endpoint_by_rpcid_;
mukesh agrawal15908392011-11-16 18:29:25 +0000241 // Map from Services to the D-Bus path for the corresponding wpa_supplicant
242 // Network.
243 ReverseServiceMap rpcid_by_service_;
mukesh agrawal15908392011-11-16 18:29:25 +0000244 std::vector<WiFiServiceRefPtr> services_;
245 // The Service we are presently connected to. May be NULL is we're not
246 // not connected to any Service.
247 WiFiServiceRefPtr current_service_;
248 // The Service we're attempting to connect to. May be NULL if we're
249 // not attempting to connect to a new Service. If non-NULL, should
250 // be distinct from |current_service_|. (A service should not
251 // simultaneously be both pending, and current.)
252 WiFiServiceRefPtr pending_service_;
253 std::string supplicant_state_;
254 std::string supplicant_bss_;
Paul Stewart66c86002012-01-30 18:00:52 -0800255 // Signifies that ClearCachedCredentialsTask() is pending.
256 bool clear_cached_credentials_pending_;
mukesh agrawal5c05b292012-03-07 10:12:52 -0800257 // Indicates that we should flush supplicant's BSS cache after the
258 // next scan completes.
259 bool need_bss_flush_;
260 struct timeval resumed_at_;
mukesh agrawalab87ea42011-05-18 11:44:49 -0700261
Chris Masone853b81b2011-06-24 14:11:41 -0700262 // Properties
263 std::string bgscan_method_;
mukesh agrawal4d0401c2012-01-06 16:05:31 -0800264 uint16 bgscan_short_interval_seconds_;
265 int32 bgscan_signal_threshold_dbm_;
Chris Masone853b81b2011-06-24 14:11:41 -0700266 bool scan_pending_;
mukesh agrawal4d0401c2012-01-06 16:05:31 -0800267 uint16 scan_interval_seconds_;
Chris Masone853b81b2011-06-24 14:11:41 -0700268
Paul Stewartb50f0b92011-05-16 16:31:42 -0700269 DISALLOW_COPY_AND_ASSIGN(WiFi);
270};
271
272} // namespace shill
273
274#endif // SHILL_WIFI_