/* * hidl interface for wpa_supplicant daemon * Copyright (c) 2004-2016, Jouni Malinen * Copyright (c) 2004-2016, Roshan Pius * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "hidl_manager.h" #include "hidl_return_util.h" #include "p2p_network.h" extern "C" { #include "config_ssid.h" } namespace android { namespace hardware { namespace wifi { namespace supplicant { namespace V1_0 { namespace implementation { using hidl_return_util::validateAndCall; P2pNetwork::P2pNetwork( struct wpa_global *wpa_global, const char ifname[], int network_id) : wpa_global_(wpa_global), ifname_(ifname), network_id_(network_id), is_valid_(true) { } void P2pNetwork::invalidate() { is_valid_ = false; } bool P2pNetwork::isValid() { return (is_valid_ && (retrieveNetworkPtr() != nullptr)); } Return P2pNetwork::getId(getId_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::getIdInternal, _hidl_cb); } Return P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::getInterfaceNameInternal, _hidl_cb); } Return P2pNetwork::getType(getType_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::getTypeInternal, _hidl_cb); } Return P2pNetwork::registerCallback( const sp &callback, registerCallback_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::registerCallbackInternal, _hidl_cb, callback); } Return P2pNetwork::getSsid(getSsid_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::getSsidInternal, _hidl_cb); } Return P2pNetwork::getBssid(getBssid_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::getBssidInternal, _hidl_cb); } Return P2pNetwork::isCurrent(isCurrent_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::isCurrentInternal, _hidl_cb); } Return P2pNetwork::isPersistent(isPersistent_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::isPersistentInternal, _hidl_cb); } Return P2pNetwork::isGo(isGo_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::isGoInternal, _hidl_cb); } Return P2pNetwork::setClientList( const hidl_vec> &clients, setClientList_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::setClientListInternal, _hidl_cb, clients); } Return P2pNetwork::getClientList(getClientList_cb _hidl_cb) { return validateAndCall( this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, &P2pNetwork::getClientListInternal, _hidl_cb); } std::pair P2pNetwork::getIdInternal() { return {{SupplicantStatusCode::SUCCESS, ""}, network_id_}; } std::pair P2pNetwork::getInterfaceNameInternal() { return {{SupplicantStatusCode::SUCCESS, ""}, ifname_}; } std::pair P2pNetwork::getTypeInternal() { return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P}; } SupplicantStatus P2pNetwork::registerCallbackInternal( const sp &callback) { HidlManager *hidl_manager = HidlManager::getInstance(); if (!hidl_manager || hidl_manager->addP2pNetworkCallbackHidlObject( ifname_, network_id_, callback)) { return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; } return {SupplicantStatusCode::SUCCESS, ""}; } std::pair> P2pNetwork::getSsidInternal() { struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len}}; } std::pair> P2pNetwork::getBssidInternal() { struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); std::array bssid{}; if (wpa_ssid->bssid_set) { os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN); } return {{SupplicantStatusCode::SUCCESS, ""}, bssid}; } std::pair P2pNetwork::isCurrentInternal() { struct wpa_supplicant *wpa_s = retrieveIfacePtr(); struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_s->current_ssid == wpa_ssid)}; } std::pair P2pNetwork::isPersistentInternal() { struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->disabled == 2)}; } std::pair P2pNetwork::isGoInternal() { struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->mode == wpa_ssid::wpas_mode::WPAS_MODE_P2P_GO)}; } SupplicantStatus P2pNetwork::setClientListInternal( const std::vector> &clients) { struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); os_free(wpa_ssid->p2p_client_list); // Internal representation uses a generic MAC addr/mask storage format // (even though the mask is always 0xFF'ed for p2p_client_list). So, the // first 6 bytes holds the client MAC address and the next 6 bytes are // OxFF'ed. wpa_ssid->p2p_client_list = (u8 *)os_malloc(ETH_ALEN * 2 * clients.size()); if (!wpa_ssid->p2p_client_list) { return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; } u8 *list = wpa_ssid->p2p_client_list; for (const auto &client : clients) { os_memcpy(list, client.data(), ETH_ALEN); list += ETH_ALEN; os_memset(list, 0xFF, ETH_ALEN); list += ETH_ALEN; } wpa_ssid->num_p2p_clients = clients.size(); return {SupplicantStatusCode::SUCCESS, ""}; } std::pair>> P2pNetwork::getClientListInternal() { struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); if (!wpa_ssid->p2p_client_list) { return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}}; } std::vector> clients; u8 *list = wpa_ssid->p2p_client_list; for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) { clients.emplace_back(list); list += 2 * ETH_ALEN; } return {{SupplicantStatusCode::SUCCESS, ""}, clients}; } /** * Retrieve the underlying |wpa_ssid| struct pointer for * this network. * If the underlying network is removed or the interface * this network belong to is removed, all RPC method calls * on this object will return failure. */ struct wpa_ssid *P2pNetwork::retrieveNetworkPtr() { wpa_supplicant *wpa_s = retrieveIfacePtr(); if (!wpa_s) return nullptr; return wpa_config_get_network(wpa_s->conf, network_id_); } /** * Retrieve the underlying |wpa_supplicant| struct * pointer for this network. */ struct wpa_supplicant *P2pNetwork::retrieveIfacePtr() { return wpa_supplicant_get_iface( (struct wpa_global *)wpa_global_, ifname_.c_str()); } } // namespace implementation } // namespace V1_0 } // namespace wifi } // namespace supplicant } // namespace hardware } // namespace android