1//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "apmanager/config.h"
18
19#include <base/strings/stringprintf.h>
20
21#if !defined(__ANDROID__)
22#include <chromeos/dbus/service_constants.h>
23#else
24#include <dbus/apmanager/dbus-constants.h>
25#endif  // __ANDROID__
26
27#include "apmanager/error.h"
28#include "apmanager/daemon.h"
29#include "apmanager/device.h"
30#include "apmanager/manager.h"
31
32using std::string;
33
34namespace apmanager {
35
36// static
37const char Config::kHostapdConfigKeyBridgeInterface[] = "bridge";
38const char Config::kHostapdConfigKeyChannel[] = "channel";
39const char Config::kHostapdConfigKeyControlInterface[] = "ctrl_interface";
40const char Config::kHostapdConfigKeyControlInterfaceGroup[] =
41    "ctrl_interface_group";
42const char Config::kHostapdConfigKeyDriver[] = "driver";
43const char Config::kHostapdConfigKeyFragmThreshold[] = "fragm_threshold";
44const char Config::kHostapdConfigKeyHTCapability[] = "ht_capab";
45const char Config::kHostapdConfigKeyHwMode[] = "hw_mode";
46const char Config::kHostapdConfigKeyIeee80211ac[] = "ieee80211ac";
47const char Config::kHostapdConfigKeyIeee80211n[] = "ieee80211n";
48const char Config::kHostapdConfigKeyIgnoreBroadcastSsid[] =
49    "ignore_broadcast_ssid";
50const char Config::kHostapdConfigKeyInterface[] = "interface";
51const char Config::kHostapdConfigKeyRsnPairwise[] = "rsn_pairwise";
52const char Config::kHostapdConfigKeyRtsThreshold[] = "rts_threshold";
53const char Config::kHostapdConfigKeySsid[] = "ssid";
54const char Config::kHostapdConfigKeyWepDefaultKey[] = "wep_default_key";
55const char Config::kHostapdConfigKeyWepKey0[] = "wep_key0";
56const char Config::kHostapdConfigKeyWpa[] = "wpa";
57const char Config::kHostapdConfigKeyWpaKeyMgmt[] = "wpa_key_mgmt";
58const char Config::kHostapdConfigKeyWpaPassphrase[] = "wpa_passphrase";
59
60const char Config::kHostapdHwMode80211a[] = "a";
61const char Config::kHostapdHwMode80211b[] = "b";
62const char Config::kHostapdHwMode80211g[] = "g";
63
64// static
65const uint16_t Config::kPropertyDefaultChannel = 6;
66const uint16_t Config::kPropertyDefaultServerAddressIndex = 0;
67const bool Config::kPropertyDefaultHiddenNetwork = false;
68
69// static
70const char Config::kHostapdDefaultDriver[] = "nl80211";
71const char Config::kHostapdDefaultRsnPairwise[] = "CCMP";
72const char Config::kHostapdDefaultWpaKeyMgmt[] = "WPA-PSK";
73// Fragmentation threshold: disabled.
74const int Config::kHostapdDefaultFragmThreshold = 2346;
75// RTS threshold: disabled.
76const int Config::kHostapdDefaultRtsThreshold = 2347;
77
78// static
79const uint16_t Config::kBand24GHzChannelLow = 1;
80const uint16_t Config::kBand24GHzChannelHigh = 13;
81const uint32_t Config::kBand24GHzBaseFrequency = 2412;
82const uint16_t Config::kBand5GHzChannelLow = 34;
83const uint16_t Config::kBand5GHzChannelHigh = 165;
84const uint16_t Config::kBand5GHzBaseFrequency = 5170;
85
86// static
87const int Config::kSsidMinLength = 1;
88const int Config::kSsidMaxLength = 32;
89const int Config::kPassphraseMinLength = 8;
90const int Config::kPassphraseMaxLength = 63;
91
92Config::Config(Manager* manager, int service_identifier)
93    : manager_(manager),
94      adaptor_(
95          manager->control_interface()->CreateConfigAdaptor(
96              this, service_identifier)) {
97  // Initialize default configuration values.
98  SetSecurityMode(kSecurityModeNone);
99  SetHwMode(kHwMode80211g);
100  SetOperationMode(kOperationModeServer);
101  SetServerAddressIndex(kPropertyDefaultServerAddressIndex);
102  SetChannel(kPropertyDefaultChannel);
103  SetHiddenNetwork(kPropertyDefaultHiddenNetwork);
104  SetFullDeviceControl(true);
105}
106
107Config::~Config() {}
108
109// static.
110bool Config::GetFrequencyFromChannel(uint16_t channel, uint32_t* freq) {
111  bool ret_value = true;
112  if (channel >= kBand24GHzChannelLow && channel <= kBand24GHzChannelHigh) {
113    *freq = kBand24GHzBaseFrequency + (channel - kBand24GHzChannelLow) * 5;
114  } else if (channel >= kBand5GHzChannelLow &&
115             channel <= kBand5GHzChannelHigh) {
116    *freq = kBand5GHzBaseFrequency + (channel - kBand5GHzChannelLow) * 5;
117  } else {
118    ret_value = false;
119  }
120  return ret_value;
121}
122
123bool Config::ValidateSsid(Error* error, const string& value) {
124  if (value.length() < kSsidMinLength || value.length() > kSsidMaxLength) {
125    Error::PopulateAndLog(
126        error,
127        Error::kInvalidArguments,
128        base::StringPrintf("SSID must contain between %d and %d characters",
129                           kSsidMinLength, kSsidMaxLength),
130        FROM_HERE);
131    return false;
132  }
133  return true;
134}
135
136bool Config::ValidateSecurityMode(Error* error, const string& value) {
137  if (value != kSecurityModeNone && value != kSecurityModeRSN) {
138    Error::PopulateAndLog(
139        error,
140        Error::kInvalidArguments,
141        base::StringPrintf("Invalid/unsupported security mode [%s]",
142                           value.c_str()),
143        FROM_HERE);
144    return false;
145  }
146  return true;
147}
148
149bool Config::ValidatePassphrase(Error* error, const string& value) {
150  if (value.length() < kPassphraseMinLength ||
151      value.length() > kPassphraseMaxLength) {
152    Error::PopulateAndLog(
153        error,
154        Error::kInvalidArguments,
155        base::StringPrintf("Passphrase must contain between %d and %d characters",
156                           kPassphraseMinLength, kPassphraseMaxLength),
157        FROM_HERE);
158
159    return false;
160  }
161  return true;
162}
163
164bool Config::ValidateHwMode(Error* error, const string& value) {
165  if (value != kHwMode80211a && value != kHwMode80211b &&
166      value != kHwMode80211g && value != kHwMode80211n &&
167      value != kHwMode80211ac) {
168    Error::PopulateAndLog(
169        error,
170        Error::kInvalidArguments,
171        base::StringPrintf("Invalid HW mode [%s]", value.c_str()),
172        FROM_HERE);
173    return false;
174  }
175  return true;
176}
177
178bool Config::ValidateOperationMode(Error* error, const string& value) {
179  if (value != kOperationModeServer && value != kOperationModeBridge) {
180    Error::PopulateAndLog(
181        error,
182        Error::kInvalidArguments,
183        base::StringPrintf("Invalid operation mode [%s]", value.c_str()),
184        FROM_HERE);
185    return false;
186  }
187  return true;
188}
189
190bool Config::ValidateChannel(Error* error, const uint16_t& value) {
191  if ((value >= kBand24GHzChannelLow && value <= kBand24GHzChannelHigh) ||
192      (value >= kBand5GHzChannelLow && value <= kBand5GHzChannelHigh)) {
193    return true;
194  }
195  Error::PopulateAndLog(error,
196                        Error::kInvalidArguments,
197                        base::StringPrintf("Invalid channel [%d]", value),
198                        FROM_HERE);
199  return false;
200}
201
202bool Config::GenerateConfigFile(Error* error, string* config_str) {
203  // SSID.
204  string ssid = GetSsid();
205  if (ssid.empty()) {
206    Error::PopulateAndLog(error,
207                          Error::kInvalidConfiguration,
208                          "SSID not specified",
209                          FROM_HERE);
210    return false;
211  }
212  base::StringAppendF(
213      config_str, "%s=%s\n", kHostapdConfigKeySsid, ssid.c_str());
214
215  // Bridge interface is required for bridge mode operation.
216  if (GetOperationMode() == kOperationModeBridge) {
217    if (GetBridgeInterface().empty()) {
218      Error::PopulateAndLog(
219          error,
220          Error::kInvalidConfiguration,
221          "Bridge interface not specified, required for bridge mode",
222          FROM_HERE);
223      return false;
224    }
225    base::StringAppendF(config_str,
226                        "%s=%s\n",
227                        kHostapdConfigKeyBridgeInterface,
228                        GetBridgeInterface().c_str());
229  }
230
231  // Channel.
232  base::StringAppendF(
233      config_str, "%s=%d\n", kHostapdConfigKeyChannel, GetChannel());
234
235  // Interface.
236  if (!AppendInterface(error, config_str)) {
237    return false;
238  }
239
240  // Hardware mode.
241  if (!AppendHwMode(error, config_str)) {
242    return false;
243  }
244
245  // Security mode configurations.
246  if (!AppendSecurityMode(error, config_str)) {
247    return false;
248  }
249
250  // Control interface.
251  if (!control_interface_.empty()) {
252    base::StringAppendF(config_str,
253                        "%s=%s\n",
254                        kHostapdConfigKeyControlInterface,
255                        control_interface_.c_str());
256    base::StringAppendF(config_str,
257                        "%s=%s\n",
258                        kHostapdConfigKeyControlInterfaceGroup,
259                        Daemon::kAPManagerGroupName);
260  }
261
262  // Hostapd default configurations.
263  if (!AppendHostapdDefaults(error, config_str)) {
264    return false;
265  }
266
267  return true;
268}
269
270bool Config::ClaimDevice() {
271  if (!device_) {
272    LOG(ERROR) << "Failed to claim device: device doesn't exist.";
273    return false;
274  }
275  return device_->ClaimDevice(GetFullDeviceControl());
276}
277
278bool Config::ReleaseDevice() {
279  if (!device_) {
280    LOG(ERROR) << "Failed to release device: device doesn't exist.";
281    return false;
282  }
283  return device_->ReleaseDevice();
284}
285
286void Config::SetSsid(const string& ssid) {
287  adaptor_->SetSsid(ssid);
288}
289
290string Config::GetSsid() const {
291  return adaptor_->GetSsid();
292}
293
294void Config::SetInterfaceName(const std::string& interface_name) {
295  adaptor_->SetInterfaceName(interface_name);
296}
297
298string Config::GetInterfaceName() const {
299  return adaptor_->GetInterfaceName();
300}
301
302void Config::SetSecurityMode(const std::string& mode) {
303  adaptor_->SetSecurityMode(mode);
304}
305
306string Config::GetSecurityMode() const {
307  return adaptor_->GetSecurityMode();
308}
309
310void Config::SetPassphrase(const std::string& passphrase) {
311  adaptor_->SetPassphrase(passphrase);
312}
313
314string Config::GetPassphrase() const {
315  return adaptor_->GetPassphrase();
316}
317
318void Config::SetHwMode(const std::string& hw_mode) {
319  adaptor_->SetHwMode(hw_mode);
320}
321
322string Config::GetHwMode() const {
323  return adaptor_->GetHwMode();
324}
325
326void Config::SetOperationMode(const std::string& op_mode) {
327  adaptor_->SetOperationMode(op_mode);
328}
329
330string Config::GetOperationMode() const {
331  return adaptor_->GetOperationMode();
332}
333
334void Config::SetChannel(uint16_t channel) {
335  adaptor_->SetChannel(channel);
336}
337
338uint16_t Config::GetChannel() const {
339  return adaptor_->GetChannel();
340}
341
342void Config::SetHiddenNetwork(bool hidden_network) {
343  adaptor_->SetHiddenNetwork(hidden_network);
344}
345
346bool Config::GetHiddenNetwork() const {
347  return adaptor_->GetHiddenNetwork();
348}
349
350void Config::SetBridgeInterface(const std::string& interface_name) {
351  adaptor_->SetBridgeInterface(interface_name);
352}
353
354string Config::GetBridgeInterface() const {
355  return adaptor_->GetBridgeInterface();
356}
357
358void Config::SetServerAddressIndex(uint16_t index) {
359  adaptor_->SetServerAddressIndex(index);
360}
361
362uint16_t Config::GetServerAddressIndex() const {
363  return adaptor_->GetServerAddressIndex();
364}
365
366void Config::SetFullDeviceControl(bool full_control) {
367  adaptor_->SetFullDeviceControl(full_control);
368}
369
370bool Config::GetFullDeviceControl() const {
371  return adaptor_->GetFullDeviceControl();
372}
373
374bool Config::AppendHwMode(Error* error, string* config_str) {
375  string hw_mode = GetHwMode();
376  string hostapd_hw_mode;
377  if (hw_mode == kHwMode80211a) {
378    hostapd_hw_mode = kHostapdHwMode80211a;
379  } else if (hw_mode == kHwMode80211b) {
380    hostapd_hw_mode = kHostapdHwMode80211b;
381  } else if (hw_mode == kHwMode80211g) {
382    hostapd_hw_mode = kHostapdHwMode80211g;
383  } else if (hw_mode == kHwMode80211n) {
384    // Use 802.11a for 5GHz channel and 802.11g for 2.4GHz channel
385    if (GetChannel() >= 34) {
386      hostapd_hw_mode = kHostapdHwMode80211a;
387    } else {
388      hostapd_hw_mode = kHostapdHwMode80211g;
389    }
390    base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211n);
391
392    // Get HT Capability.
393    string ht_cap;
394    if (!device_->GetHTCapability(GetChannel(), &ht_cap)) {
395      Error::PopulateAndLog(error,
396                            Error::kInvalidConfiguration,
397                            "Failed to get HT Capability",
398                            FROM_HERE);
399      return false;
400    }
401    base::StringAppendF(config_str, "%s=%s\n",
402                        kHostapdConfigKeyHTCapability,
403                        ht_cap.c_str());
404  } else if (hw_mode == kHwMode80211ac) {
405    if (GetChannel() >= 34) {
406      hostapd_hw_mode = kHostapdHwMode80211a;
407    } else {
408      hostapd_hw_mode = kHostapdHwMode80211g;
409    }
410    base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211ac);
411
412    // TODO(zqiu): Determine VHT Capabilities based on the interface PHY's
413    // capababilites.
414  } else {
415    Error::PopulateAndLog(
416        error,
417        Error::kInvalidConfiguration,
418        base::StringPrintf("Invalid hardware mode: %s", hw_mode.c_str()),
419        FROM_HERE);
420    return false;
421  }
422
423  base::StringAppendF(
424      config_str, "%s=%s\n", kHostapdConfigKeyHwMode, hostapd_hw_mode.c_str());
425  return true;
426}
427
428bool Config::AppendHostapdDefaults(Error* error, string* config_str) {
429  // Driver: NL80211.
430  base::StringAppendF(
431      config_str, "%s=%s\n", kHostapdConfigKeyDriver, kHostapdDefaultDriver);
432
433  // Fragmentation threshold: disabled.
434  base::StringAppendF(config_str,
435                      "%s=%d\n",
436                      kHostapdConfigKeyFragmThreshold,
437                      kHostapdDefaultFragmThreshold);
438
439  // RTS threshold: disabled.
440  base::StringAppendF(config_str,
441                      "%s=%d\n",
442                      kHostapdConfigKeyRtsThreshold,
443                      kHostapdDefaultRtsThreshold);
444
445  return true;
446}
447
448bool Config::AppendInterface(Error* error, string* config_str) {
449  string interface = GetInterfaceName();
450  if (interface.empty()) {
451    // Ask manager for unused ap capable device.
452    device_ = manager_->GetAvailableDevice();
453    if (!device_) {
454      Error::PopulateAndLog(
455          error, Error::kInternalError, "No device available", FROM_HERE);
456      return false;
457    }
458  } else {
459    device_ = manager_->GetDeviceFromInterfaceName(interface);
460    if (!device_) {
461      Error::PopulateAndLog(
462          error,
463          Error::kInvalidConfiguration,
464          base::StringPrintf(
465              "Unable to find device for the specified interface [%s]",
466              interface.c_str()),
467          FROM_HERE);
468      return false;
469    }
470    if (device_->GetInUse()) {
471      Error::PopulateAndLog(
472          error,
473          Error::kInvalidConfiguration,
474          base::StringPrintf("Device [%s] for interface [%s] already in use",
475                             device_->GetDeviceName().c_str(),
476                             interface.c_str()),
477          FROM_HERE);
478      return false;
479    }
480  }
481
482  // Use the preferred AP interface from the device.
483  selected_interface_ = device_->GetPreferredApInterface();
484  base::StringAppendF(config_str,
485                      "%s=%s\n",
486                      kHostapdConfigKeyInterface,
487                      selected_interface_.c_str());
488  return true;
489}
490
491bool Config::AppendSecurityMode(Error* error, string* config_str) {
492  string security_mode = GetSecurityMode();
493  if (security_mode == kSecurityModeNone) {
494    // Nothing need to be done for open network.
495    return true;
496  }
497
498  if (security_mode == kSecurityModeRSN) {
499    string passphrase = GetPassphrase();
500    if (passphrase.empty()) {
501      Error::PopulateAndLog(
502          error,
503          Error::kInvalidConfiguration,
504          base::StringPrintf("Passphrase not set for security mode: %s",
505                             security_mode.c_str()),
506          FROM_HERE);
507      return false;
508    }
509
510    base::StringAppendF(config_str, "%s=2\n", kHostapdConfigKeyWpa);
511    base::StringAppendF(config_str,
512                        "%s=%s\n",
513                        kHostapdConfigKeyRsnPairwise,
514                        kHostapdDefaultRsnPairwise);
515    base::StringAppendF(config_str,
516                        "%s=%s\n",
517                        kHostapdConfigKeyWpaKeyMgmt,
518                        kHostapdDefaultWpaKeyMgmt);
519    base::StringAppendF(config_str,
520                        "%s=%s\n",
521                        kHostapdConfigKeyWpaPassphrase,
522                        passphrase.c_str());
523    return true;
524  }
525
526  Error::PopulateAndLog(
527      error,
528      Error::kInvalidConfiguration,
529      base::StringPrintf("Invalid security mode: %s", security_mode.c_str()),
530      FROM_HERE);
531  return false;
532}
533
534}  // namespace apmanager
535