]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Interworking: Prefer last added network during network selection
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 25 Feb 2014 20:37:57 +0000 (22:37 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 25 Feb 2014 20:37:57 +0000 (22:37 +0200)
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 <jouni@qca.qualcomm.com>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/interworking.c
wpa_supplicant/notify.c
wpa_supplicant/wpa_supplicant_i.h

index e95b55bf064e7d1318b9828a409e319d42631424..1fbbddae188e1012901d96fbdd942793d7c13821 100644 (file)
@@ -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;
 }
 
 
index 47434e4b3454824f08248ad0917a50599a7d9068..44449440f94d5419912af1f743a78da8b41ae605 100644 (file)
@@ -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;
                }
index da8971d9bffd08b6dbdf7abfeada37f44b402ad6..eaf231bc4e9107f5ccd7bdd060915e81ba2edfa1 100644 (file)
@@ -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);
 
index a82fbf3a9a81f71ed0bb233de07664097c267f7c..2db1d54413f1d89fcc4e5a65c8940208853692f3 100644 (file)
@@ -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)
index 3dcc900070eab16c5c14bc48796efa2ee62e12b3..765f5b6c56f08da1a5e52cdcd3960de9c690eb69 100644 (file)
@@ -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;