blob: cec2d983a0cd51a8c50a89b36671e077c600b7ca [file] [log] [blame]
Paul Stewartb50f0b92011-05-16 16:31:42 -07001// Copyright (c) 2011 The Chromium OS 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
5#include <time.h>
6#include <stdio.h>
mukesh agrawalc7426a42011-06-03 13:04:28 -07007#include <string.h>
Paul Stewartb50f0b92011-05-16 16:31:42 -07008
mukesh agrawalab87ea42011-05-18 11:44:49 -07009#include <map>
Paul Stewartb50f0b92011-05-16 16:31:42 -070010#include <string>
mukesh agrawalab87ea42011-05-18 11:44:49 -070011#include <vector>
Paul Stewartb50f0b92011-05-16 16:31:42 -070012
13#include <base/logging.h>
mukesh agrawalb54601c2011-06-07 17:39:22 -070014#include <base/string_number_conversions.h>
Paul Stewartb50f0b92011-05-16 16:31:42 -070015
16#include "shill/control_interface.h"
17#include "shill/device.h"
18#include "shill/shill_event.h"
mukesh agrawalb54601c2011-06-07 17:39:22 -070019#include "shill/wifi_endpoint.h"
20#include "shill/wifi_service.h"
Paul Stewartb50f0b92011-05-16 16:31:42 -070021
22#include "shill/wifi.h"
23
mukesh agrawalab87ea42011-05-18 11:44:49 -070024using std::string;
25
Paul Stewartb50f0b92011-05-16 16:31:42 -070026namespace shill {
mukesh agrawalb54601c2011-06-07 17:39:22 -070027const char WiFi::kSupplicantPath[] = "/fi/w1/wpa_supplicant1";
28const char WiFi::kSupplicantDBusAddr[] = "fi.w1.wpa_supplicant1";
29const char WiFi::kSupplicantWiFiDriver[] = "nl80211";
mukesh agrawalc7426a42011-06-03 13:04:28 -070030const char WiFi::kSupplicantErrorInterfaceExists[] =
31 "fi.w1.wpa_supplicant1.InterfaceExists";
mukesh agrawalb54601c2011-06-07 17:39:22 -070032const char WiFi::kSupplicantKeyModeNone[] = "NONE";
33
34unsigned int WiFi::service_id_serial_ = 0;
mukesh agrawalab87ea42011-05-18 11:44:49 -070035
36WiFi::SupplicantProcessProxy::SupplicantProcessProxy(DBus::Connection *bus)
37 : DBus::ObjectProxy(*bus, kSupplicantPath, kSupplicantDBusAddr) {}
38
39void WiFi::SupplicantProcessProxy::InterfaceAdded(
40 const ::DBus::Path& path,
41 const std::map<string, ::DBus::Variant> &properties) {
42 LOG(INFO) << __func__;
43 // XXX
44}
45
46void WiFi::SupplicantProcessProxy::InterfaceRemoved(const ::DBus::Path& path) {
47 LOG(INFO) << __func__;
48 // XXX
49}
50
51void WiFi::SupplicantProcessProxy::PropertiesChanged(
52 const std::map<string, ::DBus::Variant>& properties) {
53 LOG(INFO) << __func__;
54 // XXX
55}
56
57WiFi::SupplicantInterfaceProxy::SupplicantInterfaceProxy(
58 WiFi *wifi,
59 DBus::Connection *bus,
60 const ::DBus::Path &object_path)
61 : wifi_(*wifi),
62 DBus::ObjectProxy(*bus, object_path, kSupplicantDBusAddr) {}
63
64void WiFi::SupplicantInterfaceProxy::ScanDone(const bool& success) {
65 LOG(INFO) << __func__ << " " << success;
66 if (success) {
67 wifi_.ScanDone();
68 }
69}
70
71void WiFi::SupplicantInterfaceProxy::BSSAdded(
72 const ::DBus::Path &BSS,
73 const std::map<string, ::DBus::Variant> &properties) {
74 LOG(INFO) << __func__;
75 wifi_.BSSAdded(BSS, properties);
76}
77
78void WiFi::SupplicantInterfaceProxy::BSSRemoved(const ::DBus::Path &BSS) {
79 LOG(INFO) << __func__;
80 // XXX
81}
82
83void WiFi::SupplicantInterfaceProxy::BlobAdded(const string &blobname) {
84 LOG(INFO) << __func__;
85 // XXX
86}
87
88void WiFi::SupplicantInterfaceProxy::BlobRemoved(const string &blobname) {
89 LOG(INFO) << __func__;
90 // XXX
91}
92
93void WiFi::SupplicantInterfaceProxy::NetworkAdded(
94 const ::DBus::Path &network,
95 const std::map<string, ::DBus::Variant> &properties) {
96 LOG(INFO) << __func__;
97 // XXX
98}
99
100void WiFi::SupplicantInterfaceProxy::NetworkRemoved(
101 const ::DBus::Path &network) {
102 LOG(INFO) << __func__;
103 // XXX
104}
105
106void WiFi::SupplicantInterfaceProxy::NetworkSelected(
107 const ::DBus::Path &network) {
108 LOG(INFO) << __func__;
109 // XXX
110}
111
112void WiFi::SupplicantInterfaceProxy::PropertiesChanged(
113 const std::map<string, ::DBus::Variant> &properties) {
114 LOG(INFO) << __func__;
115 // XXX
116}
117
118// NB: we assume supplicant is already running. [quiche.20110518]
Paul Stewartb50f0b92011-05-16 16:31:42 -0700119WiFi::WiFi(ControlInterface *control_interface,
120 EventDispatcher *dispatcher,
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700121 Manager *manager,
mukesh agrawalb54601c2011-06-07 17:39:22 -0700122 const string& link_name,
Paul Stewartb50f0b92011-05-16 16:31:42 -0700123 int interface_index)
Chris Masonea82b7112011-05-25 15:16:29 -0700124 : Device(control_interface,
125 dispatcher,
126 manager,
127 link_name,
mukesh agrawalab87ea42011-05-18 11:44:49 -0700128 interface_index),
mukesh agrawalb54601c2011-06-07 17:39:22 -0700129 task_factory_(this),
130 control_interface_(control_interface),
131 dispatcher_(dispatcher),
132 dbus_(DBus::Connection::SystemBus()),
133 scan_pending_(false) {
Chris Masonea82b7112011-05-25 15:16:29 -0700134 VLOG(2) << "WiFi device " << link_name_ << " initialized.";
Paul Stewartb50f0b92011-05-16 16:31:42 -0700135}
136
137WiFi::~WiFi() {
138}
139
mukesh agrawalab87ea42011-05-18 11:44:49 -0700140void WiFi::Start() {
mukesh agrawalab87ea42011-05-18 11:44:49 -0700141 ::DBus::Path interface_path;
142
143 supplicant_process_proxy_.reset(new SupplicantProcessProxy(&dbus_));
mukesh agrawalc7426a42011-06-03 13:04:28 -0700144 try {
145 std::map<string, DBus::Variant> create_interface_args;
146 create_interface_args["Ifname"].writer().
147 append_string(link_name_.c_str());
148 create_interface_args["Driver"].writer().
149 append_string(kSupplicantWiFiDriver);
150 // TODO(quiche) create_interface_args["ConfigFile"].writer().append_string
151 // (file with pkcs config info)
152 interface_path =
153 supplicant_process_proxy_->CreateInterface(create_interface_args);
154 } catch (const DBus::Error e) { // NOLINT
155 if (!strcmp(e.name(), kSupplicantErrorInterfaceExists)) {
156 interface_path =
157 supplicant_process_proxy_->GetInterface(link_name_);
mukesh agrawalb54601c2011-06-07 17:39:22 -0700158 // XXX crash here, if device missing?
mukesh agrawalc7426a42011-06-03 13:04:28 -0700159 } else {
160 // XXX
161 }
162 }
163
mukesh agrawalab87ea42011-05-18 11:44:49 -0700164 supplicant_interface_proxy_.reset(
165 new SupplicantInterfaceProxy(this, &dbus_, interface_path));
mukesh agrawalc7426a42011-06-03 13:04:28 -0700166
mukesh agrawalab87ea42011-05-18 11:44:49 -0700167 // TODO(quiche) set ApScan=1 and BSSExpireAge=190, like flimflam does?
mukesh agrawalc7426a42011-06-03 13:04:28 -0700168
169 // clear out any networks that might previously have been configured
170 // for this interface.
171 supplicant_interface_proxy_->RemoveAllNetworks();
172
173 // flush interface's BSS cache, so that we get BSSAdded signals for
174 // all BSSes (not just new ones since the last scan).
175 supplicant_interface_proxy_->FlushBSS(0);
176
mukesh agrawalab87ea42011-05-18 11:44:49 -0700177 LOG(INFO) << "initiating Scan.";
mukesh agrawalc7426a42011-06-03 13:04:28 -0700178 std::map<string, DBus::Variant> scan_args;
179 scan_args["Type"].writer().append_string("active");
mukesh agrawalab87ea42011-05-18 11:44:49 -0700180 // TODO(quiche) indicate scanning in UI
181 supplicant_interface_proxy_->Scan(scan_args);
182 scan_pending_ = true;
183 Device::Start();
184}
185
mukesh agrawalab87ea42011-05-18 11:44:49 -0700186void WiFi::Stop() {
187 LOG(INFO) << __func__;
188 // XXX
189 Device::Stop();
190}
191
Paul Stewartb50f0b92011-05-16 16:31:42 -0700192bool WiFi::TechnologyIs(const Device::Technology type) {
193 return type == Device::kWifi;
194}
195
mukesh agrawalb54601c2011-06-07 17:39:22 -0700196void WiFi::BSSAdded(
197 const ::DBus::Path &BSS,
198 const std::map<string, ::DBus::Variant> &properties) {
199 // TODO(quiche): write test to verify correct behavior in the case
200 // where we get multiple BSSAdded events for a single endpoint.
201 // (old Endpoint's refcount should fall to zero, and old Endpoint
202 // should be destroyed)
203 //
204 // note: we assume that BSSIDs are unique across endpoints. this
205 // means that if an AP reuses the same BSSID for multiple SSIDs, we
206 // lose.
207 WiFiEndpointRefPtr endpoint(new WiFiEndpoint(properties));
208 endpoint_by_bssid_[endpoint->bssid_hex()] = endpoint;
209}
210
211void WiFi::ScanDone() {
212 LOG(INFO) << __func__;
213
214 // defer handling of scan result processing, because that processing
215 // may require the the registration of new D-Bus objects. and such
216 // registration can't be done in the context of a D-Bus signal
217 // handler.
218 dispatcher_->PostTask(
219 task_factory_.NewRunnableMethod(&WiFi::RealScanDone));
220}
221
222::DBus::Path WiFi::AddNetwork(
223 const std::map<string, ::DBus::Variant> &args) {
224 return supplicant_interface_proxy_->AddNetwork(args);
225}
226
227void WiFi::SelectNetwork(const ::DBus::Path &network) {
228 supplicant_interface_proxy_->SelectNetwork(network);
229}
230
231void WiFi::RealScanDone() {
232 LOG(INFO) << __func__;
233
234 scan_pending_ = false;
235
236 // TODO(quiche): group endpoints into services, instead of creating
237 // a service for every endpoint.
238 for (EndpointMap::iterator i(endpoint_by_bssid_.begin());
239 i != endpoint_by_bssid_.end(); ++i) {
240 const WiFiEndpoint &endpoint(*(i->second));
241 string service_id_private;
242
243 service_id_private =
244 endpoint.ssid_hex() + "_" + endpoint.bssid_hex();
245 if (service_by_private_id_.find(service_id_private) ==
246 service_by_private_id_.end()) {
247 unsigned int new_service_id_serial = service_id_serial_++;
248 string service_name(base::UintToString(new_service_id_serial));
249
250 LOG(INFO) << "found new endpoint. "
251 << "ssid: " << endpoint.ssid_string() << ", "
252 << "bssid: " << endpoint.bssid_string() << ", "
253 << "signal: " << endpoint.signal_strength() << ", "
254 << "service name: " << "/service/" << service_name;
255
256 // XXX key mode should reflect endpoint params (not always use
257 // kSupplicantKeyModeNone)
258 ServiceRefPtr service(
259 new WiFiService(control_interface_, dispatcher_, this,
260 endpoint.ssid(), endpoint.network_mode(),
261 kSupplicantKeyModeNone, service_name));
262 services_.push_back(service);
263 service_by_private_id_[service_id_private] = service;
264 }
265 }
266
267 // TODO(quiche): register new services with manager
268 // TODO(quiche): unregister removed services from manager
269}
270
Paul Stewartb50f0b92011-05-16 16:31:42 -0700271} // namespace shill