blob: c35e91fda321d17081f23be6c77556d4b8646e02 [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 Shmidt7f2c7532016-08-15 09:48:12 -070010#include "binder_manager.h"
Roshan Pius0470cc82016-07-14 16:37:07 -070011#include "supplicant.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 -070016android::binder::Status Supplicant::CreateInterface(
Roshan Piusb01b7962016-07-11 15:25:47 -070017 const fi::w1::wpa_supplicant::ParcelableIfaceParams &params,
Roshan Piusc9422c72016-07-11 10:18:22 -070018 android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
Dmitry Shmidte4663042016-04-04 10:07:49 -070019{
Dmitry Shmidte4663042016-04-04 10:07:49 -070020 /* Check if required Ifname argument is missing */
Roshan Piusb01b7962016-07-11 15:25:47 -070021 if (params.ifname_.isEmpty()) {
Roshan Piusd6e37512016-07-07 13:20:46 -070022 return android::binder::Status::fromExceptionCode(
23 android::binder::Status::EX_ILLEGAL_ARGUMENT,
24 "Ifname missing in params.");
Roshan Pius32c15e22016-07-07 13:46:39 -070025 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070026 /*
27 * Try to get the wpa_supplicant record for this iface, return
28 * an error if we already control it.
29 */
Roshan Piusb01b7962016-07-11 15:25:47 -070030 if (wpa_supplicant_get_iface(wpa_global_, params.ifname_.string()) !=
31 NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070032 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070033 ERROR_IFACE_EXISTS,
Roshan Piusd6e37512016-07-07 13:20:46 -070034 "wpa_supplicant already controls this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070035 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070036
37 android::binder::Status status;
38 struct wpa_supplicant *wpa_s = NULL;
39 struct wpa_interface iface;
40
41 os_memset(&iface, 0, sizeof(iface));
Roshan Piusb01b7962016-07-11 15:25:47 -070042 iface.driver = os_strdup(params.driver_.string());
43 iface.ifname = os_strdup(params.ifname_.string());
44 iface.confname = os_strdup(params.config_file_.string());
45 iface.bridge_ifname = os_strdup(params.bridge_ifname_.string());
Dmitry Shmidte4663042016-04-04 10:07:49 -070046 /* Otherwise, have wpa_supplicant attach to it. */
47 wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
48 /* The supplicant core creates a corresponding binder object via
49 * BinderManager when |wpa_supplicant_add_iface| is called. */
Roshan Pius32c15e22016-07-07 13:46:39 -070050 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070051 status = android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070052 ERROR_GENERIC,
53 "wpa_supplicant couldn't grab this interface.");
Dmitry Shmidte4663042016-04-04 10:07:49 -070054 } else {
55 BinderManager *binder_manager = BinderManager::getInstance();
56
57 if (!binder_manager ||
Roshan Pius32c15e22016-07-07 13:46:39 -070058 binder_manager->getIfaceBinderObjectByIfname(
Roshan Piusc9422c72016-07-11 10:18:22 -070059 wpa_s->ifname, iface_object_out)) {
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070060 status =
61 android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070062 ERROR_GENERIC,
63 "wpa_supplicant encountered a binder error.");
Roshan Pius32c15e22016-07-07 13:46:39 -070064 } else {
Dmitry Shmidte4663042016-04-04 10:07:49 -070065 status = android::binder::Status::ok();
Roshan Pius32c15e22016-07-07 13:46:39 -070066 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070067 }
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070068 os_free((void *)iface.driver);
69 os_free((void *)iface.ifname);
70 os_free((void *)iface.confname);
71 os_free((void *)iface.bridge_ifname);
Dmitry Shmidte4663042016-04-04 10:07:49 -070072 return status;
73}
74
Dmitry Shmidte4663042016-04-04 10:07:49 -070075android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
76{
77 struct wpa_supplicant *wpa_s;
78
79 wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
Roshan Pius32c15e22016-07-07 13:46:39 -070080 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070081 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070082 ERROR_IFACE_UNKNOWN,
Roshan Piusd6e37512016-07-07 13:20:46 -070083 "wpa_supplicant does not control this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070084 }
85 if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070086 return android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070087 ERROR_GENERIC,
88 "wpa_supplicant couldn't remove this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070089 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070090 return android::binder::Status::ok();
91}
92
Dmitry Shmidte4663042016-04-04 10:07:49 -070093android::binder::Status Supplicant::GetInterface(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070094 const std::string &ifname,
Roshan Piusc9422c72016-07-11 10:18:22 -070095 android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
Dmitry Shmidte4663042016-04-04 10:07:49 -070096{
97 struct wpa_supplicant *wpa_s;
98
99 wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
Roshan Pius32c15e22016-07-07 13:46:39 -0700100 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700101 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700102 ERROR_IFACE_UNKNOWN,
Roshan Piusd6e37512016-07-07 13:20:46 -0700103 "wpa_supplicant does not control this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -0700104 }
Dmitry Shmidte4663042016-04-04 10:07:49 -0700105
106 BinderManager *binder_manager = BinderManager::getInstance();
107 if (!binder_manager ||
Roshan Pius32c15e22016-07-07 13:46:39 -0700108 binder_manager->getIfaceBinderObjectByIfname(
Roshan Piusc9422c72016-07-11 10:18:22 -0700109 wpa_s->ifname, iface_object_out)) {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700110 return android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -0700111 ERROR_GENERIC,
112 "wpa_supplicant encountered a binder error.");
Roshan Pius32c15e22016-07-07 13:46:39 -0700113 }
Dmitry Shmidte4663042016-04-04 10:07:49 -0700114
115 return android::binder::Status::ok();
116}
117
Roshan Pius32f9f5f2016-08-15 14:44:22 -0700118android::binder::Status Supplicant::SetDebugParams(
119 int level, bool show_timestamp, bool show_keys)
Roshan Piusc9422c72016-07-11 10:18:22 -0700120{
121 int internal_level;
122 if (convertDebugLevelToInternalLevel(level, &internal_level)) {
123 const std::string error_msg =
124 "invalid debug level: " + std::to_string(level);
125 return android::binder::Status::fromExceptionCode(
126 android::binder::Status::EX_ILLEGAL_ARGUMENT,
127 error_msg.c_str());
128 }
129 if (wpa_supplicant_set_debug_params(
130 wpa_global_, internal_level, show_timestamp, show_keys)) {
131 return android::binder::Status::fromServiceSpecificError(
132 ERROR_GENERIC,
133 "wpa_supplicant could not set debug params.");
134 }
135 return android::binder::Status::ok();
136}
137
138android::binder::Status Supplicant::GetDebugLevel(int *level_out)
139{
140 if (convertDebugLevelToExternalLevel(wpa_debug_level, level_out)) {
141 const std::string error_msg =
142 "invalid debug level: " + std::to_string(wpa_debug_level);
143 return android::binder::Status::fromExceptionCode(
144 android::binder::Status::EX_ILLEGAL_ARGUMENT,
145 error_msg.c_str());
146 }
147 return android::binder::Status::ok();
148}
149
Roshan Pius32f9f5f2016-08-15 14:44:22 -0700150android::binder::Status Supplicant::GetDebugShowTimestamp(
151 bool *show_timestamp_out)
Roshan Piusc9422c72016-07-11 10:18:22 -0700152{
153 *show_timestamp_out = wpa_debug_timestamp ? true : false;
154 return android::binder::Status::ok();
155}
156
157android::binder::Status Supplicant::GetDebugShowKeys(bool *show_keys_out)
158{
159 *show_keys_out = wpa_debug_show_keys ? true : false;
160 return android::binder::Status::ok();
161}
162
Roshan Pius0470cc82016-07-14 16:37:07 -0700163android::binder::Status Supplicant::RegisterCallback(
164 const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback> &callback)
165{
166 BinderManager *binder_manager = BinderManager::getInstance();
167 if (!binder_manager ||
168 binder_manager->addSupplicantCallbackBinderObject(callback)) {
169 return android::binder::Status::fromServiceSpecificError(
170 ERROR_GENERIC,
171 "wpa_supplicant encountered a binder error.");
172 }
173 return android::binder::Status::ok();
174}
175
Roshan Piusc9422c72016-07-11 10:18:22 -0700176/**
177 * Helper function to convert the debug level parameter from the binder
178 * interface values to internal values.
179 */
180int Supplicant::convertDebugLevelToInternalLevel(
181 int external_level, int *internal_level)
182{
183 switch (external_level) {
184 case DEBUG_LEVEL_EXCESSIVE:
185 *internal_level = MSG_EXCESSIVE;
186 return 0;
187 case DEBUG_LEVEL_MSGDUMP:
188 *internal_level = MSG_MSGDUMP;
189 return 0;
190 case DEBUG_LEVEL_DEBUG:
191 *internal_level = MSG_DEBUG;
192 return 0;
193 case DEBUG_LEVEL_INFO:
194 *internal_level = MSG_INFO;
195 return 0;
196 case DEBUG_LEVEL_WARNING:
197 *internal_level = MSG_WARNING;
198 return 0;
199 case DEBUG_LEVEL_ERROR:
200 *internal_level = MSG_ERROR;
201 return 0;
202 default:
203 wpa_printf(
204 MSG_ERROR, "Invalid external log level: %d",
205 external_level);
206 return 1;
207 }
208}
209
210/**
211 * Helper function to convert the debug level parameter from the internal values
212 * to binder interface values.
213 */
214int Supplicant::convertDebugLevelToExternalLevel(
215 int internal_level, int *external_level)
216{
217 switch (internal_level) {
218 case MSG_EXCESSIVE:
219 *external_level = DEBUG_LEVEL_EXCESSIVE;
220 return 0;
221 case MSG_MSGDUMP:
222 *external_level = DEBUG_LEVEL_MSGDUMP;
223 return 0;
224 case MSG_DEBUG:
225 *external_level = DEBUG_LEVEL_DEBUG;
226 return 0;
227 case MSG_INFO:
228 *external_level = DEBUG_LEVEL_INFO;
229 return 0;
230 case MSG_WARNING:
231 *external_level = DEBUG_LEVEL_WARNING;
232 return 0;
233 case MSG_ERROR:
234 *external_level = DEBUG_LEVEL_ERROR;
235 return 0;
236 default:
237 wpa_printf(
238 MSG_ERROR, "Invalid internal log level: %d",
239 internal_level);
240 return 1;
241 }
242}
Dmitry Shmidte4663042016-04-04 10:07:49 -0700243} /* namespace wpa_supplicant_binder */