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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-10-28 18:02:04 +02:00
parent e65552ddf2
commit bd3a373767
6 changed files with 50 additions and 1 deletions

View file

@ -42,6 +42,7 @@ struct wps_parse_attr;
* @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); * @cred_attr: Unparsed Credential attribute data (used only in cred_cb());
* this may be %NULL, if not used * this may be %NULL, if not used
* @cred_attr_len: Length of cred_attr in octets * @cred_attr_len: Length of cred_attr in octets
* @ap_channel: AP channel
*/ */
struct wps_credential { struct wps_credential {
u8 ssid[32]; u8 ssid[32];
@ -54,6 +55,7 @@ struct wps_credential {
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
const u8 *cred_attr; const u8 *cred_attr;
size_t cred_attr_len; size_t cred_attr_len;
u16 ap_channel;
}; };
#define WPS_DEV_TYPE_LEN 8 #define WPS_DEV_TYPE_LEN 8

View 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) if (wps_parse_vendor_ext(attr, pos, len) < 0)
return -1; return -1;
break; 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: default:
wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
"len=%u", type, len); "len=%u", type, len);

View file

@ -56,6 +56,7 @@ struct wps_parse_attr {
const u8 *settings_delay_time; /* 1 octet */ const u8 *settings_delay_time; /* 1 octet */
const u8 *network_key_shareable; /* 1 octet (Bool) */ const u8 *network_key_shareable; /* 1 octet (Bool) */
const u8 *request_to_enroll; /* 1 octet (Bool) */ const u8 *request_to_enroll; /* 1 octet (Bool) */
const u8 *ap_channel; /* 2 octets */
/* variable length fields */ /* variable length fields */
const u8 *manufacturer; const u8 *manufacturer;

View 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) static int wps_workaround_cred_key(struct wps_credential *cred)
{ {
if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && 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, wps_process_cred_eap_identity(cred, attr->eap_identity,
attr->eap_identity_len) || attr->eap_identity_len) ||
wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || 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 -1;
return wps_workaround_cred_key(cred); return wps_workaround_cred_key(cred);

View file

@ -589,6 +589,7 @@ struct wpa_supplicant {
int after_wps; int after_wps;
int known_wps_freq; int known_wps_freq;
unsigned int wps_freq; unsigned int wps_freq;
u16 wps_ap_channel;
int wps_fragment_size; int wps_fragment_size;
int auto_reconnect_disabled; int auto_reconnect_disabled;

View file

@ -403,6 +403,9 @@ static int wpa_supplicant_wps_cred(void *ctx,
wpas_wps_security_workaround(wpa_s, ssid, cred); 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 #ifndef CONFIG_NO_CONFIG_WRITE
if (wpa_s->conf->update_config && if (wpa_s->conf->update_config &&
wpa_config_write(wpa_s->confname, wpa_s->conf)) { 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, static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
struct wps_parse_attr *attr) struct wps_parse_attr *attr)
{ {
wpa_s->wps_ap_channel = 0;
if (wps_oob_use_cred(wpa_s->wps, attr) < 0) if (wps_oob_use_cred(wpa_s->wps, attr) < 0)
return -1; return -1;
@ -1906,6 +1911,24 @@ static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
"based on the received credential added"); "based on the received credential added");
wpa_s->normal_scans = 0; wpa_s->normal_scans = 0;
wpa_supplicant_reinit_autoscan(wpa_s); 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->disconnected = 0;
wpa_s->reassociate = 1; wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0); wpa_supplicant_req_scan(wpa_s, 0, 0);