This CL implements the methods defined in Supplicant service: 1. CreateInterface 2. RemoveInterface 3. GetInterface The binder service returns the corresponding iface binder object references which can be used by clients to control a specific interface. BUG: 22957177 TEST: `mmm -j32 external/wpa_supplicant_8/wpa_supplicant` with CONFIG_CTRL_IFACE_BINDER=y. Change-Id: I086b1a17016eca13a9ce8759f63c048044e9f0f4 Signed-off-by: Roshan Pius <rpius@xxxxxxxxxx> --- wpa_supplicant/binder/binder.cpp | 27 ++++++ wpa_supplicant/binder/binder.h | 15 ++++ wpa_supplicant/binder/binder_manager.cpp | 51 +++++++++++ wpa_supplicant/binder/binder_manager.h | 5 ++ .../binder/fi/w1/wpa_supplicant/ISupplicant.aidl | 38 +++++++++ wpa_supplicant/binder/supplicant.cpp | 99 ++++++++++++++++++++++ wpa_supplicant/binder/supplicant.h | 10 +++ wpa_supplicant/wpa_supplicant_i.h | 3 + 8 files changed, 248 insertions(+) diff --git a/wpa_supplicant/binder/binder.cpp b/wpa_supplicant/binder/binder.cpp index 580f585..4419d7b 100644 --- a/wpa_supplicant/binder/binder.cpp +++ b/wpa_supplicant/binder/binder.cpp @@ -84,3 +84,30 @@ void wpas_binder_deinit(struct wpas_binder_priv *priv) eloop_unregister_read_sock(priv->binder_fd); android::IPCThreadState::shutdown(); } + +int wpas_binder_register_interface(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->global->binder == NULL) + return 1; + + wpa_supplicant_binder::BinderManager *binder_manager = + wpa_supplicant_binder::BinderManager::getInstance(); + if (binder_manager == NULL) + return 1; + + return binder_manager->registerInterface(wpa_s); +} + +int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->global->binder == NULL) + return 1; + + wpa_supplicant_binder::BinderManager *binder_manager = + wpa_supplicant_binder::BinderManager::getInstance(); + if (binder_manager == NULL) + return 1; + + return binder_manager->unregisterInterface(wpa_s); +} + diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h index eb7b70f..8444ac5 100644 --- a/wpa_supplicant/binder/binder.h +++ b/wpa_supplicant/binder/binder.h @@ -32,6 +32,21 @@ struct wpa_global; struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global); void wpas_binder_deinit(struct wpas_binder_priv *priv); +#ifdef CONFIG_CTRL_IFACE_BINDER +int wpas_binder_register_interface(struct wpa_supplicant *wpa_s); +int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s); + +#else /* CONFIG_CTRL_IFACE_BINDER */ +static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s) +{ + return 0; +} +static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s) +{ + return 0; +} +#endif /* CONFIG_CTRL_IFACE_BINDER */ + #ifdef _cplusplus } #endif /* _cplusplus */ diff --git a/wpa_supplicant/binder/binder_manager.cpp b/wpa_supplicant/binder/binder_manager.cpp index eb2d60b..f57002d 100644 --- a/wpa_supplicant/binder/binder_manager.cpp +++ b/wpa_supplicant/binder/binder_manager.cpp @@ -53,4 +53,55 @@ int BinderManager::registerBinderService(struct wpa_global *global) return 0; } +int BinderManager::registerInterface(struct wpa_supplicant *wpa_s) +{ + if (wpa_s == NULL) + return 1; + + // Using the corresponding wpa_supplicant pointer as key to our + // object map. + const void *iface_key = wpa_s; + + // Return failure if we already have an object for that iface_key. + if (iface_object_map_.find(iface_key) != iface_object_map_.end()) + return 1; + + iface_object_map_[iface_key] = new Iface(wpa_s); + if (iface_object_map_[iface_key].get() == NULL) + return 1; + + wpa_s->binder_object_key = iface_key; + + return 0; +} + +int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s) +{ + if (wpa_s == NULL || wpa_s->binder_object_key == NULL) + return 1; + + const void *iface_key = wpa_s; + if (iface_object_map_.find(iface_key) == iface_object_map_.end()) + return 1; + + // Delete the corresponding iface object from our map. + iface_object_map_.erase(iface_key); + wpa_s->binder_object_key = NULL; + return 0; +} + +int BinderManager::getIfaceBinderObjectByKey( + const void *iface_object_key, + android::sp<fi::w1::wpa_supplicant::IIface> *iface_object) +{ + if (iface_object_key == NULL || iface_object == NULL) + return 1; + + if (iface_object_map_.find(iface_object_key) == iface_object_map_.end()) + return 1; + + *iface_object = iface_object_map_[iface_object_key]; + return 0; +} + } // namespace wpa_supplicant_binder diff --git a/wpa_supplicant/binder/binder_manager.h b/wpa_supplicant/binder/binder_manager.h index 7b9d95f..8021c0e 100644 --- a/wpa_supplicant/binder/binder_manager.h +++ b/wpa_supplicant/binder/binder_manager.h @@ -40,6 +40,11 @@ public: static BinderManager *getInstance(); static void destroyInstance(); int registerBinderService(struct wpa_global *global); + int registerInterface(struct wpa_supplicant *wpa_s); + int unregisterInterface(struct wpa_supplicant *wpa_s); + int getIfaceBinderObjectByKey( + const void *iface_object_key, + android::sp<fi::w1::wpa_supplicant::IIface> *iface_object); private: BinderManager() = default; diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl index 889663d..67d4e2f 100644 --- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl +++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl @@ -17,10 +17,48 @@ package fi.w1.wpa_supplicant; import android.os.PersistableBundle; +import fi.w1.wpa_supplicant.IIface; /** * Interface exposed by the wpa_supplicant binder service registered * with the service manager with name: fi.w1.wpa_supplicant. */ interface ISupplicant { + /* Error values returned by the service to RPC method calls. */ + const int ERROR_INVALID_ARGS = 1; + const int ERROR_UNKNOWN = 2; + const int ERROR_IFACE_EXISTS = 3; + const int ERROR_IFACE_UNKNOWN = 4; + + /** + * Registers a wireless interface in wpa_supplicant. + * + * @param args A dictionary with arguments used to add the interface to + * wpa_supplicant. + * The dictionary may contain the following entries: + * Ifname(String) Name of the network interface to control, e.g., wlan0. + * BridgeIfname(String) Name of the bridge interface to control, e.g., br0. + * Driver(String) Driver name which the interface uses, e.g., nl80211. + * ConfigFile(String) Configuration file path. + * + * @return Binder object representing the interface. + */ + IIface CreateInterface(in PersistableBundle args); + + /** + * Deregisters a wireless interface from wpa_supplicant. + * + * @param ifname Name of the network interface, e.g., wlan0 + */ + void RemoveInterface(in String ifname); + + /** + * Gets a binder object for the interface corresponding to ifname + * which wpa_supplicant already controls. + * + * @param ifname Name of the network interface, e.g., wlan0 + * + * @return Binder object representing the interface. + */ + IIface GetInterface(in String ifname); } diff --git a/wpa_supplicant/binder/supplicant.cpp b/wpa_supplicant/binder/supplicant.cpp index 8eafcb7..be02142 100644 --- a/wpa_supplicant/binder/supplicant.cpp +++ b/wpa_supplicant/binder/supplicant.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "binder_manager.h" #include "supplicant.h" namespace wpa_supplicant_binder { @@ -23,4 +24,102 @@ Supplicant::Supplicant(struct 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::fromServiceSpecificError( + ERROR_INVALID_ARGS, android::String8("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, + android::String8("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 = strdup(android::String8(driver).string()); + iface.ifname = strdup(android::String8(ifname).string()); + iface.confname = strdup(android::String8(confname).string()); + iface.bridge_ifname = 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 == NULL || wpa_s->binder_object_key == NULL) + status = android::binder::Status::fromServiceSpecificError( + ERROR_UNKNOWN, + android::String8("wpa_supplicant couldn't grab this interface.")); + else { + BinderManager *binder_manager = BinderManager::getInstance(); + if (binder_manager == NULL || + binder_manager->getIfaceBinderObjectByKey( + wpa_s->binder_object_key, aidl_return)) + status = android::binder::Status::fromServiceSpecificError( + ERROR_UNKNOWN, + android::String8("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 android::String16 &ifname) +{ + struct wpa_supplicant *wpa_s = NULL; + wpa_s = wpa_supplicant_get_iface( + wpa_global_, android::String8(ifname).string()); + if (wpa_s == NULL || wpa_s->binder_object_key == NULL) + return android::binder::Status::fromServiceSpecificError( + ERROR_IFACE_UNKNOWN, + android::String8("wpa_supplicant does not control this interface.")); + else if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) + return android::binder::Status::fromServiceSpecificError( + ERROR_UNKNOWN, + android::String8("wpa_supplicant couldn't remove this interface.")); + return android::binder::Status::ok(); +} + +android::binder::Status Supplicant::GetInterface( + const android::String16 &ifname, + android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) +{ + struct wpa_supplicant *wpa_s = NULL; + wpa_s = wpa_supplicant_get_iface( + wpa_global_, android::String8(ifname).string()); + if (wpa_s == NULL || wpa_s->binder_object_key == NULL) + return android::binder::Status::fromServiceSpecificError( + ERROR_IFACE_UNKNOWN, + android::String8("wpa_supplicant does not control this interface.")); + BinderManager *binder_manager = BinderManager::getInstance(); + if (binder_manager == NULL || + binder_manager->getIfaceBinderObjectByKey( + wpa_s->binder_object_key, aidl_return)) + return android::binder::Status::fromServiceSpecificError( + ERROR_UNKNOWN, + android::String8("wpa_supplicant encountered a binder error.")); + return android::binder::Status::ok(); +} + } // namespace wpa_supplicant_binder diff --git a/wpa_supplicant/binder/supplicant.h b/wpa_supplicant/binder/supplicant.h index c5858f8..22ad038 100644 --- a/wpa_supplicant/binder/supplicant.h +++ b/wpa_supplicant/binder/supplicant.h @@ -18,6 +18,7 @@ #define SUPPLICANT_H #include "fi/w1/wpa_supplicant/BnSupplicant.h" +#include "fi/w1/wpa_supplicant/IIface.h" #include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h" extern "C" { @@ -38,6 +39,15 @@ public: Supplicant(struct wpa_global *global); virtual ~Supplicant() = default; + android::binder::Status CreateInterface( + const android::os::PersistableBundle ¶ms, + android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override; + android::binder::Status RemoveInterface( + const android::String16 &ifname) override; + android::binder::Status GetInterface( + const android::String16 &ifname, + android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override; + private: // Raw pointer to the global structure maintained by the core. struct wpa_global *wpa_global_; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d049e8a..267accc 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -465,6 +465,9 @@ struct wpa_supplicant { char *preq_notify_peer; #endif /* CONFIG_AP */ #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ +#ifdef CONFIG_CTRL_IFACE_BINDER + const void *binder_object_key; +#endif /* CONFIG_CTRL_IFACE_BINDER */ char bridge_ifname[16]; char *confname; -- 2.7.0.rc3.207.g0ac5344 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap