Added support for global driver data (shared by multiple interfaces)
Driver wrappers can now register global_init() and global_deinit() driver_ops handlers to get a global data structure that can be shared for all interfaces. This allows driver wrappers to initialize some functionality (e.g., interface monitoring) before any interfaces have been initialized.
This commit is contained in:
parent
e83a089818
commit
ac305589a3
6 changed files with 110 additions and 6 deletions
|
@ -956,6 +956,41 @@ struct wpa_driver_ops {
|
||||||
* of setting a regulatory domain.
|
* of setting a regulatory domain.
|
||||||
*/
|
*/
|
||||||
int (*set_country)(void *priv, const char *alpha2);
|
int (*set_country)(void *priv, const char *alpha2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* global_init - Global driver initialization
|
||||||
|
* Returns: Pointer to private data (global), %NULL on failure
|
||||||
|
*
|
||||||
|
* This optional function is called to initialize the driver wrapper
|
||||||
|
* for global data, i.e., data that applies to all interfaces. If this
|
||||||
|
* function is implemented, global_deinit() will also need to be
|
||||||
|
* implemented to free the private data. The driver will also likely
|
||||||
|
* use init2() function instead of init() to get the pointer to global
|
||||||
|
* data available to per-interface initializer.
|
||||||
|
*/
|
||||||
|
void * (*global_init)(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* global_deinit - Global driver deinitialization
|
||||||
|
* @priv: private driver global data from global_init()
|
||||||
|
*
|
||||||
|
* Terminate any global driver related functionality and free the
|
||||||
|
* global data structure.
|
||||||
|
*/
|
||||||
|
void (*global_deinit)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init2 - Initialize driver interface (with global data)
|
||||||
|
* @ctx: context to be used when calling wpa_supplicant functions,
|
||||||
|
* e.g., wpa_supplicant_event()
|
||||||
|
* @ifname: interface name, e.g., wlan0
|
||||||
|
* @global_priv: private driver global data from global_init()
|
||||||
|
* Returns: Pointer to private data, %NULL on failure
|
||||||
|
*
|
||||||
|
* This function can be used instead of init() if the driver wrapper
|
||||||
|
* uses global data.
|
||||||
|
*/
|
||||||
|
void * (*init2)(void *ctx, const char *ifname, void *global_priv);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Function to check whether a driver is for wired connections */
|
/* Function to check whether a driver is for wired connections */
|
||||||
|
|
|
@ -2884,5 +2884,8 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
||||||
wpa_driver_ndis_get_scan_results,
|
wpa_driver_ndis_get_scan_results,
|
||||||
NULL /* set_probe_req_ie */,
|
NULL /* set_probe_req_ie */,
|
||||||
NULL /* set_mode */,
|
NULL /* set_mode */,
|
||||||
NULL /* set_country */
|
NULL /* set_country */,
|
||||||
|
NULL /* global_init */,
|
||||||
|
NULL /* global_deinit */,
|
||||||
|
NULL /* init2 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -775,7 +775,10 @@ struct wpa_driver_ops wpa_driver_privsep_ops = {
|
||||||
wpa_driver_privsep_get_scan_results2,
|
wpa_driver_privsep_get_scan_results2,
|
||||||
NULL /* set_probe_req_ie */,
|
NULL /* set_probe_req_ie */,
|
||||||
wpa_driver_privsep_set_mode,
|
wpa_driver_privsep_set_mode,
|
||||||
NULL /* set_country */
|
NULL /* set_country */,
|
||||||
|
NULL /* global_init */,
|
||||||
|
NULL /* global_deinit */,
|
||||||
|
NULL /* init2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,12 @@
|
||||||
#include "ieee802_11_defs.h"
|
#include "ieee802_11_defs.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct wpa_driver_test_global {
|
||||||
|
int dummy;
|
||||||
|
};
|
||||||
|
|
||||||
struct wpa_driver_test_data {
|
struct wpa_driver_test_data {
|
||||||
|
struct wpa_driver_test_global *global;
|
||||||
void *ctx;
|
void *ctx;
|
||||||
u8 own_addr[ETH_ALEN];
|
u8 own_addr[ETH_ALEN];
|
||||||
int test_socket;
|
int test_socket;
|
||||||
|
@ -579,13 +584,15 @@ static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void * wpa_driver_test_init(void *ctx, const char *ifname)
|
static void * wpa_driver_test_init2(void *ctx, const char *ifname,
|
||||||
|
void *global_priv)
|
||||||
{
|
{
|
||||||
struct wpa_driver_test_data *drv;
|
struct wpa_driver_test_data *drv;
|
||||||
|
|
||||||
drv = os_zalloc(sizeof(*drv));
|
drv = os_zalloc(sizeof(*drv));
|
||||||
if (drv == NULL)
|
if (drv == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
drv->global = global_priv;
|
||||||
drv->ctx = ctx;
|
drv->ctx = ctx;
|
||||||
drv->test_socket = -1;
|
drv->test_socket = -1;
|
||||||
|
|
||||||
|
@ -1122,6 +1129,22 @@ int wpa_driver_set_probe_req_ie(void *priv, const u8 *ies, size_t ies_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void * wpa_driver_test_global_init(void)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_global *global;
|
||||||
|
|
||||||
|
global = os_zalloc(sizeof(*global));
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_driver_test_global_deinit(void *priv)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_global *global = priv;
|
||||||
|
os_free(global);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_test_ops = {
|
const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
"test",
|
"test",
|
||||||
"wpa_supplicant test driver",
|
"wpa_supplicant test driver",
|
||||||
|
@ -1129,7 +1152,7 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
wpa_driver_test_get_ssid,
|
wpa_driver_test_get_ssid,
|
||||||
wpa_driver_test_set_wpa,
|
wpa_driver_test_set_wpa,
|
||||||
wpa_driver_test_set_key,
|
wpa_driver_test_set_key,
|
||||||
wpa_driver_test_init,
|
NULL /* init */,
|
||||||
wpa_driver_test_deinit,
|
wpa_driver_test_deinit,
|
||||||
wpa_driver_test_set_param,
|
wpa_driver_test_set_param,
|
||||||
NULL /* set_countermeasures */,
|
NULL /* set_countermeasures */,
|
||||||
|
@ -1172,5 +1195,8 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
wpa_driver_test_get_scan_results2,
|
wpa_driver_test_get_scan_results2,
|
||||||
wpa_driver_set_probe_req_ie,
|
wpa_driver_set_probe_req_ie,
|
||||||
NULL /* set_mode */,
|
NULL /* set_mode */,
|
||||||
NULL /* set_country */
|
NULL /* set_country */,
|
||||||
|
wpa_driver_test_global_init,
|
||||||
|
wpa_driver_test_global_deinit,
|
||||||
|
wpa_driver_test_init2
|
||||||
};
|
};
|
||||||
|
|
|
@ -1999,7 +1999,7 @@ struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
|
||||||
struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
|
struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
|
||||||
{
|
{
|
||||||
struct wpa_global *global;
|
struct wpa_global *global;
|
||||||
int ret;
|
int ret, i;
|
||||||
|
|
||||||
if (params == NULL)
|
if (params == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2054,6 +2054,30 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; wpa_supplicant_drivers[i]; i++)
|
||||||
|
global->drv_count++;
|
||||||
|
if (global->drv_count == 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "No drivers enabled");
|
||||||
|
wpa_supplicant_deinit(global);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
|
||||||
|
if (global->drv_priv == NULL) {
|
||||||
|
wpa_supplicant_deinit(global);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (i = 0; wpa_supplicant_drivers[i]; i++) {
|
||||||
|
if (!wpa_supplicant_drivers[i]->global_init)
|
||||||
|
continue;
|
||||||
|
global->drv_priv[i] = wpa_supplicant_drivers[i]->global_init();
|
||||||
|
if (global->drv_priv[i] == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "Failed to initialize driver "
|
||||||
|
"'%s'", wpa_supplicant_drivers[i]->name);
|
||||||
|
wpa_supplicant_deinit(global);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2100,6 +2124,8 @@ int wpa_supplicant_run(struct wpa_global *global)
|
||||||
*/
|
*/
|
||||||
void wpa_supplicant_deinit(struct wpa_global *global)
|
void wpa_supplicant_deinit(struct wpa_global *global)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (global == NULL)
|
if (global == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2113,6 +2139,13 @@ void wpa_supplicant_deinit(struct wpa_global *global)
|
||||||
|
|
||||||
eap_peer_unregister_methods();
|
eap_peer_unregister_methods();
|
||||||
|
|
||||||
|
for (i = 0; wpa_supplicant_drivers[i]; i++) {
|
||||||
|
if (!global->drv_priv[i])
|
||||||
|
continue;
|
||||||
|
wpa_supplicant_drivers[i]->global_deinit(global->drv_priv[i]);
|
||||||
|
}
|
||||||
|
os_free(global->drv_priv);
|
||||||
|
|
||||||
eloop_destroy();
|
eloop_destroy();
|
||||||
|
|
||||||
if (global->params.pid_file) {
|
if (global->params.pid_file) {
|
||||||
|
|
|
@ -156,6 +156,8 @@ struct wpa_global {
|
||||||
struct wpa_params params;
|
struct wpa_params params;
|
||||||
struct ctrl_iface_global_priv *ctrl_iface;
|
struct ctrl_iface_global_priv *ctrl_iface;
|
||||||
struct ctrl_iface_dbus_priv *dbus_ctrl_iface;
|
struct ctrl_iface_dbus_priv *dbus_ctrl_iface;
|
||||||
|
void **drv_priv;
|
||||||
|
size_t drv_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -396,6 +398,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s);
|
||||||
static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,
|
static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,
|
||||||
const char *ifname)
|
const char *ifname)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->driver->init2)
|
||||||
|
return wpa_s->driver->init2(wpa_s, ifname, wpa_s->global);
|
||||||
if (wpa_s->driver->init) {
|
if (wpa_s->driver->init) {
|
||||||
return wpa_s->driver->init(wpa_s, ifname);
|
return wpa_s->driver->init(wpa_s, ifname);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue