Interworking: Avoid duplicated network blocks
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 6 Nov 2013 21:32:43 +0000 (23:32 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 6 Nov 2013 22:12:30 +0000 (00:12 +0200)
Do not add multiple network blocks for the same network from a single
credential. INTERWORKING_CONNECT used to generate a new network block
for each instance regardless of what network blocks have already been
configured. While this allows the connection to go through, it is not
efficient to leave behind potentially large number of network blocks
with the same contents (or worse, changed contents). Address this by
removing an older network block for the same credential before adding a
new one.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

wpa_supplicant/interworking.c

index 22e28a2..ffb3cb3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Interworking (IEEE 802.11u)
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -19,6 +19,7 @@
 #include "eap_peer/eap.h"
 #include "eap_peer/eap_methods.h"
 #include "eapol_supp/eapol_supp_sm.h"
+#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
 #include "config_ssid.h"
@@ -770,6 +771,39 @@ static int already_connected(struct wpa_supplicant *wpa_s,
 }
 
 
+static void remove_duplicate_network(struct wpa_supplicant *wpa_s,
+                                    struct wpa_cred *cred,
+                                    struct wpa_bss *bss)
+{
+       struct wpa_ssid *ssid;
+
+       for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+               if (ssid->parent_cred != cred)
+                       continue;
+               if (ssid->ssid_len != bss->ssid_len ||
+                   os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
+                       continue;
+
+               break;
+       }
+
+       if (ssid == NULL)
+               return;
+
+       wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential");
+
+       if (ssid == wpa_s->current_ssid) {
+               wpa_sm_set_config(wpa_s->wpa, NULL);
+               eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
+       }
+
+       wpas_notify_network_removed(wpa_s, ssid);
+       wpa_config_remove_network(wpa_s->conf, ssid->id);
+}
+
+
 static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
                                        struct wpa_ssid *ssid)
 {
@@ -811,6 +845,8 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
                return 0;
        }
 
+       remove_duplicate_network(wpa_s, cred, bss);
+
        ssid = wpa_config_add_network(wpa_s->conf);
        if (ssid == NULL)
                return -1;
@@ -1176,6 +1212,8 @@ static int interworking_connect_roaming_consortium(
                return 0;
        }
 
+       remove_duplicate_network(wpa_s, cred, bss);
+
        ssid = wpa_config_add_network(wpa_s->conf);
        if (ssid == NULL)
                return -1;
@@ -1318,6 +1356,8 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
                return 0;
        }
 
+       remove_duplicate_network(wpa_s, cred, bss);
+
        ssid = wpa_config_add_network(wpa_s->conf);
        if (ssid == NULL) {
                nai_realm_free(realm, count);