aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/driver.h35
-rw-r--r--src/drivers/driver_ndis.c5
-rw-r--r--src/drivers/driver_privsep.c5
-rw-r--r--src/drivers/driver_test.c32
-rw-r--r--wpa_supplicant/wpa_supplicant.c35
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h4
6 files changed, 110 insertions, 6 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 9037c20..67d0181 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -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 */
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 34710ef..20425bb 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -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 */
};
diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c
index 9c98ed3..8aa05aa 100644
--- a/src/drivers/driver_privsep.c
+++ b/src/drivers/driver_privsep.c
@@ -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 */
};
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index feeb8a2..b055b27 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -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
};
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6701f84..9813a47 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -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) {
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 3232198..dcfa59b 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -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);
}