From f9f0526bcde038c23f071c05af3c27d6ad924bfe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 27 Aug 2012 13:48:11 +0300 Subject: [PATCH] WPS: Maintain more AP state during WPS PIN iteration Maintain state of WPS APs during iteration to find the correct AP for WPS PIN operation when no specific BSSID is specified. This information can be used for optimizing the order in which the APs are tried. This commit is only adding the collection of the information and more detailed debug information to make debug logs more helpful in figuring out how the AP selection order could be improved. Signed-hostap: Jouni Malinen --- src/wps/wps.c | 8 +- wpa_supplicant/events.c | 4 + wpa_supplicant/wpa_supplicant_i.h | 15 ++++ wpa_supplicant/wps_supplicant.c | 142 +++++++++++++++++++++++++++++- wpa_supplicant/wps_supplicant.h | 14 +++ 5 files changed, 179 insertions(+), 4 deletions(-) diff --git a/src/wps/wps.c b/src/wps/wps.c index 5453962a5..4c2322df8 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -287,7 +287,8 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg) * @msg: WPS IE contents from Beacon or Probe Response frame * @addr: MAC address to search for * @ver1_compat: Whether to use version 1 compatibility mode - * Returns: 1 if address is authorized, 0 if not + * Returns: 2 if the specified address is explicit authorized, 1 if address is + * authorized (broadcast), 0 if not */ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, int ver1_compat) @@ -313,8 +314,9 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, pos = attr.authorized_macs; for (i = 0; i < attr.authorized_macs_len / ETH_ALEN; i++) { - if (os_memcmp(pos, addr, ETH_ALEN) == 0 || - os_memcmp(pos, bcast, ETH_ALEN) == 0) + if (os_memcmp(pos, addr, ETH_ALEN) == 0) + return 2; + if (os_memcmp(pos, bcast, ETH_ALEN) == 0) return 1; pos += ETH_ALEN; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 9f12a16d9..cddcce72d 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1158,6 +1158,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, return 0; } + wpas_wps_update_ap_info(wpa_s, scan_res); + selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid); if (selected) { @@ -1732,6 +1734,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, ibss_rsn_set_psk(wpa_s->ibss_rsn, wpa_s->current_ssid->psk); } #endif /* CONFIG_IBSS_RSN */ + + wpas_wps_notify_assoc(wpa_s, bssid); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 01ea87390..632f6bc94 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -249,6 +249,17 @@ enum offchannel_send_action_result { OFFCHANNEL_SEND_ACTION_FAILED /* Frame was not sent due to a failure */ }; +struct wps_ap_info { + u8 bssid[ETH_ALEN]; + enum wps_ap_info_type { + WPS_AP_NOT_SEL_REG, + WPS_AP_SEL_REG, + WPS_AP_SEL_REG_OUR + } type; + unsigned int tries; + struct os_time last_attempt; +}; + /** * struct wpa_supplicant - Internal data for wpa_supplicant interface * @@ -538,6 +549,10 @@ struct wpa_supplicant { struct wpa_ssid *connect_without_scan; + struct wps_ap_info *wps_ap; + size_t num_wps_ap; + int wps_ap_iter; + int after_wps; int known_wps_freq; unsigned int wps_freq; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index c72da1115..3bb542757 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -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); +} diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index 5a49a8f2e..36f1e0218 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -10,6 +10,7 @@ #define WPS_SUPPLICANT_H struct wpa_scan_res; +struct wpa_scan_results; #ifdef CONFIG_WPS @@ -68,6 +69,9 @@ struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef); int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s, const struct wpabuf *data); +void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); +void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid); #else /* CONFIG_WPS */ @@ -120,6 +124,16 @@ static inline int wpas_wps_searching(struct wpa_supplicant *wpa_s) return 0; } +static inline void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ +} + +static inline void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ +} + #endif /* CONFIG_WPS */ #endif /* WPS_SUPPLICANT_H */