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