blob: fccf9cac2af58cc479ffbdceb395e56634b576bd [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
Dmitry Shmidte4663042016-04-04 10:07:49 -070010#include "supplicant.h"
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070011#include "binder_manager.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070012
13namespace wpa_supplicant_binder {
14
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070015Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
Dmitry Shmidte4663042016-04-04 10:07:49 -070016
17android::binder::Status Supplicant::CreateInterface(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070018 const android::os::PersistableBundle &params,
Roshan Piusc9422c72016-07-11 10:18:22 -070019 android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
Dmitry Shmidte4663042016-04-04 10:07:49 -070020{
21 android::String16 driver, ifname, confname, bridge_ifname;
22
23 /* Check if required Ifname argument is missing */
Roshan Pius32c15e22016-07-07 13:46:39 -070024 if (!params.getString(android::String16("Ifname"), &ifname)) {
Roshan Piusd6e37512016-07-07 13:20:46 -070025 return android::binder::Status::fromExceptionCode(
26 android::binder::Status::EX_ILLEGAL_ARGUMENT,
27 "Ifname missing in params.");
Roshan Pius32c15e22016-07-07 13:46:39 -070028 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070029 /* Retrieve the remaining params from the dictionary */
30 params.getString(android::String16("Driver"), &driver);
31 params.getString(android::String16("ConfigFile"), &confname);
32 params.getString(android::String16("BridgeIfname"), &bridge_ifname);
33
34 /*
35 * Try to get the wpa_supplicant record for this iface, return
36 * an error if we already control it.
37 */
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070038 if (wpa_supplicant_get_iface(
Roshan Pius32c15e22016-07-07 13:46:39 -070039 wpa_global_, android::String8(ifname).string()) != NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070040 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070041 ERROR_IFACE_EXISTS,
Roshan Piusd6e37512016-07-07 13:20:46 -070042 "wpa_supplicant already controls this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070043 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070044
45 android::binder::Status status;
46 struct wpa_supplicant *wpa_s = NULL;
47 struct wpa_interface iface;
48
49 os_memset(&iface, 0, sizeof(iface));
50 iface.driver = os_strdup(android::String8(driver).string());
51 iface.ifname = os_strdup(android::String8(ifname).string());
52 iface.confname = os_strdup(android::String8(confname).string());
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070053 iface.bridge_ifname =
54 os_strdup(android::String8(bridge_ifname).string());
Dmitry Shmidte4663042016-04-04 10:07:49 -070055 /* Otherwise, have wpa_supplicant attach to it. */
56 wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
57 /* The supplicant core creates a corresponding binder object via
58 * BinderManager when |wpa_supplicant_add_iface| is called. */
Roshan Pius32c15e22016-07-07 13:46:39 -070059 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070060 status = android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070061 ERROR_GENERIC,
62 "wpa_supplicant couldn't grab this interface.");
Dmitry Shmidte4663042016-04-04 10:07:49 -070063 } else {
64 BinderManager *binder_manager = BinderManager::getInstance();
65
66 if (!binder_manager ||
Roshan Pius32c15e22016-07-07 13:46:39 -070067 binder_manager->getIfaceBinderObjectByIfname(
Roshan Piusc9422c72016-07-11 10:18:22 -070068 wpa_s->ifname, iface_object_out)) {
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070069 status =
70 android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070071 ERROR_GENERIC,
72 "wpa_supplicant encountered a binder error.");
Roshan Pius32c15e22016-07-07 13:46:39 -070073 } else {
Dmitry Shmidte4663042016-04-04 10:07:49 -070074 status = android::binder::Status::ok();
Roshan Pius32c15e22016-07-07 13:46:39 -070075 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070076 }
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070077 os_free((void *)iface.driver);
78 os_free((void *)iface.ifname);
79 os_free((void *)iface.confname);
80 os_free((void *)iface.bridge_ifname);
Dmitry Shmidte4663042016-04-04 10:07:49 -070081 return status;
82}
83
Dmitry Shmidte4663042016-04-04 10:07:49 -070084android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
85{
86 struct wpa_supplicant *wpa_s;
87
88 wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
Roshan Pius32c15e22016-07-07 13:46:39 -070089 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070090 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070091 ERROR_IFACE_UNKNOWN,
Roshan Piusd6e37512016-07-07 13:20:46 -070092 "wpa_supplicant does not control this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070093 }
94 if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070095 return android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070096 ERROR_GENERIC,
97 "wpa_supplicant couldn't remove this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070098 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070099 return android::binder::Status::ok();
100}
101
Dmitry Shmidte4663042016-04-04 10:07:49 -0700102android::binder::Status Supplicant::GetInterface(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700103 const std::string &ifname,
Roshan Piusc9422c72016-07-11 10:18:22 -0700104 android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
Dmitry Shmidte4663042016-04-04 10:07:49 -0700105{
106 struct wpa_supplicant *wpa_s;
107
108 wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
Roshan Pius32c15e22016-07-07 13:46:39 -0700109 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700110 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700111 ERROR_IFACE_UNKNOWN,
Roshan Piusd6e37512016-07-07 13:20:46 -0700112 "wpa_supplicant does not control this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -0700113 }
Dmitry Shmidte4663042016-04-04 10:07:49 -0700114
115 BinderManager *binder_manager = BinderManager::getInstance();
116 if (!binder_manager ||
Roshan Pius32c15e22016-07-07 13:46:39 -0700117 binder_manager->getIfaceBinderObjectByIfname(
Roshan Piusc9422c72016-07-11 10:18:22 -0700118 wpa_s->ifname, iface_object_out)) {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700119 return android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -0700120 ERROR_GENERIC,
121 "wpa_supplicant encountered a binder error.");
Roshan Pius32c15e22016-07-07 13:46:39 -0700122 }
Dmitry Shmidte4663042016-04-04 10:07:49 -0700123
124 return android::binder::Status::ok();
125}
126
Roshan Piusc9422c72016-07-11 10:18:22 -0700127android::binder::Status
128Supplicant::SetDebugParams(int level, bool show_timestamp, bool show_keys)
129{
130 int internal_level;
131 if (convertDebugLevelToInternalLevel(level, &internal_level)) {
132 const std::string error_msg =
133 "invalid debug level: " + std::to_string(level);
134 return android::binder::Status::fromExceptionCode(
135 android::binder::Status::EX_ILLEGAL_ARGUMENT,
136 error_msg.c_str());
137 }
138 if (wpa_supplicant_set_debug_params(
139 wpa_global_, internal_level, show_timestamp, show_keys)) {
140 return android::binder::Status::fromServiceSpecificError(
141 ERROR_GENERIC,
142 "wpa_supplicant could not set debug params.");
143 }
144 return android::binder::Status::ok();
145}
146
147android::binder::Status Supplicant::GetDebugLevel(int *level_out)
148{
149 if (convertDebugLevelToExternalLevel(wpa_debug_level, level_out)) {
150 const std::string error_msg =
151 "invalid debug level: " + std::to_string(wpa_debug_level);
152 return android::binder::Status::fromExceptionCode(
153 android::binder::Status::EX_ILLEGAL_ARGUMENT,
154 error_msg.c_str());
155 }
156 return android::binder::Status::ok();
157}
158
159android::binder::Status
160Supplicant::GetDebugShowTimestamp(bool *show_timestamp_out)
161{
162 *show_timestamp_out = wpa_debug_timestamp ? true : false;
163 return android::binder::Status::ok();
164}
165
166android::binder::Status Supplicant::GetDebugShowKeys(bool *show_keys_out)
167{
168 *show_keys_out = wpa_debug_show_keys ? true : false;
169 return android::binder::Status::ok();
170}
171
172/**
173 * Helper function to convert the debug level parameter from the binder
174 * interface values to internal values.
175 */
176int Supplicant::convertDebugLevelToInternalLevel(
177 int external_level, int *internal_level)
178{
179 switch (external_level) {
180 case DEBUG_LEVEL_EXCESSIVE:
181 *internal_level = MSG_EXCESSIVE;
182 return 0;
183 case DEBUG_LEVEL_MSGDUMP:
184 *internal_level = MSG_MSGDUMP;
185 return 0;
186 case DEBUG_LEVEL_DEBUG:
187 *internal_level = MSG_DEBUG;
188 return 0;
189 case DEBUG_LEVEL_INFO:
190 *internal_level = MSG_INFO;
191 return 0;
192 case DEBUG_LEVEL_WARNING:
193 *internal_level = MSG_WARNING;
194 return 0;
195 case DEBUG_LEVEL_ERROR:
196 *internal_level = MSG_ERROR;
197 return 0;
198 default:
199 wpa_printf(
200 MSG_ERROR, "Invalid external log level: %d",
201 external_level);
202 return 1;
203 }
204}
205
206/**
207 * Helper function to convert the debug level parameter from the internal values
208 * to binder interface values.
209 */
210int Supplicant::convertDebugLevelToExternalLevel(
211 int internal_level, int *external_level)
212{
213 switch (internal_level) {
214 case MSG_EXCESSIVE:
215 *external_level = DEBUG_LEVEL_EXCESSIVE;
216 return 0;
217 case MSG_MSGDUMP:
218 *external_level = DEBUG_LEVEL_MSGDUMP;
219 return 0;
220 case MSG_DEBUG:
221 *external_level = DEBUG_LEVEL_DEBUG;
222 return 0;
223 case MSG_INFO:
224 *external_level = DEBUG_LEVEL_INFO;
225 return 0;
226 case MSG_WARNING:
227 *external_level = DEBUG_LEVEL_WARNING;
228 return 0;
229 case MSG_ERROR:
230 *external_level = DEBUG_LEVEL_ERROR;
231 return 0;
232 default:
233 wpa_printf(
234 MSG_ERROR, "Invalid internal log level: %d",
235 internal_level);
236 return 1;
237 }
238}
Dmitry Shmidte4663042016-04-04 10:07:49 -0700239} /* namespace wpa_supplicant_binder */