1/* 2 * hidl interface for wpa_supplicant daemon 3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> 4 * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com> 5 * 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. 8 */ 9 10#include "hidl_manager.h" 11#include "hidl_return_util.h" 12#include "p2p_network.h" 13 14extern "C" { 15#include "config_ssid.h" 16} 17 18namespace android { 19namespace hardware { 20namespace wifi { 21namespace supplicant { 22namespace V1_1 { 23namespace implementation { 24using hidl_return_util::validateAndCall; 25 26P2pNetwork::P2pNetwork( 27 struct wpa_global *wpa_global, const char ifname[], int network_id) 28 : wpa_global_(wpa_global), 29 ifname_(ifname), 30 network_id_(network_id), 31 is_valid_(true) 32{ 33} 34 35void P2pNetwork::invalidate() { is_valid_ = false; } 36bool P2pNetwork::isValid() 37{ 38 return (is_valid_ && (retrieveNetworkPtr() != nullptr)); 39} 40 41Return<void> P2pNetwork::getId(getId_cb _hidl_cb) 42{ 43 return validateAndCall( 44 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 45 &P2pNetwork::getIdInternal, _hidl_cb); 46} 47 48Return<void> P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb) 49{ 50 return validateAndCall( 51 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 52 &P2pNetwork::getInterfaceNameInternal, _hidl_cb); 53} 54 55Return<void> P2pNetwork::getType(getType_cb _hidl_cb) 56{ 57 return validateAndCall( 58 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 59 &P2pNetwork::getTypeInternal, _hidl_cb); 60} 61 62Return<void> P2pNetwork::registerCallback( 63 const sp<ISupplicantP2pNetworkCallback> &callback, 64 registerCallback_cb _hidl_cb) 65{ 66 return validateAndCall( 67 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 68 &P2pNetwork::registerCallbackInternal, _hidl_cb, callback); 69} 70 71Return<void> P2pNetwork::getSsid(getSsid_cb _hidl_cb) 72{ 73 return validateAndCall( 74 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 75 &P2pNetwork::getSsidInternal, _hidl_cb); 76} 77 78Return<void> P2pNetwork::getBssid(getBssid_cb _hidl_cb) 79{ 80 return validateAndCall( 81 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 82 &P2pNetwork::getBssidInternal, _hidl_cb); 83} 84 85Return<void> P2pNetwork::isCurrent(isCurrent_cb _hidl_cb) 86{ 87 return validateAndCall( 88 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 89 &P2pNetwork::isCurrentInternal, _hidl_cb); 90} 91 92Return<void> P2pNetwork::isPersistent(isPersistent_cb _hidl_cb) 93{ 94 return validateAndCall( 95 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 96 &P2pNetwork::isPersistentInternal, _hidl_cb); 97} 98 99Return<void> P2pNetwork::isGo(isGo_cb _hidl_cb) 100{ 101 return validateAndCall( 102 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 103 &P2pNetwork::isGoInternal, _hidl_cb); 104} 105 106Return<void> P2pNetwork::setClientList( 107 const hidl_vec<hidl_array<uint8_t, 6>> &clients, setClientList_cb _hidl_cb) 108{ 109 return validateAndCall( 110 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 111 &P2pNetwork::setClientListInternal, _hidl_cb, clients); 112} 113 114Return<void> P2pNetwork::getClientList(getClientList_cb _hidl_cb) 115{ 116 return validateAndCall( 117 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 118 &P2pNetwork::getClientListInternal, _hidl_cb); 119} 120 121std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal() 122{ 123 return {{SupplicantStatusCode::SUCCESS, ""}, network_id_}; 124} 125 126std::pair<SupplicantStatus, std::string> P2pNetwork::getInterfaceNameInternal() 127{ 128 return {{SupplicantStatusCode::SUCCESS, ""}, ifname_}; 129} 130 131std::pair<SupplicantStatus, IfaceType> P2pNetwork::getTypeInternal() 132{ 133 return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P}; 134} 135 136SupplicantStatus P2pNetwork::registerCallbackInternal( 137 const sp<ISupplicantP2pNetworkCallback> &callback) 138{ 139 HidlManager *hidl_manager = HidlManager::getInstance(); 140 if (!hidl_manager || 141 hidl_manager->addP2pNetworkCallbackHidlObject( 142 ifname_, network_id_, callback)) { 143 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 144 } 145 return {SupplicantStatusCode::SUCCESS, ""}; 146} 147 148std::pair<SupplicantStatus, std::vector<uint8_t>> P2pNetwork::getSsidInternal() 149{ 150 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 151 return {{SupplicantStatusCode::SUCCESS, ""}, 152 {wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len}}; 153} 154 155std::pair<SupplicantStatus, std::array<uint8_t, 6>> 156P2pNetwork::getBssidInternal() 157{ 158 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 159 std::array<uint8_t, 6> bssid{}; 160 if (wpa_ssid->bssid_set) { 161 os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN); 162 } 163 return {{SupplicantStatusCode::SUCCESS, ""}, bssid}; 164} 165 166std::pair<SupplicantStatus, bool> P2pNetwork::isCurrentInternal() 167{ 168 struct wpa_supplicant *wpa_s = retrieveIfacePtr(); 169 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 170 return {{SupplicantStatusCode::SUCCESS, ""}, 171 (wpa_s->current_ssid == wpa_ssid)}; 172} 173 174std::pair<SupplicantStatus, bool> P2pNetwork::isPersistentInternal() 175{ 176 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 177 return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->disabled == 2)}; 178} 179 180std::pair<SupplicantStatus, bool> P2pNetwork::isGoInternal() 181{ 182 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 183 return {{SupplicantStatusCode::SUCCESS, ""}, 184 (wpa_ssid->mode == wpa_ssid::wpas_mode::WPAS_MODE_P2P_GO)}; 185} 186 187SupplicantStatus P2pNetwork::setClientListInternal( 188 const std::vector<hidl_array<uint8_t, 6>> &clients) 189{ 190 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 191 os_free(wpa_ssid->p2p_client_list); 192 // Internal representation uses a generic MAC addr/mask storage format 193 // (even though the mask is always 0xFF'ed for p2p_client_list). So, the 194 // first 6 bytes holds the client MAC address and the next 6 bytes are 195 // OxFF'ed. 196 wpa_ssid->p2p_client_list = 197 (u8 *)os_malloc(ETH_ALEN * 2 * clients.size()); 198 if (!wpa_ssid->p2p_client_list) { 199 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 200 } 201 u8 *list = wpa_ssid->p2p_client_list; 202 for (const auto &client : clients) { 203 os_memcpy(list, client.data(), ETH_ALEN); 204 list += ETH_ALEN; 205 os_memset(list, 0xFF, ETH_ALEN); 206 list += ETH_ALEN; 207 } 208 wpa_ssid->num_p2p_clients = clients.size(); 209 return {SupplicantStatusCode::SUCCESS, ""}; 210} 211 212std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>> 213P2pNetwork::getClientListInternal() 214{ 215 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 216 if (!wpa_ssid->p2p_client_list) { 217 return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}}; 218 } 219 std::vector<hidl_array<uint8_t, 6>> clients; 220 u8 *list = wpa_ssid->p2p_client_list; 221 for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) { 222 clients.emplace_back(list); 223 list += 2 * ETH_ALEN; 224 } 225 return {{SupplicantStatusCode::SUCCESS, ""}, clients}; 226} 227 228/** 229 * Retrieve the underlying |wpa_ssid| struct pointer for 230 * this network. 231 * If the underlying network is removed or the interface 232 * this network belong to is removed, all RPC method calls 233 * on this object will return failure. 234 */ 235struct wpa_ssid *P2pNetwork::retrieveNetworkPtr() 236{ 237 wpa_supplicant *wpa_s = retrieveIfacePtr(); 238 if (!wpa_s) 239 return nullptr; 240 return wpa_config_get_network(wpa_s->conf, network_id_); 241} 242 243/** 244 * Retrieve the underlying |wpa_supplicant| struct 245 * pointer for this network. 246 */ 247struct wpa_supplicant *P2pNetwork::retrieveIfacePtr() 248{ 249 return wpa_supplicant_get_iface( 250 (struct wpa_global *)wpa_global_, ifname_.c_str()); 251} 252} // namespace implementation 253} // namespace V1_1 254} // namespace wifi 255} // namespace supplicant 256} // namespace hardware 257} // namespace android 258