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 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 64 ApInterfaceImpl::~ApInterfaceImpl() { 65 binder_->NotifyImplDead(); 66 if_tool_->SetUpState(interface_name_.c_str(), false); 67 netlink_utils_->UnsubscribeStationEvent(interface_index_); 68 } 69 70 sp<IApInterface> ApInterfaceImpl::GetBinder() const { 71 return binder_; 72 } 73 74 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 83 bool ApInterfaceImpl::StartHostapd() { 84 return hostapd_manager_->StartHostapd(); 85 } 86 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 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 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 148 int ApInterfaceImpl::GetNumberOfAssociatedStations() const { 149 return number_of_associated_stations_; 150 } 151 152 } // namespace wificond 153 } // namespace android 154