| /* |
| * binder interface for wpa_supplicant daemon |
| * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> |
| * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com> |
| * |
| * This software may be distributed under the terms of the BSD license. |
| * See README for more details. |
| */ |
| |
| #include "supplicant.h" |
| #include "binder_manager.h" |
| |
| namespace wpa_supplicant_binder { |
| |
| Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {} |
| |
| android::binder::Status Supplicant::CreateInterface( |
| const android::os::PersistableBundle ¶ms, |
| android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) |
| { |
| android::String16 driver, ifname, confname, bridge_ifname; |
| |
| /* Check if required Ifname argument is missing */ |
| if (!params.getString(android::String16("Ifname"), &ifname)) { |
| return android::binder::Status::fromExceptionCode( |
| android::binder::Status::EX_ILLEGAL_ARGUMENT, |
| "Ifname missing in params."); |
| } |
| /* Retrieve the remaining params from the dictionary */ |
| params.getString(android::String16("Driver"), &driver); |
| params.getString(android::String16("ConfigFile"), &confname); |
| params.getString(android::String16("BridgeIfname"), &bridge_ifname); |
| |
| /* |
| * Try to get the wpa_supplicant record for this iface, return |
| * an error if we already control it. |
| */ |
| if (wpa_supplicant_get_iface( |
| wpa_global_, android::String8(ifname).string()) != NULL) { |
| return android::binder::Status::fromServiceSpecificError( |
| ERROR_IFACE_EXISTS, |
| "wpa_supplicant already controls this interface."); |
| } |
| |
| android::binder::Status status; |
| struct wpa_supplicant *wpa_s = NULL; |
| struct wpa_interface iface; |
| |
| os_memset(&iface, 0, sizeof(iface)); |
| iface.driver = os_strdup(android::String8(driver).string()); |
| iface.ifname = os_strdup(android::String8(ifname).string()); |
| iface.confname = os_strdup(android::String8(confname).string()); |
| iface.bridge_ifname = |
| os_strdup(android::String8(bridge_ifname).string()); |
| /* Otherwise, have wpa_supplicant attach to it. */ |
| wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL); |
| /* The supplicant core creates a corresponding binder object via |
| * BinderManager when |wpa_supplicant_add_iface| is called. */ |
| if (!wpa_s) { |
| status = android::binder::Status::fromServiceSpecificError( |
| ERROR_GENERIC, |
| "wpa_supplicant couldn't grab this interface."); |
| } else { |
| BinderManager *binder_manager = BinderManager::getInstance(); |
| |
| if (!binder_manager || |
| binder_manager->getIfaceBinderObjectByIfname( |
| wpa_s->ifname, aidl_return)) { |
| status = |
| android::binder::Status::fromServiceSpecificError( |
| ERROR_GENERIC, |
| "wpa_supplicant encountered a binder error."); |
| } else { |
| status = android::binder::Status::ok(); |
| } |
| } |
| os_free((void *)iface.driver); |
| os_free((void *)iface.ifname); |
| os_free((void *)iface.confname); |
| os_free((void *)iface.bridge_ifname); |
| return status; |
| } |
| |
| android::binder::Status Supplicant::RemoveInterface(const std::string &ifname) |
| { |
| struct wpa_supplicant *wpa_s; |
| |
| wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str()); |
| if (!wpa_s) { |
| return android::binder::Status::fromServiceSpecificError( |
| ERROR_IFACE_UNKNOWN, |
| "wpa_supplicant does not control this interface."); |
| } |
| if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) { |
| return android::binder::Status::fromServiceSpecificError( |
| ERROR_GENERIC, |
| "wpa_supplicant couldn't remove this interface."); |
| } |
| return android::binder::Status::ok(); |
| } |
| |
| android::binder::Status Supplicant::GetInterface( |
| const std::string &ifname, |
| android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) |
| { |
| struct wpa_supplicant *wpa_s; |
| |
| wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str()); |
| if (!wpa_s) { |
| return android::binder::Status::fromServiceSpecificError( |
| ERROR_IFACE_UNKNOWN, |
| "wpa_supplicant does not control this interface."); |
| } |
| |
| BinderManager *binder_manager = BinderManager::getInstance(); |
| if (!binder_manager || |
| binder_manager->getIfaceBinderObjectByIfname( |
| wpa_s->ifname, aidl_return)) { |
| return android::binder::Status::fromServiceSpecificError( |
| ERROR_GENERIC, |
| "wpa_supplicant encountered a binder error."); |
| } |
| |
| return android::binder::Status::ok(); |
| } |
| |
| } /* namespace wpa_supplicant_binder */ |