From 3d910ef497b11e149cf41e772670f7a7fe3a1e19 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Feb 2014 22:37:57 +0200 Subject: [PATCH] Interworking: Prefer last added network during network selection Previously, any network block could be used to select the BSS to connect to when processing scan results after Interworking network selection. This can result in somewhat unexpected network selection in cases where credential preferences indicated that a specific network was selected, but another network ended up getting used for the connection. While the older networks continue to be valid, add special processing for this initial post-interworking-connect case to get more consistent network selection to match with the Interworking network selection result. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 2 ++ wpa_supplicant/events.c | 38 +++++++++++++++++++++++++------ wpa_supplicant/interworking.c | 3 +++ wpa_supplicant/notify.c | 2 ++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index e95b55bf0..1fbbddae1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5462,6 +5462,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) eapol_sm_notify_logoff(wpa_s->eapol, FALSE); radio_remove_works(wpa_s, NULL, 1); + + wpa_s->next_ssid = NULL; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 47434e4b3..44449440f 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -728,7 +728,8 @@ static int bss_is_ess(struct wpa_bss *bss) static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_bss *bss, - struct wpa_ssid *group) + struct wpa_ssid *group, + int only_first_ssid) { u8 wpa_ie_len, rsn_ie_len; int wpa; @@ -789,7 +790,7 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, wpa = wpa_ie_len > 0 || rsn_ie_len > 0; - for (ssid = group; ssid; ssid = ssid->pnext) { + for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) { int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); int res; @@ -938,16 +939,22 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, static struct wpa_bss * wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, - struct wpa_ssid **selected_ssid) + struct wpa_ssid **selected_ssid, + int only_first_ssid) { unsigned int i; - wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d", - group->priority); + if (only_first_ssid) + wpa_dbg(wpa_s, MSG_DEBUG, "Try to find BSS matching pre-selected network id=%d", + group->id); + else + wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d", + group->priority); for (i = 0; i < wpa_s->last_scan_res_used; i++) { struct wpa_bss *bss = wpa_s->last_scan_res[i]; - *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group); + *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group, + only_first_ssid); if (!*selected_ssid) continue; wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR @@ -972,10 +979,27 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, return NULL; /* no scan results from last update */ while (selected == NULL) { + if (wpa_s->next_ssid) { + struct wpa_ssid *ssid; + + /* check that next_ssid is still valid */ + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) + if (ssid == wpa_s->next_ssid) + break; + wpa_s->next_ssid = NULL; + + if (ssid) { + selected = wpa_supplicant_select_bss( + wpa_s, ssid, selected_ssid, 1); + if (selected) + break; + } + } + for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { selected = wpa_supplicant_select_bss( wpa_s, wpa_s->conf->pssid[prio], - selected_ssid); + selected_ssid, 0); if (selected) break; } diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index da8971d9b..eaf231bc4 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -918,6 +918,7 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, wpa_config_set_quoted(ssid, "password", cred->password) < 0) goto fail; + wpa_s->next_ssid = ssid; wpa_config_update_prio_list(wpa_s->conf); interworking_reconnect(wpa_s); @@ -1241,6 +1242,7 @@ static int interworking_connect_roaming_consortium( cred->eap_method->method == EAP_TYPE_TTLS) < 0) goto fail; + wpa_s->next_ssid = ssid; wpa_config_update_prio_list(wpa_s->conf); interworking_reconnect(wpa_s); @@ -1443,6 +1445,7 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) nai_realm_free(realm, count); + wpa_s->next_ssid = ssid; wpa_config_update_prio_list(wpa_s->conf); interworking_reconnect(wpa_s); diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index a82fbf3a9..2db1d5441 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -252,6 +252,8 @@ void wpas_notify_persistent_group_removed(struct wpa_supplicant *wpa_s, void wpas_notify_network_removed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { + if (wpa_s->next_ssid == ssid) + wpa_s->next_ssid = NULL; if (wpa_s->wpa) wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s) diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 3dcc90007..765f5b6c5 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -420,6 +420,9 @@ struct wpa_supplicant { enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband; + /* Preferred network for the next connection attempt */ + struct wpa_ssid *next_ssid; + /* previous scan was wildcard when interleaving between * wildcard scans and specific SSID scan when max_ssids=1 */ int prev_scan_wildcard;