1 //
2 // Copyright (C) 2015 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 "shill/wifi/tdls_manager.h"
18 
19 #include <base/bind.h>
20 #if defined(__ANDROID__)
21 #include <dbus/service_constants.h>
22 #else
23 #include <chromeos/dbus/service_constants.h>
24 #endif  // __ANDROID__
25 
26 #include "shill/error.h"
27 #include "shill/event_dispatcher.h"
28 #include "shill/logging.h"
29 #include "shill/supplicant/supplicant_interface_proxy_interface.h"
30 #include "shill/supplicant/wpa_supplicant.h"
31 
32 using base::Bind;
33 using std::string;
34 
35 namespace shill {
36 
37 namespace Logging {
38 static auto kModuleLogScope = ScopeLogger::kWiFi;
ObjectID(const TDLSManager * c)39 static string ObjectID(const TDLSManager* c) {
40   return "(" + c->interface_name() + "-tdlsmanager)";
41 }
42 }
43 
44 const int TDLSManager::kPeerDiscoveryCleanupTimeoutSeconds = 30;
45 
TDLSManager(EventDispatcher * dispatcher,SupplicantInterfaceProxyInterface * supplicant_interface_proxy,const string & interface_name)46 TDLSManager::TDLSManager(
47     EventDispatcher* dispatcher,
48     SupplicantInterfaceProxyInterface* supplicant_interface_proxy,
49     const string& interface_name)
50     : dispatcher_(dispatcher),
51       supplicant_interface_proxy_(supplicant_interface_proxy),
52       interface_name_(interface_name) {}
53 
~TDLSManager()54 TDLSManager::~TDLSManager() {}
55 
PerformOperation(const string & peer_mac_address,const string & operation,Error * error)56 string TDLSManager::PerformOperation(const string& peer_mac_address,
57                                      const string& operation,
58                                      Error* error) {
59   CHECK(supplicant_interface_proxy_);
60 
61   SLOG(this, 2) << "Processing TDLS command: " << operation
62                 << " for peer " << peer_mac_address;
63 
64   bool success = false;
65   if (operation == kTDLSDiscoverOperation) {
66     success = DiscoverPeer(peer_mac_address);
67   } else if (operation == kTDLSSetupOperation) {
68     success = SetupPeer(peer_mac_address);
69   } else if (operation == kTDLSStatusOperation) {
70     string supplicant_status = PeerStatus(peer_mac_address);
71     SLOG(this, 2) << "TDLS status returned: " << supplicant_status;
72     if (!supplicant_status.empty()) {
73       if (supplicant_status == WPASupplicant::kTDLSStateConnected) {
74         return kTDLSConnectedState;
75       } else if (supplicant_status == WPASupplicant::kTDLSStateDisabled) {
76         return kTDLSDisabledState;
77       } else if (supplicant_status ==
78                  WPASupplicant::kTDLSStatePeerDoesNotExist) {
79         if (CheckDiscoveryState(peer_mac_address) ==
80             PeerDiscoveryState::kResponseReceived) {
81           return kTDLSDisconnectedState;
82         } else {
83           return kTDLSNonexistentState;
84         }
85       } else if (supplicant_status ==
86                  WPASupplicant::kTDLSStatePeerNotConnected) {
87         return kTDLSDisconnectedState;
88       } else {
89         return kTDLSUnknownState;
90       }
91     }
92   } else if (operation == kTDLSTeardownOperation) {
93     success = TearDownPeer(peer_mac_address);
94   } else {
95     error->Populate(Error::kInvalidArguments, "Unknown operation");
96     return "";
97   }
98 
99   if (!success) {
100     Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
101                           "TDLS operation failed");
102   }
103 
104   return "";
105 }
106 
OnDiscoverResponseReceived(const string & peer_mac_address)107 void TDLSManager::OnDiscoverResponseReceived(const string& peer_mac_address) {
108   if (CheckDiscoveryState(peer_mac_address) ==
109       PeerDiscoveryState::kRequestSent) {
110     peer_discovery_state_[peer_mac_address] =
111         PeerDiscoveryState::kResponseReceived;
112   }
113 }
114 
DiscoverPeer(const string & peer_mac_address)115 bool TDLSManager::DiscoverPeer(const string& peer_mac_address) {
116   if (!supplicant_interface_proxy_->TDLSDiscover(peer_mac_address)) {
117     LOG(ERROR) << "Failed to perform TDLS discover";
118     return false;
119   }
120   peer_discovery_state_[peer_mac_address] = PeerDiscoveryState::kRequestSent;
121   StartPeerDiscoveryCleanupTimer();
122   return true;
123 }
124 
SetupPeer(const string & peer_mac_address)125 bool TDLSManager::SetupPeer(const string& peer_mac_address) {
126   if (!supplicant_interface_proxy_->TDLSSetup(peer_mac_address)) {
127     LOG(ERROR) << "Failed to perform TDLS setup";
128     return false;
129   }
130   return true;
131 }
132 
TearDownPeer(const string & peer_mac_address)133 bool TDLSManager::TearDownPeer(const string& peer_mac_address) {
134   if (!supplicant_interface_proxy_->TDLSTeardown(peer_mac_address)) {
135     LOG(ERROR) << "Failed to perform TDLS teardown";
136     return false;
137   }
138   return true;
139 }
140 
PeerStatus(const string & peer_mac_address)141 string TDLSManager::PeerStatus(const string& peer_mac_address) {
142   string status;
143   if (!supplicant_interface_proxy_->TDLSStatus(peer_mac_address, &status)) {
144     LOG(ERROR) << "Failed to perform TDLS status";
145     return "";
146   }
147   return status;
148 }
149 
StartPeerDiscoveryCleanupTimer()150 void TDLSManager::StartPeerDiscoveryCleanupTimer() {
151   if (!peer_discovery_cleanup_callback_.IsCancelled()) {
152     LOG(INFO) << __func__ << " TDLS cleanup timer restarted.";
153   } else {
154     LOG(INFO) << __func__ << " TDLS cleanup timer started.";
155   }
156   peer_discovery_cleanup_callback_.Reset(
157       Bind(&TDLSManager::PeerDiscoveryCleanup, base::Unretained(this)));
158   dispatcher_->PostDelayedTask(peer_discovery_cleanup_callback_.callback(),
159                                kPeerDiscoveryCleanupTimeoutSeconds * 1000);
160 }
161 
PeerDiscoveryCleanup()162 void TDLSManager::PeerDiscoveryCleanup() {
163   LOG(INFO) << __func__ << " TDLS peer discovery map cleared.";
164   peer_discovery_state_.clear();
165 }
166 
CheckDiscoveryState(const string & peer_mac_address)167 TDLSManager::PeerDiscoveryState TDLSManager::CheckDiscoveryState(
168     const string& peer_mac_address) {
169   auto iter = peer_discovery_state_.find(peer_mac_address);
170   if (iter == peer_discovery_state_.end()) {
171     return PeerDiscoveryState::kNone;
172   }
173 
174   return iter->second;
175 }
176 
177 
178 }  // namespace shill.
179