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 { 16 #include "config_ssid.h" 17 } 18 19 namespace android { 20 namespace hardware { 21 namespace wifi { 22 namespace supplicant { 23 namespace V1_2 { 24 namespace implementation { 25 using hidl_return_util::validateAndCall; 26 27 P2pNetwork::P2pNetwork( 28 struct wpa_global *wpa_global, const char ifname[], int network_id) 29 : wpa_global_(wpa_global), 30 ifname_(ifname), 31 network_id_(network_id), 32 is_valid_(true) 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 || hidl_manager->addP2pNetworkCallbackHidlObject( 141 ifname_, network_id_, callback)) { 142 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 143 } 144 return {SupplicantStatusCode::SUCCESS, ""}; 145 } 146 147 std::pair<SupplicantStatus, std::vector<uint8_t>> P2pNetwork::getSsidInternal() 148 { 149 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 150 return {{SupplicantStatusCode::SUCCESS, ""}, 151 {wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len}}; 152 } 153 154 std::pair<SupplicantStatus, std::array<uint8_t, 6>> 155 P2pNetwork::getBssidInternal() 156 { 157 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 158 std::array<uint8_t, 6> bssid{}; 159 if (wpa_ssid->bssid_set) { 160 os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN); 161 } 162 return {{SupplicantStatusCode::SUCCESS, ""}, bssid}; 163 } 164 165 std::pair<SupplicantStatus, bool> P2pNetwork::isCurrentInternal() 166 { 167 struct wpa_supplicant *wpa_s = retrieveIfacePtr(); 168 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 169 return {{SupplicantStatusCode::SUCCESS, ""}, 170 (wpa_s->current_ssid == wpa_ssid)}; 171 } 172 173 std::pair<SupplicantStatus, bool> P2pNetwork::isPersistentInternal() 174 { 175 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 176 return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->disabled == 2)}; 177 } 178 179 std::pair<SupplicantStatus, bool> P2pNetwork::isGoInternal() 180 { 181 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 182 return {{SupplicantStatusCode::SUCCESS, ""}, 183 (wpa_ssid->mode == wpa_ssid::wpas_mode::WPAS_MODE_P2P_GO)}; 184 } 185 186 SupplicantStatus P2pNetwork::setClientListInternal( 187 const std::vector<hidl_array<uint8_t, 6>> &clients) 188 { 189 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 190 os_free(wpa_ssid->p2p_client_list); 191 // Internal representation uses a generic MAC addr/mask storage format 192 // (even though the mask is always 0xFF'ed for p2p_client_list). So, the 193 // first 6 bytes holds the client MAC address and the next 6 bytes are 194 // OxFF'ed. 195 wpa_ssid->p2p_client_list = 196 (u8 *)os_malloc(ETH_ALEN * 2 * clients.size()); 197 if (!wpa_ssid->p2p_client_list) { 198 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 199 } 200 u8 *list = wpa_ssid->p2p_client_list; 201 for (const auto &client : clients) { 202 os_memcpy(list, client.data(), ETH_ALEN); 203 list += ETH_ALEN; 204 os_memset(list, 0xFF, ETH_ALEN); 205 list += ETH_ALEN; 206 } 207 wpa_ssid->num_p2p_clients = clients.size(); 208 return {SupplicantStatusCode::SUCCESS, ""}; 209 } 210 211 std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>> 212 P2pNetwork::getClientListInternal() 213 { 214 struct wpa_ssid *wpa_ssid = retrieveNetworkPtr(); 215 if (!wpa_ssid->p2p_client_list) { 216 return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}}; 217 } 218 std::vector<hidl_array<uint8_t, 6>> clients; 219 u8 *list = wpa_ssid->p2p_client_list; 220 for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) { 221 clients.emplace_back(list); 222 list += 2 * ETH_ALEN; 223 } 224 return {{SupplicantStatusCode::SUCCESS, ""}, clients}; 225 } 226 227 /** 228 * Retrieve the underlying |wpa_ssid| struct pointer for 229 * this network. 230 * If the underlying network is removed or the interface 231 * this network belong to is removed, all RPC method calls 232 * on this object will return failure. 233 */ 234 struct wpa_ssid *P2pNetwork::retrieveNetworkPtr() 235 { 236 wpa_supplicant *wpa_s = retrieveIfacePtr(); 237 if (!wpa_s) 238 return nullptr; 239 return wpa_config_get_network(wpa_s->conf, network_id_); 240 } 241 242 /** 243 * Retrieve the underlying |wpa_supplicant| struct 244 * pointer for this network. 245 */ 246 struct wpa_supplicant *P2pNetwork::retrieveIfacePtr() 247 { 248 return wpa_supplicant_get_iface( 249 (struct wpa_global *)wpa_global_, ifname_.c_str()); 250 } 251 } // namespace implementation 252 } // namespace V1_2 253 } // namespace supplicant 254 } // namespace wifi 255 } // namespace hardware 256 } // namespace android 257