[PATCH v3] wpa_supplicant: Denitialize the driver if the last user went away
Lubomir Rintel
lkundrak
Sat Aug 29 05:30:44 PDT 2015
It might be that the underlying infrastrucutre went away and the state is no
longer valid. We ought to reinitialize it once a device appears again.
This is the case when the nl80211 devices disappear and cfg8011 is remoed
afterwards. The netlink handle is no longer valid (returns ENOENT) and a new
one needs to be open if it's loaded back.
Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>
---
This was just updated to address the crashes during test suite run;
moved the interface removal from the list just above the driver
cleanup attempt.
wpa_supplicant/wpa_supplicant.c | 48 ++++++++++++++++++++++++++++++-----------
1 file changed, 36 insertions(+), 12 deletions(-)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 493b3a8..8bc9a48 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4468,6 +4468,28 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return 0;
}
+/* Deinitialize the driver if we're the last user. */
+static void wpa_drv_cleanup(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_global *global = wpa_s->global;
+ struct wpa_supplicant *iface;
+ int i;
+
+ if (!wpa_s->driver)
+ return;
+
+ for (iface = global->ifaces; iface; iface = iface->next)
+ if (iface->driver == wpa_s->driver)
+ return;
+
+ for (i = 0; wpa_drivers[i]; i++)
+ if (global->drv_priv[i] == wpa_s->global_drv_priv)
+ global->drv_priv[i] = NULL;
+
+ if (wpa_s->driver->global_deinit)
+ wpa_s->driver->global_deinit (wpa_s->global_drv_priv);
+ wpa_s->global_drv_priv = NULL;
+}
static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
int notify, int terminate)
@@ -4656,18 +4678,6 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
char *ifname = NULL;
#endif /* CONFIG_MESH */
- /* Remove interface from the global list of interfaces */
- prev = global->ifaces;
- if (prev == wpa_s) {
- global->ifaces = wpa_s->next;
- } else {
- while (prev && prev->next != wpa_s)
- prev = prev->next;
- if (prev == NULL)
- return -1;
- prev->next = wpa_s->next;
- }
-
wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
#ifdef CONFIG_MESH
@@ -4694,6 +4704,20 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
}
#endif /* CONFIG_MESH */
+ /* Remove interface from the global list of interfaces */
+ prev = global->ifaces;
+ if (prev == wpa_s) {
+ global->ifaces = wpa_s->next;
+ } else {
+ while (prev && prev->next != wpa_s)
+ prev = prev->next;
+ if (prev == NULL)
+ return -1;
+ prev->next = wpa_s->next;
+ }
+
+ wpa_drv_cleanup(wpa_s);
+
return 0;
}
--
2.4.3
More information about the Hostap
mailing list