blob: 38b7e44b855dcf470dff4f9998fb07e0a541f92e [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(
Roshan Piusb01b7962016-07-11 15:25:47 -070018 const fi::w1::wpa_supplicant::ParcelableIfaceParams &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{
Dmitry Shmidte4663042016-04-04 10:07:49 -070021 /* Check if required Ifname argument is missing */
Roshan Piusb01b7962016-07-11 15:25:47 -070022 if (params.ifname_.isEmpty()) {
Roshan Piusd6e37512016-07-07 13:20:46 -070023 return android::binder::Status::fromExceptionCode(
24 android::binder::Status::EX_ILLEGAL_ARGUMENT,
25 "Ifname missing in params.");
Roshan Pius32c15e22016-07-07 13:46:39 -070026 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070027 /*
28 * Try to get the wpa_supplicant record for this iface, return
29 * an error if we already control it.
30 */
Roshan Piusb01b7962016-07-11 15:25:47 -070031 if (wpa_supplicant_get_iface(wpa_global_, params.ifname_.string()) !=
32 NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070033 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070034 ERROR_IFACE_EXISTS,
Roshan Piusd6e37512016-07-07 13:20:46 -070035 "wpa_supplicant already controls this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070036 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070037
38 android::binder::Status status;
39 struct wpa_supplicant *wpa_s = NULL;
40 struct wpa_interface iface;
41
42 os_memset(&iface, 0, sizeof(iface));
Roshan Piusb01b7962016-07-11 15:25:47 -070043 iface.driver = os_strdup(params.driver_.string());
44 iface.ifname = os_strdup(params.ifname_.string());
45 iface.confname = os_strdup(params.config_file_.string());
46 iface.bridge_ifname = os_strdup(params.bridge_ifname_.string());
Dmitry Shmidte4663042016-04-04 10:07:49 -070047 /* Otherwise, have wpa_supplicant attach to it. */
48 wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
49 /* The supplicant core creates a corresponding binder object via
50 * BinderManager when |wpa_supplicant_add_iface| is called. */
Roshan Pius32c15e22016-07-07 13:46:39 -070051 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070052 status = android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070053 ERROR_GENERIC,
54 "wpa_supplicant couldn't grab this interface.");
Dmitry Shmidte4663042016-04-04 10:07:49 -070055 } else {
56 BinderManager *binder_manager = BinderManager::getInstance();
57
58 if (!binder_manager ||
Roshan Pius32c15e22016-07-07 13:46:39 -070059 binder_manager->getIfaceBinderObjectByIfname(
Roshan Piusc9422c72016-07-11 10:18:22 -070060 wpa_s->ifname, iface_object_out)) {
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070061 status =
62 android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070063 ERROR_GENERIC,
64 "wpa_supplicant encountered a binder error.");
Roshan Pius32c15e22016-07-07 13:46:39 -070065 } else {
Dmitry Shmidte4663042016-04-04 10:07:49 -070066 status = android::binder::Status::ok();
Roshan Pius32c15e22016-07-07 13:46:39 -070067 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070068 }
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070069 os_free((void *)iface.driver);
70 os_free((void *)iface.ifname);
71 os_free((void *)iface.confname);
72 os_free((void *)iface.bridge_ifname);
Dmitry Shmidte4663042016-04-04 10:07:49 -070073 return status;
74}
75
Dmitry Shmidte4663042016-04-04 10:07:49 -070076android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
77{
78 struct wpa_supplicant *wpa_s;
79
80 wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
Roshan Pius32c15e22016-07-07 13:46:39 -070081 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070082 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070083 ERROR_IFACE_UNKNOWN,
Roshan Piusd6e37512016-07-07 13:20:46 -070084 "wpa_supplicant does not control this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070085 }
86 if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
Dmitry Shmidte4663042016-04-04 10:07:49 -070087 return android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -070088 ERROR_GENERIC,
89 "wpa_supplicant couldn't remove this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -070090 }
Dmitry Shmidte4663042016-04-04 10:07:49 -070091 return android::binder::Status::ok();
92}
93
Dmitry Shmidte4663042016-04-04 10:07:49 -070094android::binder::Status Supplicant::GetInterface(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070095 const std::string &ifname,
Roshan Piusc9422c72016-07-11 10:18:22 -070096 android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
Dmitry Shmidte4663042016-04-04 10:07:49 -070097{
98 struct wpa_supplicant *wpa_s;
99
100 wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
Roshan Pius32c15e22016-07-07 13:46:39 -0700101 if (!wpa_s) {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700102 return android::binder::Status::fromServiceSpecificError(
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700103 ERROR_IFACE_UNKNOWN,
Roshan Piusd6e37512016-07-07 13:20:46 -0700104 "wpa_supplicant does not control this interface.");
Roshan Pius32c15e22016-07-07 13:46:39 -0700105 }
Dmitry Shmidte4663042016-04-04 10:07:49 -0700106
107 BinderManager *binder_manager = BinderManager::getInstance();
108 if (!binder_manager ||
Roshan Pius32c15e22016-07-07 13:46:39 -0700109 binder_manager->getIfaceBinderObjectByIfname(
Roshan Piusc9422c72016-07-11 10:18:22 -0700110 wpa_s->ifname, iface_object_out)) {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700111 return android::binder::Status::fromServiceSpecificError(
Roshan Piusd6e37512016-07-07 13:20:46 -0700112 ERROR_GENERIC,
113 "wpa_supplicant encountered a binder error.");
Roshan Pius32c15e22016-07-07 13:46:39 -0700114 }
Dmitry Shmidte4663042016-04-04 10:07:49 -0700115
116 return android::binder::Status::ok();
117}
118
Roshan Piusc9422c72016-07-11 10:18:22 -0700119android::binder::Status
120Supplicant::SetDebugParams(int level, bool show_timestamp, bool show_keys)
121{
122 int internal_level;
123 if (convertDebugLevelToInternalLevel(level, &internal_level)) {
124 const std::string error_msg =
125 "invalid debug level: " + std::to_string(level);
126 return android::binder::Status::fromExceptionCode(
127 android::binder::Status::EX_ILLEGAL_ARGUMENT,
128 error_msg.c_str());
129 }
130 if (wpa_supplicant_set_debug_params(
131 wpa_global_, internal_level, show_timestamp, show_keys)) {
132 return android::binder::Status::fromServiceSpecificError(
133 ERROR_GENERIC,
134 "wpa_supplicant could not set debug params.");
135 }
136 return android::binder::Status::ok();
137}
138
139android::binder::Status Supplicant::GetDebugLevel(int *level_out)
140{
141 if (convertDebugLevelToExternalLevel(wpa_debug_level, level_out)) {
142 const std::string error_msg =
143 "invalid debug level: " + std::to_string(wpa_debug_level);
144 return android::binder::Status::fromExceptionCode(
145 android::binder::Status::EX_ILLEGAL_ARGUMENT,
146 error_msg.c_str());
147 }
148 return android::binder::Status::ok();
149}
150
151android::binder::Status
152Supplicant::GetDebugShowTimestamp(bool *show_timestamp_out)
153{
154 *show_timestamp_out = wpa_debug_timestamp ? true : false;
155 return android::binder::Status::ok();
156}
157
158android::binder::Status Supplicant::GetDebugShowKeys(bool *show_keys_out)
159{
160 *show_keys_out = wpa_debug_show_keys ? true : false;
161 return android::binder::Status::ok();
162}
163
164/**
165 * Helper function to convert the debug level parameter from the binder
166 * interface values to internal values.
167 */
168int Supplicant::convertDebugLevelToInternalLevel(
169 int external_level, int *internal_level)
170{
171 switch (external_level) {
172 case DEBUG_LEVEL_EXCESSIVE:
173 *internal_level = MSG_EXCESSIVE;
174 return 0;
175 case DEBUG_LEVEL_MSGDUMP:
176 *internal_level = MSG_MSGDUMP;
177 return 0;
178 case DEBUG_LEVEL_DEBUG:
179 *internal_level = MSG_DEBUG;
180 return 0;
181 case DEBUG_LEVEL_INFO:
182 *internal_level = MSG_INFO;
183 return 0;
184 case DEBUG_LEVEL_WARNING:
185 *internal_level = MSG_WARNING;
186 return 0;
187 case DEBUG_LEVEL_ERROR:
188 *internal_level = MSG_ERROR;
189 return 0;
190 default:
191 wpa_printf(
192 MSG_ERROR, "Invalid external log level: %d",
193 external_level);
194 return 1;
195 }
196}
197
198/**
199 * Helper function to convert the debug level parameter from the internal values
200 * to binder interface values.
201 */
202int Supplicant::convertDebugLevelToExternalLevel(
203 int internal_level, int *external_level)
204{
205 switch (internal_level) {
206 case MSG_EXCESSIVE:
207 *external_level = DEBUG_LEVEL_EXCESSIVE;
208 return 0;
209 case MSG_MSGDUMP:
210 *external_level = DEBUG_LEVEL_MSGDUMP;
211 return 0;
212 case MSG_DEBUG:
213 *external_level = DEBUG_LEVEL_DEBUG;
214 return 0;
215 case MSG_INFO:
216 *external_level = DEBUG_LEVEL_INFO;
217 return 0;
218 case MSG_WARNING:
219 *external_level = DEBUG_LEVEL_WARNING;
220 return 0;
221 case MSG_ERROR:
222 *external_level = DEBUG_LEVEL_ERROR;
223 return 0;
224 default:
225 wpa_printf(
226 MSG_ERROR, "Invalid internal log level: %d",
227 internal_level);
228 return 1;
229 }
230}
Dmitry Shmidte4663042016-04-04 10:07:49 -0700231} /* namespace wpa_supplicant_binder */