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