1 /*
2  * Copyright (C) 2016 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 "wificond/ap_interface_impl.h"
18 
19 #include <android-base/logging.h>
20 
21 #include "wificond/net/netlink_utils.h"
22 
23 #include "wificond/ap_interface_binder.h"
24 #include "wificond/logging_utils.h"
25 
26 using android::net::wifi::IApInterface;
27 using android::wifi_system::HostapdManager;
28 using android::wifi_system::InterfaceTool;
29 using std::endl;
30 using std::string;
31 using std::unique_ptr;
32 using std::vector;
33 
34 using EncryptionType = android::wifi_system::HostapdManager::EncryptionType;
35 
36 using namespace std::placeholders;
37 
38 namespace android {
39 namespace wificond {
40 
ApInterfaceImpl(const string & interface_name,uint32_t interface_index,NetlinkUtils * netlink_utils,InterfaceTool * if_tool,HostapdManager * hostapd_manager)41 ApInterfaceImpl::ApInterfaceImpl(const string& interface_name,
42                                  uint32_t interface_index,
43                                  NetlinkUtils* netlink_utils,
44                                  InterfaceTool* if_tool,
45                                  HostapdManager* hostapd_manager)
46     : interface_name_(interface_name),
47       interface_index_(interface_index),
48       netlink_utils_(netlink_utils),
49       if_tool_(if_tool),
50       hostapd_manager_(hostapd_manager),
51       binder_(new ApInterfaceBinder(this)),
52       number_of_associated_stations_(0) {
53   // This log keeps compiler happy.
54   LOG(DEBUG) << "Created ap interface " << interface_name_
55              << " with index " << interface_index_;
56 
57   netlink_utils_->SubscribeStationEvent(
58       interface_index_,
59       std::bind(&ApInterfaceImpl::OnStationEvent,
60                 this,
61                 _1, _2));
62 }
63 
~ApInterfaceImpl()64 ApInterfaceImpl::~ApInterfaceImpl() {
65   binder_->NotifyImplDead();
66   if_tool_->SetUpState(interface_name_.c_str(), false);
67   netlink_utils_->UnsubscribeStationEvent(interface_index_);
68 }
69 
GetBinder() const70 sp<IApInterface> ApInterfaceImpl::GetBinder() const {
71   return binder_;
72 }
73 
Dump(std::stringstream * ss) const74 void ApInterfaceImpl::Dump(std::stringstream* ss) const {
75   *ss << "------- Dump of AP interface with index: "
76       << interface_index_ << " and name: " << interface_name_
77       << "-------" << endl;
78   *ss << "Number of associated stations: "
79       <<  number_of_associated_stations_ << endl;
80   *ss << "------- Dump End -------" << endl;
81 }
82 
StartHostapd()83 bool ApInterfaceImpl::StartHostapd() {
84   return hostapd_manager_->StartHostapd();
85 }
86 
StopHostapd()87 bool ApInterfaceImpl::StopHostapd() {
88   // Drop SIGKILL on hostapd.
89   if (!hostapd_manager_->StopHostapd()) {
90     // Logging was done internally.
91     return false;
92   }
93 
94   // Take down the interface.
95   if (!if_tool_->SetUpState(interface_name_.c_str(), false)) {
96     // Logging was done internally.
97     return false;
98   }
99 
100   // Since wificond SIGKILLs hostapd, hostapd has no chance to handle
101   // the cleanup.
102   // Besides taking down the interface, we also need to set the interface mode
103   // back to station mode for the cleanup.
104   if (!netlink_utils_->SetInterfaceMode(interface_index_,
105                                         NetlinkUtils::STATION_MODE)) {
106     LOG(ERROR) << "Failed to set interface back to station mode";
107     return false;
108   }
109 
110   return true;
111 }
112 
WriteHostapdConfig(const vector<uint8_t> & ssid,bool is_hidden,int32_t channel,EncryptionType encryption_type,const vector<uint8_t> & passphrase)113 bool ApInterfaceImpl::WriteHostapdConfig(const vector<uint8_t>& ssid,
114                                          bool is_hidden,
115                                          int32_t channel,
116                                          EncryptionType encryption_type,
117                                          const vector<uint8_t>& passphrase) {
118   string config = hostapd_manager_->CreateHostapdConfig(
119       interface_name_, ssid, is_hidden, channel, encryption_type, passphrase);
120 
121   if (config.empty()) {
122     return false;
123   }
124 
125   return hostapd_manager_->WriteHostapdConfig(config);
126 }
127 
OnStationEvent(StationEvent event,const vector<uint8_t> & mac_address)128 void ApInterfaceImpl::OnStationEvent(StationEvent event,
129                                      const vector<uint8_t>& mac_address) {
130   if (event == NEW_STATION) {
131     LOG(INFO) << "New station "
132               << LoggingUtils::GetMacString(mac_address)
133               << " associated with hotspot";
134     number_of_associated_stations_++;
135   } else if (event == DEL_STATION) {
136     LOG(INFO) << "Station "
137               << LoggingUtils::GetMacString(mac_address)
138               << " disassociated from hotspot";
139     if (number_of_associated_stations_ <= 0) {
140       LOG(ERROR) << "Received DEL_STATION event when station counter is: "
141                  << number_of_associated_stations_;
142     } else {
143       number_of_associated_stations_--;
144     }
145   }
146 }
147 
GetNumberOfAssociatedStations() const148 int ApInterfaceImpl::GetNumberOfAssociatedStations() const {
149   return number_of_associated_stations_;
150 }
151 
152 }  // namespace wificond
153 }  // namespace android
154