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 {
16 #include "config_ssid.h"
17 }
18 
19 namespace android {
20 namespace hardware {
21 namespace wifi {
22 namespace supplicant {
23 namespace V1_4 {
24 namespace implementation {
25 using hidl_return_util::validateAndCall;
26 using V1_0::SupplicantStatusCode;
27 
P2pNetwork(struct wpa_global * wpa_global,const char ifname[],int network_id)28 P2pNetwork::P2pNetwork(
29     struct wpa_global *wpa_global, const char ifname[], int network_id)
30     : wpa_global_(wpa_global),
31       ifname_(ifname),
32       network_id_(network_id),
33       is_valid_(true)
34 {}
35 
invalidate()36 void P2pNetwork::invalidate() { is_valid_ = false; }
isValid()37 bool P2pNetwork::isValid()
38 {
39 	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
40 }
41 
getId(getId_cb _hidl_cb)42 Return<void> P2pNetwork::getId(getId_cb _hidl_cb)
43 {
44 	return validateAndCall(
45 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
46 	    &P2pNetwork::getIdInternal, _hidl_cb);
47 }
48 
getInterfaceName(getInterfaceName_cb _hidl_cb)49 Return<void> P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb)
50 {
51 	return validateAndCall(
52 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
53 	    &P2pNetwork::getInterfaceNameInternal, _hidl_cb);
54 }
55 
getType(getType_cb _hidl_cb)56 Return<void> P2pNetwork::getType(getType_cb _hidl_cb)
57 {
58 	return validateAndCall(
59 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
60 	    &P2pNetwork::getTypeInternal, _hidl_cb);
61 }
62 
registerCallback(const sp<ISupplicantP2pNetworkCallback> & callback,registerCallback_cb _hidl_cb)63 Return<void> P2pNetwork::registerCallback(
64     const sp<ISupplicantP2pNetworkCallback> &callback,
65     registerCallback_cb _hidl_cb)
66 {
67 	return validateAndCall(
68 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
69 	    &P2pNetwork::registerCallbackInternal, _hidl_cb, callback);
70 }
71 
getSsid(getSsid_cb _hidl_cb)72 Return<void> P2pNetwork::getSsid(getSsid_cb _hidl_cb)
73 {
74 	return validateAndCall(
75 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
76 	    &P2pNetwork::getSsidInternal, _hidl_cb);
77 }
78 
getBssid(getBssid_cb _hidl_cb)79 Return<void> P2pNetwork::getBssid(getBssid_cb _hidl_cb)
80 {
81 	return validateAndCall(
82 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
83 	    &P2pNetwork::getBssidInternal, _hidl_cb);
84 }
85 
isCurrent(isCurrent_cb _hidl_cb)86 Return<void> P2pNetwork::isCurrent(isCurrent_cb _hidl_cb)
87 {
88 	return validateAndCall(
89 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
90 	    &P2pNetwork::isCurrentInternal, _hidl_cb);
91 }
92 
isPersistent(isPersistent_cb _hidl_cb)93 Return<void> P2pNetwork::isPersistent(isPersistent_cb _hidl_cb)
94 {
95 	return validateAndCall(
96 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
97 	    &P2pNetwork::isPersistentInternal, _hidl_cb);
98 }
99 
isGo(isGo_cb _hidl_cb)100 Return<void> P2pNetwork::isGo(isGo_cb _hidl_cb)
101 {
102 	return validateAndCall(
103 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
104 	    &P2pNetwork::isGoInternal, _hidl_cb);
105 }
106 
setClientList(const hidl_vec<hidl_array<uint8_t,6>> & clients,setClientList_cb _hidl_cb)107 Return<void> P2pNetwork::setClientList(
108     const hidl_vec<hidl_array<uint8_t, 6>> &clients, setClientList_cb _hidl_cb)
109 {
110 	return validateAndCall(
111 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
112 	    &P2pNetwork::setClientListInternal, _hidl_cb, clients);
113 }
114 
getClientList(getClientList_cb _hidl_cb)115 Return<void> P2pNetwork::getClientList(getClientList_cb _hidl_cb)
116 {
117 	return validateAndCall(
118 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
119 	    &P2pNetwork::getClientListInternal, _hidl_cb);
120 }
121 
getIdInternal()122 std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal()
123 {
124 	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
125 }
126 
getInterfaceNameInternal()127 std::pair<SupplicantStatus, std::string> P2pNetwork::getInterfaceNameInternal()
128 {
129 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
130 }
131 
getTypeInternal()132 std::pair<SupplicantStatus, IfaceType> P2pNetwork::getTypeInternal()
133 {
134 	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
135 }
136 
registerCallbackInternal(const sp<ISupplicantP2pNetworkCallback> & callback)137 SupplicantStatus P2pNetwork::registerCallbackInternal(
138     const sp<ISupplicantP2pNetworkCallback> &callback)
139 {
140 	HidlManager *hidl_manager = HidlManager::getInstance();
141 	if (!hidl_manager || 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 == 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_4
254 }  // namespace supplicant
255 }  // namespace wifi
256 }  // namespace hardware
257 }  // namespace android
258