WPS: Use AP Channel attribute in credential to speed up scan
authorJouni Malinen <j@w1.fi>
Sun, 28 Oct 2012 16:02:04 +0000 (18:02 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 28 Oct 2012 16:02:04 +0000 (18:02 +0200)
When WPS is used with NFC connection handover, the AP may indicate its
operating channel within the credential information. Use this
informatiom, if present, to speed up the scan process.

Signed-hostap: Jouni Malinen <j@w1.fi>

src/wps/wps.h
src/wps/wps_attr_parse.c
src/wps/wps_attr_parse.h
src/wps/wps_attr_process.c
wpa_supplicant/wpa_supplicant_i.h
wpa_supplicant/wps_supplicant.c

index 17ee620..74304dc 100644 (file)
@@ -42,6 +42,7 @@ struct wps_parse_attr;
  * @cred_attr: Unparsed Credential attribute data (used only in cred_cb());
  *     this may be %NULL, if not used
  * @cred_attr_len: Length of cred_attr in octets
+ * @ap_channel: AP channel
  */
 struct wps_credential {
        u8 ssid[32];
@@ -54,6 +55,7 @@ struct wps_credential {
        u8 mac_addr[ETH_ALEN];
        const u8 *cred_attr;
        size_t cred_attr_len;
+       u16 ap_channel;
 };
 
 #define WPS_DEV_TYPE_LEN 8
index 5aa9b00..3999b1b 100644 (file)
@@ -542,6 +542,14 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
                if (wps_parse_vendor_ext(attr, pos, len) < 0)
                        return -1;
                break;
+       case ATTR_AP_CHANNEL:
+               if (len != 2) {
+                       wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
+                                  "length %u", len);
+                       return -1;
+               }
+               attr->ap_channel = pos;
+               break;
        default:
                wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
                           "len=%u", type, len);
index 332e966..88e51a4 100644 (file)
@@ -56,6 +56,7 @@ struct wps_parse_attr {
        const u8 *settings_delay_time; /* 1 octet */
        const u8 *network_key_shareable; /* 1 octet (Bool) */
        const u8 *request_to_enroll; /* 1 octet (Bool) */
+       const u8 *ap_channel; /* 2 octets */
 
        /* variable length fields */
        const u8 *manufacturer;
index d4c6e88..b81f106 100644 (file)
@@ -258,6 +258,19 @@ static int wps_process_cred_802_1x_enabled(struct wps_credential *cred,
 }
 
 
+static int wps_process_cred_ap_channel(struct wps_credential *cred,
+                                      const u8 *ap_channel)
+{
+       if (ap_channel == NULL)
+               return 0; /* optional attribute */
+
+       cred->ap_channel = WPA_GET_BE16(ap_channel);
+       wpa_printf(MSG_DEBUG, "WPS: AP Channel: %u", cred->ap_channel);
+
+       return 0;
+}
+
+
 static int wps_workaround_cred_key(struct wps_credential *cred)
 {
        if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
@@ -303,7 +316,8 @@ int wps_process_cred(struct wps_parse_attr *attr,
            wps_process_cred_eap_identity(cred, attr->eap_identity,
                                          attr->eap_identity_len) ||
            wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) ||
-           wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled))
+           wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled) ||
+           wps_process_cred_ap_channel(cred, attr->ap_channel))
                return -1;
 
        return wps_workaround_cred_key(cred);
index 43e9883..3761fbf 100644 (file)
@@ -589,6 +589,7 @@ struct wpa_supplicant {
        int after_wps;
        int known_wps_freq;
        unsigned int wps_freq;
+       u16 wps_ap_channel;
        int wps_fragment_size;
        int auto_reconnect_disabled;
 
index 0655156..5977e1a 100644 (file)
@@ -403,6 +403,9 @@ static int wpa_supplicant_wps_cred(void *ctx,
 
        wpas_wps_security_workaround(wpa_s, ssid, cred);
 
+       if (cred->ap_channel)
+               wpa_s->wps_ap_channel = cred->ap_channel;
+
 #ifndef CONFIG_NO_CONFIG_WRITE
        if (wpa_s->conf->update_config &&
            wpa_config_write(wpa_s->confname, wpa_s->conf)) {
@@ -1896,6 +1899,8 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid)
 static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
                             struct wps_parse_attr *attr)
 {
+       wpa_s->wps_ap_channel = 0;
+
        if (wps_oob_use_cred(wpa_s->wps, attr) < 0)
                return -1;
 
@@ -1906,6 +1911,24 @@ static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
                   "based on the received credential added");
        wpa_s->normal_scans = 0;
        wpa_supplicant_reinit_autoscan(wpa_s);
+       if (wpa_s->wps_ap_channel) {
+               u16 chan = wpa_s->wps_ap_channel;
+               int freq = 0;
+
+               if (chan >= 1 && chan <= 13)
+                       freq = 2407 + 5 * chan;
+               else if (chan == 14)
+                       freq = 2484;
+               else if (chan >= 30)
+                       freq = 5000 + 5 * chan;
+
+               if (freq) {
+                       wpa_printf(MSG_DEBUG, "WPS: Credential indicated "
+                                  "AP channel %u -> %u MHz", chan, freq);
+                       wpa_s->after_wps = 5;
+                       wpa_s->wps_freq = freq;
+               }
+       }
        wpa_s->disconnected = 0;
        wpa_s->reassociate = 1;
        wpa_supplicant_req_scan(wpa_s, 0, 0);