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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-10-20 12:40:29 +03:00
parent eb92d389a8
commit 26fc96e89b
3 changed files with 27 additions and 3 deletions

View file

@ -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) 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) { 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 " wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
"the management interface is being removed"); "the management interface is being removed");

View file

@ -29,7 +29,6 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int pd, int ht40, int vht); int pd, int ht40, int vht);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid); 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 wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int ht40, int vht); int freq, int ht40, int vht);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, 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); int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s);
void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail); struct wps_event_fail *fail);
int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
#else /* CONFIG_P2P */ #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 /* CONFIG_P2P */
#endif /* P2P_SUPPLICANT_H */ #endif /* P2P_SUPPLICANT_H */

View file

@ -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, static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
int notify, int terminate) 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; wpa_s->disconnected = 1;
if (wpa_s->drv_priv) { if (wpa_s->drv_priv) {
wpa_supplicant_deauthenticate(wpa_s, wpa_supplicant_deauthenticate(wpa_s,