aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-01-23 11:10:58 (GMT)
committerJouni Malinen <j@w1.fi>2009-02-08 10:17:38 (GMT)
commit2292277859c08e815784213e8ed3da9a719ce64d (patch)
tree0170d25251bf6604f61dd63ec36c2fffa23496fd /wpa_supplicant
parent2b15e08f94d2f04ea67c0118c52e7bfb03d20dc0 (diff)
downloadhostap-06-2292277859c08e815784213e8ed3da9a719ce64d.zip
hostap-06-2292277859c08e815784213e8ed3da9a719ce64d.tar.gz
hostap-06-2292277859c08e815784213e8ed3da9a719ce64d.tar.bz2
Allow WPS APs for PIN enrollment even without Selected Registrar
Some WPS APs do not set Selected Registrar attribute to 1 properly when using an external Registrar. Allow such an AP to be selected for PIN registration after couple of scan runs that do not find APs marked with Selected Registrar = 1. This allows wpa_supplicant to iterate through all APs that advertise WPS support without delaying connection with implementations that set Selected Registrar = 1 properly. (cherry picked from commit a609915233c75f6dc8b942292fd8dcd79bb871bf) Conflicts: wpa_supplicant/wpa_supplicant_i.h
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/events.c13
-rw-r--r--wpa_supplicant/scan.c3
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h3
-rw-r--r--wpa_supplicant/wps_supplicant.c62
-rw-r--r--wpa_supplicant/wps_supplicant.h12
5 files changed, 73 insertions, 20 deletions
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 32b87e9..dd4595a 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -270,7 +270,8 @@ static int wpa_supplicant_match_privacy(struct wpa_scan_res *bss,
}
-static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid,
+static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
struct wpa_scan_res *bss)
{
struct wpa_ie_data ie;
@@ -278,7 +279,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid,
const u8 *rsn_ie, *wpa_ie;
int ret;
- ret = wpas_wps_ssid_bss_match(ssid, bss);
+ ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss);
if (ret >= 0)
return ret;
@@ -424,7 +425,7 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_WPS
if (ssid->ssid_len == 0 &&
- wpas_wps_ssid_wildcard_ok(ssid, bss))
+ wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss))
check_ssid = 0;
#endif /* CONFIG_WPS */
@@ -444,7 +445,7 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
continue;
}
- if (!wpa_supplicant_ssid_bss_match(ssid, bss))
+ if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
continue;
wpa_printf(MSG_DEBUG, " selected WPA AP "
@@ -514,7 +515,8 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
* with our mode. */
check_ssid = 1;
if (ssid->ssid_len == 0 &&
- wpas_wps_ssid_wildcard_ok(ssid, bss))
+ wpas_wps_ssid_wildcard_ok(wpa_s, ssid,
+ bss))
check_ssid = 0;
}
#endif /* CONFIG_WPS */
@@ -645,6 +647,7 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "No APs found - clear blacklist "
"and try again");
wpa_blacklist_clear(wpa_s);
+ wpa_s->blacklist_cleared++;
} else if (selected == NULL) {
break;
}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index afc3411..67e2282 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -204,7 +204,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
if (ret) {
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
wpa_supplicant_req_scan(wpa_s, 10, 0);
- }
+ } else
+ wpa_s->scan_runs++;
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f39709f..5e4dcc1 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -345,6 +345,7 @@ struct wpa_supplicant {
* results without a new scan request; this is used
* to speed up the first association if the driver
* has already available scan results. */
+ int scan_runs; /* number of scan runs since WPS was started */
struct wpa_client_mlme mlme;
int use_client_mlme;
@@ -355,6 +356,8 @@ struct wpa_supplicant {
int mic_errors_seen; /* Michael MIC errors with the current PTK */
struct wps_context *wps;
+ int wps_success; /* WPS success event received */
+ int blacklist_cleared;
};
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 14f1f86..2dd22f2 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -25,8 +25,10 @@
#include "wpa_ctrl.h"
#include "ctrl_iface_dbus.h"
#include "eap_common/eap_wsc_common.h"
+#include "blacklist.h"
#include "wps_supplicant.h"
+#define WPS_PIN_SCAN_IGNORE_SEL_REG 3
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
@@ -34,6 +36,27 @@ static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
{
+ if (!wpa_s->wps_success &&
+ wpa_s->current_ssid &&
+ eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
+ const u8 *bssid = wpa_s->bssid;
+ if (is_zero_ether_addr(bssid))
+ bssid = wpa_s->pending_bssid;
+
+ wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
+ " did not succeed - continue trying to find "
+ "suitable AP", MAC2STR(bssid));
+ wpa_blacklist_add(wpa_s, bssid);
+
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s,
+ wpa_s->blacklist_cleared ? 5 : 0, 0);
+ wpa_s->blacklist_cleared = 0;
+ return 1;
+ }
+
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
@@ -234,6 +257,7 @@ static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
{
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
+ wpa_s->wps_success = 1;
}
@@ -291,7 +315,8 @@ static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
- wpa_printf(MSG_DEBUG, "WPS: Requested operation timed out");
+ wpa_printf(MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
+ "out");
wpas_clear_wps(wpa_s);
}
@@ -363,6 +388,9 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
}
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->scan_runs = 0;
+ wpa_s->wps_success = 0;
+ wpa_s->blacklist_cleared = 0;
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
@@ -550,7 +578,8 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
}
-int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss)
+int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid, struct wpa_scan_res *bss)
{
struct wpabuf *wps_ie;
@@ -584,14 +613,24 @@ int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss)
return 0;
}
+ /*
+ * Start with WPS APs that advertise active PIN Registrar and
+ * allow any WPS AP after third scan since some APs do not set
+ * Selected Registrar attribute properly when using external
+ * Registrar.
+ */
if (!wps_is_selected_pin_registrar(wps_ie)) {
- wpa_printf(MSG_DEBUG, " skip - WPS AP "
- "without active PIN Registrar");
- wpabuf_free(wps_ie);
- return 0;
+ if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
+ wpa_printf(MSG_DEBUG, " skip - WPS AP "
+ "without active PIN Registrar");
+ wpabuf_free(wps_ie);
+ return 0;
+ }
+ wpa_printf(MSG_DEBUG, " selected based on WPS IE");
+ } else {
+ wpa_printf(MSG_DEBUG, " selected based on WPS IE "
+ "(Active PIN)");
}
- wpa_printf(MSG_DEBUG, " selected based on WPS IE "
- "(Active PIN)");
wpabuf_free(wps_ie);
return 1;
}
@@ -606,7 +645,8 @@ int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss)
}
-int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
+int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
struct wpa_scan_res *bss)
{
struct wpabuf *wps_ie = NULL;
@@ -620,7 +660,9 @@ int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
}
} else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
- if (wps_ie && wps_is_selected_pin_registrar(wps_ie)) {
+ if (wps_ie &&
+ (wps_is_selected_pin_registrar(wps_ie) ||
+ wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
/* allow wildcard SSID for WPS PIN */
ret = 1;
}
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index 2993049..8f81dc4 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -29,8 +29,10 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
const char *pin);
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
const char *pin);
-int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss);
-int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid, struct wpa_scan_res *bss);
+int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid, struct wpa_scan_res *bss);
+int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid, struct wpa_scan_res *bss);
int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *selected,
struct wpa_ssid *ssid);
@@ -58,13 +60,15 @@ static inline u8 wpas_wps_get_req_type(struct wpa_ssid *ssid)
return 0;
}
-static inline int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid,
+static inline int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
struct wpa_scan_res *bss)
{
return -1;
}
-static inline int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
+static inline int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
struct wpa_scan_res *bss)
{
return 0;