2467 lines
74 KiB
C++
2467 lines
74 KiB
C++
/*
|
|
* WPA Supplicant - Manager for Aidl interface objects
|
|
* Copyright (c) 2021, Google Inc. All rights reserved.
|
|
*
|
|
* This software may be distributed under the terms of the BSD license.
|
|
* See README for more details.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <regex>
|
|
|
|
#include "aidl_manager.h"
|
|
#include "misc_utils.h"
|
|
#include <android/binder_process.h>
|
|
#include <android/binder_manager.h>
|
|
#include <aidl/android/hardware/wifi/supplicant/IpVersion.h>
|
|
|
|
extern "C" {
|
|
#include "scan.h"
|
|
#include "src/eap_common/eap_sim_common.h"
|
|
#include "list.h"
|
|
}
|
|
|
|
namespace {
|
|
|
|
constexpr uint8_t kWfdDeviceInfoLen = 6;
|
|
constexpr uint8_t kWfdR2DeviceInfoLen = 2;
|
|
// GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
|
|
constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
|
|
constexpr char kGsmAuthRegex3[] =
|
|
"GSM-AUTH:([0-9a-f]+):([0-9a-f]+):([0-9a-f]+)";
|
|
// UMTS-AUTH:<RAND>:<AUTN>
|
|
constexpr char kUmtsAuthRegex[] = "UMTS-AUTH:([0-9a-f]+):([0-9a-f]+)";
|
|
constexpr size_t kGsmRandLenBytes = GSM_RAND_LEN;
|
|
constexpr size_t kUmtsRandLenBytes = EAP_AKA_RAND_LEN;
|
|
constexpr size_t kUmtsAutnLenBytes = EAP_AKA_AUTN_LEN;
|
|
const std::vector<uint8_t> kZeroBssid = {0, 0, 0, 0, 0, 0};
|
|
|
|
using aidl::android::hardware::wifi::supplicant::GsmRand;
|
|
|
|
/**
|
|
* Check if the provided |wpa_supplicant| structure represents a P2P iface or
|
|
* not.
|
|
*/
|
|
constexpr bool isP2pIface(const struct wpa_supplicant *wpa_s)
|
|
{
|
|
return wpa_s->global->p2p_init_wpa_s == wpa_s;
|
|
}
|
|
|
|
/**
|
|
* Creates a unique key for the network using the provided |ifname| and
|
|
* |network_id| to be used in the internal map of |ISupplicantNetwork| objects.
|
|
* This is of the form |ifname|_|network_id|. For ex: "wlan0_1".
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param network_id ID of the corresponding network.
|
|
*/
|
|
const std::string getNetworkObjectMapKey(
|
|
const std::string &ifname, int network_id)
|
|
{
|
|
return ifname + "_" + std::to_string(network_id);
|
|
}
|
|
|
|
/**
|
|
* Add callback to the corresponding list after linking to death on the
|
|
* corresponding aidl object reference.
|
|
*/
|
|
template <class CallbackType>
|
|
int registerForDeathAndAddCallbackAidlObjectToList(
|
|
AIBinder_DeathRecipient* death_notifier,
|
|
const std::shared_ptr<CallbackType> &callback,
|
|
std::vector<std::shared_ptr<CallbackType>> &callback_list)
|
|
{
|
|
binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
|
|
death_notifier, nullptr /* cookie */);
|
|
if (status != STATUS_OK) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Error registering for death notification for "
|
|
"supplicant callback object");
|
|
return 1;
|
|
}
|
|
callback_list.push_back(callback);
|
|
return 0;
|
|
}
|
|
|
|
template <class ObjectType>
|
|
int addAidlObjectToMap(
|
|
const std::string &key, const std::shared_ptr<ObjectType> &object,
|
|
std::map<const std::string, std::shared_ptr<ObjectType>> &object_map)
|
|
{
|
|
// Return failure if we already have an object for that |key|.
|
|
if (object_map.find(key) != object_map.end())
|
|
return 1;
|
|
object_map[key] = object;
|
|
if (!object_map[key].get())
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
template <class ObjectType>
|
|
int removeAidlObjectFromMap(
|
|
const std::string &key,
|
|
std::map<const std::string, std::shared_ptr<ObjectType>> &object_map)
|
|
{
|
|
// Return failure if we dont have an object for that |key|.
|
|
const auto &object_iter = object_map.find(key);
|
|
if (object_iter == object_map.end())
|
|
return 1;
|
|
object_iter->second->invalidate();
|
|
object_map.erase(object_iter);
|
|
return 0;
|
|
}
|
|
|
|
template <class CallbackType>
|
|
int addIfaceCallbackAidlObjectToMap(
|
|
AIBinder_DeathRecipient* death_notifier,
|
|
const std::string &ifname, const std::shared_ptr<CallbackType> &callback,
|
|
std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
if (ifname.empty())
|
|
return 1;
|
|
|
|
auto iface_callback_map_iter = callbacks_map.find(ifname);
|
|
if (iface_callback_map_iter == callbacks_map.end())
|
|
return 1;
|
|
auto &iface_callback_list = iface_callback_map_iter->second;
|
|
|
|
// Register for death notification before we add it to our list.
|
|
return registerForDeathAndAddCallbackAidlObjectToList<CallbackType>(
|
|
death_notifier, callback, iface_callback_list);
|
|
}
|
|
|
|
template <class CallbackType>
|
|
int addNetworkCallbackAidlObjectToMap(
|
|
AIBinder_DeathRecipient* death_notifier,
|
|
const std::string &ifname, int network_id,
|
|
const std::shared_ptr<CallbackType> &callback,
|
|
std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
if (ifname.empty() || network_id < 0)
|
|
return 1;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(ifname, network_id);
|
|
auto network_callback_map_iter = callbacks_map.find(network_key);
|
|
if (network_callback_map_iter == callbacks_map.end())
|
|
return 1;
|
|
auto &network_callback_list = network_callback_map_iter->second;
|
|
|
|
// Register for death notification before we add it to our list.
|
|
return registerForDeathAndAddCallbackAidlObjectToList<CallbackType>(
|
|
death_notifier, callback, network_callback_list);
|
|
}
|
|
|
|
template <class CallbackType>
|
|
int removeAllIfaceCallbackAidlObjectsFromMap(
|
|
AIBinder_DeathRecipient* death_notifier,
|
|
const std::string &ifname,
|
|
std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
auto iface_callback_map_iter = callbacks_map.find(ifname);
|
|
if (iface_callback_map_iter == callbacks_map.end())
|
|
return 1;
|
|
const auto &iface_callback_list = iface_callback_map_iter->second;
|
|
for (const auto &callback : iface_callback_list) {
|
|
binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
|
|
death_notifier, nullptr /* cookie */);
|
|
if (status != STATUS_OK) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Error deregistering for death notification for "
|
|
"iface callback object");
|
|
}
|
|
}
|
|
callbacks_map.erase(iface_callback_map_iter);
|
|
return 0;
|
|
}
|
|
|
|
template <class CallbackType>
|
|
int removeAllNetworkCallbackAidlObjectsFromMap(
|
|
AIBinder_DeathRecipient* death_notifier,
|
|
const std::string &network_key,
|
|
std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
auto network_callback_map_iter = callbacks_map.find(network_key);
|
|
if (network_callback_map_iter == callbacks_map.end())
|
|
return 1;
|
|
const auto &network_callback_list = network_callback_map_iter->second;
|
|
for (const auto &callback : network_callback_list) {
|
|
binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
|
|
death_notifier, nullptr /* cookie */);
|
|
if (status != STATUS_OK) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Error deregistering for death "
|
|
"notification for "
|
|
"network callback object");
|
|
}
|
|
}
|
|
callbacks_map.erase(network_callback_map_iter);
|
|
return 0;
|
|
}
|
|
|
|
template <class CallbackType>
|
|
void removeIfaceCallbackAidlObjectFromMap(
|
|
const std::string &ifname, const std::shared_ptr<CallbackType> &callback,
|
|
std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
if (ifname.empty())
|
|
return;
|
|
|
|
auto iface_callback_map_iter = callbacks_map.find(ifname);
|
|
if (iface_callback_map_iter == callbacks_map.end())
|
|
return;
|
|
|
|
auto &iface_callback_list = iface_callback_map_iter->second;
|
|
iface_callback_list.erase(
|
|
std::remove(
|
|
iface_callback_list.begin(), iface_callback_list.end(),
|
|
callback),
|
|
iface_callback_list.end());
|
|
}
|
|
|
|
template <class CallbackType>
|
|
void removeNetworkCallbackAidlObjectFromMap(
|
|
const std::string &ifname, int network_id,
|
|
const std::shared_ptr<CallbackType> &callback,
|
|
std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
if (ifname.empty() || network_id < 0)
|
|
return;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(ifname, network_id);
|
|
|
|
auto network_callback_map_iter = callbacks_map.find(network_key);
|
|
if (network_callback_map_iter == callbacks_map.end())
|
|
return;
|
|
|
|
auto &network_callback_list = network_callback_map_iter->second;
|
|
network_callback_list.erase(
|
|
std::remove(
|
|
network_callback_list.begin(), network_callback_list.end(),
|
|
callback),
|
|
network_callback_list.end());
|
|
}
|
|
|
|
template <class CallbackType>
|
|
void callWithEachIfaceCallback(
|
|
const std::string &ifname,
|
|
const std::function<ndk::ScopedAStatus(std::shared_ptr<CallbackType>)> &method,
|
|
const std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
if (ifname.empty())
|
|
return;
|
|
|
|
auto iface_callback_map_iter = callbacks_map.find(ifname);
|
|
if (iface_callback_map_iter == callbacks_map.end())
|
|
return;
|
|
const auto &iface_callback_list = iface_callback_map_iter->second;
|
|
for (const auto &callback : iface_callback_list) {
|
|
if (!method(callback).isOk()) {
|
|
wpa_printf(
|
|
MSG_ERROR, "Failed to invoke AIDL iface callback");
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class CallbackType>
|
|
void callWithEachNetworkCallback(
|
|
const std::string &ifname, int network_id,
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<CallbackType>)> &method,
|
|
const std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
|
|
&callbacks_map)
|
|
{
|
|
if (ifname.empty() || network_id < 0)
|
|
return;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(ifname, network_id);
|
|
auto network_callback_map_iter = callbacks_map.find(network_key);
|
|
if (network_callback_map_iter == callbacks_map.end())
|
|
return;
|
|
const auto &network_callback_list = network_callback_map_iter->second;
|
|
for (const auto &callback : network_callback_list) {
|
|
if (!method(callback).isOk()) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to invoke AIDL network callback");
|
|
}
|
|
}
|
|
}
|
|
|
|
int parseGsmAuthNetworkRequest(
|
|
const std::string ¶ms_str,
|
|
std::vector<GsmRand> *out_rands)
|
|
{
|
|
std::smatch matches;
|
|
std::regex params_gsm_regex2(kGsmAuthRegex2);
|
|
std::regex params_gsm_regex3(kGsmAuthRegex3);
|
|
if (!std::regex_match(params_str, matches, params_gsm_regex3) &&
|
|
!std::regex_match(params_str, matches, params_gsm_regex2)) {
|
|
return 1;
|
|
}
|
|
for (uint32_t i = 1; i < matches.size(); i++) {
|
|
GsmRand rand;
|
|
rand.data = std::vector<uint8_t>(kGsmRandLenBytes);
|
|
const auto &match = matches[i];
|
|
WPA_ASSERT(match.size() >= 2 * rand.data.size());
|
|
if (hexstr2bin(match.str().c_str(), rand.data.data(), rand.data.size())) {
|
|
wpa_printf(MSG_ERROR, "Failed to parse GSM auth params");
|
|
return 1;
|
|
}
|
|
out_rands->push_back(rand);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int parseUmtsAuthNetworkRequest(
|
|
const std::string ¶ms_str,
|
|
std::vector<uint8_t> *out_rand,
|
|
std::vector<uint8_t> *out_autn)
|
|
{
|
|
std::smatch matches;
|
|
std::regex params_umts_regex(kUmtsAuthRegex);
|
|
if (!std::regex_match(params_str, matches, params_umts_regex)) {
|
|
return 1;
|
|
}
|
|
WPA_ASSERT(matches[1].size() >= 2 * out_rand->size());
|
|
if (hexstr2bin(
|
|
matches[1].str().c_str(), out_rand->data(), out_rand->size())) {
|
|
wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
|
|
return 1;
|
|
}
|
|
WPA_ASSERT(matches[2].size() >= 2 * out_autn->size());
|
|
if (hexstr2bin(
|
|
matches[2].str().c_str(), out_autn->data(), out_autn->size())) {
|
|
wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline std::vector<uint8_t> byteArrToVec(const uint8_t* arr, int len) {
|
|
return std::vector<uint8_t>{arr, arr + len};
|
|
}
|
|
|
|
inline std::vector<uint8_t> macAddrToVec(const uint8_t* mac_addr) {
|
|
return byteArrToVec(mac_addr, ETH_ALEN);
|
|
}
|
|
|
|
// Raw pointer to the global structure maintained by the core.
|
|
// Declared here to be accessible to onDeath()
|
|
struct wpa_global *wpa_global_;
|
|
|
|
void onDeath(void* cookie) {
|
|
wpa_printf(MSG_ERROR, "Client died. Terminating...");
|
|
wpa_supplicant_terminate_proc(wpa_global_);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace aidl {
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace wifi {
|
|
namespace supplicant {
|
|
|
|
AidlManager *AidlManager::instance_ = NULL;
|
|
|
|
AidlManager *AidlManager::getInstance()
|
|
{
|
|
if (!instance_)
|
|
instance_ = new AidlManager();
|
|
return instance_;
|
|
}
|
|
|
|
void AidlManager::destroyInstance()
|
|
{
|
|
if (instance_)
|
|
delete instance_;
|
|
instance_ = NULL;
|
|
}
|
|
|
|
int AidlManager::registerAidlService(struct wpa_global *global)
|
|
{
|
|
// Create the main aidl service object and register it.
|
|
wpa_printf(MSG_INFO, "Starting AIDL supplicant");
|
|
supplicant_object_ = ndk::SharedRefBase::make<Supplicant>(global);
|
|
wpa_global_ = global;
|
|
std::string instance = std::string() + Supplicant::descriptor + "/default";
|
|
if (AServiceManager_addService(supplicant_object_->asBinder().get(),
|
|
instance.c_str()) != STATUS_OK)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// Initialize the death notifier.
|
|
death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Register an interface to aidl manager.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::registerInterface(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return 1;
|
|
|
|
if (isP2pIface(wpa_s)) {
|
|
if (addAidlObjectToMap<P2pIface>(
|
|
wpa_s->ifname,
|
|
ndk::SharedRefBase::make<P2pIface>(wpa_s->global, wpa_s->ifname),
|
|
p2p_iface_object_map_)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to register P2P interface with AIDL "
|
|
"control: %s",
|
|
wpa_s->ifname);
|
|
return 1;
|
|
}
|
|
p2p_iface_callbacks_map_[wpa_s->ifname] =
|
|
std::vector<std::shared_ptr<ISupplicantP2pIfaceCallback>>();
|
|
} else {
|
|
if (addAidlObjectToMap<StaIface>(
|
|
wpa_s->ifname,
|
|
ndk::SharedRefBase::make<StaIface>(wpa_s->global, wpa_s->ifname),
|
|
sta_iface_object_map_)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to register STA interface with AIDL "
|
|
"control: %s",
|
|
wpa_s->ifname);
|
|
return 1;
|
|
}
|
|
sta_iface_callbacks_map_[wpa_s->ifname] =
|
|
std::vector<std::shared_ptr<ISupplicantStaIfaceCallback>>();
|
|
// Turn on Android specific customizations for STA interfaces
|
|
// here!
|
|
//
|
|
// Turn on scan mac randomization only if driver supports.
|
|
if (wpa_s->mac_addr_rand_supported & MAC_ADDR_RAND_SCAN) {
|
|
if (wpas_mac_addr_rand_scan_set(
|
|
wpa_s, MAC_ADDR_RAND_SCAN, nullptr, nullptr)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to enable scan mac randomization");
|
|
}
|
|
}
|
|
|
|
// Enable randomized source MAC address for GAS/ANQP
|
|
// Set the lifetime to 0, guarantees a unique address for each GAS
|
|
// session
|
|
wpa_s->conf->gas_rand_mac_addr = 1;
|
|
wpa_s->conf->gas_rand_addr_lifetime = 0;
|
|
}
|
|
|
|
// Invoke the |onInterfaceCreated| method on all registered callbacks.
|
|
callWithEachSupplicantCallback(std::bind(
|
|
&ISupplicantCallback::onInterfaceCreated, std::placeholders::_1,
|
|
misc_utils::charBufToString(wpa_s->ifname)));
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Unregister an interface from aidl manager.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::unregisterInterface(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return 1;
|
|
|
|
// Check if this interface is present in P2P map first, else check in
|
|
// STA map.
|
|
// Note: We can't use isP2pIface() here because interface
|
|
// pointers (wpa_s->global->p2p_init_wpa_s == wpa_s) used by the helper
|
|
// function is cleared by the core before notifying the AIDL interface.
|
|
bool success =
|
|
!removeAidlObjectFromMap(wpa_s->ifname, p2p_iface_object_map_);
|
|
if (success) { // assumed to be P2P
|
|
success = !removeAllIfaceCallbackAidlObjectsFromMap(
|
|
death_notifier_, wpa_s->ifname, p2p_iface_callbacks_map_);
|
|
} else { // assumed to be STA
|
|
success = !removeAidlObjectFromMap(
|
|
wpa_s->ifname, sta_iface_object_map_);
|
|
if (success) {
|
|
success = !removeAllIfaceCallbackAidlObjectsFromMap(
|
|
death_notifier_, wpa_s->ifname, sta_iface_callbacks_map_);
|
|
}
|
|
}
|
|
if (!success) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to unregister interface with AIDL "
|
|
"control: %s",
|
|
wpa_s->ifname);
|
|
return 1;
|
|
}
|
|
|
|
// Invoke the |onInterfaceRemoved| method on all registered callbacks.
|
|
callWithEachSupplicantCallback(std::bind(
|
|
&ISupplicantCallback::onInterfaceRemoved, std::placeholders::_1,
|
|
misc_utils::charBufToString(wpa_s->ifname)));
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Register a network to aidl manager.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the network is added.
|
|
* @param ssid |wpa_ssid| struct corresponding to the network being added.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::registerNetwork(
|
|
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
|
|
{
|
|
if (!wpa_s || !ssid)
|
|
return 1;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
|
|
|
|
if (isP2pIface(wpa_s)) {
|
|
if (addAidlObjectToMap<P2pNetwork>(
|
|
network_key,
|
|
ndk::SharedRefBase::make<P2pNetwork>(wpa_s->global, wpa_s->ifname, ssid->id),
|
|
p2p_network_object_map_)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to register P2P network with AIDL "
|
|
"control: %d",
|
|
ssid->id);
|
|
return 1;
|
|
}
|
|
} else {
|
|
if (addAidlObjectToMap<StaNetwork>(
|
|
network_key,
|
|
ndk::SharedRefBase::make<StaNetwork>(wpa_s->global, wpa_s->ifname, ssid->id),
|
|
sta_network_object_map_)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to register STA network with AIDL "
|
|
"control: %d",
|
|
ssid->id);
|
|
return 1;
|
|
}
|
|
sta_network_callbacks_map_[network_key] =
|
|
std::vector<std::shared_ptr<ISupplicantStaNetworkCallback>>();
|
|
// Invoke the |onNetworkAdded| method on all registered
|
|
// callbacks.
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onNetworkAdded,
|
|
std::placeholders::_1, ssid->id));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Unregister a network from aidl manager.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the network is added.
|
|
* @param ssid |wpa_ssid| struct corresponding to the network being added.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::unregisterNetwork(
|
|
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
|
|
{
|
|
if (!wpa_s || !ssid)
|
|
return 1;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
|
|
|
|
if (isP2pIface(wpa_s)) {
|
|
if (removeAidlObjectFromMap(
|
|
network_key, p2p_network_object_map_)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to unregister P2P network with AIDL "
|
|
"control: %d",
|
|
ssid->id);
|
|
return 1;
|
|
}
|
|
} else {
|
|
if (removeAidlObjectFromMap(
|
|
network_key, sta_network_object_map_)) {
|
|
wpa_printf(
|
|
MSG_ERROR,
|
|
"Failed to unregister STA network with AIDL "
|
|
"control: %d",
|
|
ssid->id);
|
|
return 1;
|
|
}
|
|
if (removeAllNetworkCallbackAidlObjectsFromMap(
|
|
death_notifier_, network_key, sta_network_callbacks_map_)) {
|
|
return 1;
|
|
}
|
|
|
|
// Invoke the |onNetworkRemoved| method on all registered
|
|
// callbacks.
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onNetworkRemoved,
|
|
std::placeholders::_1, ssid->id));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about any state changes on a particular interface.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the state change event occured.
|
|
*/
|
|
int AidlManager::notifyStateChange(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return 1;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return 1;
|
|
|
|
// Invoke the |onStateChanged| method on all registered callbacks.
|
|
uint32_t aidl_network_id = UINT32_MAX;
|
|
std::vector<uint8_t> aidl_ssid;
|
|
if (wpa_s->current_ssid) {
|
|
aidl_network_id = wpa_s->current_ssid->id;
|
|
aidl_ssid.assign(
|
|
wpa_s->current_ssid->ssid,
|
|
wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
|
|
}
|
|
std::vector<uint8_t> bssid;
|
|
// wpa_supplicant sets the |pending_bssid| field when it starts a
|
|
// connection. Only after association state does it update the |bssid|
|
|
// field. So, in the AIDL callback send the appropriate bssid.
|
|
if (wpa_s->wpa_state <= WPA_ASSOCIATED) {
|
|
bssid = macAddrToVec(wpa_s->pending_bssid);
|
|
} else {
|
|
bssid = macAddrToVec(wpa_s->bssid);
|
|
}
|
|
bool fils_hlp_sent =
|
|
(wpa_auth_alg_fils(wpa_s->auth_alg) &&
|
|
!dl_list_empty(&wpa_s->fils_hlp_req) &&
|
|
(wpa_s->wpa_state == WPA_COMPLETED)) ? true : false;
|
|
|
|
// Invoke the |onStateChanged| method on all registered callbacks.
|
|
std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaIfaceCallback::onStateChanged,
|
|
std::placeholders::_1,
|
|
static_cast<StaIfaceCallbackState>(
|
|
wpa_s->wpa_state),
|
|
bssid, aidl_network_id, aidl_ssid,
|
|
fils_hlp_sent);
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), func);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about a request on a particular network.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the network is present.
|
|
* @param ssid |wpa_ssid| struct corresponding to the network.
|
|
* @param type type of request.
|
|
* @param param addition params associated with the request.
|
|
*/
|
|
int AidlManager::notifyNetworkRequest(
|
|
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
|
|
const char *param)
|
|
{
|
|
if (!wpa_s || !ssid)
|
|
return 1;
|
|
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
|
|
if (sta_network_object_map_.find(network_key) ==
|
|
sta_network_object_map_.end())
|
|
return 1;
|
|
|
|
if (type == WPA_CTRL_REQ_EAP_IDENTITY) {
|
|
callWithEachStaNetworkCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
ssid->id,
|
|
std::bind(
|
|
&ISupplicantStaNetworkCallback::
|
|
onNetworkEapIdentityRequest,
|
|
std::placeholders::_1));
|
|
return 0;
|
|
}
|
|
if (type == WPA_CTRL_REQ_SIM) {
|
|
std::vector<GsmRand> gsm_rands;
|
|
std::vector<uint8_t> umts_rand = std::vector<uint8_t>(16);
|
|
std::vector<uint8_t> umts_autn = std::vector<uint8_t>(16);
|
|
if (!parseGsmAuthNetworkRequest(param, &gsm_rands)) {
|
|
NetworkRequestEapSimGsmAuthParams aidl_params;
|
|
aidl_params.rands = gsm_rands;
|
|
callWithEachStaNetworkCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
ssid->id,
|
|
std::bind(
|
|
&ISupplicantStaNetworkCallback::
|
|
onNetworkEapSimGsmAuthRequest,
|
|
std::placeholders::_1, aidl_params));
|
|
return 0;
|
|
}
|
|
if (!parseUmtsAuthNetworkRequest(
|
|
param, &umts_rand, &umts_autn)) {
|
|
NetworkRequestEapSimUmtsAuthParams aidl_params;
|
|
aidl_params.rand = umts_rand;
|
|
aidl_params.autn = umts_autn;
|
|
callWithEachStaNetworkCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
ssid->id,
|
|
std::bind(
|
|
&ISupplicantStaNetworkCallback::
|
|
onNetworkEapSimUmtsAuthRequest,
|
|
std::placeholders::_1, aidl_params));
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about the end of an ANQP query.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
* @param bssid BSSID of the access point.
|
|
* @param result Result of the operation ("SUCCESS" or "FAILURE").
|
|
* @param anqp |wpa_bss_anqp| ANQP data fetched.
|
|
*/
|
|
void AidlManager::notifyAnqpQueryDone(
|
|
struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
|
|
const struct wpa_bss_anqp *anqp)
|
|
{
|
|
if (!wpa_s || !bssid || !result || !anqp)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
AnqpData aidl_anqp_data;
|
|
Hs20AnqpData aidl_hs20_anqp_data;
|
|
if (std::string(result) == "SUCCESS") {
|
|
aidl_anqp_data.venueName =
|
|
misc_utils::convertWpaBufToVector(anqp->venue_name);
|
|
aidl_anqp_data.roamingConsortium =
|
|
misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
|
|
aidl_anqp_data.ipAddrTypeAvailability =
|
|
misc_utils::convertWpaBufToVector(
|
|
anqp->ip_addr_type_availability);
|
|
aidl_anqp_data.naiRealm =
|
|
misc_utils::convertWpaBufToVector(anqp->nai_realm);
|
|
aidl_anqp_data.anqp3gppCellularNetwork =
|
|
misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
|
|
aidl_anqp_data.domainName =
|
|
misc_utils::convertWpaBufToVector(anqp->domain_name);
|
|
|
|
struct wpa_bss_anqp_elem *elem;
|
|
dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
|
|
list) {
|
|
if (elem->infoid == ANQP_VENUE_URL && elem->protected_response) {
|
|
aidl_anqp_data.venueUrl =
|
|
misc_utils::convertWpaBufToVector(elem->payload);
|
|
break;
|
|
}
|
|
}
|
|
|
|
aidl_hs20_anqp_data.operatorFriendlyName =
|
|
misc_utils::convertWpaBufToVector(
|
|
anqp->hs20_operator_friendly_name);
|
|
aidl_hs20_anqp_data.wanMetrics =
|
|
misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics);
|
|
aidl_hs20_anqp_data.connectionCapability =
|
|
misc_utils::convertWpaBufToVector(
|
|
anqp->hs20_connection_capability);
|
|
aidl_hs20_anqp_data.osuProvidersList =
|
|
misc_utils::convertWpaBufToVector(
|
|
anqp->hs20_osu_providers_list);
|
|
}
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantStaIfaceCallback::onAnqpQueryDone,
|
|
std::placeholders::_1, macAddrToVec(bssid), aidl_anqp_data,
|
|
aidl_hs20_anqp_data));
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about the end of an HS20 icon query.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
* @param bssid BSSID of the access point.
|
|
* @param file_name Name of the icon file.
|
|
* @param image Raw bytes of the icon file.
|
|
* @param image_length Size of the the icon file.
|
|
*/
|
|
void AidlManager::notifyHs20IconQueryDone(
|
|
struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
|
|
const u8 *image, u32 image_length)
|
|
{
|
|
if (!wpa_s || !bssid || !file_name || !image)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onHs20IconQueryDone,
|
|
std::placeholders::_1, macAddrToVec(bssid), file_name,
|
|
std::vector<uint8_t>(image, image + image_length)));
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about the reception of HS20 subscription
|
|
* remediation notification from the server.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
* @param url URL of the server.
|
|
* @param osu_method OSU method (OMA_DM or SOAP_XML_SPP).
|
|
*/
|
|
void AidlManager::notifyHs20RxSubscriptionRemediation(
|
|
struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
|
|
{
|
|
if (!wpa_s || !url)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
OsuMethod aidl_osu_method;
|
|
if (osu_method & 0x1) {
|
|
aidl_osu_method = OsuMethod::OMA_DM;
|
|
} else if (osu_method & 0x2) {
|
|
aidl_osu_method = OsuMethod::SOAP_XML_SPP;
|
|
}
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation,
|
|
std::placeholders::_1, macAddrToVec(wpa_s->bssid), aidl_osu_method, url));
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about the reception of HS20 imminent death
|
|
* notification from the server.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
* @param code Death reason code sent from server.
|
|
* @param reauth_delay Reauthentication delay in seconds sent from server.
|
|
* @param url URL of the server containing the reason text.
|
|
*/
|
|
void AidlManager::notifyHs20RxDeauthImminentNotice(
|
|
struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onHs20DeauthImminentNotice,
|
|
std::placeholders::_1, macAddrToVec(wpa_s->bssid), code,
|
|
reauth_delay, misc_utils::charBufToString(url)));
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about the reception of HS20 terms and conditions
|
|
* acceptance notification from the server.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface.
|
|
* @param url URL of the T&C server.
|
|
*/
|
|
void AidlManager::notifyHs20RxTermsAndConditionsAcceptance(
|
|
struct wpa_supplicant *wpa_s, const char *url)
|
|
{
|
|
if (!wpa_s || !url)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname)
|
|
== sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback
|
|
::onHs20TermsAndConditionsAcceptanceRequestedNotification,
|
|
std::placeholders::_1, macAddrToVec(wpa_s->bssid), url));
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about the reason code for disconnection from the
|
|
* currently connected network.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the network is present.
|
|
*/
|
|
void AidlManager::notifyDisconnectReason(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
const u8 *bssid = wpa_s->bssid;
|
|
if (is_zero_ether_addr(bssid)) {
|
|
bssid = wpa_s->pending_bssid;
|
|
}
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onDisconnected,
|
|
std::placeholders::_1, macAddrToVec(bssid), wpa_s->disconnect_reason < 0,
|
|
static_cast<StaIfaceReasonCode>(
|
|
abs(wpa_s->disconnect_reason))));
|
|
}
|
|
|
|
/**
|
|
* Notify all listeners about association reject from the access point to which
|
|
* we are attempting to connect.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the network is present.
|
|
* @param bssid bssid of AP that rejected the association.
|
|
* @param timed_out flag to indicate failure is due to timeout
|
|
* (auth, assoc, ...) rather than explicit rejection response from the AP.
|
|
* @param assoc_resp_ie Association response IE.
|
|
* @param assoc_resp_ie_len Association response IE length.
|
|
*/
|
|
void AidlManager::notifyAssocReject(struct wpa_supplicant *wpa_s,
|
|
const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
|
|
{
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
#ifdef CONFIG_MBO
|
|
struct wpa_bss *reject_bss;
|
|
#endif /* CONFIG_MBO */
|
|
AssociationRejectionData aidl_assoc_reject_data{};
|
|
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
if (wpa_s->current_ssid) {
|
|
aidl_assoc_reject_data.ssid = std::vector<uint8_t>(
|
|
wpa_s->current_ssid->ssid,
|
|
wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
|
|
}
|
|
aidl_assoc_reject_data.bssid = macAddrToVec(bssid);
|
|
aidl_assoc_reject_data.statusCode = static_cast<StaIfaceStatusCode>(
|
|
wpa_s->assoc_status_code);
|
|
if (timed_out) {
|
|
aidl_assoc_reject_data.timedOut = true;
|
|
}
|
|
#ifdef CONFIG_MBO
|
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
|
|
reject_bss = wpa_s->current_bss;
|
|
} else {
|
|
reject_bss = wpa_bss_get_bssid(wpa_s, bssid);
|
|
}
|
|
if (reject_bss && assoc_resp_ie && assoc_resp_ie_len > 0) {
|
|
if (wpa_s->assoc_status_code ==
|
|
WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS) {
|
|
const u8 *rssi_rej;
|
|
rssi_rej = mbo_get_attr_from_ies(
|
|
assoc_resp_ie,
|
|
assoc_resp_ie_len,
|
|
OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
|
|
if (rssi_rej && rssi_rej[1] == 2) {
|
|
wpa_printf(MSG_INFO,
|
|
"OCE: RSSI-based association rejection from "
|
|
MACSTR " Delta RSSI: %u, Retry Delay: %u bss rssi: %d",
|
|
MAC2STR(reject_bss->bssid),
|
|
rssi_rej[2], rssi_rej[3], reject_bss->level);
|
|
aidl_assoc_reject_data.isOceRssiBasedAssocRejectAttrPresent = true;
|
|
aidl_assoc_reject_data.oceRssiBasedAssocRejectData.deltaRssi
|
|
= rssi_rej[2];
|
|
aidl_assoc_reject_data.oceRssiBasedAssocRejectData.retryDelayS
|
|
= rssi_rej[3];
|
|
}
|
|
} else if (wpa_s->assoc_status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY
|
|
|| wpa_s->assoc_status_code == WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA) {
|
|
const u8 *assoc_disallowed;
|
|
assoc_disallowed = mbo_get_attr_from_ies(
|
|
assoc_resp_ie,
|
|
assoc_resp_ie_len,
|
|
MBO_ATTR_ID_ASSOC_DISALLOW);
|
|
if (assoc_disallowed && assoc_disallowed[1] == 1) {
|
|
wpa_printf(MSG_INFO,
|
|
"MBO: association disallowed indication from "
|
|
MACSTR " Reason: %d",
|
|
MAC2STR(reject_bss->bssid),
|
|
assoc_disallowed[2]);
|
|
aidl_assoc_reject_data.isMboAssocDisallowedReasonCodePresent = true;
|
|
aidl_assoc_reject_data.mboAssocDisallowedReason
|
|
= static_cast<MboAssocDisallowedReasonCode>(assoc_disallowed[2]);
|
|
}
|
|
}
|
|
}
|
|
#endif /* CONFIG_MBO */
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaIfaceCallback::onAssociationRejected,
|
|
std::placeholders::_1, aidl_assoc_reject_data);
|
|
callWithEachStaIfaceCallback(aidl_ifname, func);
|
|
}
|
|
|
|
void AidlManager::notifyAuthTimeout(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
const std::string ifname(wpa_s->ifname);
|
|
if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
|
|
return;
|
|
|
|
const u8 *bssid = wpa_s->bssid;
|
|
if (is_zero_ether_addr(bssid)) {
|
|
bssid = wpa_s->pending_bssid;
|
|
}
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onAuthenticationTimeout,
|
|
std::placeholders::_1, macAddrToVec(bssid)));
|
|
}
|
|
|
|
void AidlManager::notifyBssidChanged(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
const std::string ifname(wpa_s->ifname);
|
|
if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
|
|
return;
|
|
|
|
// wpa_supplicant does not explicitly give us the reason for bssid
|
|
// change, but we figure that out from what is set out of |wpa_s->bssid|
|
|
// & |wpa_s->pending_bssid|.
|
|
const u8 *bssid;
|
|
BssidChangeReason reason;
|
|
if (is_zero_ether_addr(wpa_s->bssid) &&
|
|
!is_zero_ether_addr(wpa_s->pending_bssid)) {
|
|
bssid = wpa_s->pending_bssid;
|
|
reason = BssidChangeReason::ASSOC_START;
|
|
} else if (
|
|
!is_zero_ether_addr(wpa_s->bssid) &&
|
|
is_zero_ether_addr(wpa_s->pending_bssid)) {
|
|
bssid = wpa_s->bssid;
|
|
reason = BssidChangeReason::ASSOC_COMPLETE;
|
|
} else if (
|
|
is_zero_ether_addr(wpa_s->bssid) &&
|
|
is_zero_ether_addr(wpa_s->pending_bssid)) {
|
|
bssid = wpa_s->pending_bssid;
|
|
reason = BssidChangeReason::DISASSOC;
|
|
} else {
|
|
wpa_printf(MSG_ERROR, "Unknown bssid change reason");
|
|
return;
|
|
}
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantStaIfaceCallback::onBssidChanged,
|
|
std::placeholders::_1, reason, macAddrToVec(bssid)));
|
|
}
|
|
|
|
void AidlManager::notifyWpsEventFail(
|
|
struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
|
|
uint16_t error_indication)
|
|
{
|
|
if (!wpa_s || !peer_macaddr)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onWpsEventFail,
|
|
std::placeholders::_1, macAddrToVec(peer_macaddr),
|
|
static_cast<WpsConfigError>(
|
|
config_error),
|
|
static_cast<WpsErrorIndication>(
|
|
error_indication)));
|
|
}
|
|
|
|
void AidlManager::notifyWpsEventSuccess(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantStaIfaceCallback::onWpsEventSuccess,
|
|
std::placeholders::_1));
|
|
}
|
|
|
|
void AidlManager::notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
|
|
std::placeholders::_1));
|
|
}
|
|
|
|
void AidlManager::notifyP2pDeviceFound(
|
|
struct wpa_supplicant *wpa_s, const u8 *addr,
|
|
const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
|
|
u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
|
|
u8 peer_wfd_r2_device_info_len)
|
|
{
|
|
if (!wpa_s || !addr || !info)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
std::vector<uint8_t> aidl_peer_wfd_device_info(kWfdDeviceInfoLen);
|
|
if (peer_wfd_device_info) {
|
|
if (peer_wfd_device_info_len != kWfdDeviceInfoLen) {
|
|
wpa_printf(
|
|
MSG_ERROR, "Unexpected WFD device info len: %d",
|
|
peer_wfd_device_info_len);
|
|
} else {
|
|
os_memcpy(
|
|
aidl_peer_wfd_device_info.data(),
|
|
peer_wfd_device_info, kWfdDeviceInfoLen);
|
|
}
|
|
}
|
|
|
|
std::vector<uint8_t> aidl_peer_wfd_r2_device_info;
|
|
if (peer_wfd_r2_device_info) {
|
|
if (peer_wfd_r2_device_info_len != kWfdR2DeviceInfoLen) {
|
|
wpa_printf(
|
|
MSG_ERROR, "Unexpected WFD R2 device info len: %d",
|
|
peer_wfd_r2_device_info_len);
|
|
return;
|
|
} else {
|
|
std::copy(peer_wfd_r2_device_info,
|
|
peer_wfd_r2_device_info + peer_wfd_r2_device_info_len,
|
|
std::back_inserter(aidl_peer_wfd_r2_device_info));
|
|
}
|
|
}
|
|
|
|
std::vector<uint8_t> aidl_vendor_elems;
|
|
if (NULL != info->vendor_elems && wpabuf_len(info->vendor_elems) > 0) {
|
|
aidl_vendor_elems.reserve(wpabuf_len(info->vendor_elems));
|
|
std::copy(wpabuf_head_u8(info->vendor_elems),
|
|
wpabuf_head_u8(info->vendor_elems)
|
|
+ wpabuf_len(info->vendor_elems),
|
|
std::back_inserter(aidl_vendor_elems));
|
|
}
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantP2pIfaceCallback::onDeviceFoundWithVendorElements,
|
|
std::placeholders::_1, macAddrToVec(addr), macAddrToVec(info->p2p_device_addr),
|
|
byteArrToVec(info->pri_dev_type, 8), misc_utils::charBufToString(info->device_name),
|
|
static_cast<WpsConfigMethods>(info->config_methods),
|
|
info->dev_capab, static_cast<P2pGroupCapabilityMask>(info->group_capab), aidl_peer_wfd_device_info,
|
|
aidl_peer_wfd_r2_device_info, aidl_vendor_elems);
|
|
callWithEachP2pIfaceCallback(wpa_s->ifname, func);
|
|
}
|
|
|
|
void AidlManager::notifyP2pDeviceLost(
|
|
struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
|
|
{
|
|
if (!wpa_s || !p2p_device_addr)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantP2pIfaceCallback::onDeviceLost,
|
|
std::placeholders::_1, macAddrToVec(p2p_device_addr)));
|
|
}
|
|
|
|
void AidlManager::notifyP2pFindStopped(struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantP2pIfaceCallback::onFindStopped,
|
|
std::placeholders::_1));
|
|
}
|
|
|
|
void AidlManager::notifyP2pGoNegReq(
|
|
struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
|
|
u8 /* go_intent */)
|
|
{
|
|
if (!wpa_s || !src_addr)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onGoNegotiationRequest,
|
|
std::placeholders::_1, macAddrToVec(src_addr),
|
|
static_cast<WpsDevPasswordId>(
|
|
dev_passwd_id)));
|
|
}
|
|
|
|
void AidlManager::notifyP2pGoNegCompleted(
|
|
struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
|
|
{
|
|
if (!wpa_s || !res)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onGoNegotiationCompleted,
|
|
std::placeholders::_1,
|
|
static_cast<P2pStatusCode>(
|
|
res->status)));
|
|
}
|
|
|
|
void AidlManager::notifyP2pGroupFormationFailure(
|
|
struct wpa_supplicant *wpa_s, const char *reason)
|
|
{
|
|
if (!wpa_s || !reason)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onGroupFormationFailure,
|
|
std::placeholders::_1, reason));
|
|
}
|
|
|
|
void AidlManager::notifyP2pGroupStarted(
|
|
struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
|
|
int persistent, int client)
|
|
{
|
|
if (!wpa_group_s || !wpa_group_s->parent || !ssid)
|
|
return;
|
|
|
|
// For group notifications, need to use the parent iface for callbacks.
|
|
struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
uint32_t aidl_freq = wpa_group_s->current_bss
|
|
? wpa_group_s->current_bss->freq
|
|
: wpa_group_s->assoc_freq;
|
|
std::vector<uint8_t> aidl_psk(32);
|
|
if (ssid->psk_set) {
|
|
aidl_psk.assign(ssid->psk, ssid->psk + 32);
|
|
}
|
|
bool aidl_is_go = (client == 0 ? true : false);
|
|
bool aidl_is_persistent = (persistent == 1 ? true : false);
|
|
|
|
// notify the group device again to ensure the framework knowing this device.
|
|
struct p2p_data *p2p = wpa_s->global->p2p;
|
|
struct p2p_device *dev = p2p_get_device(p2p, wpa_group_s->go_dev_addr);
|
|
if (NULL != dev) {
|
|
wpa_printf(MSG_DEBUG, "P2P: Update GO device on group started.");
|
|
p2p->cfg->dev_found(p2p->cfg->cb_ctx, wpa_group_s->go_dev_addr,
|
|
&dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
|
|
dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
|
|
}
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onGroupStarted,
|
|
std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname),
|
|
aidl_is_go, byteArrToVec(ssid->ssid, ssid->ssid_len),
|
|
aidl_freq, aidl_psk, misc_utils::charBufToString(ssid->passphrase),
|
|
macAddrToVec(wpa_group_s->go_dev_addr), aidl_is_persistent));
|
|
}
|
|
|
|
void AidlManager::notifyP2pGroupRemoved(
|
|
struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
|
|
const char *role)
|
|
{
|
|
if (!wpa_group_s || !wpa_group_s->parent || !ssid || !role)
|
|
return;
|
|
|
|
// For group notifications, need to use the parent iface for callbacks.
|
|
struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
bool aidl_is_go = (std::string(role) == "GO");
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onGroupRemoved,
|
|
std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname), aidl_is_go));
|
|
}
|
|
|
|
void AidlManager::notifyP2pInvitationReceived(
|
|
struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
|
|
const u8 *bssid, int id, int op_freq)
|
|
{
|
|
if (!wpa_s || !sa || !go_dev_addr || !bssid)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
int aidl_network_id;
|
|
if (id < 0) {
|
|
aidl_network_id = UINT32_MAX;
|
|
}
|
|
aidl_network_id = id;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onInvitationReceived,
|
|
std::placeholders::_1, macAddrToVec(sa), macAddrToVec(go_dev_addr),
|
|
macAddrToVec(bssid), aidl_network_id, op_freq));
|
|
}
|
|
|
|
void AidlManager::notifyP2pInvitationResult(
|
|
struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onInvitationResult,
|
|
std::placeholders::_1, bssid ? macAddrToVec(bssid) : kZeroBssid,
|
|
static_cast<P2pStatusCode>(
|
|
status)));
|
|
}
|
|
|
|
void AidlManager::notifyP2pProvisionDiscovery(
|
|
struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
|
|
enum p2p_prov_disc_status status, u16 config_methods,
|
|
unsigned int generated_pin)
|
|
{
|
|
if (!wpa_s || !dev_addr)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
std::string aidl_generated_pin;
|
|
if (generated_pin > 0) {
|
|
aidl_generated_pin =
|
|
misc_utils::convertWpsPinToString(generated_pin);
|
|
}
|
|
bool aidl_is_request = (request == 1 ? true : false);
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onProvisionDiscoveryCompleted,
|
|
std::placeholders::_1, macAddrToVec(dev_addr), aidl_is_request,
|
|
static_cast<P2pProvDiscStatusCode>(status),
|
|
static_cast<WpsConfigMethods>(config_methods), aidl_generated_pin));
|
|
}
|
|
|
|
void AidlManager::notifyP2pSdResponse(
|
|
struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
|
|
const u8 *tlvs, size_t tlvs_len)
|
|
{
|
|
if (!wpa_s || !sa || !tlvs)
|
|
return;
|
|
|
|
if (p2p_iface_object_map_.find(wpa_s->ifname) ==
|
|
p2p_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onServiceDiscoveryResponse,
|
|
std::placeholders::_1, macAddrToVec(sa), update_indic,
|
|
byteArrToVec(tlvs, tlvs_len)));
|
|
}
|
|
|
|
void AidlManager::notifyApStaAuthorized(
|
|
struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
|
|
{
|
|
if (!wpa_group_s || !wpa_group_s->parent || !sta)
|
|
return;
|
|
wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
|
|
if (!wpa_s)
|
|
return;
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onStaAuthorized,
|
|
std::placeholders::_1, macAddrToVec(sta),
|
|
p2p_dev_addr ? macAddrToVec(p2p_dev_addr) : kZeroBssid));
|
|
}
|
|
|
|
void AidlManager::notifyApStaDeauthorized(
|
|
struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
|
|
{
|
|
if (!wpa_group_s || !wpa_group_s->parent || !sta)
|
|
return;
|
|
wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
callWithEachP2pIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantP2pIfaceCallback::onStaDeauthorized,
|
|
std::placeholders::_1, macAddrToVec(sta),
|
|
p2p_dev_addr ? macAddrToVec(p2p_dev_addr) : kZeroBssid));
|
|
}
|
|
|
|
void AidlManager::notifyExtRadioWorkStart(
|
|
struct wpa_supplicant *wpa_s, uint32_t id)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onExtRadioWorkStart,
|
|
std::placeholders::_1, id));
|
|
}
|
|
|
|
void AidlManager::notifyExtRadioWorkTimeout(
|
|
struct wpa_supplicant *wpa_s, uint32_t id)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
if (sta_iface_object_map_.find(wpa_s->ifname) ==
|
|
sta_iface_object_map_.end())
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
|
|
std::placeholders::_1, id));
|
|
}
|
|
|
|
void AidlManager::notifyEapError(struct wpa_supplicant *wpa_s, int error_code)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname),
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onEapFailure,
|
|
std::placeholders::_1,
|
|
macAddrToVec(wpa_s->bssid), error_code));
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a new DPP configuration received success event
|
|
*
|
|
* @param ifname Interface name
|
|
* @param config Configuration object
|
|
*/
|
|
void AidlManager::notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
|
|
struct wpa_ssid *config)
|
|
{
|
|
DppAkm securityAkm;
|
|
DppConnectionKeys aidl_keys{};
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
|
|
if ((config->key_mgmt & WPA_KEY_MGMT_SAE) &&
|
|
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
|
|
securityAkm = DppAkm::SAE;
|
|
} else if (config->key_mgmt & WPA_KEY_MGMT_PSK) {
|
|
securityAkm = DppAkm::PSK;
|
|
} else if (config->key_mgmt & WPA_KEY_MGMT_DPP) {
|
|
securityAkm = DppAkm::DPP;
|
|
} else {
|
|
/* Unsupported AKM */
|
|
wpa_printf(MSG_ERROR, "DPP: Error: Unsupported AKM 0x%X",
|
|
config->key_mgmt);
|
|
notifyDppFailure(wpa_s, DppFailureCode::NOT_SUPPORTED);
|
|
return;
|
|
}
|
|
|
|
std::string passphrase = misc_utils::charBufToString(config->passphrase);
|
|
std::vector<uint8_t> aidl_ssid(
|
|
config->ssid,
|
|
config->ssid + config->ssid_len);
|
|
|
|
if (securityAkm == DppAkm::DPP) {
|
|
std::string connector_str = misc_utils::charBufToString(config->dpp_connector);
|
|
aidl_keys.connector = std::vector<uint8_t>(connector_str.begin(),
|
|
connector_str.end());
|
|
aidl_keys.cSign = byteArrToVec(config->dpp_csign, config->dpp_csign_len);
|
|
aidl_keys.netAccessKey = byteArrToVec(config->dpp_netaccesskey,
|
|
config->dpp_netaccesskey_len);
|
|
}
|
|
|
|
/* At this point, the network is already registered, notify about new
|
|
* received configuration
|
|
*/
|
|
callWithEachStaIfaceCallback(aidl_ifname,
|
|
std::bind(
|
|
&ISupplicantStaIfaceCallback::onDppSuccessConfigReceived,
|
|
std::placeholders::_1, aidl_ssid, passphrase,
|
|
byteArrToVec(config->psk, 32), securityAkm,
|
|
aidl_keys));
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a DPP configuration sent success event
|
|
*
|
|
* @param ifname Interface name
|
|
*/
|
|
void AidlManager::notifyDppConfigSent(struct wpa_supplicant *wpa_s)
|
|
{
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
|
|
callWithEachStaIfaceCallback(aidl_ifname,
|
|
std::bind(&ISupplicantStaIfaceCallback::onDppSuccessConfigSent,
|
|
std::placeholders::_1));
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a DPP failure event
|
|
*
|
|
* @param ifname Interface name
|
|
* @param code Status code
|
|
*/
|
|
void AidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
|
|
android::hardware::wifi::supplicant::DppFailureCode code) {
|
|
notifyDppFailure(wpa_s, code, NULL, NULL, NULL, 0);
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a DPP failure event
|
|
*
|
|
* @param ifname Interface name
|
|
* @param code Status code
|
|
*/
|
|
void AidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
|
|
DppFailureCode code, const char *ssid, const char *channel_list,
|
|
unsigned short band_list[], int size) {
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
std::vector<char16_t> band_list_vec(band_list, band_list + size);
|
|
|
|
callWithEachStaIfaceCallback(aidl_ifname,
|
|
std::bind(&ISupplicantStaIfaceCallback::onDppFailure,
|
|
std::placeholders::_1, code, misc_utils::charBufToString(ssid),
|
|
misc_utils::charBufToString(channel_list), band_list_vec));
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a DPP progress event
|
|
*
|
|
* @param ifname Interface name
|
|
* @param code Status code
|
|
*/
|
|
void AidlManager::notifyDppProgress(
|
|
struct wpa_supplicant *wpa_s, DppProgressCode code) {
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
|
|
callWithEachStaIfaceCallback(aidl_ifname,
|
|
std::bind(&ISupplicantStaIfaceCallback::onDppProgress,
|
|
std::placeholders::_1, code));
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a DPP success event
|
|
*
|
|
* @param ifname Interface name
|
|
* @param code Status code
|
|
*/
|
|
void AidlManager::notifyDppSuccess(struct wpa_supplicant *wpa_s, DppEventType code)
|
|
{
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
|
|
callWithEachStaIfaceCallback(aidl_ifname,
|
|
std::bind(&ISupplicantStaIfaceCallback::onDppSuccess,
|
|
std::placeholders::_1, code));
|
|
}
|
|
|
|
/**
|
|
* Notify listener about a PMK cache added event
|
|
*
|
|
* @param ifname Interface name
|
|
* @param entry PMK cache entry
|
|
*/
|
|
void AidlManager::notifyPmkCacheAdded(
|
|
struct wpa_supplicant *wpa_s, struct rsn_pmksa_cache_entry *pmksa_entry)
|
|
{
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
|
|
// Serialize PmkCacheEntry into blob.
|
|
std::stringstream ss(
|
|
std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
misc_utils::serializePmkCacheEntry(ss, pmksa_entry);
|
|
std::vector<uint8_t> serializedEntry(
|
|
std::istreambuf_iterator<char>(ss), {});
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaIfaceCallback::onPmkCacheAdded,
|
|
std::placeholders::_1, pmksa_entry->expiration, serializedEntry);
|
|
callWithEachStaIfaceCallback(aidl_ifname, func);
|
|
}
|
|
|
|
#ifdef CONFIG_WNM
|
|
BssTmStatusCode convertSupplicantBssTmStatusToAidl(
|
|
enum bss_trans_mgmt_status_code bss_tm_status)
|
|
{
|
|
switch (bss_tm_status) {
|
|
case WNM_BSS_TM_ACCEPT:
|
|
return BssTmStatusCode::ACCEPT;
|
|
case WNM_BSS_TM_REJECT_UNSPECIFIED:
|
|
return BssTmStatusCode::REJECT_UNSPECIFIED;
|
|
case WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON:
|
|
return BssTmStatusCode::REJECT_INSUFFICIENT_BEACON;
|
|
case WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY:
|
|
return BssTmStatusCode::REJECT_INSUFFICIENT_CAPABITY;
|
|
case WNM_BSS_TM_REJECT_UNDESIRED:
|
|
return BssTmStatusCode::REJECT_BSS_TERMINATION_UNDESIRED;
|
|
case WNM_BSS_TM_REJECT_DELAY_REQUEST:
|
|
return BssTmStatusCode::REJECT_BSS_TERMINATION_DELAY_REQUEST;
|
|
case WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED:
|
|
return BssTmStatusCode::REJECT_STA_CANDIDATE_LIST_PROVIDED;
|
|
case WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES:
|
|
return BssTmStatusCode::REJECT_NO_SUITABLE_CANDIDATES;
|
|
case WNM_BSS_TM_REJECT_LEAVING_ESS:
|
|
return BssTmStatusCode::REJECT_LEAVING_ESS;
|
|
default:
|
|
return BssTmStatusCode::REJECT_UNSPECIFIED;
|
|
}
|
|
}
|
|
|
|
BssTmDataFlagsMask setBssTmDataFlagsMask(struct wpa_supplicant *wpa_s)
|
|
{
|
|
uint32_t flags = 0;
|
|
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_BSS_TERMINATION_INCLUDED);
|
|
}
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_ESS_DISASSOCIATION_IMMINENT);
|
|
}
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_DISASSOCIATION_IMMINENT);
|
|
}
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ABRIDGED) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_ABRIDGED);
|
|
}
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED);
|
|
}
|
|
#ifdef CONFIG_MBO
|
|
if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_ASSOC_RETRY_DELAY_INCLUDED);
|
|
}
|
|
if (wpa_s->wnm_mbo_trans_reason_present) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_TRANSITION_REASON_CODE_INCLUDED);
|
|
}
|
|
if (wpa_s->wnm_mbo_cell_pref_present) {
|
|
flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED);
|
|
}
|
|
#endif
|
|
return static_cast<BssTmDataFlagsMask>(flags);
|
|
}
|
|
|
|
uint32_t getBssTmDataAssocRetryDelayMs(struct wpa_supplicant *wpa_s)
|
|
{
|
|
uint32_t beacon_int;
|
|
uint32_t duration_ms = 0;
|
|
|
|
if (wpa_s->current_bss)
|
|
beacon_int = wpa_s->current_bss->beacon_int;
|
|
else
|
|
beacon_int = 100; /* best guess */
|
|
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
|
|
// number of tbtts to milliseconds
|
|
duration_ms = wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125;
|
|
}
|
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
|
|
//wnm_bss_termination_duration contains 12 bytes of BSS
|
|
//termination duration subelement. Format of IE is
|
|
// Sub eid | Length | BSS termination TSF | Duration
|
|
// 1 1 8 2
|
|
// Duration indicates number of minutes for which BSS is not
|
|
// present.
|
|
duration_ms = WPA_GET_LE16(wpa_s->wnm_bss_termination_duration + 10);
|
|
// minutes to milliseconds
|
|
duration_ms = duration_ms * 60 * 1000;
|
|
}
|
|
#ifdef CONFIG_MBO
|
|
if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
|
|
// number of seconds to milliseconds
|
|
duration_ms = wpa_s->wnm_mbo_assoc_retry_delay_sec * 1000;
|
|
}
|
|
#endif
|
|
|
|
return duration_ms;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Notify listener about the status of BSS transition management
|
|
* request frame handling.
|
|
*
|
|
* @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
|
|
* the network is present.
|
|
*/
|
|
void AidlManager::notifyBssTmStatus(struct wpa_supplicant *wpa_s)
|
|
{
|
|
#ifdef CONFIG_WNM
|
|
std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
|
|
BssTmData aidl_bsstm_data{};
|
|
|
|
aidl_bsstm_data.status = convertSupplicantBssTmStatusToAidl(wpa_s->bss_tm_status);
|
|
aidl_bsstm_data.flags = setBssTmDataFlagsMask(wpa_s);
|
|
aidl_bsstm_data.assocRetryDelayMs = getBssTmDataAssocRetryDelayMs(wpa_s);
|
|
#ifdef CONFIG_MBO
|
|
if (wpa_s->wnm_mbo_cell_pref_present) {
|
|
aidl_bsstm_data.mboCellPreference = static_cast
|
|
<MboCellularDataConnectionPrefValue>
|
|
(wpa_s->wnm_mbo_cell_preference);
|
|
}
|
|
if (wpa_s->wnm_mbo_trans_reason_present) {
|
|
aidl_bsstm_data.mboTransitionReason =
|
|
static_cast<MboTransitionReasonCode>
|
|
(wpa_s->wnm_mbo_transition_reason);
|
|
}
|
|
#endif
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaIfaceCallback::onBssTmHandlingDone,
|
|
std::placeholders::_1, aidl_bsstm_data);
|
|
callWithEachStaIfaceCallback(aidl_ifname, func);
|
|
#endif
|
|
}
|
|
|
|
TransitionDisableIndication setTransitionDisableFlagsMask(u8 bitmap)
|
|
{
|
|
uint32_t flags = 0;
|
|
|
|
if (bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) {
|
|
flags |= static_cast<uint32_t>(TransitionDisableIndication::
|
|
USE_WPA3_PERSONAL);
|
|
bitmap &= ~TRANSITION_DISABLE_WPA3_PERSONAL;
|
|
}
|
|
if (bitmap & TRANSITION_DISABLE_SAE_PK) {
|
|
flags |= static_cast<uint32_t>(TransitionDisableIndication::
|
|
USE_SAE_PK);
|
|
bitmap &= ~TRANSITION_DISABLE_SAE_PK;
|
|
}
|
|
if (bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) {
|
|
flags |= static_cast<uint32_t>(TransitionDisableIndication::
|
|
USE_WPA3_ENTERPRISE);
|
|
bitmap &= ~TRANSITION_DISABLE_WPA3_ENTERPRISE;
|
|
}
|
|
if (bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) {
|
|
flags |= static_cast<uint32_t>(TransitionDisableIndication::
|
|
USE_ENHANCED_OPEN);
|
|
bitmap &= ~TRANSITION_DISABLE_ENHANCED_OPEN;
|
|
}
|
|
|
|
if (bitmap != 0) {
|
|
wpa_printf(MSG_WARNING, "Unhandled transition disable bit: 0x%x", bitmap);
|
|
}
|
|
|
|
return static_cast<TransitionDisableIndication>(flags);
|
|
}
|
|
|
|
void AidlManager::notifyTransitionDisable(struct wpa_supplicant *wpa_s,
|
|
struct wpa_ssid *ssid, u8 bitmap)
|
|
{
|
|
TransitionDisableIndication flag = setTransitionDisableFlagsMask(bitmap);
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaNetworkCallback::onTransitionDisable,
|
|
std::placeholders::_1, flag);
|
|
|
|
callWithEachStaNetworkCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), ssid->id, func);
|
|
}
|
|
|
|
void AidlManager::notifyNetworkNotFound(struct wpa_supplicant *wpa_s)
|
|
{
|
|
std::vector<uint8_t> aidl_ssid;
|
|
|
|
if (!wpa_s->current_ssid) {
|
|
wpa_printf(MSG_ERROR, "Current network NULL. Drop WPA_EVENT_NETWORK_NOT_FOUND!");
|
|
return;
|
|
}
|
|
|
|
aidl_ssid.assign(
|
|
wpa_s->current_ssid->ssid,
|
|
wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaIfaceCallback::onNetworkNotFound,
|
|
std::placeholders::_1, aidl_ssid);
|
|
callWithEachStaIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
|
|
}
|
|
|
|
void AidlManager::notifyFrequencyChanged(struct wpa_supplicant *wpa_group_s, int frequency)
|
|
{
|
|
if (!wpa_group_s || !wpa_group_s->parent)
|
|
return;
|
|
|
|
// For group notifications, need to use the parent iface for callbacks.
|
|
struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
|
|
if (!wpa_s) {
|
|
wpa_printf(MSG_INFO, "Drop frequency changed event");
|
|
return;
|
|
}
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
|
|
func = std::bind(&ISupplicantP2pIfaceCallback::onGroupFrequencyChanged,
|
|
std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname),
|
|
frequency);
|
|
callWithEachP2pIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
|
|
}
|
|
|
|
void AidlManager::notifyCertification(struct wpa_supplicant *wpa_s,
|
|
int depth, const char *subject,
|
|
const char *altsubject[],
|
|
int num_altsubject,
|
|
const char *cert_hash,
|
|
const struct wpabuf *cert)
|
|
{
|
|
if (!wpa_s->current_ssid) {
|
|
wpa_printf(MSG_ERROR, "Current network NULL. Drop Certification event!");
|
|
return;
|
|
}
|
|
struct wpa_ssid *current_ssid = wpa_s->current_ssid;
|
|
if (NULL == subject || NULL == cert_hash || NULL == cert) {
|
|
wpa_printf(MSG_ERROR,
|
|
"Incomplete certificate information. Drop Certification event!");
|
|
return;
|
|
}
|
|
if (!wpa_key_mgmt_wpa_ieee8021x(current_ssid->key_mgmt)) {
|
|
wpa_printf(MSG_ERROR, "Not 802.1x configuration, Drop Certification event!");
|
|
return;
|
|
}
|
|
if (current_ssid->eap.cert.ca_path || current_ssid->eap.cert.ca_cert) {
|
|
wpa_printf(MSG_DEBUG, "Already has CA certificate. Drop Certification event!");
|
|
return;
|
|
}
|
|
|
|
wpa_printf(MSG_DEBUG, "notifyCertification: depth=%d subject=%s hash=%s cert-size=%zu",
|
|
depth, subject, cert_hash, cert->used);
|
|
std::vector<uint8_t> subjectBlob(subject, subject + strlen(subject));
|
|
std::vector<uint8_t> certHashBlob(cert_hash, cert_hash + strlen(cert_hash));
|
|
std::vector<uint8_t> certBlob(cert->buf, cert->buf + cert->used);
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaNetworkCallback::onServerCertificateAvailable,
|
|
std::placeholders::_1,
|
|
depth,
|
|
subjectBlob,
|
|
certHashBlob,
|
|
certBlob);
|
|
|
|
callWithEachStaNetworkCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), current_ssid->id, func);
|
|
}
|
|
|
|
void AidlManager::notifyAuxiliaryEvent(struct wpa_supplicant *wpa_s,
|
|
AuxiliarySupplicantEventCode event_code, const char *reason_string)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
func = std::bind(
|
|
&ISupplicantStaIfaceCallback::onAuxiliarySupplicantEvent,
|
|
std::placeholders::_1, event_code, macAddrToVec(wpa_s->bssid),
|
|
misc_utils::charBufToString(reason_string));
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), func);
|
|
}
|
|
|
|
/**
|
|
* Retrieve the |ISupplicantP2pIface| aidl object reference using the provided
|
|
* ifname.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param iface_object Aidl reference corresponding to the iface.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::getP2pIfaceAidlObjectByIfname(
|
|
const std::string &ifname, std::shared_ptr<ISupplicantP2pIface> *iface_object)
|
|
{
|
|
if (ifname.empty() || !iface_object)
|
|
return 1;
|
|
|
|
auto iface_object_iter = p2p_iface_object_map_.find(ifname);
|
|
if (iface_object_iter == p2p_iface_object_map_.end())
|
|
return 1;
|
|
|
|
*iface_object = iface_object_iter->second;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the |ISupplicantStaIface| aidl object reference using the provided
|
|
* ifname.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param iface_object Aidl reference corresponding to the iface.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::getStaIfaceAidlObjectByIfname(
|
|
const std::string &ifname, std::shared_ptr<ISupplicantStaIface> *iface_object)
|
|
{
|
|
if (ifname.empty() || !iface_object)
|
|
return 1;
|
|
|
|
auto iface_object_iter = sta_iface_object_map_.find(ifname);
|
|
if (iface_object_iter == sta_iface_object_map_.end())
|
|
return 1;
|
|
|
|
*iface_object = iface_object_iter->second;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the |ISupplicantP2pNetwork| aidl object reference using the provided
|
|
* ifname and network_id.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param network_id ID of the corresponding network.
|
|
* @param network_object Aidl reference corresponding to the network.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::getP2pNetworkAidlObjectByIfnameAndNetworkId(
|
|
const std::string &ifname, int network_id,
|
|
std::shared_ptr<ISupplicantP2pNetwork> *network_object)
|
|
{
|
|
if (ifname.empty() || network_id < 0 || !network_object)
|
|
return 1;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(ifname, network_id);
|
|
|
|
auto network_object_iter = p2p_network_object_map_.find(network_key);
|
|
if (network_object_iter == p2p_network_object_map_.end())
|
|
return 1;
|
|
|
|
*network_object = network_object_iter->second;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the |ISupplicantStaNetwork| aidl object reference using the provided
|
|
* ifname and network_id.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param network_id ID of the corresponding network.
|
|
* @param network_object Aidl reference corresponding to the network.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::getStaNetworkAidlObjectByIfnameAndNetworkId(
|
|
const std::string &ifname, int network_id,
|
|
std::shared_ptr<ISupplicantStaNetwork> *network_object)
|
|
{
|
|
if (ifname.empty() || network_id < 0 || !network_object)
|
|
return 1;
|
|
|
|
// Generate the key to be used to lookup the network.
|
|
const std::string network_key =
|
|
getNetworkObjectMapKey(ifname, network_id);
|
|
|
|
auto network_object_iter = sta_network_object_map_.find(network_key);
|
|
if (network_object_iter == sta_network_object_map_.end())
|
|
return 1;
|
|
|
|
*network_object = network_object_iter->second;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Add a new |ISupplicantCallback| aidl object reference to our
|
|
* global callback list.
|
|
*
|
|
* @param callback Aidl reference of the |ISupplicantCallback| object.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::addSupplicantCallbackAidlObject(
|
|
const std::shared_ptr<ISupplicantCallback> &callback)
|
|
{
|
|
return registerForDeathAndAddCallbackAidlObjectToList<
|
|
ISupplicantCallback>(
|
|
death_notifier_, callback, supplicant_callbacks_);
|
|
}
|
|
|
|
/**
|
|
* Add a new iface callback aidl object reference to our
|
|
* interface callback list.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param callback Aidl reference of the callback object.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::addP2pIfaceCallbackAidlObject(
|
|
const std::string &ifname,
|
|
const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback)
|
|
{
|
|
return addIfaceCallbackAidlObjectToMap(
|
|
death_notifier_, ifname, callback, p2p_iface_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Add a new iface callback aidl object reference to our
|
|
* interface callback list.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param callback Aidl reference of the callback object.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::addStaIfaceCallbackAidlObject(
|
|
const std::string &ifname,
|
|
const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
|
|
{
|
|
return addIfaceCallbackAidlObjectToMap(
|
|
death_notifier_, ifname, callback, sta_iface_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Add a new network callback aidl object reference to our network callback
|
|
* list.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param network_id ID of the corresponding network.
|
|
* @param callback Aidl reference of the callback object.
|
|
*
|
|
* @return 0 on success, 1 on failure.
|
|
*/
|
|
int AidlManager::addStaNetworkCallbackAidlObject(
|
|
const std::string &ifname, int network_id,
|
|
const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
|
|
{
|
|
return addNetworkCallbackAidlObjectToMap(
|
|
death_notifier_, ifname, network_id, callback,
|
|
sta_network_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Finds the correct |wpa_supplicant| object for P2P notifications
|
|
*
|
|
* @param wpa_s the |wpa_supplicant| that triggered the P2P event.
|
|
* @return appropriate |wpa_supplicant| object or NULL if not found.
|
|
*/
|
|
struct wpa_supplicant *AidlManager::getTargetP2pIfaceForGroup(
|
|
struct wpa_supplicant *wpa_group_s)
|
|
{
|
|
if (!wpa_group_s || !wpa_group_s->parent)
|
|
return NULL;
|
|
|
|
struct wpa_supplicant *target_wpa_s = wpa_group_s->parent;
|
|
|
|
// check wpa_supplicant object is a p2p device interface
|
|
if ((wpa_group_s == wpa_group_s->p2pdev) && wpa_group_s->p2p_mgmt) {
|
|
if (p2p_iface_object_map_.find(wpa_group_s->ifname) !=
|
|
p2p_iface_object_map_.end())
|
|
return wpa_group_s;
|
|
}
|
|
|
|
if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
|
|
p2p_iface_object_map_.end())
|
|
return target_wpa_s;
|
|
|
|
// try P2P device if available
|
|
if (!target_wpa_s->p2pdev || !target_wpa_s->p2pdev->p2p_mgmt)
|
|
return NULL;
|
|
|
|
target_wpa_s = target_wpa_s->p2pdev;
|
|
if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
|
|
p2p_iface_object_map_.end())
|
|
return target_wpa_s;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Removes the provided |ISupplicantCallback| aidl object reference
|
|
* from our global callback list.
|
|
*
|
|
* @param callback Aidl reference of the |ISupplicantCallback| object.
|
|
*/
|
|
void AidlManager::removeSupplicantCallbackAidlObject(
|
|
const std::shared_ptr<ISupplicantCallback> &callback)
|
|
{
|
|
supplicant_callbacks_.erase(
|
|
std::remove(
|
|
supplicant_callbacks_.begin(), supplicant_callbacks_.end(),
|
|
callback),
|
|
supplicant_callbacks_.end());
|
|
}
|
|
|
|
/**
|
|
* Removes the provided iface callback aidl object reference from
|
|
* our interface callback list.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param callback Aidl reference of the callback object.
|
|
*/
|
|
void AidlManager::removeP2pIfaceCallbackAidlObject(
|
|
const std::string &ifname,
|
|
const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback)
|
|
{
|
|
return removeIfaceCallbackAidlObjectFromMap(
|
|
ifname, callback, p2p_iface_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Removes the provided iface callback aidl object reference from
|
|
* our interface callback list.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param callback Aidl reference of the callback object.
|
|
*/
|
|
void AidlManager::removeStaIfaceCallbackAidlObject(
|
|
const std::string &ifname,
|
|
const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
|
|
{
|
|
return removeIfaceCallbackAidlObjectFromMap(
|
|
ifname, callback, sta_iface_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Removes the provided network callback aidl object reference from
|
|
* our network callback list.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param network_id ID of the corresponding network.
|
|
* @param callback Aidl reference of the callback object.
|
|
*/
|
|
void AidlManager::removeStaNetworkCallbackAidlObject(
|
|
const std::string &ifname, int network_id,
|
|
const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
|
|
{
|
|
return removeNetworkCallbackAidlObjectFromMap(
|
|
ifname, network_id, callback, sta_network_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Helper function to invoke the provided callback method on all the
|
|
* registered |ISupplicantCallback| callback aidl objects.
|
|
*
|
|
* @param method Pointer to the required aidl method from
|
|
* |ISupplicantCallback|.
|
|
*/
|
|
void AidlManager::callWithEachSupplicantCallback(
|
|
const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantCallback>)> &method)
|
|
{
|
|
for (const auto &callback : supplicant_callbacks_) {
|
|
if (!method(callback).isOk()) {
|
|
wpa_printf(MSG_ERROR, "Failed to invoke AIDL callback");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to invoke the provided callback method on all the
|
|
* registered iface callback aidl objects for the specified
|
|
* |ifname|.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param method Pointer to the required aidl method from
|
|
* |ISupplicantIfaceCallback|.
|
|
*/
|
|
void AidlManager::callWithEachP2pIfaceCallback(
|
|
const std::string &ifname,
|
|
const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
|
|
&method)
|
|
{
|
|
callWithEachIfaceCallback(ifname, method, p2p_iface_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Helper function to invoke the provided callback method on all the
|
|
* registered interface callback aidl objects for the specified
|
|
* |ifname|.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param method Pointer to the required aidl method from
|
|
* |ISupplicantIfaceCallback|.
|
|
*/
|
|
void AidlManager::callWithEachStaIfaceCallback(
|
|
const std::string &ifname,
|
|
const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
|
|
&method)
|
|
{
|
|
callWithEachIfaceCallback(ifname, method, sta_iface_callbacks_map_);
|
|
}
|
|
|
|
/**
|
|
* Helper function to invoke the provided callback method on all the
|
|
* registered network callback aidl objects for the specified
|
|
* |ifname| & |network_id|.
|
|
*
|
|
* @param ifname Name of the corresponding interface.
|
|
* @param network_id ID of the corresponding network.
|
|
* @param method Pointer to the required aidl method from
|
|
* |ISupplicantStaNetworkCallback|.
|
|
*/
|
|
void AidlManager::callWithEachStaNetworkCallback(
|
|
const std::string &ifname, int network_id,
|
|
const std::function<
|
|
ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)> &method)
|
|
{
|
|
callWithEachNetworkCallback(
|
|
ifname, network_id, method, sta_network_callbacks_map_);
|
|
}
|
|
|
|
void AidlManager::notifyQosPolicyReset(
|
|
struct wpa_supplicant *wpa_s)
|
|
{
|
|
if (!wpa_s)
|
|
return;
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantStaIfaceCallback::onQosPolicyReset,
|
|
std::placeholders::_1));
|
|
}
|
|
|
|
void AidlManager::notifyQosPolicyRequest(struct wpa_supplicant *wpa_s,
|
|
struct dscp_policy_data *policies, int num_policies)
|
|
{
|
|
if (!wpa_s || !policies)
|
|
return;
|
|
|
|
std::vector<QosPolicyData> qosPolicyData;
|
|
uint32_t mask = 0;
|
|
|
|
for (int num = 0; num < num_policies; num++) {
|
|
QosPolicyData policy;
|
|
QosPolicyClassifierParams classifier_params;
|
|
QosPolicyClassifierParamsMask classifier_param_mask;
|
|
bool ip_ver4 = false;
|
|
|
|
if (policies[num].type4_param.ip_version == 4) {
|
|
classifier_params.ipVersion = IpVersion::VERSION_4;
|
|
ip_ver4 = true;
|
|
} else {
|
|
classifier_params.ipVersion = IpVersion::VERSION_6;
|
|
ip_ver4 = false;
|
|
}
|
|
|
|
// classifier_mask parameters are defined in IEEE Std 802.11-2020, Table 9-170
|
|
if (policies[num].type4_param.classifier_mask & BIT(1)) {
|
|
mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::SRC_IP);
|
|
if (ip_ver4) {
|
|
classifier_params.srcIp =
|
|
byteArrToVec((const uint8_t *)
|
|
&policies[num].type4_param.ip_params.v4.src_ip, 4);
|
|
} else {
|
|
classifier_params.srcIp =
|
|
byteArrToVec((const uint8_t *)
|
|
&policies[num].type4_param.ip_params.v6.src_ip, 16);
|
|
}
|
|
}
|
|
if (policies[num].type4_param.classifier_mask & BIT(2)) {
|
|
mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::DST_IP);
|
|
if (ip_ver4){
|
|
classifier_params.dstIp =
|
|
byteArrToVec((const uint8_t *)
|
|
&policies[num].type4_param.ip_params.v4.dst_ip, 4);
|
|
} else {
|
|
classifier_params.dstIp =
|
|
byteArrToVec((const uint8_t *)
|
|
&policies[num].type4_param.ip_params.v6.dst_ip, 16);
|
|
}
|
|
}
|
|
if (policies[num].type4_param.classifier_mask & BIT(3)) {
|
|
mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::SRC_PORT);
|
|
if (ip_ver4){
|
|
classifier_params.srcPort =
|
|
policies[num].type4_param.ip_params.v4.src_port;
|
|
} else {
|
|
classifier_params.srcPort =
|
|
policies[num].type4_param.ip_params.v6.src_port;
|
|
}
|
|
}
|
|
|
|
if (policies[num].type4_param.classifier_mask & BIT(4)) {
|
|
mask |= static_cast<uint32_t>(
|
|
QosPolicyClassifierParamsMask::DST_PORT_RANGE);
|
|
if (ip_ver4) {
|
|
classifier_params.dstPortRange.startPort =
|
|
policies[num].type4_param.ip_params.v4.dst_port;
|
|
classifier_params.dstPortRange.endPort =
|
|
policies[num].type4_param.ip_params.v4.dst_port;
|
|
} else {
|
|
classifier_params.dstPortRange.startPort =
|
|
policies[num].type4_param.ip_params.v6.dst_port;
|
|
classifier_params.dstPortRange.endPort =
|
|
policies[num].type4_param.ip_params.v6.dst_port;
|
|
}
|
|
} else if (policies[num].port_range_info) {
|
|
mask |= static_cast<uint32_t>(
|
|
QosPolicyClassifierParamsMask::DST_PORT_RANGE);
|
|
classifier_params.dstPortRange.startPort = policies[num].start_port;
|
|
classifier_params.dstPortRange.endPort = policies[num].end_port;
|
|
}
|
|
if (policies[num].type4_param.classifier_mask & BIT(6)) {
|
|
mask |= static_cast<uint32_t>(
|
|
QosPolicyClassifierParamsMask::PROTOCOL_NEXT_HEADER);
|
|
if (ip_ver4) {
|
|
classifier_params.protocolNextHdr = static_cast<ProtocolNextHeader>(
|
|
policies[num].type4_param.ip_params.v4.protocol);
|
|
} else {
|
|
classifier_params.protocolNextHdr = static_cast<ProtocolNextHeader>(
|
|
policies[num].type4_param.ip_params.v6.next_header);
|
|
}
|
|
}
|
|
if (policies[num].type4_param.classifier_mask & BIT(7)) {
|
|
mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::FLOW_LABEL);
|
|
classifier_params.flowLabelIpv6 =
|
|
byteArrToVec(policies[num].type4_param.ip_params.v6.flow_label, 3);
|
|
}
|
|
if (policies[num].domain_name_len != 0) {
|
|
mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::DOMAIN_NAME);
|
|
classifier_params.domainName =
|
|
misc_utils::charBufToString(
|
|
reinterpret_cast<const char *>(policies[num].domain_name));
|
|
}
|
|
|
|
classifier_params.classifierParamMask =
|
|
static_cast<QosPolicyClassifierParamsMask>(mask);
|
|
policy.policyId = policies[num].policy_id;
|
|
policy.requestType = static_cast<QosPolicyRequestType>(policies[num].req_type);
|
|
policy.dscp = policies[num].dscp;
|
|
policy.classifierParams = classifier_params;
|
|
|
|
qosPolicyData.push_back(policy);
|
|
}
|
|
|
|
callWithEachStaIfaceCallback(
|
|
misc_utils::charBufToString(wpa_s->ifname), std::bind(
|
|
&ISupplicantStaIfaceCallback::onQosPolicyRequest,
|
|
std::placeholders::_1, wpa_s->dscp_req_dialog_token, qosPolicyData));
|
|
}
|
|
|
|
} // namespace supplicant
|
|
} // namespace wifi
|
|
} // namespace hardware
|
|
} // namespace android
|
|
} // namespace aidl
|