blob: 624e46714ccb435d0ec752cfd55ed6862208b887 [file] [log] [blame]
Dmitry Shmidte4663042016-04-04 10:07:49 -07001/*
2 * binder 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
Roshan Piusd3854452016-07-07 16:46:41 -070010#include "binder_manager.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070011#include "iface.h"
12
13namespace wpa_supplicant_binder {
14
Roshan Pius32f9f5f2016-08-15 14:44:22 -070015#define RETURN_IF_IFACE_INVALID(wpa_s) \
16 { \
17 if (!wpa_s) { \
18 return android::binder::Status:: \
19 fromServiceSpecificError( \
20 ERROR_IFACE_INVALID, \
21 "wpa_supplicant does not control this " \
22 "interface."); \
23 } \
24 } // #define RETURN_IF_IFACE_INVALID(wpa_s)
Roshan Pius8702ba92016-07-25 15:29:39 -070025
Roshan Pius54e763a2016-07-06 15:41:53 -070026Iface::Iface(struct wpa_global *wpa_global, const char ifname[])
27 : wpa_global_(wpa_global), ifname_(ifname)
28{
29}
Dmitry Shmidte4663042016-04-04 10:07:49 -070030
Roshan Pius54e763a2016-07-06 15:41:53 -070031android::binder::Status Iface::GetName(std::string *iface_name_out)
32{
33 // We could directly return the name we hold, but let's verify
34 // if the underlying iface still exists.
Roshan Pius8702ba92016-07-25 15:29:39 -070035 RETURN_IF_IFACE_INVALID(retrieveIfacePtr());
Roshan Pius54e763a2016-07-06 15:41:53 -070036 *iface_name_out = ifname_;
37 return android::binder::Status::ok();
38}
39
Roshan Piusd6e37512016-07-07 13:20:46 -070040android::binder::Status Iface::AddNetwork(
41 android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
42{
Roshan Piusd3854452016-07-07 16:46:41 -070043 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -070044 RETURN_IF_IFACE_INVALID(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070045
Roshan Piusf745df82016-07-14 16:00:23 -070046 struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070047 if (!ssid) {
48 return android::binder::Status::fromServiceSpecificError(
49 ERROR_GENERIC, "wpa_supplicant couldn't add this network.");
50 }
51
Roshan Piusd3854452016-07-07 16:46:41 -070052 BinderManager *binder_manager = BinderManager::getInstance();
53 if (!binder_manager ||
54 binder_manager->getNetworkBinderObjectByIfnameAndNetworkId(
55 wpa_s->ifname, ssid->id, network_object_out)) {
56 return android::binder::Status::fromServiceSpecificError(
57 ERROR_GENERIC,
58 "wpa_supplicant encountered a binder error.");
59 }
Roshan Piusd6e37512016-07-07 13:20:46 -070060 return android::binder::Status::ok();
61}
62
63android::binder::Status Iface::RemoveNetwork(int network_id)
64{
Roshan Piusd3854452016-07-07 16:46:41 -070065 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -070066 RETURN_IF_IFACE_INVALID(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070067
Roshan Piusf745df82016-07-14 16:00:23 -070068 int result = wpa_supplicant_remove_network(wpa_s, network_id);
69 if (result == -1) {
Roshan Piusd3854452016-07-07 16:46:41 -070070 return android::binder::Status::fromServiceSpecificError(
71 ERROR_NETWORK_UNKNOWN,
72 "wpa_supplicant does not control this network.");
73 }
Roshan Piusf745df82016-07-14 16:00:23 -070074
75 if (result == -2) {
Roshan Piusd3854452016-07-07 16:46:41 -070076 return android::binder::Status::fromServiceSpecificError(
77 ERROR_GENERIC,
78 "wpa_supplicant couldn't remove this network.");
79 }
80 return android::binder::Status::ok();
81}
82
83android::binder::Status Iface::GetNetwork(
84 int network_id,
85 android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
86{
87 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -070088 RETURN_IF_IFACE_INVALID(wpa_s);
Roshan Piusd3854452016-07-07 16:46:41 -070089
90 struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, network_id);
91 if (!ssid) {
92 return android::binder::Status::fromServiceSpecificError(
93 ERROR_NETWORK_UNKNOWN,
94 "wpa_supplicant does not control this network.");
95 }
96
97 BinderManager *binder_manager = BinderManager::getInstance();
98 if (!binder_manager ||
99 binder_manager->getNetworkBinderObjectByIfnameAndNetworkId(
100 wpa_s->ifname, ssid->id, network_object_out)) {
101 return android::binder::Status::fromServiceSpecificError(
102 ERROR_GENERIC,
103 "wpa_supplicant encountered a binder error.");
104 }
Roshan Piusd6e37512016-07-07 13:20:46 -0700105 return android::binder::Status::ok();
106}
107
Roshan Pius0470cc82016-07-14 16:37:07 -0700108android::binder::Status Iface::RegisterCallback(
109 const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
110{
111 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
Roshan Pius8702ba92016-07-25 15:29:39 -0700112 RETURN_IF_IFACE_INVALID(wpa_s);
113
Roshan Pius0470cc82016-07-14 16:37:07 -0700114 BinderManager *binder_manager = BinderManager::getInstance();
115 if (!binder_manager ||
116 binder_manager->addIfaceCallbackBinderObject(ifname_, callback)) {
117 return android::binder::Status::fromServiceSpecificError(
118 ERROR_GENERIC,
119 "wpa_supplicant encountered a binder error.");
120 }
121 return android::binder::Status::ok();
122}
123
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700124android::binder::Status Iface::Reassociate()
125{
126 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
127 RETURN_IF_IFACE_INVALID(wpa_s);
128
129 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
130 return android::binder::Status::fromServiceSpecificError(
131 ERROR_IFACE_DISABLED);
132 }
133 wpas_request_connection(wpa_s);
134 return android::binder::Status::ok();
135}
136
137android::binder::Status Iface::Reconnect()
138{
139 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
140 RETURN_IF_IFACE_INVALID(wpa_s);
141
142 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
143 return android::binder::Status::fromServiceSpecificError(
144 ERROR_IFACE_DISABLED);
145 }
146 if (!wpa_s->disconnected) {
147 return android::binder::Status::fromServiceSpecificError(
148 ERROR_IFACE_NOT_DISCONNECTED);
149 }
150 wpas_request_connection(wpa_s);
151 return android::binder::Status::ok();
152}
153
154android::binder::Status Iface::Disconnect()
155{
156 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
157 RETURN_IF_IFACE_INVALID(wpa_s);
158
159 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
160 return android::binder::Status::fromServiceSpecificError(
161 ERROR_IFACE_DISABLED);
162 }
163 wpas_request_disconnection(wpa_s);
164 return android::binder::Status::ok();
165}
166
Roshan Pius390ba282016-08-18 12:32:25 -0700167android::binder::Status Iface::SetPowerSave(bool enable)
168{
169 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
170 RETURN_IF_IFACE_INVALID(wpa_s);
171 if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
172 const std::string error_msg = "Failed setting power save mode" +
173 std::to_string(enable) + ".";
174 return android::binder::Status::fromServiceSpecificError(
175 ERROR_GENERIC, error_msg.c_str());
176 }
177 return android::binder::Status::ok();
178}
179
180android::binder::Status Iface::InitiateTDLSDiscover(
181 const std::vector<uint8_t> &mac_address)
182{
183 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
184 RETURN_IF_IFACE_INVALID(wpa_s);
185
186 if (mac_address.size() != MAC_ADDRESS_LEN) {
187 const std::string error_msg =
188 "Invalid MAC address value length: " +
189 std::to_string(mac_address.size()) + ".";
190 return android::binder::Status::fromExceptionCode(
191 android::binder::Status::EX_ILLEGAL_ARGUMENT,
192 error_msg.c_str());
193 }
194 int ret;
195 const u8 *peer = mac_address.data();
196 if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
197 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
198 } else {
199 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
200 }
201 if (ret) {
202 return android::binder::Status::fromServiceSpecificError(
203 ERROR_GENERIC, "Failed to initiate TDLS Discover.");
204 }
205 return android::binder::Status::ok();
206}
207
208android::binder::Status Iface::InitiateTDLSSetup(
209 const std::vector<uint8_t> &mac_address)
210{
211 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
212 RETURN_IF_IFACE_INVALID(wpa_s);
213
214 if (mac_address.size() != MAC_ADDRESS_LEN) {
215 const std::string error_msg =
216 "Invalid MAC address value length: " +
217 std::to_string(mac_address.size()) + ".";
218 return android::binder::Status::fromExceptionCode(
219 android::binder::Status::EX_ILLEGAL_ARGUMENT,
220 error_msg.c_str());
221 }
222 int ret;
223 const u8 *peer = mac_address.data();
224 if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
225 !(wpa_s->conf->tdls_external_control)) {
226 wpa_tdls_remove(wpa_s->wpa, peer);
227 ret = wpa_tdls_start(wpa_s->wpa, peer);
228 } else {
229 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
230 }
231 if (ret) {
232 return android::binder::Status::fromServiceSpecificError(
233 ERROR_GENERIC, "Failed to initiate TDLS Setup.");
234 }
235 return android::binder::Status::ok();
236}
237
238android::binder::Status Iface::InitiateTDLSTeardown(
239 const std::vector<uint8_t> &mac_address)
240{
241 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
242 RETURN_IF_IFACE_INVALID(wpa_s);
243
244 if (mac_address.size() != MAC_ADDRESS_LEN) {
245 const std::string error_msg =
246 "Invalid MAC address value length: " +
247 std::to_string(mac_address.size()) + ".";
248 return android::binder::Status::fromExceptionCode(
249 android::binder::Status::EX_ILLEGAL_ARGUMENT,
250 error_msg.c_str());
251 }
252 int ret;
253 const u8 *peer = mac_address.data();
254 if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
255 !(wpa_s->conf->tdls_external_control)) {
256 ret = wpa_tdls_teardown_link(
257 wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
258 } else {
259 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
260 }
261 if (ret) {
262 return android::binder::Status::fromServiceSpecificError(
263 ERROR_GENERIC, "Failed to initiate TDLS Teardown.");
264 }
265 return android::binder::Status::ok();
266}
267
Roshan Pius54e763a2016-07-06 15:41:53 -0700268/**
269 * Retrieve the underlying |wpa_supplicant| struct pointer for
270 * this iface.
271 * If the underlying iface is removed, then all RPC method calls
272 * on this object will return failure.
273 */
274wpa_supplicant *Iface::retrieveIfacePtr()
275{
276 return wpa_supplicant_get_iface(
277 (struct wpa_global *)wpa_global_, ifname_.c_str());
278}
Roshan Pius32f9f5f2016-08-15 14:44:22 -0700279} // namespace wpa_supplicant_binder