• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_2 {
24 namespace implementation {
25 using hidl_return_util::validateAndCall;
26 
P2pNetwork(struct wpa_global * wpa_global,const char ifname[],int network_id)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 
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 || hidl_manager->addP2pNetworkCallbackHidlObject(
141 				 ifname_, network_id_, callback)) {
142 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
143 	}
144 	return {SupplicantStatusCode::SUCCESS, ""};
145 }
146 
getSsidInternal()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>>
getBssidInternal()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 
isCurrentInternal()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 
isPersistentInternal()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 
isGoInternal()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 
setClientListInternal(const std::vector<hidl_array<uint8_t,6>> & clients)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>>>
getClientListInternal()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  */
retrieveNetworkPtr()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  */
retrieveIfacePtr()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