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>
This commit is contained in:
parent
7b4bbb9f94
commit
f1a5a34d8e
8 changed files with 262 additions and 0 deletions
|
@ -78,3 +78,31 @@ void wpas_binder_deinit(struct wpas_binder_priv *priv)
|
||||||
eloop_unregister_read_sock(priv->binder_fd);
|
eloop_unregister_read_sock(priv->binder_fd);
|
||||||
android::IPCThreadState::shutdown();
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,20 @@ struct wpa_global;
|
||||||
struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global);
|
struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global);
|
||||||
void wpas_binder_deinit(struct wpas_binder_priv *priv);
|
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
|
#ifdef _cplusplus
|
||||||
}
|
}
|
||||||
#endif /* _cplusplus */
|
#endif /* _cplusplus */
|
||||||
|
|
|
@ -50,4 +50,58 @@ int BinderManager::registerBinderService(struct wpa_global *global)
|
||||||
return 0;
|
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 */
|
} /* namespace wpa_supplicant_binder */
|
||||||
|
|
|
@ -34,6 +34,11 @@ public:
|
||||||
static BinderManager * getInstance();
|
static BinderManager * getInstance();
|
||||||
static void destroyInstance();
|
static void destroyInstance();
|
||||||
int registerBinderService(struct wpa_global *global);
|
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:
|
private:
|
||||||
BinderManager() = default;
|
BinderManager() = default;
|
||||||
|
|
|
@ -10,10 +10,50 @@
|
||||||
package fi.w1.wpa_supplicant;
|
package fi.w1.wpa_supplicant;
|
||||||
|
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
|
import fi.w1.wpa_supplicant.IIface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface exposed by the wpa_supplicant binder service registered
|
* Interface exposed by the wpa_supplicant binder service registered
|
||||||
* with the service manager with name: fi.w1.wpa_supplicant.
|
* with the service manager with name: fi.w1.wpa_supplicant.
|
||||||
*/
|
*/
|
||||||
interface ISupplicant {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "binder_manager.h"
|
||||||
#include "supplicant.h"
|
#include "supplicant.h"
|
||||||
|
|
||||||
namespace wpa_supplicant_binder {
|
namespace wpa_supplicant_binder {
|
||||||
|
@ -16,4 +17,109 @@ 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 = 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 */
|
} /* namespace wpa_supplicant_binder */
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define SUPPLICANT_H
|
#define SUPPLICANT_H
|
||||||
|
|
||||||
#include "fi/w1/wpa_supplicant/BnSupplicant.h"
|
#include "fi/w1/wpa_supplicant/BnSupplicant.h"
|
||||||
|
#include "fi/w1/wpa_supplicant/IIface.h"
|
||||||
#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
|
#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -32,6 +33,17 @@ public:
|
||||||
Supplicant(struct wpa_global *global);
|
Supplicant(struct wpa_global *global);
|
||||||
virtual ~Supplicant() = default;
|
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 std::string &ifname) override;
|
||||||
|
android::binder::Status GetInterface(
|
||||||
|
const std::string &ifname,
|
||||||
|
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
|
||||||
|
override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* Raw pointer to the global structure maintained by the core. */
|
/* Raw pointer to the global structure maintained by the core. */
|
||||||
struct wpa_global *wpa_global_;
|
struct wpa_global *wpa_global_;
|
||||||
|
|
|
@ -484,6 +484,9 @@ struct wpa_supplicant {
|
||||||
char *preq_notify_peer;
|
char *preq_notify_peer;
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
#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 bridge_ifname[16];
|
||||||
|
|
||||||
char *confname;
|
char *confname;
|
||||||
|
|
Loading…
Reference in a new issue