blob: 7fa98da3f1028c1f84ae564fed0c5ccbc106fc9a [file] [log] [blame]
Peter Qiuf0731732014-11-11 09:46:41 -08001// Copyright 2014 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 "apmanager/config.h"
6
7#include <base/strings/stringprintf.h>
8#include <chromeos/dbus/service_constants.h>
9
Peter Qiufb39ba42014-11-21 09:09:59 -080010#include "apmanager/device.h"
11#include "apmanager/manager.h"
12
Peter Qiu376e4042014-11-13 09:40:28 -080013using chromeos::dbus_utils::AsyncEventSequencer;
14using chromeos::dbus_utils::ExportedObjectManager;
Peter Qiuf0731732014-11-11 09:46:41 -080015using chromeos::ErrorPtr;
16using std::string;
17
18namespace apmanager {
19
20// static
21const char Config::kHostapdConfigKeyBridgeInterface[] = "bridge";
22const char Config::kHostapdConfigKeyChannel[] = "channel";
23const char Config::kHostapdConfigKeyControlInterface[] = "ctrl_interface";
24const char Config::kHostapdConfigKeyDriver[] = "driver";
25const char Config::kHostapdConfigKeyFragmThreshold[] = "fragm_threshold";
Peter Qiu8e785b92014-11-24 10:01:08 -080026const char Config::kHostapdConfigKeyHTCapability[] = "ht_capab";
Peter Qiuf0731732014-11-11 09:46:41 -080027const char Config::kHostapdConfigKeyHwMode[] = "hw_mode";
28const char Config::kHostapdConfigKeyIeee80211ac[] = "ieee80211ac";
29const char Config::kHostapdConfigKeyIeee80211n[] = "ieee80211n";
30const char Config::kHostapdConfigKeyIgnoreBroadcastSsid[] =
31 "ignore_broadcast_ssid";
32const char Config::kHostapdConfigKeyInterface[] = "interface";
33const char Config::kHostapdConfigKeyRsnPairwise[] = "rsn_pairwise";
34const char Config::kHostapdConfigKeyRtsThreshold[] = "rts_threshold";
35const char Config::kHostapdConfigKeySsid[] = "ssid";
36const char Config::kHostapdConfigKeyWepDefaultKey[] = "wep_default_key";
37const char Config::kHostapdConfigKeyWepKey0[] = "wep_key0";
38const char Config::kHostapdConfigKeyWpa[] = "wpa";
39const char Config::kHostapdConfigKeyWpaKeyMgmt[] = "wpa_key_mgmt";
40const char Config::kHostapdConfigKeyWpaPassphrase[] = "wpa_passphrase";
41
42const char Config::kHostapdHwMode80211a[] = "a";
43const char Config::kHostapdHwMode80211b[] = "b";
44const char Config::kHostapdHwMode80211g[] = "g";
45
46// static
47const uint16_t Config::kPropertyDefaultChannel = 6;
48const uint16_t Config::kPropertyDefaultServerAddressIndex = 0;
49const bool Config::kPropertyDefaultHiddenNetwork = false;
50
51// static
52const char Config::kHostapdDefaultDriver[] = "nl80211";
53const char Config::kHostapdDefaultRsnPairwise[] = "CCMP";
54const char Config::kHostapdDefaultWpaKeyMgmt[] = "WPA-PSK";
55// Fragmentation threshold: disabled.
56const int Config::kHostapdDefaultFragmThreshold = 2346;
57// RTS threshold: disabled.
58const int Config::kHostapdDefaultRtsThreshold = 2347;
59
Peter Qiu8e785b92014-11-24 10:01:08 -080060// static
61const uint16_t Config::kBand24GHzChannelLow = 1;
62const uint16_t Config::kBand24GHzChannelHigh = 13;
63const uint32_t Config::kBand24GHzBaseFrequency = 2412;
64const uint16_t Config::kBand5GHzChannelLow = 34;
65const uint16_t Config::kBand5GHzChannelHigh = 165;
66const uint16_t Config::kBand5GHzBaseFrequency = 5170;
67
Peter Qiufb39ba42014-11-21 09:09:59 -080068Config::Config(Manager* manager, const string& service_path)
Peter Qiuf0731732014-11-11 09:46:41 -080069 : org::chromium::apmanager::ConfigAdaptor(this),
Peter Qiufb39ba42014-11-21 09:09:59 -080070 manager_(manager),
Peter Qiuf0731732014-11-11 09:46:41 -080071 dbus_path_(dbus::ObjectPath(
72 base::StringPrintf("%s/config", service_path.c_str()))) {
73 // Initialize default configuration values.
74 SetSecurityMode(kSecurityModeNone);
75 SetHwMode(kHwMode80211g);
76 SetOperationMode(kOperationModeServer);
77 SetServerAddressIndex(kPropertyDefaultServerAddressIndex);
78 SetChannel(kPropertyDefaultChannel);
79 SetHiddenNetwork(kPropertyDefaultHiddenNetwork);
80}
81
82Config::~Config() {}
83
Peter Qiu8e785b92014-11-24 10:01:08 -080084// static.
85bool Config::GetFrequencyFromChannel(uint16_t channel, uint32_t* freq) {
86 bool ret_value = true;
87 if (channel >= kBand24GHzChannelLow && channel <= kBand24GHzChannelHigh) {
88 *freq = kBand24GHzBaseFrequency + (channel - kBand24GHzChannelLow) * 5;
89 } else if (channel >= kBand5GHzChannelLow &&
90 channel <= kBand5GHzChannelHigh) {
91 *freq = kBand5GHzBaseFrequency + (channel - kBand5GHzChannelLow) * 5;
92 } else {
93 ret_value = false;
94 }
95 return ret_value;
96}
97
Peter Qiu376e4042014-11-13 09:40:28 -080098void Config::RegisterAsync(ExportedObjectManager* object_manager,
99 AsyncEventSequencer* sequencer) {
100 CHECK(!dbus_object_) << "Already registered";
101 dbus_object_.reset(
102 new chromeos::dbus_utils::DBusObject(
103 object_manager,
104 object_manager ? object_manager->GetBus() : nullptr,
105 dbus_path_));
106 RegisterWithDBusObject(dbus_object_.get());
107 dbus_object_->RegisterAsync(
108 sequencer->GetHandler("Config.RegisterAsync() failed.", true));
109}
110
Peter Qiuf0731732014-11-11 09:46:41 -0800111bool Config::GenerateConfigFile(ErrorPtr* error, string* config_str) {
112 // SSID.
113 string ssid = GetSsid();
114 if (ssid.empty()) {
Peter Qiu376e4042014-11-13 09:40:28 -0800115 chromeos::Error::AddTo(
116 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
117 "SSID not specified");
Peter Qiuf0731732014-11-11 09:46:41 -0800118 return false;
119 }
120 base::StringAppendF(
121 config_str, "%s=%s\n", kHostapdConfigKeySsid, ssid.c_str());
122
123 // Channel.
124 base::StringAppendF(
125 config_str, "%s=%d\n", kHostapdConfigKeyChannel, GetChannel());
126
Peter Qiu8e785b92014-11-24 10:01:08 -0800127 // Interface.
128 if (!AppendInterface(error, config_str)) {
Peter Qiuf0731732014-11-11 09:46:41 -0800129 return false;
130 }
131
Peter Qiu8e785b92014-11-24 10:01:08 -0800132 // Hardware mode.
133 if (!AppendHwMode(error, config_str)) {
Peter Qiuf0731732014-11-11 09:46:41 -0800134 return false;
135 }
136
137 // Security mode configurations.
138 if (!AppendSecurityMode(error, config_str)) {
139 return false;
140 }
141
142 // Hostapd default configurations.
143 if (!AppendHostapdDefaults(error, config_str)) {
144 return false;
145 }
146
147 return true;
148}
149
Peter Qiufb39ba42014-11-21 09:09:59 -0800150bool Config::ClaimDevice() {
151 if (!device_) {
152 LOG(ERROR) << "Failed to claim device: device doesn't exist.";
153 return false;
154 }
155 return device_->ClaimDevice();
156}
157
158bool Config::ReleaseDevice() {
159 if (!device_) {
160 LOG(ERROR) << "Failed to release device: device doesn't exist.";
161 return false;
162 }
163 return device_->ReleaseDevice();
164}
165
Peter Qiu376e4042014-11-13 09:40:28 -0800166bool Config::AppendHwMode(ErrorPtr* error, std::string* config_str) {
Peter Qiuf0731732014-11-11 09:46:41 -0800167 string hw_mode = GetHwMode();
168 string hostapd_hw_mode;
169 if (hw_mode == kHwMode80211a) {
170 hostapd_hw_mode = kHostapdHwMode80211a;
171 } else if (hw_mode == kHwMode80211b) {
172 hostapd_hw_mode = kHostapdHwMode80211b;
173 } else if (hw_mode == kHwMode80211g) {
174 hostapd_hw_mode = kHostapdHwMode80211g;
175 } else if (hw_mode == kHwMode80211n) {
176 // Use 802.11a for 5GHz channel and 802.11g for 2.4GHz channel
177 if (GetChannel() >= 34) {
178 hostapd_hw_mode = kHostapdHwMode80211a;
179 } else {
180 hostapd_hw_mode = kHostapdHwMode80211g;
181 }
182 base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211n);
183
Peter Qiu8e785b92014-11-24 10:01:08 -0800184 // Get HT Capability.
185 string ht_cap;
186 if (!device_->GetHTCapability(GetChannel(), &ht_cap)) {
187 chromeos::Error::AddTo(
188 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
189 "Failed to get HT Capability");
190 return false;
191 }
192 base::StringAppendF(config_str, "%s=%s\n",
193 kHostapdConfigKeyHTCapability,
194 ht_cap.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800195 } else if (hw_mode == kHwMode80211ac) {
196 if (GetChannel() >= 34) {
197 hostapd_hw_mode = kHostapdHwMode80211a;
198 } else {
199 hostapd_hw_mode = kHostapdHwMode80211g;
200 }
201 base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211ac);
202
203 // TODO(zqiu): Determine VHT Capabilities based on the interface PHY's
204 // capababilites.
205 } else {
Peter Qiu376e4042014-11-13 09:40:28 -0800206 chromeos::Error::AddToPrintf(
207 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
208 "Invalid hardware mode: %s", hw_mode.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800209 return false;
210 }
211
212 base::StringAppendF(
213 config_str, "%s=%s\n", kHostapdConfigKeyHwMode, hostapd_hw_mode.c_str());
214 return true;
215}
216
Peter Qiu376e4042014-11-13 09:40:28 -0800217bool Config::AppendHostapdDefaults(ErrorPtr* error,
Peter Qiuf0731732014-11-11 09:46:41 -0800218 std::string* config_str) {
219 // Driver: NL80211.
220 base::StringAppendF(
221 config_str, "%s=%s\n", kHostapdConfigKeyDriver, kHostapdDefaultDriver);
222
223 // Fragmentation threshold: disabled.
224 base::StringAppendF(config_str,
225 "%s=%d\n",
226 kHostapdConfigKeyFragmThreshold,
227 kHostapdDefaultFragmThreshold);
228
229 // RTS threshold: disabled.
230 base::StringAppendF(config_str,
231 "%s=%d\n",
232 kHostapdConfigKeyRtsThreshold,
233 kHostapdDefaultRtsThreshold);
234
235 return true;
236}
237
Peter Qiu376e4042014-11-13 09:40:28 -0800238bool Config::AppendInterface(ErrorPtr* error,
Peter Qiuf0731732014-11-11 09:46:41 -0800239 std::string* config_str) {
240 string interface = GetInterfaceName();
241 if (interface.empty()) {
Peter Qiufb39ba42014-11-21 09:09:59 -0800242 // Ask manager for unused ap capable device.
243 device_ = manager_->GetAvailableDevice();
244 if (!device_) {
245 chromeos::Error::AddTo(
246 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
247 "No device available");
248 return false;
249 }
250 } else {
251 device_ = manager_->GetDeviceFromInterfaceName(interface);
252 if (device_->GetInUsed()) {
253 chromeos::Error::AddToPrintf(
254 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
255 "Device [%s] for interface [%s] already in use",
256 device_->GetDeviceName().c_str(),
257 interface.c_str());
258 return false;
259 }
Peter Qiuf0731732014-11-11 09:46:41 -0800260 }
261
Peter Qiufb39ba42014-11-21 09:09:59 -0800262 // Use the preferred AP interface from the device.
263 interface = device_->GetPreferredApInterface();
264
Peter Qiuf0731732014-11-11 09:46:41 -0800265 base::StringAppendF(
266 config_str, "%s=%s\n", kHostapdConfigKeyInterface, interface.c_str());
267 return true;
268}
269
Peter Qiu376e4042014-11-13 09:40:28 -0800270bool Config::AppendSecurityMode(ErrorPtr* error,
Peter Qiuf0731732014-11-11 09:46:41 -0800271 std::string* config_str) {
272 string security_mode = GetSecurityMode();
273 if (security_mode == kSecurityModeNone) {
274 // Nothing need to be done for open network.
275 return true;
276 }
277
278 if (security_mode == kSecurityModeRSN) {
279 string passphrase = GetPassphrase();
280 if (passphrase.empty()) {
Peter Qiu376e4042014-11-13 09:40:28 -0800281 chromeos::Error::AddToPrintf(
282 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
283 "Passphrase not set for security mode: %s", security_mode.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800284 return false;
285 }
286
287 base::StringAppendF(config_str, "%s=2\n", kHostapdConfigKeyWpa);
288 base::StringAppendF(config_str,
289 "%s=%s\n",
290 kHostapdConfigKeyRsnPairwise,
291 kHostapdDefaultRsnPairwise);
292 base::StringAppendF(config_str,
293 "%s=%s\n",
294 kHostapdConfigKeyWpaKeyMgmt,
295 kHostapdDefaultWpaKeyMgmt);
296 base::StringAppendF(config_str,
297 "%s=%s\n",
298 kHostapdConfigKeyWpaPassphrase,
299 passphrase.c_str());
300 return true;
301 }
302
Peter Qiuf0731732014-11-11 09:46:41 -0800303 chromeos::Error::AddToPrintf(
Peter Qiu376e4042014-11-13 09:40:28 -0800304 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
305 "Invalid security mode: %s", security_mode.c_str());
306 return false;
Peter Qiuf0731732014-11-11 09:46:41 -0800307}
308
309} // namespace apmanager