Interworking: Add optional use of network selection on normal scans
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 28 Aug 2012 13:14:13 +0000 (16:14 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 28 Aug 2012 13:14:13 +0000 (16:14 +0300)
auto_interworking=1 configuration parameter can be used to request
wpa_supplicant to use Interworking network selection automatically as a
part of the normal (non-Interworking) network selection if the scan
results do not match with enabled networks. This makes scanning work
similarly to the "interworking_select auto" command.

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

wpa_supplicant/README-HS20
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/events.c
wpa_supplicant/interworking.c
wpa_supplicant/interworking.h
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpa_supplicant_i.h

index 0181e8b..feb9049 100644 (file)
@@ -24,6 +24,31 @@ standardized in IEEE Std 802.11u-2011 which is now part of the IEEE Std
 802.11-2012.
 
 
+wpa_supplicant network selection
+--------------------------------
+
+Interworking support added option for configuring credentials that can
+work with multiple networks as an alternative to configuration of
+network blocks (e.g., per-SSID parameters). When requested to perform
+network selection, wpa_supplicant picks the highest priority enabled
+network block or credential. If a credential is picked (based on ANQP
+information from APs), a temporary network block is created
+automatically for the matching network. This temporary network block is
+used similarly to the network blocks that can be configured by the user,
+but it is not stored into the configuration file and is meant to be used
+only for temporary period of time since a new one can be created
+whenever needed based on ANQP information and the credential.
+
+By default, wpa_supplicant is not using automatic network selection
+unless requested explicitly with the interworking_select command. This
+can be changed with the auto_interworking=1 parameter to perform network
+selection automatically whenever trying to find a network for connection
+and none of the enabled network blocks match with the scan results. This
+case works similarly to "interworking_select auto", i.e., wpa_supplicant
+will internally determine which network or credential is going to be
+used based on configured priorities, scan results, and ANQP information.
+
+
 wpa_supplicant configuration
 ----------------------------
 
@@ -65,6 +90,14 @@ hs20=1
 # This value controls the Access Network Type value in Probe Request frames.
 #access_network_type=15
 
+# Automatic network selection behavior
+# 0 = do not automatically go through Interworking network selection
+#     (i.e., require explicit interworking_select command for this; default)
+# 1 = perform Interworking network selection if one or more
+#     credentials have been configured and scan did not find a
+#     matching network block
+#auto_interworking=0
+
 
 Credentials can be pre-configured for automatic network selection:
 
index cecf648..c970745 100644 (file)
@@ -3010,6 +3010,7 @@ static const struct global_parse_data global_fields[] = {
        { BIN(wps_nfc_dev_pw), 0 },
        { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
        { INT(p2p_go_max_inactivity), 0 },
+       { INT_RANGE(auto_interworking, 0, 1), 0 },
 };
 
 #undef FUNC
index c3c90e2..b889ab8 100644 (file)
@@ -736,6 +736,17 @@ struct wpa_config {
        int p2p_go_max_inactivity;
 
        struct hostapd_wmm_ac_params wmm_ac_params[4];
+
+       /**
+        * auto_interworking - Whether to use network selection automatically
+        *
+        * 0 = do not automatically go through Interworking network selection
+        *     (i.e., require explicit interworking_select command for this)
+        * 1 = perform Interworking network selection if one or more
+        *     credentials have been configured and scan did not find a
+        *     matching network block
+        */
+       int auto_interworking;
 };
 
 
index bd59a80..531957a 100644 (file)
@@ -916,6 +916,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY)
                fprintf(f, "p2p_go_max_inactivity=%d\n",
                        config->p2p_go_max_inactivity);
+       if (config->auto_interworking)
+               fprintf(f, "auto_interworking=%d\n",
+                       config->auto_interworking);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
index cddcce7..517e11f 100644 (file)
@@ -41,6 +41,7 @@
 #include "bss.h"
 #include "scan.h"
 #include "offchannel.h"
+#include "interworking.h"
 
 
 static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
@@ -1204,6 +1205,19 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
                                return 0;
                        }
 #endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+                       if (wpa_s->conf->auto_interworking &&
+                           wpa_s->conf->interworking &&
+                           wpa_s->conf->cred) {
+                               wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: "
+                                       "start ANQP fetch since no matching "
+                                       "networks found");
+                               wpa_s->network_select = 1;
+                               wpa_s->auto_network_select = 1;
+                               interworking_start_fetch_anqp(wpa_s);
+                               return 0;
+                       }
+#endif /* CONFIG_INTERWORKING */
                        if (wpa_supplicant_req_sched_scan(wpa_s))
                                wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
                                                            timeout_usec);
index 11c57b4..7b5b20e 100644 (file)
@@ -1411,7 +1411,9 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
                        type = "unknown";
                wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR " type=%s",
                        MAC2STR(bss->bssid), type);
-               if (wpa_s->auto_select) {
+               if (wpa_s->auto_select ||
+                   (wpa_s->conf->auto_interworking &&
+                    wpa_s->auto_network_select)) {
                        if (selected == NULL ||
                            cred->priority > selected_prio) {
                                selected = bss;
@@ -1446,6 +1448,14 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
                        return;
                }
 
+               if (wpa_s->auto_network_select) {
+                       wpa_printf(MSG_DEBUG, "Interworking: Continue "
+                                  "scanning after ANQP fetch");
+                       wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval,
+                                               0);
+                       return;
+               }
+
                wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network "
                        "with matching credentials found");
        }
@@ -1490,7 +1500,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
 }
 
 
-static void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s)
+void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s)
 {
        struct wpa_bss *bss;
 
@@ -1748,6 +1758,7 @@ int interworking_select(struct wpa_supplicant *wpa_s, int auto_select)
 {
        interworking_stop_fetch_anqp(wpa_s);
        wpa_s->network_select = 1;
+       wpa_s->auto_network_select = 0;
        wpa_s->auto_select = !!auto_select;
        wpa_printf(MSG_DEBUG, "Interworking: Start scan for network "
                   "selection");
index 60566e5..cb8438e 100644 (file)
@@ -24,5 +24,6 @@ int interworking_fetch_anqp(struct wpa_supplicant *wpa_s);
 void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s);
 int interworking_select(struct wpa_supplicant *wpa_s, int auto_select);
 int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
+void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s);
 
 #endif /* INTERWORKING_H */
index 93d152e..71e7d8d 100644 (file)
@@ -89,6 +89,9 @@ int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
                        count++;
                ssid = ssid->next;
        }
+       if (wpa_s->conf->cred && wpa_s->conf->interworking &&
+           wpa_s->conf->auto_interworking)
+               count++;
        return count;
 }
 
index 4cf0ce1..2c07fd0 100644 (file)
@@ -277,6 +277,14 @@ fast_reauth=1
 # is enabled.
 # hessid=00:11:22:33:44:55
 
+# Automatic network selection behavior
+# 0 = do not automatically go through Interworking network selection
+#     (i.e., require explicit interworking_select command for this; default)
+# 1 = perform Interworking network selection if one or more
+#     credentials have been configured and scan did not find a
+#     matching network block
+#auto_interworking=0
+
 # credential block
 #
 # Each credential used for automatic network selection is configured as a set
index 4494bcc..01d67d9 100644 (file)
@@ -570,6 +570,7 @@ struct wpa_supplicant {
        unsigned int fetch_anqp_in_progress:1;
        unsigned int network_select:1;
        unsigned int auto_select:1;
+       unsigned int auto_network_select:1;
 #endif /* CONFIG_INTERWORKING */
        unsigned int drv_capa_known;