399 lines
17 KiB
C++
399 lines
17 KiB
C++
//
|
|
// Copyright (C) 2012 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#ifndef SHILL_WIFI_WIFI_SERVICE_H_
|
|
#define SHILL_WIFI_WIFI_SERVICE_H_
|
|
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "shill/event_dispatcher.h"
|
|
#include "shill/key_value_store.h"
|
|
#include "shill/refptr_types.h"
|
|
#include "shill/service.h"
|
|
|
|
namespace shill {
|
|
|
|
class CertificateFile;
|
|
class ControlInterface;
|
|
class EventDispatcher;
|
|
class Error;
|
|
class Manager;
|
|
class Metrics;
|
|
class WiFiProvider;
|
|
|
|
class WiFiService : public Service {
|
|
public:
|
|
// TODO(pstew): Storage constants shouldn't need to be public
|
|
// crbug.com/208736
|
|
static const char kStorageHiddenSSID[];
|
|
static const char kStorageMode[];
|
|
static const char kStoragePassphrase[];
|
|
static const char kStorageSecurity[];
|
|
static const char kStorageSecurityClass[];
|
|
static const char kStorageSSID[];
|
|
static const char kStoragePreferredDevice[];
|
|
static const char kStorageRoamThreshold[];
|
|
static const char kStorageRoamThresholdSet[];
|
|
|
|
WiFiService(ControlInterface* control_interface,
|
|
EventDispatcher* dispatcher,
|
|
Metrics* metrics,
|
|
Manager* manager,
|
|
WiFiProvider* provider,
|
|
const std::vector<uint8_t>& ssid,
|
|
const std::string& mode,
|
|
const std::string& security,
|
|
bool hidden_ssid);
|
|
~WiFiService();
|
|
|
|
// Inherited from Service.
|
|
void Connect(Error* error, const char* reason) override;
|
|
void Disconnect(Error* error, const char* reason) override;
|
|
bool Is8021x() const override;
|
|
|
|
virtual void AddEndpoint(const WiFiEndpointConstRefPtr& endpoint);
|
|
virtual void RemoveEndpoint(const WiFiEndpointConstRefPtr& endpoint);
|
|
virtual int GetEndpointCount() const { return endpoints_.size(); }
|
|
|
|
// Called to update the identity of the currently connected endpoint.
|
|
// To indicate that there is no currently connect endpoint, call with
|
|
// |endpoint| set to nullptr.
|
|
virtual void NotifyCurrentEndpoint(const WiFiEndpointConstRefPtr& endpoint);
|
|
// Called to inform of changes in the properties of an endpoint.
|
|
// (Not necessarily the currently connected endpoint.)
|
|
virtual void NotifyEndpointUpdated(const WiFiEndpointConstRefPtr& endpoint);
|
|
|
|
// wifi_<MAC>_<BSSID>_<mode_string>_<security_string>
|
|
std::string GetStorageIdentifier() const override;
|
|
static bool ParseStorageIdentifier(const std::string& storage_name,
|
|
std::string* address,
|
|
std::string* mode,
|
|
std::string* security);
|
|
|
|
// Iterate over |storage| looking for WiFi servces with "old-style"
|
|
// properties that don't include explicit type/mode/security, and add
|
|
// these properties. Returns true if any entries were fixed.
|
|
static bool FixupServiceEntries(StoreInterface* storage);
|
|
|
|
// Validate |mode| against all valid and supported service modes.
|
|
static bool IsValidMode(const std::string& mode);
|
|
|
|
// Validate |method| against all valid and supported security methods.
|
|
static bool IsValidSecurityMethod(const std::string& method);
|
|
|
|
// Validate |security_class| against all valid and supported
|
|
// security classes.
|
|
static bool IsValidSecurityClass(const std::string& security_class);
|
|
|
|
const std::string& mode() const { return mode_; }
|
|
const std::string& key_management() const { return GetEAPKeyManagement(); }
|
|
const std::vector<uint8_t>& ssid() const { return ssid_; }
|
|
const std::string& bssid() const { return bssid_; }
|
|
const std::vector<uint16_t>& frequency_list() const {
|
|
return frequency_list_;
|
|
}
|
|
uint16_t physical_mode() const { return physical_mode_; }
|
|
uint16_t frequency() const { return frequency_; }
|
|
|
|
// WiFi services can load from profile entries other than their current
|
|
// storage identifier. Override the methods from the parent Service
|
|
// class which pertain to whether this service may be loaded from |storage|.
|
|
std::string GetLoadableStorageIdentifier(
|
|
const StoreInterface& storage) const override;
|
|
bool IsLoadableFrom(const StoreInterface& storage) const override;
|
|
|
|
// Override Load and Save from parent Service class. We will call
|
|
// the parent method.
|
|
bool Load(StoreInterface* storage) override;
|
|
bool Save(StoreInterface* storage) override;
|
|
bool Unload() override;
|
|
|
|
// Override SetState from parent Service class. We will call the
|
|
// parent method.
|
|
void SetState(ConnectState state) override;
|
|
|
|
virtual bool HasEndpoints() const { return !endpoints_.empty(); }
|
|
bool IsVisible() const override;
|
|
bool IsSecurityMatch(const std::string& security) const;
|
|
|
|
// Used by WiFi objects to indicate that the credentials for this network
|
|
// have been called into question. This method returns true if given this
|
|
// suspicion, if it is probable that indeed these credentials are likely
|
|
// to be incorrect. Credentials that have never been used before are
|
|
// considered suspect by default, while those which have been used
|
|
// successfully in the past must have this method called a number of times
|
|
// since the last time ResetSuspectedCredentialsFailures() was called.
|
|
virtual bool AddSuspectedCredentialFailure();
|
|
virtual void ResetSuspectedCredentialFailures();
|
|
|
|
bool hidden_ssid() const { return hidden_ssid_; }
|
|
bool ieee80211w_required() const { return ieee80211w_required_; }
|
|
|
|
void InitializeCustomMetrics() const;
|
|
void SendPostReadyStateMetrics(
|
|
int64_t time_resume_to_ready_milliseconds) const override;
|
|
|
|
// Clear any cached credentials stored in wpa_supplicant related to |this|.
|
|
// This will disconnect this service if it is currently connected.
|
|
void ClearCachedCredentials();
|
|
|
|
// Override from parent Service class to correctly update connectability
|
|
// when the EAP credentials change for 802.1x networks.
|
|
void OnEapCredentialsChanged(
|
|
Service::UpdateCredentialsReason reason) override;
|
|
|
|
// Called by WiFiService to reset state associated with prior success
|
|
// of a connection with particular EAP credentials or a passphrase.
|
|
void OnCredentialChange(Service::UpdateCredentialsReason reason);
|
|
|
|
// Override from parent Service class to register hidden services once they
|
|
// have been configured.
|
|
void OnProfileConfigured() override;
|
|
|
|
// Called by WiFiProvider to reset the WiFi device reference on shutdown.
|
|
virtual void ResetWiFi();
|
|
|
|
// Called by WiFi to retrieve configuration parameters for wpa_supplicant.
|
|
virtual KeyValueStore GetSupplicantConfigurationParameters() const;
|
|
|
|
// "wpa", "rsn" and "psk" are equivalent from a configuration perspective.
|
|
// This function maps them all into "psk".
|
|
static std::string ComputeSecurityClass(const std::string& security);
|
|
|
|
bool IsAutoConnectable(const char** reason) const override;
|
|
|
|
// Signal level in dBm. If no current endpoint, returns
|
|
// std::numeric_limits<int>::min().
|
|
int16_t SignalLevel() const;
|
|
|
|
void set_expecting_disconnect(bool val) { expecting_disconnect_ = val; }
|
|
bool expecting_disconnect() const { return expecting_disconnect_; }
|
|
|
|
uint16_t roam_threshold_db() { return roam_threshold_db_; }
|
|
bool roam_threshold_db_set() { return roam_threshold_db_set_; }
|
|
|
|
protected:
|
|
void SetEAPKeyManagement(const std::string& key_management) override;
|
|
std::string GetTethering(Error* error) const override;
|
|
|
|
private:
|
|
friend class WiFiServiceSecurityTest;
|
|
friend class WiFiServiceTest; // SetPassphrase
|
|
friend class WiFiServiceUpdateFromEndpointsTest; // SignalToStrength
|
|
FRIEND_TEST(MetricsTest, WiFiServicePostReady);
|
|
FRIEND_TEST(MetricsTest, WiFiServicePostReadyAdHoc);
|
|
FRIEND_TEST(MetricsTest, WiFiServicePostReadyEAP);
|
|
FRIEND_TEST(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint);
|
|
FRIEND_TEST(WiFiMainTest, RoamThresholdProperty);
|
|
FRIEND_TEST(WiFiProviderTest, OnEndpointAddedWithSecurity); // security_
|
|
FRIEND_TEST(WiFiServiceTest, AutoConnect);
|
|
FRIEND_TEST(WiFiServiceTest, ClearWriteOnlyDerivedProperty); // passphrase_
|
|
FRIEND_TEST(WiFiServiceTest, ComputeCipher8021x);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTask8021x);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTaskDynamicWEP);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTaskPSK);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTaskRSN);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTaskWEP);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTaskWPA);
|
|
FRIEND_TEST(WiFiServiceTest, ConnectTaskWPA80211w);
|
|
FRIEND_TEST(WiFiServiceTest, GetTethering);
|
|
FRIEND_TEST(WiFiServiceTest, IsAutoConnectable);
|
|
FRIEND_TEST(WiFiServiceTest, LoadHidden);
|
|
FRIEND_TEST(WiFiServiceTest, SetPassphraseForNonPassphraseService);
|
|
FRIEND_TEST(WiFiServiceTest, LoadAndUnloadPassphrase);
|
|
FRIEND_TEST(WiFiServiceTest, LoadPassphraseClearCredentials);
|
|
FRIEND_TEST(WiFiServiceTest, SecurityFromCurrentEndpoint); // GetSecurity
|
|
FRIEND_TEST(WiFiServiceTest, SetPassphraseResetHasEverConnected);
|
|
FRIEND_TEST(WiFiServiceTest, SetPassphraseRemovesCachedCredentials);
|
|
FRIEND_TEST(WiFiServiceTest, SignalToStrength); // SignalToStrength
|
|
FRIEND_TEST(WiFiServiceTest, SuspectedCredentialFailure);
|
|
FRIEND_TEST(WiFiServiceTest, UpdateSecurity); // SetEAPKeyManagement
|
|
FRIEND_TEST(WiFiServiceTest, ConnectWithPreferredDevice);
|
|
FRIEND_TEST(WiFiServiceTest, ConfigurePreferredDevice);
|
|
FRIEND_TEST(WiFiServiceTest, LoadAndUnloadPreferredDevice);
|
|
FRIEND_TEST(WiFiServiceTest, ChooseDevice);
|
|
FRIEND_TEST(WiFiServiceUpdateFromEndpointsTest,
|
|
AddEndpointWithPreferredDevice);
|
|
FRIEND_TEST(WiFiServiceTest, SaveLoadRoamThreshold);
|
|
|
|
static const char kAutoConnNoEndpoint[];
|
|
static const char kAnyDeviceAddress[];
|
|
static const int kSuspectedCredentialFailureThreshold;
|
|
|
|
// Override the base clase implementation, because we need to allow
|
|
// arguments that aren't base class methods.
|
|
void HelpRegisterConstDerivedString(
|
|
const std::string& name,
|
|
std::string(WiFiService::*get)(Error* error));
|
|
void HelpRegisterDerivedString(
|
|
const std::string& name,
|
|
std::string(WiFiService::*get)(Error* error),
|
|
bool(WiFiService::*set)(const std::string& value, Error* error));
|
|
void HelpRegisterWriteOnlyDerivedString(
|
|
const std::string& name,
|
|
bool(WiFiService::*set)(const std::string& value, Error* error),
|
|
void(WiFiService::*clear)(Error* error),
|
|
const std::string* default_value);
|
|
void HelpRegisterDerivedUint16(
|
|
const std::string& name,
|
|
uint16_t(WiFiService::*get)(Error* error),
|
|
bool(WiFiService::*set)(const uint16_t& value, Error* error),
|
|
void(WiFiService::*clear)(Error* error));
|
|
|
|
std::string GetDeviceRpcId(Error* error) const override;
|
|
|
|
void ClearPassphrase(Error* error);
|
|
void UpdateConnectable();
|
|
void UpdateFromEndpoints();
|
|
void UpdateSecurity();
|
|
|
|
static CryptoAlgorithm ComputeCipher8021x(
|
|
const std::set<WiFiEndpointConstRefPtr>& endpoints);
|
|
static void ValidateWEPPassphrase(const std::string& passphrase,
|
|
Error* error);
|
|
static void ValidateWPAPassphrase(const std::string& passphrase,
|
|
Error* error);
|
|
static void ParseWEPPassphrase(const std::string& passphrase,
|
|
int* key_index,
|
|
std::vector<uint8_t>* password_bytes,
|
|
Error* error);
|
|
static bool CheckWEPIsHex(const std::string& passphrase, Error* error);
|
|
static bool CheckWEPKeyIndex(const std::string& passphrase, Error* error);
|
|
static bool CheckWEPPrefix(const std::string& passphrase, Error* error);
|
|
|
|
// Maps a signal value, in dBm, to a "strength" value, from
|
|
// |Service::kStrengthMin| to |Service:kStrengthMax|.
|
|
static uint8_t SignalToStrength(int16_t signal_dbm);
|
|
|
|
// Create a default group name for this WiFi service.
|
|
std::string GetDefaultStorageIdentifier() const;
|
|
|
|
// Return the security of this service. If connected, the security
|
|
// reported from the currently connected endpoint is returned. Otherwise
|
|
// the configured security for the service is returned.
|
|
std::string GetSecurity(Error* error);
|
|
|
|
// Return the security class of this service. If connected, the
|
|
// security class of the currently connected endpoint is returned.
|
|
// Otherwise the configured security class for the service is
|
|
// returned.
|
|
//
|
|
// See also: ComputeSecurityClass.
|
|
std::string GetSecurityClass(Error* error);
|
|
|
|
// Profile data for a WPA/RSN service can be stored under a number of
|
|
// different security types. These functions create different storage
|
|
// property lists based on whether they are saved with their generic
|
|
// "psk" name or if they use the (legacy) specific "wpa" or "rsn" names.
|
|
KeyValueStore GetStorageProperties() const;
|
|
|
|
// Called from DBus and during Load to validate and apply a passphrase for
|
|
// this service. If the passphrase is successfully changed, UpdateConnectable
|
|
// and OnCredentialChange are both called and the method returns true. This
|
|
// method will return false if the passphrase cannot be set. If the
|
|
// passphrase is already set to the value of |passphrase|, this method will
|
|
// return false. If it is due to an error, |error| will be populated with the
|
|
// appropriate information.
|
|
bool SetPassphrase(const std::string& passphrase, Error* error);
|
|
|
|
// Called by SetPassphrase and LoadPassphrase to perform the check on a
|
|
// passphrase change. |passphrase| is the new passphrase to be used for the
|
|
// service. If the new passphrase is not different from the existing
|
|
// passphrase, SetPassphraseInternal will return false. |reason| signals how
|
|
// the SetPassphraseInternal method was triggered. If the method was called
|
|
// from Load, the has_ever_connected flag will not be reset. If the method
|
|
// was called from SetPassphrase, has_ever_connected will be set to false.
|
|
bool SetPassphraseInternal(const std::string& passphrase,
|
|
Service::UpdateCredentialsReason reason);
|
|
|
|
// Select a WiFi device (e.g, for connecting a hidden service with no
|
|
// endpoints).
|
|
WiFiRefPtr ChooseDevice();
|
|
|
|
std::string GetPreferredDevice(Error* error);
|
|
// Called from DBus and during load to apply the preferred device for this
|
|
// service.
|
|
bool SetPreferredDevice(const std::string& device_name, Error* error);
|
|
|
|
void SetWiFi(const WiFiRefPtr& new_wifi);
|
|
|
|
// This method can't be 'const' because it is passed to
|
|
// HelpRegisterDerivedUint16, which doesn't take const methods.
|
|
uint16_t GetRoamThreshold(Error* error) /*const*/;
|
|
bool SetRoamThreshold(const uint16_t& threshold, Error* error);
|
|
void ClearRoamThreshold(Error* error);
|
|
|
|
// Properties
|
|
std::string passphrase_;
|
|
bool need_passphrase_;
|
|
const std::string security_;
|
|
// TODO(cmasone): see if the below can be pulled from the endpoint associated
|
|
// with this service instead.
|
|
const std::string mode_;
|
|
std::string auth_mode_;
|
|
bool hidden_ssid_;
|
|
uint16_t frequency_;
|
|
std::vector<uint16_t> frequency_list_;
|
|
uint16_t physical_mode_;
|
|
// Preferred device to use for connecting to this service.
|
|
std::string preferred_device_;
|
|
// The raw dBm signal strength from the associated endpoint.
|
|
int16_t raw_signal_strength_;
|
|
std::string hex_ssid_;
|
|
std::string storage_identifier_;
|
|
std::string bssid_;
|
|
Stringmap vendor_information_;
|
|
// The country code reported by the current endpoint.
|
|
std::string country_code_;
|
|
// If |security_| == kSecurity8021x, the crypto algorithm being used.
|
|
// (Otherwise, crypto algorithm is implied by |security_|.)
|
|
CryptoAlgorithm cipher_8021x_;
|
|
|
|
// Track the number of consecutive times our current credentials have
|
|
// been called into question.
|
|
int suspected_credential_failures_;
|
|
|
|
// Track whether or not we've warned about large signal values.
|
|
// Used to avoid spamming the log.
|
|
static bool logged_signal_warning;
|
|
|
|
WiFiRefPtr wifi_;
|
|
std::set<WiFiEndpointConstRefPtr> endpoints_;
|
|
WiFiEndpointConstRefPtr current_endpoint_;
|
|
const std::vector<uint8_t> ssid_;
|
|
// Track whether IEEE 802.11w (Protected Management Frame) support is
|
|
// mandated by one or more endpoints we have seen that provide this service.
|
|
bool ieee80211w_required_;
|
|
// Flag indicating if service disconnect is initiated by user for
|
|
// connecting to other service.
|
|
bool expecting_disconnect_;
|
|
std::unique_ptr<CertificateFile> certificate_file_;
|
|
uint16_t roam_threshold_db_;
|
|
bool roam_threshold_db_set_;
|
|
// Bare pointer is safe because WiFi service instances are owned by
|
|
// the WiFiProvider and are guaranteed to be deallocated by the time
|
|
// the WiFiProvider is.
|
|
WiFiProvider* provider_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(WiFiService);
|
|
};
|
|
|
|
} // namespace shill
|
|
|
|
#endif // SHILL_WIFI_WIFI_SERVICE_H_
|