Blame SOURCES/0017-rh1085473-nl-event-resubscribe.patch

ae491f
From 3a5179e49fbbd5eb3df00e476e380915dd84eb05 Mon Sep 17 00:00:00 2001
ae491f
From: Jouni Malinen <j@w1.fi>
ae491f
Date: Sun, 22 Feb 2015 18:03:42 +0200
ae491f
Subject: [PATCH] nl80211: Resubscribe to nl80211 events on global nl_event
ae491f
 socket
ae491f
ae491f
This allows wpa_supplicant to recover from some of the cases where
ae491f
cfg80211 is unloaded and reloaded without restarting wpa_supplicant. The
ae491f
netlink socket used for nl80211 events (global->nl_event) seemed to end
ae491f
up in otherwise functionality state, but with all the event memberships
ae491f
lost when cfg80211 gets reloaded.
ae491f
ae491f
There does not seem to be any clear way of determining when this has
ae491f
happened, so it looks simplest to just try to re-subscribe to all the
ae491f
events whenever an interface is re-enabled or added.
ae491f
ae491f
[lkundrak@v3.sk: 2.0 backport]
ae491f
ae491f
Signed-off-by: Jouni Malinen <j@w1.fi>
ae491f
(cherry picked from commit f51f54a007e0de1d413dee3523472d3bbeed2ecc)
ae491f
---
ae491f
 src/drivers/driver_nl80211.c | 27 +++++++++++++++++++++++++++
ae491f
 1 file changed, 27 insertions(+)
ae491f
ae491f
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
ae491f
index 37b6be9..097265c 100644
ae491f
--- a/src/drivers/driver_nl80211.c
ae491f
+++ b/src/drivers/driver_nl80211.c
ae491f
@@ -184,6 +184,7 @@ struct nl80211_wiphy_data {
ae491f
 };
ae491f
 
ae491f
 static void nl80211_global_deinit(void *priv);
ae491f
+static void nl80211_check_global(struct nl80211_global *global);
ae491f
 static void wpa_driver_nl80211_deinit(void *priv);
ae491f
 
ae491f
 struct i802_bss {
ae491f
@@ -852,6 +853,7 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
ae491f
 		return 1;
ae491f
 
ae491f
 	if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
ae491f
+		nl80211_check_global(drv->global);
ae491f
 		drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname);
ae491f
 		wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
ae491f
 			   "interface");
ae491f
@@ -2918,6 +2920,30 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
ae491f
 }
ae491f
 
ae491f
 
ae491f
+static void nl80211_check_global(struct nl80211_global *global)
ae491f
+{
ae491f
+	const char *groups[] = { "scan", "mlme", "regulatory", "vendor", NULL };
ae491f
+	int ret;
ae491f
+	unsigned int i;
ae491f
+
ae491f
+	/*
ae491f
+	 * Try to re-add memberships to handle case of cfg80211 getting reloaded
ae491f
+	 * and all registration having been cleared.
ae491f
+	 */
ae491f
+
ae491f
+	for (i = 0; groups[i]; i++) {
ae491f
+		ret = nl_get_multicast_id(global, "nl80211", groups[i]);
ae491f
+		if (ret >= 0)
ae491f
+			ret = nl_socket_add_membership(global->nl_event, ret);
ae491f
+		if (ret < 0) {
ae491f
+			wpa_printf(MSG_INFO,
ae491f
+				   "nl80211: Could not re-add multicast membership for %s events: %d (%s)",
ae491f
+				   groups[i], ret, strerror(-ret));
ae491f
+		}
ae491f
+	}
ae491f
+}
ae491f
+
ae491f
+
ae491f
 static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
ae491f
 {
ae491f
 	wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
ae491f
@@ -3137,6 +3163,7 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
ae491f
 	}
ae491f
 
ae491f
 	if (drv->global) {
ae491f
+		nl80211_check_global(drv->global);
ae491f
 		dl_list_add(&drv->global->interfaces, &drv->list);
ae491f
 		drv->in_interface_list = 1;
ae491f
 	}
ae491f
-- 
ae491f
2.5.0
ae491f