Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 1 | /* |
| 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 Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 10 | #include "binder_manager.h" |
Roshan Pius | 0470cc8 | 2016-07-14 16:37:07 -0700 | [diff] [blame] | 11 | #include "supplicant.h" |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 12 | |
| 13 | namespace wpa_supplicant_binder { |
| 14 | |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 15 | Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {} |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 16 | android::binder::Status Supplicant::CreateInterface( |
Roshan Pius | b01b796 | 2016-07-11 15:25:47 -0700 | [diff] [blame] | 17 | const fi::w1::wpa_supplicant::ParcelableIfaceParams ¶ms, |
Roshan Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 18 | android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out) |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 19 | { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 20 | /* Check if required Ifname argument is missing */ |
Roshan Pius | b01b796 | 2016-07-11 15:25:47 -0700 | [diff] [blame] | 21 | if (params.ifname_.isEmpty()) { |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 22 | return android::binder::Status::fromExceptionCode( |
| 23 | android::binder::Status::EX_ILLEGAL_ARGUMENT, |
| 24 | "Ifname missing in params."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 25 | } |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 26 | /* |
| 27 | * Try to get the wpa_supplicant record for this iface, return |
| 28 | * an error if we already control it. |
| 29 | */ |
Roshan Pius | b01b796 | 2016-07-11 15:25:47 -0700 | [diff] [blame] | 30 | if (wpa_supplicant_get_iface(wpa_global_, params.ifname_.string()) != |
| 31 | NULL) { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 32 | return android::binder::Status::fromServiceSpecificError( |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 33 | ERROR_IFACE_EXISTS, |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 34 | "wpa_supplicant already controls this interface."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 35 | } |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 36 | |
| 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 Pius | b01b796 | 2016-07-11 15:25:47 -0700 | [diff] [blame] | 42 | 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 Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 46 | /* 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 Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 50 | if (!wpa_s) { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 51 | status = android::binder::Status::fromServiceSpecificError( |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 52 | ERROR_GENERIC, |
| 53 | "wpa_supplicant couldn't grab this interface."); |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 54 | } else { |
| 55 | BinderManager *binder_manager = BinderManager::getInstance(); |
| 56 | |
| 57 | if (!binder_manager || |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 58 | binder_manager->getIfaceBinderObjectByIfname( |
Roshan Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 59 | wpa_s->ifname, iface_object_out)) { |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 60 | status = |
| 61 | android::binder::Status::fromServiceSpecificError( |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 62 | ERROR_GENERIC, |
| 63 | "wpa_supplicant encountered a binder error."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 64 | } else { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 65 | status = android::binder::Status::ok(); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 66 | } |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 67 | } |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 68 | 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 Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 72 | return status; |
| 73 | } |
| 74 | |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 75 | android::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 Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 80 | if (!wpa_s) { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 81 | return android::binder::Status::fromServiceSpecificError( |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 82 | ERROR_IFACE_UNKNOWN, |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 83 | "wpa_supplicant does not control this interface."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 84 | } |
| 85 | if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 86 | return android::binder::Status::fromServiceSpecificError( |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 87 | ERROR_GENERIC, |
| 88 | "wpa_supplicant couldn't remove this interface."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 89 | } |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 90 | return android::binder::Status::ok(); |
| 91 | } |
| 92 | |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 93 | android::binder::Status Supplicant::GetInterface( |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 94 | const std::string &ifname, |
Roshan Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 95 | android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out) |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 96 | { |
| 97 | struct wpa_supplicant *wpa_s; |
| 98 | |
| 99 | wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str()); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 100 | if (!wpa_s) { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 101 | return android::binder::Status::fromServiceSpecificError( |
Dmitry Shmidt | 7f2c753 | 2016-08-15 09:48:12 -0700 | [diff] [blame] | 102 | ERROR_IFACE_UNKNOWN, |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 103 | "wpa_supplicant does not control this interface."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 104 | } |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 105 | |
| 106 | BinderManager *binder_manager = BinderManager::getInstance(); |
| 107 | if (!binder_manager || |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 108 | binder_manager->getIfaceBinderObjectByIfname( |
Roshan Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 109 | wpa_s->ifname, iface_object_out)) { |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 110 | return android::binder::Status::fromServiceSpecificError( |
Roshan Pius | d6e3751 | 2016-07-07 13:20:46 -0700 | [diff] [blame] | 111 | ERROR_GENERIC, |
| 112 | "wpa_supplicant encountered a binder error."); |
Roshan Pius | 32c15e2 | 2016-07-07 13:46:39 -0700 | [diff] [blame] | 113 | } |
Dmitry Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 114 | |
| 115 | return android::binder::Status::ok(); |
| 116 | } |
| 117 | |
Roshan Pius | 32f9f5f | 2016-08-15 14:44:22 -0700 | [diff] [blame^] | 118 | android::binder::Status Supplicant::SetDebugParams( |
| 119 | int level, bool show_timestamp, bool show_keys) |
Roshan Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 120 | { |
| 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 | |
| 138 | android::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 Pius | 32f9f5f | 2016-08-15 14:44:22 -0700 | [diff] [blame^] | 150 | android::binder::Status Supplicant::GetDebugShowTimestamp( |
| 151 | bool *show_timestamp_out) |
Roshan Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 152 | { |
| 153 | *show_timestamp_out = wpa_debug_timestamp ? true : false; |
| 154 | return android::binder::Status::ok(); |
| 155 | } |
| 156 | |
| 157 | android::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 Pius | 0470cc8 | 2016-07-14 16:37:07 -0700 | [diff] [blame] | 163 | android::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 Pius | c9422c7 | 2016-07-11 10:18:22 -0700 | [diff] [blame] | 176 | /** |
| 177 | * Helper function to convert the debug level parameter from the binder |
| 178 | * interface values to internal values. |
| 179 | */ |
| 180 | int 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 | */ |
| 214 | int 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 Shmidt | e466304 | 2016-04-04 10:07:49 -0700 | [diff] [blame] | 243 | } /* namespace wpa_supplicant_binder */ |