aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/binder
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2016-02-17 00:40:06 (GMT)
committerJouni Malinen <j@w1.fi>2016-04-02 14:35:28 (GMT)
commitf1a5a34d8e5554d4286842f91797d811a713a5fc (patch)
tree7530798d290bc1c60d8085686707e79a7ed53036 /wpa_supplicant/binder
parent7b4bbb9f946fb6861b2b4ded0f10949277514047 (diff)
downloadhostap-f1a5a34d8e5554d4286842f91797d811a713a5fc.zip
hostap-f1a5a34d8e5554d4286842f91797d811a713a5fc.tar.gz
hostap-f1a5a34d8e5554d4286842f91797d811a713a5fc.tar.bz2
binder: Implement interface add/remove methods
This commit 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. Signed-off-by: Roshan Pius <rpius@google.com>
Diffstat (limited to 'wpa_supplicant/binder')
-rw-r--r--wpa_supplicant/binder/binder.cpp28
-rw-r--r--wpa_supplicant/binder/binder.h14
-rw-r--r--wpa_supplicant/binder/binder_manager.cpp54
-rw-r--r--wpa_supplicant/binder/binder_manager.h5
-rw-r--r--wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl40
-rw-r--r--wpa_supplicant/binder/supplicant.cpp106
-rw-r--r--wpa_supplicant/binder/supplicant.h12
7 files changed, 259 insertions, 0 deletions
diff --git a/wpa_supplicant/binder/binder.cpp b/wpa_supplicant/binder/binder.cpp
index 59ee9a5..28f7a2b 100644
--- a/wpa_supplicant/binder/binder.cpp
+++ b/wpa_supplicant/binder/binder.cpp
@@ -78,3 +78,31 @@ 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)
+ return 1;
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ return 1;
+
+ return binder_manager->registerInterface(wpa_s);
+}
+
+
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->global->binder)
+ return 1;
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ return 1;
+
+ return binder_manager->unregisterInterface(wpa_s);
+}
diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h
index 6406f09..a165074 100644
--- a/wpa_supplicant/binder/binder.h
+++ b/wpa_supplicant/binder/binder.h
@@ -25,6 +25,20 @@ 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 9c35b23..728f4b7 100644
--- a/wpa_supplicant/binder/binder_manager.cpp
+++ b/wpa_supplicant/binder/binder_manager.cpp
@@ -50,4 +50,58 @@ int BinderManager::registerBinderService(struct wpa_global *global)
return 0;
}
+
+int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ 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())
+ return 1;
+
+ wpa_s->binder_object_key = iface_key;
+
+ return 0;
+}
+
+
+int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s || !wpa_s->binder_object_key)
+ 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 || !iface_object)
+ 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 011fa3e..687e740 100644
--- a/wpa_supplicant/binder/binder_manager.h
+++ b/wpa_supplicant/binder/binder_manager.h
@@ -34,6 +34,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 5be2391..1cbee20 100644
--- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
@@ -10,10 +10,50 @@
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 @utf8InCpp 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 @utf8InCpp String ifname);
}
diff --git a/wpa_supplicant/binder/supplicant.cpp b/wpa_supplicant/binder/supplicant.cpp
index 053f329..6844e5a 100644
--- a/wpa_supplicant/binder/supplicant.cpp
+++ b/wpa_supplicant/binder/supplicant.cpp
@@ -7,6 +7,7 @@
* See README for more details.
*/
+#include "binder_manager.h"
#include "supplicant.h"
namespace wpa_supplicant_binder {
@@ -16,4 +17,109 @@ Supplicant::Supplicant(struct wpa_global *global)
{
}
+
+android::binder::Status Supplicant::CreateInterface(
+ const android::os::PersistableBundle &params,
+ 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 = 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 || !wpa_s->binder_object_key) {
+ 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 ||
+ 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 std::string &ifname)
+{
+ struct wpa_supplicant *wpa_s;
+
+ wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
+ if (!wpa_s || !wpa_s->binder_object_key)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_UNKNOWN,
+ android::String8("wpa_supplicant does not control this interface."));
+ 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 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 || !wpa_s->binder_object_key)
+ 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 ||
+ 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 02b5918..b96f4e6 100644
--- a/wpa_supplicant/binder/supplicant.h
+++ b/wpa_supplicant/binder/supplicant.h
@@ -11,6 +11,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" {
@@ -32,6 +33,17 @@ public:
Supplicant(struct wpa_global *global);
virtual ~Supplicant() = default;
+ android::binder::Status CreateInterface(
+ const android::os::PersistableBundle &params,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+ override;
+ android::binder::Status RemoveInterface(
+ const std::string &ifname) override;
+ android::binder::Status GetInterface(
+ const std::string &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_;