[PATCH v3] wpa_supplicant: Denitialize the driver if the last user went away

Lubomir Rintel lkundrak at v3.sk
Sat Aug 29 08:30:44 EDT 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