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);