From bd3a3737672aaf6eb50dba2b8caa3941c8df42e9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 28 Oct 2012 18:02:04 +0200 Subject: [PATCH] WPS: Use AP Channel attribute in credential to speed up scan 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 --- src/wps/wps.h | 2 ++ src/wps/wps_attr_parse.c | 8 ++++++++ src/wps/wps_attr_parse.h | 1 + src/wps/wps_attr_process.c | 16 +++++++++++++++- wpa_supplicant/wpa_supplicant_i.h | 1 + wpa_supplicant/wps_supplicant.c | 23 +++++++++++++++++++++++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/wps/wps.h b/src/wps/wps.h index 17ee620c9..74304dc23 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -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 diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c index 5aa9b004f..3999b1b88 100644 --- a/src/wps/wps_attr_parse.c +++ b/src/wps/wps_attr_parse.c @@ -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); diff --git a/src/wps/wps_attr_parse.h b/src/wps/wps_attr_parse.h index 332e966a4..88e51a449 100644 --- a/src/wps/wps_attr_parse.h +++ b/src/wps/wps_attr_parse.h @@ -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; diff --git a/src/wps/wps_attr_process.c b/src/wps/wps_attr_process.c index d4c6e883b..b81f106e7 100644 --- a/src/wps/wps_attr_process.c +++ b/src/wps/wps_attr_process.c @@ -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); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 43e98830d..3761fbf66 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 06551567f..5977e1a1a 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -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);