IEEE 802.11u: Allow Interworking and HESSID to be configured
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 27 Sep 2011 20:15:05 +0000 (23:15 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 16 Oct 2011 20:55:34 +0000 (23:55 +0300)
The new wpa_supplicant.conf file global parameters interworking and
hessid can be used to configure wpa_supplicant to include
Interworking element in Probe Request frames.

src/common/ieee802_11_defs.h
wpa_supplicant/Makefile
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/defconfig
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant.conf

index e510245..3485bd4 100644 (file)
 #define INTERWORKING_ANO_ESR 0x40
 #define INTERWORKING_ANO_UESA 0x80
 
+#define INTERWORKING_ANT_PRIVATE 0
+#define INTERWORKING_ANT_PRIVATE_WITH_GUEST 1
+#define INTERWORKING_ANT_CHARGEABLE_PUBLIC 2
+#define INTERWORKING_ANT_FREE_PUBLIC 3
+#define INTERWORKING_ANT_PERSONAL_DEVICE 4
+#define INTERWORKING_ANT_EMERGENCY_SERVICES 5
+#define INTERWORKING_ANT_TEST 6
+#define INTERWORKING_ANT_WILDCARD 15
+
 /* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */
 enum adv_proto_id {
        ACCESS_NETWORK_QUERY_PROTOCOL = 0,
index 8bf7927..1ec7b68 100644 (file)
@@ -209,6 +209,11 @@ CFLAGS += -DCONFIG_P2P_STRICT
 endif
 endif
 
+ifdef CONFIG_INTERWORKING
+CFLAGS += -DCONFIG_INTERWORKING
+NEED_GAS=y
+endif
+
 ifdef CONFIG_NO_WPA2
 CFLAGS += -DCONFIG_NO_WPA2
 endif
index 7ec4531..31ce26f 100644 (file)
@@ -2381,6 +2381,20 @@ static int wpa_config_process_sec_device_type(
 #endif /* CONFIG_P2P */
 
 
+static int wpa_config_process_hessid(
+       const struct global_parse_data *data,
+       struct wpa_config *config, int line, const char *pos)
+{
+       if (hwaddr_aton2(pos, config->hessid) < 0) {
+               wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
+                          line, pos);
+               return -1;
+       }
+
+       return 0;
+}
+
+
 #ifdef OFFSET
 #undef OFFSET
 #endif /* OFFSET */
@@ -2445,7 +2459,9 @@ static const struct global_parse_data global_fields[] = {
        { INT(bss_expiration_scan_count), 0 },
        { INT_RANGE(filter_ssids, 0, 1), 0 },
        { INT(max_num_sta), 0 },
-       { INT_RANGE(disassoc_low_ack, 0, 1), 0 }
+       { INT_RANGE(disassoc_low_ack, 0, 1), 0 },
+       { INT_RANGE(interworking, 0, 1), 0 },
+       { FUNC(hessid), 0 }
 };
 
 #undef FUNC
index 2bc05da..300cf28 100644 (file)
@@ -426,6 +426,20 @@ struct wpa_config {
         * disassoc_low_ack - Disassocicate stations with massive packet loss
         */
        int disassoc_low_ack;
+
+       /**
+        * interworking - Whether Interworking (IEEE 802.11u) is enabled
+        */
+       int interworking;
+
+       /**
+        * hessid - Homogenous ESS identifier
+        *
+        * If this is set (any octet is non-zero), scans will be used to
+        * request response only from BSSes belonging to the specified
+        * Homogeneous ESS. This is used only if interworking is enabled.
+        */
+       u8 hessid[ETH_ALEN];
 };
 
 
index 2d5fdd6..a5d0843 100644 (file)
@@ -703,6 +703,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "max_num_sta=%u\n", config->max_num_sta);
        if (config->disassoc_low_ack)
                fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack);
+       if (config->interworking)
+               fprintf(f, "interworking=%u\n", config->interworking);
+       if (!is_zero_ether_addr(config->hessid))
+               fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid));
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
index 452bdeb..022e998 100644 (file)
@@ -457,3 +457,9 @@ CONFIG_PEERKEY=y
 
 # IEEE 802.11n (High Throughput) support (mainly for AP mode)
 #CONFIG_IEEE80211N=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks (GAS/ANQP to learn more about the networks and network
+# selection based on available credentials).
+#CONFIG_INTERWORKING=y
index 67f46ed..2d3a38f 100644 (file)
@@ -354,41 +354,73 @@ static void wpa_supplicant_optimize_freqs(
 }
 
 
+#ifdef CONFIG_INTERWORKING
+static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
+                                          struct wpabuf *buf)
+{
+       if (wpa_s->conf->interworking == 0)
+               return;
+
+       wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
+       wpabuf_put_u8(buf, 4);
+       wpabuf_put_u8(buf, 0x00);
+       wpabuf_put_u8(buf, 0x00);
+       wpabuf_put_u8(buf, 0x00);
+       wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
+
+       wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
+       wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
+                     1 + ETH_ALEN);
+       wpabuf_put_u8(buf, INTERWORKING_ANT_WILDCARD);
+       /* No Venue Info */
+       if (!is_zero_ether_addr(wpa_s->conf->hessid))
+               wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
+}
+#endif /* CONFIG_INTERWORKING */
+
+
 static struct wpabuf *
 wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s,
                         struct wpa_driver_scan_params *params)
 {
-       struct wpabuf *wps_ie = NULL;
+       struct wpabuf *extra_ie = NULL;
 #ifdef CONFIG_WPS
        int wps = 0;
        enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_INTERWORKING
+       if (wpa_s->conf->interworking &&
+           wpabuf_resize(&extra_ie, 100) == 0)
+               wpas_add_interworking_elements(wpa_s, extra_ie);
+#endif /* CONFIG_INTERWORKING */
 
+#ifdef CONFIG_WPS
        wps = wpas_wps_in_use(wpa_s, &req_type);
 
        if (wps) {
+               struct wpabuf *wps_ie;
                wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
                                                wpa_s->wps->uuid, req_type,
                                                0, NULL);
                if (wps_ie) {
-                       params->extra_ies = wpabuf_head(wps_ie);
-                       params->extra_ies_len = wpabuf_len(wps_ie);
+                       if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
+                               wpabuf_put_buf(extra_ie, wps_ie);
+                       wpabuf_free(wps_ie);
                }
        }
 
 #ifdef CONFIG_P2P
-       if (wps_ie) {
+       if (wps) {
                size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
-               if (wpabuf_resize(&wps_ie, ielen) == 0) {
-                       wpas_p2p_scan_ie(wpa_s, wps_ie);
-                       params->extra_ies = wpabuf_head(wps_ie);
-                       params->extra_ies_len = wpabuf_len(wps_ie);
-               }
+               if (wpabuf_resize(&extra_ie, ielen) == 0)
+                       wpas_p2p_scan_ie(wpa_s, extra_ie);
        }
 #endif /* CONFIG_P2P */
 
 #endif /* CONFIG_WPS */
 
-       return wps_ie;
+       return extra_ie;
 }
 
 
@@ -397,7 +429,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
        struct wpa_supplicant *wpa_s = eloop_ctx;
        struct wpa_ssid *ssid;
        int scan_req = 0, ret;
-       struct wpabuf *wps_ie;
+       struct wpabuf *extra_ie;
        struct wpa_driver_scan_params params;
        size_t max_ssids;
        enum wpa_states prev_state;
@@ -558,7 +590,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
        }
 
        wpa_supplicant_optimize_freqs(wpa_s, &params);
-       wps_ie = wpa_supplicant_extra_ies(wpa_s, &params);
+       extra_ie = wpa_supplicant_extra_ies(wpa_s, &params);
 
        if (params.freqs == NULL && wpa_s->next_scan_freqs) {
                wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
@@ -570,10 +602,14 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 
        params.filter_ssids = wpa_supplicant_build_filter_ssids(
                wpa_s->conf, &params.num_filter_ssids);
+       if (extra_ie) {
+               params.extra_ies = wpabuf_head(extra_ie);
+               params.extra_ies_len = wpabuf_len(extra_ie);
+       }
 
        ret = wpa_supplicant_trigger_scan(wpa_s, &params);
 
-       wpabuf_free(wps_ie);
+       wpabuf_free(extra_ie);
        os_free(params.freqs);
        os_free(params.filter_ssids);
 
index a7c3fcc..12dd7fd 100644 (file)
@@ -228,6 +228,17 @@ fast_reauth=1
 #filter_ssids=0
 
 
+# Interworking (IEEE 802.11u)
+
+# Enable Interworking
+# interworking=1
+
+# Homogenous ESS identifier
+# If this is set, scans will be used to request response only from BSSes
+# belonging to the specified Homogeneous ESS. This is used only if interworking
+# is enabled.
+# hessid=00:11:22:33:44:55
+
 # network block
 #
 # Each network (usually AP's sharing the same SSID) is configured as a separate