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:
Jouni Malinen 2008-12-22 22:24:31 +02:00
parent e83a089818
commit ac305589a3
6 changed files with 110 additions and 6 deletions

View file

@ -956,6 +956,41 @@ struct wpa_driver_ops {
* of setting a regulatory domain.
*/
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 */

View file

@ -2884,5 +2884,8 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
wpa_driver_ndis_get_scan_results,
NULL /* set_probe_req_ie */,
NULL /* set_mode */,
NULL /* set_country */
NULL /* set_country */,
NULL /* global_init */,
NULL /* global_deinit */,
NULL /* init2 */
};

View file

@ -775,7 +775,10 @@ struct wpa_driver_ops wpa_driver_privsep_ops = {
wpa_driver_privsep_get_scan_results2,
NULL /* set_probe_req_ie */,
wpa_driver_privsep_set_mode,
NULL /* set_country */
NULL /* set_country */,
NULL /* global_init */,
NULL /* global_deinit */,
NULL /* init2 */
};

View file

@ -35,7 +35,12 @@
#include "ieee802_11_defs.h"
struct wpa_driver_test_global {
int dummy;
};
struct wpa_driver_test_data {
struct wpa_driver_test_global *global;
void *ctx;
u8 own_addr[ETH_ALEN];
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;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->global = global_priv;
drv->ctx = ctx;
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 = {
"test",
"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_set_wpa,
wpa_driver_test_set_key,
wpa_driver_test_init,
NULL /* init */,
wpa_driver_test_deinit,
wpa_driver_test_set_param,
NULL /* set_countermeasures */,
@ -1172,5 +1195,8 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
wpa_driver_test_get_scan_results2,
wpa_driver_set_probe_req_ie,
NULL /* set_mode */,
NULL /* set_country */
NULL /* set_country */,
wpa_driver_test_global_init,
wpa_driver_test_global_deinit,
wpa_driver_test_init2
};

View file

@ -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 *global;
int ret;
int ret, i;
if (params == 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;
}
@ -2100,6 +2124,8 @@ int wpa_supplicant_run(struct wpa_global *global)
*/
void wpa_supplicant_deinit(struct wpa_global *global)
{
int i;
if (global == NULL)
return;
@ -2113,6 +2139,13 @@ void wpa_supplicant_deinit(struct wpa_global *global)
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();
if (global->params.pid_file) {

View file

@ -156,6 +156,8 @@ struct wpa_global {
struct wpa_params params;
struct ctrl_iface_global_priv *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,
const char *ifname)
{
if (wpa_s->driver->init2)
return wpa_s->driver->init2(wpa_s, ifname, wpa_s->global);
if (wpa_s->driver->init) {
return wpa_s->driver->init(wpa_s, ifname);
}