wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
- radio_remove_unstarted_work(wpa_s, NULL);
+ radio_remove_works(wpa_s, NULL, 1);
}
struct wpa_external_work *ework = work->ctx;
if (deinit) {
+ if (work->started)
+ eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
+ work, NULL);
+
os_free(ework);
return;
}
#endif /* CONFIG_P2P */
wpa_supplicant_mark_disassoc(wpa_s);
+ radio_remove_works(wpa_s, NULL, 0);
+
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
break;
case EVENT_CHANNEL_LIST_CHANGED:
struct gas_query *gas = query->gas;
if (deinit) {
+ if (work->started) {
+ gas->work = NULL;
+ gas_query_done(gas, query, GAS_QUERY_DELETED_AT_DEINIT);
+ return;
+ }
+
gas_query_free(query, 1);
return;
}
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
int group_added);
static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
+static void wpas_stop_listen(void *ctx);
/*
int ret;
if (deinit) {
- wpa_scan_free_params(params);
+ if (!work->started) {
+ wpa_scan_free_params(params);
+ return;
+ }
+
+ wpa_s->p2p_scan_work = NULL;
return;
}
break;
}
- radio_remove_unstarted_work(wpa_s, "p2p-scan");
+ radio_remove_works(wpa_s, "p2p-scan", 0);
if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
params) < 0)
goto fail;
struct send_action_work *awork = work->ctx;
if (deinit) {
+ if (work->started) {
+ eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
+ wpa_s, NULL);
+ wpa_s->p2p_send_action_work = NULL;
+ offchannel_send_action_done(wpa_s);
+ }
os_free(awork);
return;
}
struct wpas_p2p_listen_work *lwork = work->ctx;
if (deinit) {
+ if (work->started) {
+ wpa_s->p2p_listen_work = NULL;
+ wpas_stop_listen(wpa_s);
+ }
wpas_p2p_listen_work_free(lwork);
return;
}
int ret;
if (deinit) {
- wpa_scan_free_params(params);
+ if (!work->started) {
+ wpa_scan_free_params(params);
+ return;
+ }
+ wpa_supplicant_notify_scanning(wpa_s, 0);
+ wpas_notify_scan_done(wpa_s, 0);
+ wpa_s->scan_work = NULL;
return;
}
struct wpa_supplicant *wpa_s = work->wpa_s;
if (deinit) {
+ if (work->started)
+ wpa_s->connect_work = NULL;
+
wpas_connect_work_free(cwork);
return;
}
#endif /* CONFIG_HT_OVERRIDES */
if (deinit) {
+ if (work->started) {
+ wpa_s->connect_work = NULL;
+
+ /* cancel possible auth. timeout */
+ eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
+ NULL);
+ }
wpas_connect_work_free(cwork);
return;
}
}
-void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
+/*
+ * This function removes both started and pending radio works running on
+ * the provided interface's radio.
+ * Prior to the removal of the radio work, its callback (cb) is called with
+ * deinit set to be 1. Each work's callback is responsible for clearing its
+ * internal data and restoring to a correct state.
+ * @wpa_s: wpa_supplicant data
+ * @type: type of works to be removed
+ * @remove_all: 1 to remove all the works on this radio, 0 to remove only
+ * this interface's works.
+ */
+void radio_remove_works(struct wpa_supplicant *wpa_s,
+ const char *type, int remove_all)
{
struct wpa_radio_work *work, *tmp;
struct wpa_radio *radio = wpa_s->radio;
dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
list) {
- if (type && (work->started || os_strcmp(type, work->type) != 0))
+ if (type && os_strcmp(type, work->type) != 0)
continue;
- if (work->started) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
- work->type, work);
+
+ /* skip other ifaces' works */
+ if (!remove_all && work->wpa_s != wpa_s)
continue;
- }
- wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
- work->type, work);
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
+ work->type, work, work->started ? " (started)" : "");
work->cb(work, 1);
radio_work_free(work);
}
+
+ /* in case we removed the started work */
+ radio_work_check_next(wpa_s);
}
}
wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
- radio_remove_unstarted_work(wpa_s, NULL);
+ radio_remove_works(wpa_s, NULL, 0);
eloop_cancel_timeout(radio_start_next_work, radio, NULL);
wpa_s->radio = NULL;
os_free(radio);
void (*cb)(struct wpa_radio_work *work, int deinit),
void *ctx);
void radio_work_done(struct wpa_radio_work *work);
-void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s,
- const char *type);
+void radio_remove_works(struct wpa_supplicant *wpa_s,
+ const char *type, int remove_all);
void radio_work_check_next(struct wpa_supplicant *wpa_s);
struct wpa_connect_work {