WPS: Use different scan result sorting rules when doing WPS provisioning
The AP configuration may change after provisioning, so it is better not to use the current security policy to prioritize results. Instead, use WPS Selected Registrar attribute as the main sorting key and use signal strength next without considering security policy or rate sets. The non-WPS provisioning case remains as-is, i.e., this change applies only when trying to find an AP for WPS provisioning.
This commit is contained in:
parent
f62c2315f7
commit
41e650ae5c
5 changed files with 104 additions and 1 deletions
|
@ -236,6 +236,36 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wps_ap_priority_compar - Prioritize WPS IE from two APs
|
||||||
|
* @wps_a: WPS IE contents from Beacon or Probe Response frame
|
||||||
|
* @wps_b: WPS IE contents from Beacon or Probe Response frame
|
||||||
|
* Returns: 1 if wps_b is considered more likely selection for WPS
|
||||||
|
* provisioning, -1 if wps_a is considered more like, or 0 if no preference
|
||||||
|
*/
|
||||||
|
int wps_ap_priority_compar(const struct wpabuf *wps_a,
|
||||||
|
const struct wpabuf *wps_b)
|
||||||
|
{
|
||||||
|
struct wps_parse_attr attr_a, attr_b;
|
||||||
|
int sel_a, sel_b;
|
||||||
|
|
||||||
|
if (wps_a == NULL || wps_parse_msg(wps_a, &attr_a) < 0)
|
||||||
|
return 1;
|
||||||
|
if (wps_b == NULL || wps_parse_msg(wps_b, &attr_b) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sel_a = attr_a.selected_registrar && *attr_a.selected_registrar != 0;
|
||||||
|
sel_b = attr_b.selected_registrar && *attr_b.selected_registrar != 0;
|
||||||
|
|
||||||
|
if (sel_a && !sel_b)
|
||||||
|
return -1;
|
||||||
|
if (!sel_a && sel_b)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wps_get_uuid_e - Get UUID-E from WPS IE
|
* wps_get_uuid_e - Get UUID-E from WPS IE
|
||||||
* @msg: WPS IE contents from Beacon or Probe Response frame
|
* @msg: WPS IE contents from Beacon or Probe Response frame
|
||||||
|
|
|
@ -195,6 +195,8 @@ struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code);
|
||||||
|
|
||||||
int wps_is_selected_pbc_registrar(const struct wpabuf *msg);
|
int wps_is_selected_pbc_registrar(const struct wpabuf *msg);
|
||||||
int wps_is_selected_pin_registrar(const struct wpabuf *msg);
|
int wps_is_selected_pin_registrar(const struct wpabuf *msg);
|
||||||
|
int wps_ap_priority_compar(const struct wpabuf *wps_a,
|
||||||
|
const struct wpabuf *wps_b);
|
||||||
const u8 * wps_get_uuid_e(const struct wpabuf *msg);
|
const u8 * wps_get_uuid_e(const struct wpabuf *msg);
|
||||||
|
|
||||||
struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type);
|
struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type);
|
||||||
|
|
|
@ -641,6 +641,54 @@ static int wpa_scan_result_compar(const void *a, const void *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WPS
|
||||||
|
/* Compare function for sorting scan results when searching a WPS AP for
|
||||||
|
* provisioning. Return >0 if @b is considered better. */
|
||||||
|
static int wpa_scan_result_wps_compar(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
struct wpa_scan_res **_wa = (void *) a;
|
||||||
|
struct wpa_scan_res **_wb = (void *) b;
|
||||||
|
struct wpa_scan_res *wa = *_wa;
|
||||||
|
struct wpa_scan_res *wb = *_wb;
|
||||||
|
int uses_wps_a, uses_wps_b;
|
||||||
|
struct wpabuf *wps_a, *wps_b;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* Optimization - check WPS IE existence before allocated memory and
|
||||||
|
* doing full reassembly. */
|
||||||
|
uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
|
||||||
|
uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
|
||||||
|
if (uses_wps_a && !uses_wps_b)
|
||||||
|
return -1;
|
||||||
|
if (!uses_wps_a && uses_wps_b)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (uses_wps_a && uses_wps_b) {
|
||||||
|
wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
|
||||||
|
wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
|
||||||
|
res = wps_ap_priority_compar(wps_a, wps_b);
|
||||||
|
wpabuf_free(wps_a);
|
||||||
|
wpabuf_free(wps_b);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not use current AP security policy as a sorting criteria during
|
||||||
|
* WPS provisioning step since the AP may get reconfigured at the
|
||||||
|
* completion of provisioning.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* all things being equal, use signal level; if signal levels are
|
||||||
|
* identical, use quality values since some drivers may only report
|
||||||
|
* that value and leave the signal level zero */
|
||||||
|
if (wb->level == wa->level)
|
||||||
|
return wb->qual - wa->qual;
|
||||||
|
return wb->level - wa->level;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_supplicant_get_scan_results - Get scan results
|
* wpa_supplicant_get_scan_results - Get scan results
|
||||||
* @wpa_s: Pointer to wpa_supplicant data
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
@ -658,6 +706,7 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
|
||||||
{
|
{
|
||||||
struct wpa_scan_results *scan_res;
|
struct wpa_scan_results *scan_res;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int (*compar)(const void *, const void *) = wpa_scan_result_compar;
|
||||||
|
|
||||||
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
|
||||||
scan_res = ieee80211_sta_get_scan_results(wpa_s);
|
scan_res = ieee80211_sta_get_scan_results(wpa_s);
|
||||||
|
@ -668,8 +717,16 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_WPS
|
||||||
|
if (wpas_wps_in_progress(wpa_s)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Order scan results with WPS "
|
||||||
|
"provisioning rules");
|
||||||
|
compar = wpa_scan_result_wps_compar;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
|
qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
|
||||||
wpa_scan_result_compar);
|
compar);
|
||||||
|
|
||||||
wpa_bss_update_start(wpa_s);
|
wpa_bss_update_start(wpa_s);
|
||||||
for (i = 0; i < scan_res->num; i++)
|
for (i = 0; i < scan_res->num; i++)
|
||||||
|
|
|
@ -1264,3 +1264,16 @@ int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s)
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_wps_in_progress(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpa_ssid *ssid;
|
||||||
|
|
||||||
|
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
|
||||||
|
if (!ssid->disabled && ssid->key_mgmt == WPA_KEY_MGMT_WPS)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
|
int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
const char *pin, struct wps_new_ap_settings *settings);
|
const char *pin, struct wps_new_ap_settings *settings);
|
||||||
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
|
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
|
||||||
|
int wpas_wps_in_progress(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#else /* CONFIG_WPS */
|
#else /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue