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
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
P2pNetwork(struct wpa_global * wpa_global,const char ifname[],int network_id)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
invalidate()35 void P2pNetwork::invalidate() { is_valid_ = false; }
isValid()36 bool P2pNetwork::isValid()
37 {
38 return (is_valid_ && (retrieveNetworkPtr() != nullptr));
39 }
40
getId(getId_cb _hidl_cb)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
getInterfaceName(getInterfaceName_cb _hidl_cb)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
getType(getType_cb _hidl_cb)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
registerCallback(const sp<ISupplicantP2pNetworkCallback> & callback,registerCallback_cb _hidl_cb)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
getSsid(getSsid_cb _hidl_cb)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
getBssid(getBssid_cb _hidl_cb)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
isCurrent(isCurrent_cb _hidl_cb)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
isPersistent(isPersistent_cb _hidl_cb)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
isGo(isGo_cb _hidl_cb)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
setClientList(const hidl_vec<hidl_array<uint8_t,6>> & clients,setClientList_cb _hidl_cb)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
getClientList(getClientList_cb _hidl_cb)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
getIdInternal()121 std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal()
122 {
123 return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
124 }
125
getInterfaceNameInternal()126 std::pair<SupplicantStatus, std::string> P2pNetwork::getInterfaceNameInternal()
127 {
128 return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
129 }
130
getTypeInternal()131 std::pair<SupplicantStatus, IfaceType> P2pNetwork::getTypeInternal()
132 {
133 return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
134 }
135
registerCallbackInternal(const sp<ISupplicantP2pNetworkCallback> & callback)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
getSsidInternal()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>>
getBssidInternal()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
isCurrentInternal()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
isPersistentInternal()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
isGoInternal()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
setClientListInternal(const std::vector<hidl_array<uint8_t,6>> & clients)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>>>
getClientListInternal()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 */
retrieveNetworkPtr()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 */
retrieveIfacePtr()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