diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 39f58ff83..d994dcb85 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3189,7 +3189,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx); rfkill_deinit(drv->rfkill); - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); + eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx); if (!drv->start_iface_up) (void) i802_set_iface_flags(bss, 0); @@ -4207,6 +4207,22 @@ struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id) } +u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link) +{ + u8 link_id; + + if (link == bss->flink) + return 0; + + for_each_link(bss->valid_links, link_id) { + if (&bss->links[link_id] == link) + return link_id; + } + + return 0; +} + + static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq) { struct i802_link *link = nl80211_get_link(bss, link_id); @@ -10252,6 +10268,8 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) int err; union wpa_event_data data; struct survey_results *survey_results; + void *ctx = (bss->scan_link && bss->scan_link->ctx) ? + bss->scan_link->ctx : bss->ctx; os_memset(&data, 0, sizeof(data)); survey_results = &data.survey_results; @@ -10274,7 +10292,7 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) if (err) wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data"); else - wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data); + wpa_supplicant_event(ctx, EVENT_SURVEY, &data); clean_survey_results(survey_results); return err; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 618746e67..8e1426465 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -67,7 +67,7 @@ struct i802_bss { u16 valid_links; struct i802_link links[MAX_NUM_MLD_LINKS]; - struct i802_link *flink; + struct i802_link *flink, *scan_link; int ifindex; int br_ifindex; @@ -352,6 +352,7 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode); void nl80211_restore_ap_mode(struct i802_bss *bss); struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id); +u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link); static inline bool nl80211_link_valid(u16 links, s8 link_id) { diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index aee815e97..3d07790e0 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1965,9 +1965,10 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv, } -static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, +static void send_scan_event(struct i802_bss *bss, int aborted, struct nlattr *tb[], int external_scan) { + struct wpa_driver_nl80211_data *drv = bss->drv; union wpa_event_data event; struct nlattr *nl; int rem; @@ -1975,6 +1976,8 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, #define MAX_REPORT_FREQS 110 int freqs[MAX_REPORT_FREQS]; int num_freqs = 0; + struct i802_link *mld_link; + void *ctx = bss->ctx; if (!external_scan && drv->scan_for_auth) { drv->scan_for_auth = 0; @@ -2038,7 +2041,24 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, ETH_ALEN); } - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event); + /* Need to pass to the correct link ctx during AP MLD operation */ + if (is_ap_interface(drv->nlmode)) { + mld_link = bss->scan_link; + if (!mld_link) { + wpa_printf(MSG_DEBUG, + "nl80211: Scan event on unknown link"); + } else if (mld_link->ctx) { + u8 link_id = nl80211_get_link_id_from_link(bss, + mld_link); + + wpa_printf(MSG_DEBUG, + "nl80211: Scan event for link_id %d", + link_id); + ctx = mld_link->ctx; + } + } + + wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, &event); } @@ -3055,7 +3075,7 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv, drv->scan_state = SCAN_ABORTED; eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, - drv->ctx); + drv->first_bss->ctx); drv->vendor_scan_cookie = 0; drv->last_scan_cmd = 0; } @@ -3894,7 +3914,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, switch (cmd) { case NL80211_CMD_TRIGGER_SCAN: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger"); + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan trigger"); drv->scan_state = SCAN_STARTED; if (drv->scan_for_auth) { /* @@ -3906,40 +3926,40 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth"); break; } - wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL); + wpa_supplicant_event(bss->ctx, EVENT_SCAN_STARTED, NULL); break; case NL80211_CMD_START_SCHED_SCAN: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started"); + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan started"); drv->scan_state = SCHED_SCAN_STARTED; break; case NL80211_CMD_SCHED_SCAN_STOPPED: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped"); + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan stopped"); drv->scan_state = SCHED_SCAN_STOPPED; - wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL); + wpa_supplicant_event(bss->ctx, EVENT_SCHED_SCAN_STOPPED, NULL); break; case NL80211_CMD_NEW_SCAN_RESULTS: - wpa_dbg(drv->ctx, MSG_DEBUG, + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: New scan results available"); if (drv->last_scan_cmd != NL80211_CMD_VENDOR) drv->scan_state = SCAN_COMPLETED; drv->scan_complete_events = 1; if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) { eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, - drv, drv->ctx); + drv, bss->ctx); drv->last_scan_cmd = 0; } else { external_scan_event = 1; } - send_scan_event(drv, 0, tb, external_scan_event); + send_scan_event(bss, 0, tb, external_scan_event); break; case NL80211_CMD_SCHED_SCAN_RESULTS: - wpa_dbg(drv->ctx, MSG_DEBUG, + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: New sched scan results available"); drv->scan_state = SCHED_SCAN_RESULTS; - send_scan_event(drv, 0, tb, 0); + send_scan_event(bss, 0, tb, 0); break; case NL80211_CMD_SCAN_ABORTED: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted"); + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan aborted"); if (drv->last_scan_cmd != NL80211_CMD_VENDOR) drv->scan_state = SCAN_ABORTED; if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) { @@ -3948,12 +3968,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, * order not to make wpa_supplicant stop its scanning. */ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, - drv, drv->ctx); + drv, bss->ctx); drv->last_scan_cmd = 0; } else { external_scan_event = 1; } - send_scan_event(drv, 1, tb, external_scan_event); + send_scan_event(bss, 1, tb, external_scan_event); break; case NL80211_CMD_AUTHENTICATE: case NL80211_CMD_ASSOCIATE: diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index b055e684a..9a1e36f32 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -153,6 +153,7 @@ fail: void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_driver_nl80211_data *drv = eloop_ctx; + struct i802_bss *bss; wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it"); #ifdef CONFIG_DRIVER_NL80211_QCA @@ -160,14 +161,27 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0) return; #endif /* CONFIG_DRIVER_NL80211_QCA */ - if (!drv->vendor_scan_cookie && - nl80211_abort_scan(drv->first_bss) == 0) + + for (bss = drv->first_bss; bss; bss = bss->next) { + if (bss->scan_link) + break; + } + + if (!bss) { + wpa_printf(MSG_DEBUG, "nl80211: Failed to find scan BSS"); return; + } + + if (!drv->vendor_scan_cookie && + nl80211_abort_scan(bss) == 0) { + bss->scan_link = NULL; + return; + } wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan"); if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) - nl80211_restore_ap_mode(drv->first_bss); + nl80211_restore_ap_mode(bss); wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results"); wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); @@ -347,7 +361,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss, int ret = -1, timeout; struct nl_msg *msg = NULL; - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request"); + wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: scan request"); drv->scan_for_auth = 0; if (TEST_FAIL()) @@ -435,11 +449,20 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss, } wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " "seconds", ret, timeout); - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); + eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx); eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, - drv, drv->ctx); + drv, bss->ctx); drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN; + bss->scan_link = bss->flink; + if (is_ap_interface(drv->nlmode) && + nl80211_link_valid(bss->valid_links, params->link_id)) { + wpa_dbg(bss->ctx, MSG_DEBUG, + "nl80211: Scan requested for link %d", + params->link_id); + bss->scan_link = nl80211_get_link(bss, params->link_id); + } + fail: nlmsg_free(msg); return ret; @@ -1294,9 +1317,9 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, wpa_printf(MSG_DEBUG, "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx", ret, (long long unsigned int) cookie); - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); + eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx); eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout, - drv, drv->ctx); + drv, bss->ctx); drv->last_scan_cmd = NL80211_CMD_VENDOR; fail: