nl80211: Do not notify interface as re-enabled if initialization fails
wpa_supplicant tries to reinitialize an interface when a previously removed netdev is restored (e.g., re-insert a USB dongle). If that initialization fails (e.g., driver ejects ifconfig UP), the previous implementation resulted in leaving the interface in incomplete state while still claiming to upper layers that the interface status has changed back to functional one. Fix this by skipping the interface status update if reinitialization fails. In other words, remain in INTERFACE_DISABLED state if the interface cannot be re-enabled successfully. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
8696e61702
commit
5e0c20ff3e
1 changed files with 23 additions and 7 deletions
|
@ -911,7 +911,8 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
|
|||
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);
|
||||
if (wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL) < 0)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -920,13 +921,25 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
|
|||
|
||||
|
||||
static struct wpa_driver_nl80211_data *
|
||||
nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
|
||||
nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len,
|
||||
int *init_failed)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv;
|
||||
int res;
|
||||
|
||||
if (init_failed)
|
||||
*init_failed = 0;
|
||||
dl_list_for_each(drv, &global->interfaces,
|
||||
struct wpa_driver_nl80211_data, list) {
|
||||
if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
|
||||
have_ifidx(drv, idx, IFIDX_ANY))
|
||||
res = wpa_driver_nl80211_own_ifindex(drv, idx, buf, len);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Found matching own interface, but failed to complete reinitialization");
|
||||
if (init_failed)
|
||||
*init_failed = 1;
|
||||
return drv;
|
||||
}
|
||||
if (res > 0 || have_ifidx(drv, idx, IFIDX_ANY))
|
||||
return drv;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -969,6 +982,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
|||
char namebuf[IFNAMSIZ];
|
||||
char ifname[IFNAMSIZ + 1];
|
||||
char extra[100], *pos, *end;
|
||||
int init_failed;
|
||||
|
||||
extra[0] = '\0';
|
||||
pos = extra;
|
||||
|
@ -1013,9 +1027,11 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
|||
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
||||
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
|
||||
|
||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len, &init_failed);
|
||||
if (!drv)
|
||||
goto event_newlink;
|
||||
if (init_failed)
|
||||
return; /* do not update interface state */
|
||||
|
||||
if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
|
||||
namebuf[0] = '\0';
|
||||
|
@ -1049,7 +1065,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
|||
* dynamic interfaces
|
||||
*/
|
||||
drv = nl80211_find_drv(global, ifi->ifi_index,
|
||||
buf, len);
|
||||
buf, len, NULL);
|
||||
if (!drv)
|
||||
return;
|
||||
}
|
||||
|
@ -1175,7 +1191,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
|
|||
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
||||
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
|
||||
|
||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len, NULL);
|
||||
|
||||
if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
|
||||
/* device has been removed from bridge */
|
||||
|
|
Loading…
Reference in a new issue