Use BSS entries instead of scan results for BSS selection

This allows the BSS selection functions to be called without having the
scan result data structure. This can be used to skip extra scans in
cases where previous results can be considered fresh.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-09-02 19:56:57 +03:00
parent cf8baca6a5
commit 620c783753
3 changed files with 36 additions and 46 deletions

View file

@ -321,7 +321,7 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
#ifndef CONFIG_NO_SCAN_PROCESSING #ifndef CONFIG_NO_SCAN_PROCESSING
static int wpa_supplicant_match_privacy(struct wpa_scan_res *bss, static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
struct wpa_ssid *ssid) struct wpa_ssid *ssid)
{ {
int i, privacy = 0; int i, privacy = 0;
@ -358,7 +358,7 @@ static int wpa_supplicant_match_privacy(struct wpa_scan_res *bss,
static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_ssid *ssid,
struct wpa_scan_res *bss) struct wpa_bss *bss)
{ {
struct wpa_ie_data ie; struct wpa_ie_data ie;
int proto_match = 0; int proto_match = 0;
@ -376,7 +376,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) || ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) ||
(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)); (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
rsn_ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) { while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) {
proto_match++; proto_match++;
@ -431,7 +431,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
return 1; return 1;
} }
wpa_ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) { while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
proto_match++; proto_match++;
@ -533,7 +533,7 @@ static int ht_supported(const struct hostapd_hw_modes *mode)
} }
static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss) static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{ {
const struct hostapd_hw_modes *mode = NULL, *modes; const struct hostapd_hw_modes *mode = NULL, *modes;
const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES }; const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
@ -571,7 +571,7 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss)
return 0; return 0;
for (i = 0; i < (int) sizeof(scan_ie); i++) { for (i = 0; i < (int) sizeof(scan_ie); i++) {
rate_ie = wpa_scan_get_ie(bss, scan_ie[i]); rate_ie = wpa_bss_get_ie(bss, scan_ie[i]);
if (rate_ie == NULL) if (rate_ie == NULL)
continue; continue;
@ -625,31 +625,26 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss)
static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_scan_res *bss, int i, struct wpa_bss *bss,
struct wpa_ssid *group) struct wpa_ssid *group)
{ {
const u8 *ssid_; u8 wpa_ie_len, rsn_ie_len;
u8 wpa_ie_len, rsn_ie_len, ssid_len;
int wpa; int wpa;
struct wpa_blacklist *e; struct wpa_blacklist *e;
const u8 *ie; const u8 *ie;
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
ssid_ = ie ? ie + 2 : (u8 *) "";
ssid_len = ie ? ie[1] : 0;
ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0; wpa_ie_len = ie ? ie[1] : 0;
ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
rsn_ie_len = ie ? ie[1] : 0; rsn_ie_len = ie ? ie[1] : 0;
wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
"wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s", "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s",
i, MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len), i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
wpa_ie_len, rsn_ie_len, bss->caps, bss->level, wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
wpa_scan_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : ""); wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "");
e = wpa_blacklist_get(wpa_s, bss->bssid); e = wpa_blacklist_get(wpa_s, bss->bssid);
if (e) { if (e) {
@ -672,7 +667,7 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
} }
} }
if (ssid_len == 0) { if (bss->ssid_len == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
return NULL; return NULL;
} }
@ -722,8 +717,8 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
check_ssid = 0; check_ssid = 0;
if (check_ssid && if (check_ssid &&
(ssid_len != ssid->ssid_len || (bss->ssid_len != ssid->ssid_len ||
os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) { os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch");
continue; continue;
} }
@ -789,32 +784,24 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
static struct wpa_bss * static struct wpa_bss *
wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res,
struct wpa_ssid *group, struct wpa_ssid *group,
struct wpa_ssid **selected_ssid) struct wpa_ssid **selected_ssid)
{ {
size_t i; unsigned int i;
wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d", wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d",
group->priority); group->priority);
for (i = 0; i < scan_res->num; i++) { for (i = 0; i < wpa_s->last_scan_res_used; i++) {
struct wpa_scan_res *bss = scan_res->res[i]; struct wpa_bss *bss = wpa_s->last_scan_res[i];
const u8 *ie, *ssid;
u8 ssid_len;
*selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group); *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group);
if (!*selected_ssid) if (!*selected_ssid)
continue; continue;
ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
ssid = ie ? ie + 2 : (u8 *) "";
ssid_len = ie ? ie[1] : 0;
wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
" ssid='%s'", " ssid='%s'",
MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len)); MAC2STR(bss->bssid),
return wpa_bss_get(wpa_s, bss->bssid, ssid, ssid_len); wpa_ssid_txt(bss->ssid, bss->ssid_len));
return bss;
} }
return NULL; return NULL;
@ -823,16 +810,19 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
static struct wpa_bss * static struct wpa_bss *
wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res,
struct wpa_ssid **selected_ssid) struct wpa_ssid **selected_ssid)
{ {
struct wpa_bss *selected = NULL; struct wpa_bss *selected = NULL;
int prio; int prio;
if (wpa_s->last_scan_res == NULL ||
wpa_s->last_scan_res_used == 0)
return NULL; /* no scan results from last update */
while (selected == NULL) { while (selected == NULL) {
for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
selected = wpa_supplicant_select_bss( selected = wpa_supplicant_select_bss(
wpa_s, scan_res, wpa_s->conf->pssid[prio], wpa_s, wpa_s->conf->pssid[prio],
selected_ssid); selected_ssid);
if (selected) if (selected)
break; break;
@ -1158,10 +1148,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
wpas_wps_update_ap_info(wpa_s, scan_res); wpas_wps_update_ap_info(wpa_s, scan_res);
selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid);
wpa_scan_results_free(scan_res); wpa_scan_results_free(scan_res);
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
if (selected) { if (selected) {
int skip; int skip;
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid); skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);

View file

@ -1270,14 +1270,14 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s, int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_scan_res *bss) struct wpa_ssid *ssid, struct wpa_bss *bss)
{ {
struct wpabuf *wps_ie; struct wpabuf *wps_ie;
if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
return -1; return -1;
wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
if (eap_is_wps_pbc_enrollee(&ssid->eap)) { if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
if (!wps_ie) { if (!wps_ie) {
wpa_printf(MSG_DEBUG, " skip - non-WPS AP"); wpa_printf(MSG_DEBUG, " skip - non-WPS AP");
@ -1339,19 +1339,19 @@ int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_ssid *ssid,
struct wpa_scan_res *bss) struct wpa_bss *bss)
{ {
struct wpabuf *wps_ie = NULL; struct wpabuf *wps_ie = NULL;
int ret = 0; int ret = 0;
if (eap_is_wps_pbc_enrollee(&ssid->eap)) { if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) { if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) {
/* allow wildcard SSID for WPS PBC */ /* allow wildcard SSID for WPS PBC */
ret = 1; ret = 1;
} }
} else if (eap_is_wps_pin_enrollee(&ssid->eap)) { } else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
if (wps_ie && if (wps_ie &&
(wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1) || (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1) ||
wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) { wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
@ -1373,7 +1373,7 @@ int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
ret = 0; ret = 0;
if (bss->beacon_ie_len) { if (bss->beacon_ie_len) {
struct wpabuf *bcn_wps; struct wpabuf *bcn_wps;
bcn_wps = wpa_scan_get_vendor_ie_multi_beacon( bcn_wps = wpa_bss_get_vendor_ie_multi_beacon(
bss, WPS_IE_VENDOR_TYPE); bss, WPS_IE_VENDOR_TYPE);
if (bcn_wps == NULL) { if (bcn_wps == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE " wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE "

View file

@ -40,9 +40,9 @@ int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
const char *pin, struct wps_new_ap_settings *settings); const char *pin, struct wps_new_ap_settings *settings);
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s, int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_scan_res *bss); struct wpa_ssid *ssid, struct wpa_bss *bss);
int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_scan_res *bss); struct wpa_ssid *ssid, struct wpa_bss *bss);
int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
struct wpa_bss *selected, struct wpa_ssid *ssid); struct wpa_bss *selected, struct wpa_ssid *ssid);
void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s); void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s);