From 26fc96e89b9f0ecd16e1ecbdc41a375b2cc752a7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 20 Oct 2014 12:40:29 +0300 Subject: [PATCH] P2P: Remove all child interfaces when removing the parent This is needed to allow dynamic removal of an interface that adds the P2P Device interface without leaving behind the management interface with invalid wpa_s->parent pointer. Signed-off-by: Jouni Malinen --- wpa_supplicant/p2p_supplicant.c | 2 -- wpa_supplicant/p2p_supplicant.h | 8 +++++++- wpa_supplicant/wpa_supplicant.c | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index b4cef9e27..d0e9e05dd 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -7981,8 +7981,6 @@ void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s) void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s) { - if (wpa_s == wpa_s->parent) - wpas_p2p_group_remove(wpa_s, "*"); if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing " "the management interface is being removed"); diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index b61d57ff5..4bc90fbf3 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -29,7 +29,6 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int pd, int ht40, int vht); int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq, struct wpa_ssid *ssid); -int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname); int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int freq, int ht40, int vht); int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, @@ -170,6 +169,7 @@ int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s); int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s); void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, struct wps_event_fail *fail); +int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname); #else /* CONFIG_P2P */ @@ -293,6 +293,12 @@ static inline void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, { } +static inline int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, + const char *ifname) +{ + return 0; +} + #endif /* CONFIG_P2P */ #endif /* P2P_SUPPLICANT_H */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index b05eb86c6..4ada8ce6a 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3905,6 +3905,26 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, int notify, int terminate) { + struct wpa_global *global = wpa_s->global; + struct wpa_supplicant *iface, *prev; + + if (wpa_s == wpa_s->parent) + wpas_p2p_group_remove(wpa_s, "*"); + + iface = global->ifaces; + while (iface) { + if (iface == wpa_s || iface->parent != wpa_s) { + iface = iface->next; + continue; + } + wpa_printf(MSG_DEBUG, + "Remove remaining child interface %s from parent %s", + iface->ifname, wpa_s->ifname); + prev = iface; + iface = iface->next; + wpa_supplicant_remove_iface(global, prev, terminate); + } + wpa_s->disconnected = 1; if (wpa_s->drv_priv) { wpa_supplicant_deauthenticate(wpa_s,