1 /* 2 * hidl interface for wpa_supplicant daemon 3 * Copyright (c) 2004-2016, Jouni Malinen <j (at) w1.fi> 4 * Copyright (c) 2004-2016, Roshan Pius <rpius (at) 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 14 extern "C" { 15 #include "config_ssid.h" 16 } 17 18 namespace android { 19 namespace hardware { 20 namespace wifi { 21 namespace supplicant { 22 namespace V1_0 { 23 namespace implementation { 24 using hidl_return_util::validateAndCall; 25 26 P2pNetwork::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 35 void P2pNetwork::invalidate() { is_valid_ = false; } 36 bool P2pNetwork::isValid() 37 { 38 return (is_valid_ && (retrieveNetworkPtr() != nullptr)); 39 } 40 41 Return<void> P2pNetwork::getId(getId_cb _hidl_cb) 42 { 43 return validateAndCall( 44 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 45 &P2pNetwork::getIdInternal, _hidl_cb); 46 } 47 48 Return<void> P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb) 49 { 50 return validateAndCall( 51 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 52 &P2pNetwork::getInterfaceNameInternal, _hidl_cb); 53 } 54 55 Return<void> P2pNetwork::getType(getType_cb _hidl_cb) 56 { 57 return validateAndCall( 58 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 59 &P2pNetwork::getTypeInternal, _hidl_cb); 60 } 61 62 Return<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 71 Return<void> P2pNetwork::getSsid(getSsid_cb _hidl_cb) 72 { 73 return validateAndCall( 74 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 75 &P2pNetwork::getSsidInternal, _hidl_cb); 76 } 77 78 Return<void> P2pNetwork::getBssid(getBssid_cb _hidl_cb) 79 { 80 return validateAndCall( 81 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 82 &P2pNetwork::getBssidInternal, _hidl_cb); 83 } 84 85 Return<void> P2pNetwork::isCurrent(isCurrent_cb _hidl_cb) 86 { 87 return validateAndCall( 88 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 89 &P2pNetwork::isCurrentInternal, _hidl_cb); 90 } 91 92 Return<void> P2pNetwork::isPersistent(isPersistent_cb _hidl_cb) 93 { 94 return validateAndCall( 95 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 96 &P2pNetwork::isPersistentInternal, _hidl_cb); 97 } 98 99 Return<void> P2pNetwork::isGo(isGo_cb _hidl_cb) 100 { 101 return validateAndCall( 102 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 103 &P2pNetwork::isGoInternal, _hidl_cb); 104 } 105 106 Return<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 114 Return<void> P2pNetwork::getClientList(getClientList_cb _hidl_cb) 115 { 116 return validateAndCall( 117 this, SupplicantStatusCode::FAILURE_NETWORK_INVALID, 118 &P2pNetwork::getClientListInternal, _hidl_cb); 119 } 120 121 std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal() 122 { 123 return {{SupplicantStatusCode::SUCCESS, ""}, network_id_}; 124 } 125 126 std::pair<SupplicantStatus, std::string> P2pNetwork::getInterfaceNameInternal() 127 { 128 return {{SupplicantStatusCode::SUCCESS, ""}, ifname_}; 129 } 130 131 std::pair<SupplicantStatus, IfaceType> P2pNetwork::getTypeInternal() 132 { 133 return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P}; 134 } 135 136 SupplicantStatus 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 148 std::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 155 std::pair<SupplicantStatus, std::array<uint8_t, 6>> 156 P2pNetwork::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 166 std::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 174 std::pair<SupplicantStatus, bool> P2pNetwork::isPersistentInternal() 175 { 176 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 177 return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->disabled == 2)}; 178 } 179 180 std::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 187 SupplicantStatus 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 212 std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>> 213 P2pNetwork::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 */ 235 struct 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 */ 247 struct 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_0 254 } // namespace wifi 255 } // namespace supplicant 256 } // namespace hardware 257 } // namespace android 258