blob: 82f31353ece8cf0afa51392c94c5321f81ad3a45 [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 Qiubf8e36c2014-12-03 22:59:45 -080098bool Config::SsidSet(ErrorPtr* error, const string& ssid) {
99 // TODO(zqiu): validate ssid string.
100 SetSsid(ssid);
101 return true;
102}
103
Peter Qiu376e4042014-11-13 09:40:28 -0800104void Config::RegisterAsync(ExportedObjectManager* object_manager,
105 AsyncEventSequencer* sequencer) {
106 CHECK(!dbus_object_) << "Already registered";
107 dbus_object_.reset(
108 new chromeos::dbus_utils::DBusObject(
109 object_manager,
110 object_manager ? object_manager->GetBus() : nullptr,
111 dbus_path_));
112 RegisterWithDBusObject(dbus_object_.get());
113 dbus_object_->RegisterAsync(
114 sequencer->GetHandler("Config.RegisterAsync() failed.", true));
115}
116
Peter Qiuf0731732014-11-11 09:46:41 -0800117bool Config::GenerateConfigFile(ErrorPtr* error, string* config_str) {
118 // SSID.
119 string ssid = GetSsid();
120 if (ssid.empty()) {
Peter Qiu376e4042014-11-13 09:40:28 -0800121 chromeos::Error::AddTo(
122 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
123 "SSID not specified");
Peter Qiuf0731732014-11-11 09:46:41 -0800124 return false;
125 }
126 base::StringAppendF(
127 config_str, "%s=%s\n", kHostapdConfigKeySsid, ssid.c_str());
128
129 // Channel.
130 base::StringAppendF(
131 config_str, "%s=%d\n", kHostapdConfigKeyChannel, GetChannel());
132
Peter Qiu8e785b92014-11-24 10:01:08 -0800133 // Interface.
134 if (!AppendInterface(error, config_str)) {
Peter Qiuf0731732014-11-11 09:46:41 -0800135 return false;
136 }
137
Peter Qiu8e785b92014-11-24 10:01:08 -0800138 // Hardware mode.
139 if (!AppendHwMode(error, config_str)) {
Peter Qiuf0731732014-11-11 09:46:41 -0800140 return false;
141 }
142
143 // Security mode configurations.
144 if (!AppendSecurityMode(error, config_str)) {
145 return false;
146 }
147
148 // Hostapd default configurations.
149 if (!AppendHostapdDefaults(error, config_str)) {
150 return false;
151 }
152
153 return true;
154}
155
Peter Qiufb39ba42014-11-21 09:09:59 -0800156bool Config::ClaimDevice() {
157 if (!device_) {
158 LOG(ERROR) << "Failed to claim device: device doesn't exist.";
159 return false;
160 }
161 return device_->ClaimDevice();
162}
163
164bool Config::ReleaseDevice() {
165 if (!device_) {
166 LOG(ERROR) << "Failed to release device: device doesn't exist.";
167 return false;
168 }
169 return device_->ReleaseDevice();
170}
171
Peter Qiu376e4042014-11-13 09:40:28 -0800172bool Config::AppendHwMode(ErrorPtr* error, std::string* config_str) {
Peter Qiuf0731732014-11-11 09:46:41 -0800173 string hw_mode = GetHwMode();
174 string hostapd_hw_mode;
175 if (hw_mode == kHwMode80211a) {
176 hostapd_hw_mode = kHostapdHwMode80211a;
177 } else if (hw_mode == kHwMode80211b) {
178 hostapd_hw_mode = kHostapdHwMode80211b;
179 } else if (hw_mode == kHwMode80211g) {
180 hostapd_hw_mode = kHostapdHwMode80211g;
181 } else if (hw_mode == kHwMode80211n) {
182 // Use 802.11a for 5GHz channel and 802.11g for 2.4GHz channel
183 if (GetChannel() >= 34) {
184 hostapd_hw_mode = kHostapdHwMode80211a;
185 } else {
186 hostapd_hw_mode = kHostapdHwMode80211g;
187 }
188 base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211n);
189
Peter Qiu8e785b92014-11-24 10:01:08 -0800190 // Get HT Capability.
191 string ht_cap;
192 if (!device_->GetHTCapability(GetChannel(), &ht_cap)) {
193 chromeos::Error::AddTo(
194 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
195 "Failed to get HT Capability");
196 return false;
197 }
198 base::StringAppendF(config_str, "%s=%s\n",
199 kHostapdConfigKeyHTCapability,
200 ht_cap.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800201 } else if (hw_mode == kHwMode80211ac) {
202 if (GetChannel() >= 34) {
203 hostapd_hw_mode = kHostapdHwMode80211a;
204 } else {
205 hostapd_hw_mode = kHostapdHwMode80211g;
206 }
207 base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211ac);
208
209 // TODO(zqiu): Determine VHT Capabilities based on the interface PHY's
210 // capababilites.
211 } else {
Peter Qiu376e4042014-11-13 09:40:28 -0800212 chromeos::Error::AddToPrintf(
213 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
214 "Invalid hardware mode: %s", hw_mode.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800215 return false;
216 }
217
218 base::StringAppendF(
219 config_str, "%s=%s\n", kHostapdConfigKeyHwMode, hostapd_hw_mode.c_str());
220 return true;
221}
222
Peter Qiu376e4042014-11-13 09:40:28 -0800223bool Config::AppendHostapdDefaults(ErrorPtr* error,
Peter Qiuf0731732014-11-11 09:46:41 -0800224 std::string* config_str) {
225 // Driver: NL80211.
226 base::StringAppendF(
227 config_str, "%s=%s\n", kHostapdConfigKeyDriver, kHostapdDefaultDriver);
228
229 // Fragmentation threshold: disabled.
230 base::StringAppendF(config_str,
231 "%s=%d\n",
232 kHostapdConfigKeyFragmThreshold,
233 kHostapdDefaultFragmThreshold);
234
235 // RTS threshold: disabled.
236 base::StringAppendF(config_str,
237 "%s=%d\n",
238 kHostapdConfigKeyRtsThreshold,
239 kHostapdDefaultRtsThreshold);
240
241 return true;
242}
243
Peter Qiu376e4042014-11-13 09:40:28 -0800244bool Config::AppendInterface(ErrorPtr* error,
Peter Qiuf0731732014-11-11 09:46:41 -0800245 std::string* config_str) {
246 string interface = GetInterfaceName();
247 if (interface.empty()) {
Peter Qiufb39ba42014-11-21 09:09:59 -0800248 // Ask manager for unused ap capable device.
249 device_ = manager_->GetAvailableDevice();
250 if (!device_) {
251 chromeos::Error::AddTo(
252 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
253 "No device available");
254 return false;
255 }
256 } else {
257 device_ = manager_->GetDeviceFromInterfaceName(interface);
258 if (device_->GetInUsed()) {
259 chromeos::Error::AddToPrintf(
260 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
261 "Device [%s] for interface [%s] already in use",
262 device_->GetDeviceName().c_str(),
263 interface.c_str());
264 return false;
265 }
Peter Qiuf0731732014-11-11 09:46:41 -0800266 }
267
Peter Qiufb39ba42014-11-21 09:09:59 -0800268 // Use the preferred AP interface from the device.
Peter Qiubf8e36c2014-12-03 22:59:45 -0800269 selected_interface_ = device_->GetPreferredApInterface();
270 base::StringAppendF(config_str,
271 "%s=%s\n",
272 kHostapdConfigKeyInterface,
273 selected_interface_.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800274 return true;
275}
276
Peter Qiu376e4042014-11-13 09:40:28 -0800277bool Config::AppendSecurityMode(ErrorPtr* error,
Peter Qiuf0731732014-11-11 09:46:41 -0800278 std::string* config_str) {
279 string security_mode = GetSecurityMode();
280 if (security_mode == kSecurityModeNone) {
281 // Nothing need to be done for open network.
282 return true;
283 }
284
285 if (security_mode == kSecurityModeRSN) {
286 string passphrase = GetPassphrase();
287 if (passphrase.empty()) {
Peter Qiu376e4042014-11-13 09:40:28 -0800288 chromeos::Error::AddToPrintf(
289 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
290 "Passphrase not set for security mode: %s", security_mode.c_str());
Peter Qiuf0731732014-11-11 09:46:41 -0800291 return false;
292 }
293
294 base::StringAppendF(config_str, "%s=2\n", kHostapdConfigKeyWpa);
295 base::StringAppendF(config_str,
296 "%s=%s\n",
297 kHostapdConfigKeyRsnPairwise,
298 kHostapdDefaultRsnPairwise);
299 base::StringAppendF(config_str,
300 "%s=%s\n",
301 kHostapdConfigKeyWpaKeyMgmt,
302 kHostapdDefaultWpaKeyMgmt);
303 base::StringAppendF(config_str,
304 "%s=%s\n",
305 kHostapdConfigKeyWpaPassphrase,
306 passphrase.c_str());
307 return true;
308 }
309
Peter Qiuf0731732014-11-11 09:46:41 -0800310 chromeos::Error::AddToPrintf(
Peter Qiu376e4042014-11-13 09:40:28 -0800311 error, FROM_HERE, chromeos::errors::dbus::kDomain, kConfigError,
312 "Invalid security mode: %s", security_mode.c_str());
313 return false;
Peter Qiuf0731732014-11-11 09:46:41 -0800314}
315
316} // namespace apmanager