From 6ae9318536ecffa7374431767e2e3cb0c6b56758 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Nov 2009 17:06:03 +0200 Subject: [PATCH] Split scan processing for RSN preauthentication into parts This avoids passing the raw scan results into the RSN code and by doing so, removes the only dependency on src/drivers from the src/rsn_supp code (or from any src subdirectory for that matter). --- src/rsn_supp/preauth.c | 76 ++++++++++++++++++++--------------------- src/rsn_supp/preauth.h | 17 ++++++--- wpa_supplicant/events.c | 33 ++++++++++++++++-- 3 files changed, 80 insertions(+), 46 deletions(-) diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index 07d5b81b8..f4e8cbb48 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - RSN pre-authentication - * Copyright (c) 2003-2008, Jouni Malinen + * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,7 +16,6 @@ #include "common.h" #include "wpa.h" -#include "drivers/driver.h" #include "eloop.h" #include "l2_packet/l2_packet.h" #include "eapol_supp/eapol_supp_sm.h" @@ -423,23 +422,18 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, /* TODO: schedule periodic scans if current AP supports preauth */ /** - * rsn_preauth_scan_results - Process scan results to find PMKSA candidates + * rsn_preauth_scan_results - Start processing scan results for canditates * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @results: Scan results + * Returns: 0 if ready to process results or -1 to skip processing * - * This functions goes through the scan results and adds all suitable APs - * (Authenticators) into PMKSA candidate list. + * This functions is used to notify RSN code about start of new scan results + * processing. The actual scan results will be provided by calling + * rsn_preauth_scan_result() for each BSS if this function returned 0. */ -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results) +int rsn_preauth_scan_results(struct wpa_sm *sm) { - struct wpa_scan_res *r; - struct wpa_ie_data ie; - int i; - struct rsn_pmksa_cache_entry *pmksa; - if (sm->ssid_len == 0) - return; + return -1; /* * TODO: is it ok to free all candidates? What about the entries @@ -447,37 +441,41 @@ void rsn_preauth_scan_results(struct wpa_sm *sm, */ pmksa_candidate_free(sm); - for (i = results->num - 1; i >= 0; i--) { - const u8 *ssid, *rsn; + return 0; +} - r = results->res[i]; - ssid = wpa_scan_get_ie(r, WLAN_EID_SSID); - if (ssid == NULL || ssid[1] != sm->ssid_len || - os_memcmp(ssid + 2, sm->ssid, ssid[1]) != 0) - continue; +/** + * rsn_preauth_scan_result - Processing scan result for PMKSA canditates + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * + * Add all suitable APs (Authenticators) from scan results into PMKSA + * candidate list. + */ +void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, + const u8 *ssid, const u8 *rsn) +{ + struct wpa_ie_data ie; + struct rsn_pmksa_cache_entry *pmksa; - if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0) - continue; + if (ssid[1] != sm->ssid_len || + os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0) + return; /* Not for the current SSID */ - rsn = wpa_scan_get_ie(r, WLAN_EID_RSN); - if (rsn == NULL || wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) - continue; + if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0) + return; /* Ignore current AP */ - pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL); - if (pmksa && - (!pmksa->opportunistic || - !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) - continue; + if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) + return; - /* - * Give less priority to candidates found from normal - * scan results. - */ - pmksa_candidate_add(sm, r->bssid, - PMKID_CANDIDATE_PRIO_SCAN, - ie.capabilities & WPA_CAPABILITY_PREAUTH); - } + pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL); + if (pmksa && (!pmksa->opportunistic || + !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) + return; + + /* Give less priority to candidates found from normal scan results. */ + pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN, + ie.capabilities & WPA_CAPABILITY_PREAUTH); } diff --git a/src/rsn_supp/preauth.h b/src/rsn_supp/preauth.h index b9ac57b53..36aedb697 100644 --- a/src/rsn_supp/preauth.h +++ b/src/rsn_supp/preauth.h @@ -1,6 +1,6 @@ /* * wpa_supplicant - WPA2/RSN pre-authentication functions - * Copyright (c) 2003-2005, Jouni Malinen + * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,8 +23,9 @@ void pmksa_candidate_free(struct wpa_sm *sm); int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, struct eap_peer_config *eap_conf); void rsn_preauth_deinit(struct wpa_sm *sm); -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results); +int rsn_preauth_scan_results(struct wpa_sm *sm); +void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, + const u8 *ssid, const u8 *rsn); void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, int prio, int preauth); void rsn_preauth_candidate_process(struct wpa_sm *sm); @@ -51,8 +52,14 @@ static inline int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, static inline void rsn_preauth_deinit(struct wpa_sm *sm) { } -static inline void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results) + +static inline int rsn_preauth_scan_results(struct wpa_sm *sm) +{ + return -1; +} + +void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, + const u8 *ssid, const u8 *rsn) { } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 5f551808a..dc28c2f71 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Driver event processing - * Copyright (c) 2003-2008, Jouni Malinen + * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -711,7 +711,6 @@ static void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "Already associated with the selected " "AP"); } - rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); } @@ -735,6 +734,34 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) } +static void wpa_supplicant_rsn_preauth_scan_results( + struct wpa_supplicant *wpa_s) +{ + int i; + + if (rsn_preauth_scan_results(wpa_s->wpa) < 0) + return; + + for (i = wpa_s->scan_res->num - 1; i >= 0; i--) { + const u8 *ssid, *rsn; + struct wpa_scan_res *r; + + r = wpa_s->scan_res->res[i]; + + ssid = wpa_scan_get_ie(r, WLAN_EID_SSID); + if (ssid == NULL) + continue; + + rsn = wpa_scan_get_ie(r, WLAN_EID_RSN); + if (rsn == NULL) + continue; + + rsn_preauth_scan_result(wpa_s->wpa, r->bssid, ssid, rsn); + } + +} + + static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) { struct wpa_scan_res *selected; @@ -778,6 +805,8 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) if (bgscan_notify_scan(wpa_s) == 1) return; + wpa_supplicant_rsn_preauth_scan_results(wpa_s); + selected = wpa_supplicant_pick_network(wpa_s, &ssid); if (selected) { wpa_supplicant_connect(wpa_s, selected, ssid);