/* * Copyright (C) 2016 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. */ #include "wificond/ap_interface_impl.h" #include #include "wificond/net/netlink_utils.h" #include "wificond/ap_interface_binder.h" #include "wificond/logging_utils.h" using android::net::wifi::IApInterface; using android::wifi_system::HostapdManager; using android::wifi_system::InterfaceTool; using std::endl; using std::string; using std::unique_ptr; using std::vector; using EncryptionType = android::wifi_system::HostapdManager::EncryptionType; using namespace std::placeholders; namespace android { namespace wificond { ApInterfaceImpl::ApInterfaceImpl(const string& interface_name, uint32_t interface_index, NetlinkUtils* netlink_utils, InterfaceTool* if_tool, HostapdManager* hostapd_manager) : interface_name_(interface_name), interface_index_(interface_index), netlink_utils_(netlink_utils), if_tool_(if_tool), hostapd_manager_(hostapd_manager), binder_(new ApInterfaceBinder(this)), number_of_associated_stations_(0) { // This log keeps compiler happy. LOG(DEBUG) << "Created ap interface " << interface_name_ << " with index " << interface_index_; netlink_utils_->SubscribeStationEvent( interface_index_, std::bind(&ApInterfaceImpl::OnStationEvent, this, _1, _2)); } ApInterfaceImpl::~ApInterfaceImpl() { binder_->NotifyImplDead(); if_tool_->SetUpState(interface_name_.c_str(), false); netlink_utils_->UnsubscribeStationEvent(interface_index_); } sp ApInterfaceImpl::GetBinder() const { return binder_; } void ApInterfaceImpl::Dump(std::stringstream* ss) const { *ss << "------- Dump of AP interface with index: " << interface_index_ << " and name: " << interface_name_ << "-------" << endl; *ss << "Number of associated stations: " << number_of_associated_stations_ << endl; *ss << "------- Dump End -------" << endl; } bool ApInterfaceImpl::StartHostapd() { return hostapd_manager_->StartHostapd(); } bool ApInterfaceImpl::StopHostapd() { // Drop SIGKILL on hostapd. if (!hostapd_manager_->StopHostapd()) { // Logging was done internally. return false; } // Take down the interface. if (!if_tool_->SetUpState(interface_name_.c_str(), false)) { // Logging was done internally. return false; } // Since wificond SIGKILLs hostapd, hostapd has no chance to handle // the cleanup. // Besides taking down the interface, we also need to set the interface mode // back to station mode for the cleanup. if (!netlink_utils_->SetInterfaceMode(interface_index_, NetlinkUtils::STATION_MODE)) { LOG(ERROR) << "Failed to set interface back to station mode"; return false; } return true; } bool ApInterfaceImpl::WriteHostapdConfig(const vector& ssid, bool is_hidden, int32_t channel, EncryptionType encryption_type, const vector& passphrase) { string config = hostapd_manager_->CreateHostapdConfig( interface_name_, ssid, is_hidden, channel, encryption_type, passphrase); if (config.empty()) { return false; } return hostapd_manager_->WriteHostapdConfig(config); } void ApInterfaceImpl::OnStationEvent(StationEvent event, const vector& mac_address) { if (event == NEW_STATION) { LOG(INFO) << "New station " << LoggingUtils::GetMacString(mac_address) << " associated with hotspot"; number_of_associated_stations_++; } else if (event == DEL_STATION) { LOG(INFO) << "Station " << LoggingUtils::GetMacString(mac_address) << " disassociated from hotspot"; if (number_of_associated_stations_ <= 0) { LOG(ERROR) << "Received DEL_STATION event when station counter is: " << number_of_associated_stations_; } else { number_of_associated_stations_--; } } } int ApInterfaceImpl::GetNumberOfAssociatedStations() const { return number_of_associated_stations_; } } // namespace wificond } // namespace android