|
@@ -43,6 +43,15 @@ static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
|
|
|
static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
|
|
|
|
|
|
|
|
|
+static void wpas_wps_clear_ap_info(struct wpa_supplicant *wpa_s)
|
|
|
+{
|
|
|
+ os_free(wpa_s->wps_ap);
|
|
|
+ wpa_s->wps_ap = NULL;
|
|
|
+ wpa_s->num_wps_ap = 0;
|
|
|
+ wpa_s->wps_ap_iter = 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
|
|
|
{
|
|
|
if (!wpa_s->wps_success &&
|
|
@@ -66,6 +75,7 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+ wpas_wps_clear_ap_info(wpa_s);
|
|
|
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
|
|
|
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && !wpa_s->wps_success)
|
|
|
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL);
|
|
@@ -706,6 +716,8 @@ static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
|
|
|
wpa_config_remove_network(wpa_s->conf, id);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ wpas_wps_clear_ap_info(wpa_s);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -901,6 +913,7 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|
|
ssid->eap.fragment_size = wpa_s->wps_fragment_size;
|
|
|
eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
|
|
|
wpa_s, NULL);
|
|
|
+ wpa_s->wps_ap_iter = 1;
|
|
|
wpas_wps_reassoc(wpa_s, ssid, bssid);
|
|
|
return rpin;
|
|
|
}
|
|
@@ -927,7 +940,8 @@ int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
|
|
|
wpa_supplicant_deauthenticate(wpa_s,
|
|
|
WLAN_REASON_DEAUTH_LEAVING);
|
|
|
wpas_clear_wps(wpa_s);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ wpas_wps_clear_ap_info(wpa_s);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -1233,6 +1247,7 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s)
|
|
|
void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
|
|
|
{
|
|
|
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
|
|
|
+ wpas_wps_clear_ap_info(wpa_s);
|
|
|
|
|
|
if (wpa_s->wps == NULL)
|
|
|
return;
|
|
@@ -1914,3 +1929,128 @@ int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
|
|
|
}
|
|
|
|
|
|
#endif /* CONFIG_WPS_NFC */
|
|
|
+
|
|
|
+
|
|
|
+extern int wpa_debug_level;
|
|
|
+
|
|
|
+static void wpas_wps_dump_ap_info(struct wpa_supplicant *wpa_s)
|
|
|
+{
|
|
|
+ size_t i;
|
|
|
+ struct os_time now;
|
|
|
+
|
|
|
+ if (wpa_debug_level > MSG_DEBUG)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (wpa_s->wps_ap == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ os_get_time(&now);
|
|
|
+
|
|
|
+ for (i = 0; i < wpa_s->num_wps_ap; i++) {
|
|
|
+ struct wps_ap_info *ap = &wpa_s->wps_ap[i];
|
|
|
+ struct wpa_blacklist *e = wpa_blacklist_get(wpa_s, ap->bssid);
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "WPS: AP[%d] " MACSTR " type=%d "
|
|
|
+ "tries=%d last_attempt=%d sec ago blacklist=%d",
|
|
|
+ (int) i, MAC2STR(ap->bssid), ap->type, ap->tries,
|
|
|
+ ap->last_attempt.sec > 0 ?
|
|
|
+ (int) now.sec - (int) ap->last_attempt.sec : -1,
|
|
|
+ e ? e->count : 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static struct wps_ap_info * wpas_wps_get_ap_info(struct wpa_supplicant *wpa_s,
|
|
|
+ const u8 *bssid)
|
|
|
+{
|
|
|
+ size_t i;
|
|
|
+
|
|
|
+ if (wpa_s->wps_ap == NULL)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ for (i = 0; i < wpa_s->num_wps_ap; i++) {
|
|
|
+ struct wps_ap_info *ap = &wpa_s->wps_ap[i];
|
|
|
+ if (os_memcmp(ap->bssid, bssid, ETH_ALEN) == 0)
|
|
|
+ return ap;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void wpas_wps_update_ap_info_bss(struct wpa_supplicant *wpa_s,
|
|
|
+ struct wpa_scan_res *res)
|
|
|
+{
|
|
|
+ struct wpabuf *wps;
|
|
|
+ enum wps_ap_info_type type;
|
|
|
+ struct wps_ap_info *ap;
|
|
|
+ int r;
|
|
|
+
|
|
|
+ if (wpa_scan_get_vendor_ie(res, WPS_IE_VENDOR_TYPE) == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ wps = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
|
|
|
+ if (wps == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ r = wps_is_addr_authorized(wps, wpa_s->own_addr, 1);
|
|
|
+ if (r == 2)
|
|
|
+ type = WPS_AP_SEL_REG_OUR;
|
|
|
+ else if (r == 1)
|
|
|
+ type = WPS_AP_SEL_REG;
|
|
|
+ else
|
|
|
+ type = WPS_AP_NOT_SEL_REG;
|
|
|
+
|
|
|
+ wpabuf_free(wps);
|
|
|
+
|
|
|
+ ap = wpas_wps_get_ap_info(wpa_s, res->bssid);
|
|
|
+ if (ap) {
|
|
|
+ if (ap->type != type) {
|
|
|
+ wpa_printf(MSG_DEBUG, "WPS: AP " MACSTR
|
|
|
+ " changed type %d -> %d",
|
|
|
+ MAC2STR(res->bssid), ap->type, type);
|
|
|
+ ap->type = type;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ap = os_realloc_array(wpa_s->wps_ap, wpa_s->num_wps_ap + 1,
|
|
|
+ sizeof(struct wps_ap_info));
|
|
|
+ if (ap == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ wpa_s->wps_ap = ap;
|
|
|
+ ap = &wpa_s->wps_ap[wpa_s->num_wps_ap];
|
|
|
+ wpa_s->num_wps_ap++;
|
|
|
+
|
|
|
+ os_memset(ap, 0, sizeof(*ap));
|
|
|
+ os_memcpy(ap->bssid, res->bssid, ETH_ALEN);
|
|
|
+ ap->type = type;
|
|
|
+ wpa_printf(MSG_DEBUG, "WPS: AP " MACSTR " type %d added",
|
|
|
+ MAC2STR(ap->bssid), ap->type);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
|
|
|
+ struct wpa_scan_results *scan_res)
|
|
|
+{
|
|
|
+ size_t i;
|
|
|
+
|
|
|
+ for (i = 0; i < scan_res->num; i++)
|
|
|
+ wpas_wps_update_ap_info_bss(wpa_s, scan_res->res[i]);
|
|
|
+
|
|
|
+ wpas_wps_dump_ap_info(wpa_s);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
|
|
+{
|
|
|
+ struct wps_ap_info *ap;
|
|
|
+ if (!wpa_s->wps_ap_iter)
|
|
|
+ return;
|
|
|
+ ap = wpas_wps_get_ap_info(wpa_s, bssid);
|
|
|
+ if (ap == NULL)
|
|
|
+ return;
|
|
|
+ ap->tries++;
|
|
|
+ os_get_time(&ap->last_attempt);
|
|
|
+}
|