nl80211: Resubscribe to nl80211 events on global nl_event socket
This allows wpa_supplicant to recover from some of the cases where cfg80211 is unloaded and reloaded without restarting wpa_supplicant. The netlink socket used for nl80211 events (global->nl_event) seemed to end up in otherwise functionality state, but with all the event memberships lost when cfg80211 gets reloaded. There does not seem to be any clear way of determining when this has happened, so it looks simplest to just try to re-subscribe to all the events whenever an interface is re-enabled or added. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
52352802ee
commit
f51f54a007
1 changed files with 30 additions and 0 deletions
|
@ -164,6 +164,7 @@ static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
|
|||
|
||||
|
||||
static void nl80211_global_deinit(void *priv);
|
||||
static void nl80211_check_global(struct nl80211_global *global);
|
||||
|
||||
static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
|
||||
static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
|
||||
|
@ -864,6 +865,7 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
|
|||
return 1;
|
||||
|
||||
if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
|
||||
nl80211_check_global(drv->global);
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
|
||||
"interface");
|
||||
wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL);
|
||||
|
@ -1481,6 +1483,33 @@ err:
|
|||
}
|
||||
|
||||
|
||||
static void nl80211_check_global(struct nl80211_global *global)
|
||||
{
|
||||
struct nl_handle *handle;
|
||||
const char *groups[] = { "scan", "mlme", "regulatory", "vendor", NULL };
|
||||
int ret;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Try to re-add memberships to handle case of cfg80211 getting reloaded
|
||||
* and all registration having been cleared.
|
||||
*/
|
||||
handle = (void *) (((intptr_t) global->nl_event) ^
|
||||
ELOOP_SOCKET_INVALID);
|
||||
|
||||
for (i = 0; groups[i]; i++) {
|
||||
ret = nl_get_multicast_id(global, "nl80211", groups[i]);
|
||||
if (ret >= 0)
|
||||
ret = nl_socket_add_membership(handle, ret);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"nl80211: Could not re-add multicast membership for %s events: %d (%s)",
|
||||
groups[i], ret, strerror(-ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
|
||||
|
@ -1674,6 +1703,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
|
|||
}
|
||||
|
||||
if (drv->global) {
|
||||
nl80211_check_global(drv->global);
|
||||
dl_list_add(&drv->global->interfaces, &drv->list);
|
||||
drv->in_interface_list = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue