blob: 1ba93b792f9d24d1560731417e86d611eb967fff [file] [log] [blame]
Dmitry Shmidte4663042016-04-04 10:07:49 -07001/*
Roshan Pius57ffbcf2016-09-27 09:12:46 -07002 * hidl interface for wpa_supplicant daemon
Dmitry Shmidte4663042016-04-04 10:07:49 -07003 * 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 Pius57ffbcf2016-09-27 09:12:46 -070010#include "hidl_manager.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070011#include "iface.h"
12
Roshan Pius57ffbcf2016-09-27 09:12:46 -070013namespace wpa_supplicant_hidl {
Dmitry Shmidte4663042016-04-04 10:07:49 -070014
Roshan Pius32f9f5f2016-08-15 14:44:22 -070015#define RETURN_IF_IFACE_INVALID(wpa_s) \
16 { \
17 if (!wpa_s) { \
Roshan Pius57ffbcf2016-09-27 09:12:46 -070018 return android::hidl::Status:: \
Roshan Pius32f9f5f2016-08-15 14:44:22 -070019 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 Pius57ffbcf2016-09-27 09:12:46 -070031android::hidl::Status Iface::GetName(std::string *iface_name_out)
Roshan Pius54e763a2016-07-06 15:41:53 -070032{
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_;
Roshan Pius57ffbcf2016-09-27 09:12:46 -070037 return android::hidl::Status::ok();
Roshan Pius54e763a2016-07-06 15:41:53 -070038}
39
Roshan Pius57ffbcf2016-09-27 09:12:46 -070040android::hidl::Status Iface::AddNetwork(
Roshan Piusd6e37512016-07-07 13:20:46 -070041 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) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -070048 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusd3854452016-07-07 16:46:41 -070049 ERROR_GENERIC, "wpa_supplicant couldn't add this network.");
50 }
51
Roshan Pius57ffbcf2016-09-27 09:12:46 -070052 HidlManager *hidl_manager = HidlManager::getInstance();
53 if (!hidl_manager ||
54 hidl_manager->getNetworkHidlObjectByIfnameAndNetworkId(
Roshan Piusd3854452016-07-07 16:46:41 -070055 wpa_s->ifname, ssid->id, network_object_out)) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -070056 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusd3854452016-07-07 16:46:41 -070057 ERROR_GENERIC,
Roshan Pius57ffbcf2016-09-27 09:12:46 -070058 "wpa_supplicant encountered a hidl error.");
Roshan Piusd3854452016-07-07 16:46:41 -070059 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -070060 return android::hidl::Status::ok();
Roshan Piusd6e37512016-07-07 13:20:46 -070061}
62
Roshan Pius57ffbcf2016-09-27 09:12:46 -070063android::hidl::Status Iface::RemoveNetwork(int network_id)
Roshan Piusd6e37512016-07-07 13:20:46 -070064{
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 Pius57ffbcf2016-09-27 09:12:46 -070070 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusd3854452016-07-07 16:46:41 -070071 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 Pius57ffbcf2016-09-27 09:12:46 -070076 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusd3854452016-07-07 16:46:41 -070077 ERROR_GENERIC,
78 "wpa_supplicant couldn't remove this network.");
79 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -070080 return android::hidl::Status::ok();
Roshan Piusd3854452016-07-07 16:46:41 -070081}
82
Roshan Pius57ffbcf2016-09-27 09:12:46 -070083android::hidl::Status Iface::GetNetwork(
Roshan Piusd3854452016-07-07 16:46:41 -070084 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) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -070092 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusd3854452016-07-07 16:46:41 -070093 ERROR_NETWORK_UNKNOWN,
94 "wpa_supplicant does not control this network.");
95 }
96
Roshan Pius57ffbcf2016-09-27 09:12:46 -070097 HidlManager *hidl_manager = HidlManager::getInstance();
98 if (!hidl_manager ||
99 hidl_manager->getNetworkHidlObjectByIfnameAndNetworkId(
Roshan Piusd3854452016-07-07 16:46:41 -0700100 wpa_s->ifname, ssid->id, network_object_out)) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700101 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusd3854452016-07-07 16:46:41 -0700102 ERROR_GENERIC,
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700103 "wpa_supplicant encountered a hidl error.");
Roshan Piusd3854452016-07-07 16:46:41 -0700104 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700105 return android::hidl::Status::ok();
Roshan Piusd6e37512016-07-07 13:20:46 -0700106}
107
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700108android::hidl::Status Iface::RegisterCallback(
Roshan Pius0470cc82016-07-14 16:37:07 -0700109 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 Pius57ffbcf2016-09-27 09:12:46 -0700114 HidlManager *hidl_manager = HidlManager::getInstance();
115 if (!hidl_manager ||
116 hidl_manager->addIfaceCallbackHidlObject(ifname_, callback)) {
117 return android::hidl::Status::fromServiceSpecificError(
Roshan Pius0470cc82016-07-14 16:37:07 -0700118 ERROR_GENERIC,
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700119 "wpa_supplicant encountered a hidl error.");
Roshan Pius0470cc82016-07-14 16:37:07 -0700120 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700121 return android::hidl::Status::ok();
Roshan Pius0470cc82016-07-14 16:37:07 -0700122}
123
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700124android::hidl::Status Iface::Reassociate()
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700125{
126 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
127 RETURN_IF_IFACE_INVALID(wpa_s);
128
129 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700130 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700131 ERROR_IFACE_DISABLED);
132 }
133 wpas_request_connection(wpa_s);
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700134 return android::hidl::Status::ok();
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700135}
136
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700137android::hidl::Status Iface::Reconnect()
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700138{
139 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
140 RETURN_IF_IFACE_INVALID(wpa_s);
141
142 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700143 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700144 ERROR_IFACE_DISABLED);
145 }
146 if (!wpa_s->disconnected) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700147 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700148 ERROR_IFACE_NOT_DISCONNECTED);
149 }
150 wpas_request_connection(wpa_s);
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700151 return android::hidl::Status::ok();
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700152}
153
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700154android::hidl::Status Iface::Disconnect()
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700155{
156 struct wpa_supplicant *wpa_s = retrieveIfacePtr();
157 RETURN_IF_IFACE_INVALID(wpa_s);
158
159 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700160 return android::hidl::Status::fromServiceSpecificError(
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700161 ERROR_IFACE_DISABLED);
162 }
163 wpas_request_disconnection(wpa_s);
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700164 return android::hidl::Status::ok();
Roshan Piusf4e46cf2016-08-09 15:42:42 -0700165}
166
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700167android::hidl::Status Iface::SetPowerSave(bool enable)
Roshan Pius390ba282016-08-18 12:32:25 -0700168{
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) + ".";
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700174 return android::hidl::Status::fromServiceSpecificError(
Roshan Pius390ba282016-08-18 12:32:25 -0700175 ERROR_GENERIC, error_msg.c_str());
176 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700177 return android::hidl::Status::ok();
Roshan Pius390ba282016-08-18 12:32:25 -0700178}
179
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700180android::hidl::Status Iface::InitiateTDLSDiscover(
Roshan Pius390ba282016-08-18 12:32:25 -0700181 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()) + ".";
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700190 return android::hidl::Status::fromExceptionCode(
191 android::hidl::Status::EX_ILLEGAL_ARGUMENT,
Roshan Pius390ba282016-08-18 12:32:25 -0700192 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) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700202 return android::hidl::Status::fromServiceSpecificError(
Roshan Pius390ba282016-08-18 12:32:25 -0700203 ERROR_GENERIC, "Failed to initiate TDLS Discover.");
204 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700205 return android::hidl::Status::ok();
Roshan Pius390ba282016-08-18 12:32:25 -0700206}
207
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700208android::hidl::Status Iface::InitiateTDLSSetup(
Roshan Pius390ba282016-08-18 12:32:25 -0700209 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()) + ".";
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700218 return android::hidl::Status::fromExceptionCode(
219 android::hidl::Status::EX_ILLEGAL_ARGUMENT,
Roshan Pius390ba282016-08-18 12:32:25 -0700220 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) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700232 return android::hidl::Status::fromServiceSpecificError(
Roshan Pius390ba282016-08-18 12:32:25 -0700233 ERROR_GENERIC, "Failed to initiate TDLS Setup.");
234 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700235 return android::hidl::Status::ok();
Roshan Pius390ba282016-08-18 12:32:25 -0700236}
237
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700238android::hidl::Status Iface::InitiateTDLSTeardown(
Roshan Pius390ba282016-08-18 12:32:25 -0700239 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()) + ".";
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700248 return android::hidl::Status::fromExceptionCode(
249 android::hidl::Status::EX_ILLEGAL_ARGUMENT,
Roshan Pius390ba282016-08-18 12:32:25 -0700250 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) {
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700262 return android::hidl::Status::fromServiceSpecificError(
Roshan Pius390ba282016-08-18 12:32:25 -0700263 ERROR_GENERIC, "Failed to initiate TDLS Teardown.");
264 }
Roshan Pius57ffbcf2016-09-27 09:12:46 -0700265 return android::hidl::Status::ok();
Roshan Pius390ba282016-08-18 12:32:25 -0700266}
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 Pius57ffbcf2016-09-27 09:12:46 -0700279} // namespace wpa_supplicant_hidl