diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 2b06d5a47..28a48ed1a 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2272,13 +2272,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data); const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie); -const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, - u32 vendor_type); -struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, - u32 vendor_type); -int wpa_scan_get_max_rate(const struct wpa_scan_res *res); void wpa_scan_results_free(struct wpa_scan_results *res); -void wpa_scan_sort_results(struct wpa_scan_results *res); /* diff --git a/src/drivers/scan_helpers.c b/src/drivers/scan_helpers.c index a8c1c025d..a4ec634e6 100644 --- a/src/drivers/scan_helpers.c +++ b/src/drivers/scan_helpers.c @@ -38,80 +38,6 @@ const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) } -const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, - u32 vendor_type) -{ - const u8 *end, *pos; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; - } - - return NULL; -} - - -struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, - u32 vendor_type) -{ - struct wpabuf *buf; - const u8 *end, *pos; - - buf = wpabuf_alloc(res->ie_len); - if (buf == NULL) - return NULL; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; - } - - if (wpabuf_len(buf) == 0) { - wpabuf_free(buf); - buf = NULL; - } - - return buf; -} - - -int wpa_scan_get_max_rate(const struct wpa_scan_res *res) -{ - int rate = 0; - const u8 *ie; - int i; - - ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); - for (i = 0; ie && i < ie[1]; i++) { - if ((ie[i + 2] & 0x7f) > rate) - rate = ie[i + 2] & 0x7f; - } - - ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); - for (i = 0; ie && i < ie[1]; i++) { - if ((ie[i + 2] & 0x7f) > rate) - rate = ie[i + 2] & 0x7f; - } - - return rate; -} - - void wpa_scan_results_free(struct wpa_scan_results *res) { size_t i; @@ -124,59 +50,3 @@ void wpa_scan_results_free(struct wpa_scan_results *res) os_free(res->res); os_free(res); } - - -/* Compare function for sorting scan results. Return >0 if @b is considered - * better. */ -static int wpa_scan_result_compar(const void *a, const void *b) -{ - struct wpa_scan_res **_wa = (void *) a; - struct wpa_scan_res **_wb = (void *) b; - struct wpa_scan_res *wa = *_wa; - struct wpa_scan_res *wb = *_wb; - int wpa_a, wpa_b, maxrate_a, maxrate_b; - - /* WPA/WPA2 support preferred */ - wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || - wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; - wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || - wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; - - if (wpa_b && !wpa_a) - return 1; - if (!wpa_b && wpa_a) - return -1; - - /* privacy support preferred */ - if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && - (wb->caps & IEEE80211_CAP_PRIVACY)) - return 1; - if ((wa->caps & IEEE80211_CAP_PRIVACY) && - (wb->caps & IEEE80211_CAP_PRIVACY) == 0) - return -1; - - /* best/max rate preferred if signal level close enough XXX */ - if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) || - (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { - maxrate_a = wpa_scan_get_max_rate(wa); - maxrate_b = wpa_scan_get_max_rate(wb); - if (maxrate_a != maxrate_b) - return maxrate_b - maxrate_a; - } - - /* use freq for channel preference */ - - /* all things being equal, use signal level; if signal levels are - * identical, use quality values since some drivers may only report - * that value and leave the signal level zero */ - if (wb->level == wa->level) - return wb->qual - wa->qual; - return wb->level - wa->level; -} - - -void wpa_scan_sort_results(struct wpa_scan_results *res) -{ - qsort(res->res, res->num, sizeof(struct wpa_scan_res *), - wpa_scan_result_compar); -} diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c index dacddff4f..bf780d5e1 100644 --- a/wpa_supplicant/bgscan_simple.c +++ b/wpa_supplicant/bgscan_simple.c @@ -19,6 +19,7 @@ #include "drivers/driver.h" #include "config_ssid.h" #include "wpa_supplicant_i.h" +#include "scan.h" #include "bgscan.h" struct bgscan_simple_data { diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 9706ca741..7242e5ca4 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -33,6 +33,7 @@ #include "ap.h" #include "notify.h" #include "bss.h" +#include "scan.h" #include "ctrl_iface.h" extern struct wpa_driver_ops *wpa_drivers[]; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index cbb52f641..5f521d48b 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -26,6 +26,7 @@ #include "../notify.h" #include "../wpas_glue.h" #include "../bss.h" +#include "../scan.h" #include "dbus_new_helpers.h" #include "dbus_new.h" #include "dbus_new_handlers.h" diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c index 8e1f7b0a2..6527e66ce 100644 --- a/wpa_supplicant/dbus/dbus_old_handlers.c +++ b/wpa_supplicant/dbus/dbus_old_handlers.c @@ -26,6 +26,7 @@ #include "../notify.h" #include "../wpas_glue.h" #include "../bss.h" +#include "../scan.h" #include "dbus_old.h" #include "dbus_old_handlers.h" #include "dbus_dict_helpers.h" diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 9fcfcbabd..a4670a050 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -39,6 +39,7 @@ #include "ap.h" #include "bss.h" #include "mlme.h" +#include "scan.h" static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 71290906f..819061f83 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Scanning - * Copyright (c) 2003-2008, Jouni Malinen + * Copyright (c) 2003-2010, 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 @@ -12,16 +12,19 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "common.h" -#include "eloop.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" #include "config.h" #include "wpa_supplicant_i.h" #include "driver_i.h" #include "mlme.h" #include "wps_supplicant.h" #include "notify.h" +#include "bss.h" +#include "scan.h" static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) @@ -434,3 +437,176 @@ void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, } } + +static int wpa_scan_get_max_rate(const struct wpa_scan_res *res) +{ + int rate = 0; + const u8 *ie; + int i; + + ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); + for (i = 0; ie && i < ie[1]; i++) { + if ((ie[i + 2] & 0x7f) > rate) + rate = ie[i + 2] & 0x7f; + } + + ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); + for (i = 0; ie && i < ie[1]; i++) { + if ((ie[i + 2] & 0x7f) > rate) + rate = ie[i + 2] & 0x7f; + } + + return rate; +} + + +const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, + u32 vendor_type) +{ + const u8 *end, *pos; + + pos = (const u8 *) (res + 1); + end = pos + res->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, + u32 vendor_type) +{ + struct wpabuf *buf; + const u8 *end, *pos; + + buf = wpabuf_alloc(res->ie_len); + if (buf == NULL) + return NULL; + + pos = (const u8 *) (res + 1); + end = pos + res->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); + pos += 2 + pos[1]; + } + + if (wpabuf_len(buf) == 0) { + wpabuf_free(buf); + buf = NULL; + } + + return buf; +} + + +/* Compare function for sorting scan results. Return >0 if @b is considered + * better. */ +static int wpa_scan_result_compar(const void *a, const void *b) +{ + struct wpa_scan_res **_wa = (void *) a; + struct wpa_scan_res **_wb = (void *) b; + struct wpa_scan_res *wa = *_wa; + struct wpa_scan_res *wb = *_wb; + int wpa_a, wpa_b, maxrate_a, maxrate_b; + + /* WPA/WPA2 support preferred */ + wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || + wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; + wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || + wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; + + if (wpa_b && !wpa_a) + return 1; + if (!wpa_b && wpa_a) + return -1; + + /* privacy support preferred */ + if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && + (wb->caps & IEEE80211_CAP_PRIVACY)) + return 1; + if ((wa->caps & IEEE80211_CAP_PRIVACY) && + (wb->caps & IEEE80211_CAP_PRIVACY) == 0) + return -1; + + /* best/max rate preferred if signal level close enough XXX */ + if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) || + (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { + maxrate_a = wpa_scan_get_max_rate(wa); + maxrate_b = wpa_scan_get_max_rate(wb); + if (maxrate_a != maxrate_b) + return maxrate_b - maxrate_a; + } + + /* use freq for channel preference */ + + /* all things being equal, use signal level; if signal levels are + * identical, use quality values since some drivers may only report + * that value and leave the signal level zero */ + if (wb->level == wa->level) + return wb->qual - wa->qual; + return wb->level - wa->level; +} + + +/** + * wpa_supplicant_get_scan_results - Get scan results + * @wpa_s: Pointer to wpa_supplicant data + * @info: Information about what was scanned or %NULL if not available + * @new_scan: Whether a new scan was performed + * Returns: Scan results, %NULL on failure + * + * This function request the current scan results from the driver and updates + * the local BSS list wpa_s->bss. The caller is responsible for freeing the + * results with wpa_scan_results_free(). + */ +struct wpa_scan_results * +wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, + struct scan_info *info, int new_scan) +{ + struct wpa_scan_results *scan_res; + size_t i; + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) + scan_res = ieee80211_sta_get_scan_results(wpa_s); + else + scan_res = wpa_drv_get_scan_results2(wpa_s); + if (scan_res == NULL) { + wpa_printf(MSG_DEBUG, "Failed to get scan results"); + return NULL; + } + + qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), + wpa_scan_result_compar); + + wpa_bss_update_start(wpa_s); + for (i = 0; i < scan_res->num; i++) + wpa_bss_update_scan_res(wpa_s, scan_res->res[i]); + wpa_bss_update_end(wpa_s, info, new_scan); + + return scan_res; +} + + +int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) +{ + struct wpa_scan_results *scan_res; + scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); + if (scan_res == NULL) + return -1; + wpa_scan_results_free(scan_res); + + return 0; +} diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h new file mode 100644 index 000000000..b3557f967 --- /dev/null +++ b/wpa_supplicant/scan.h @@ -0,0 +1,35 @@ +/* + * WPA Supplicant - Scanning + * Copyright (c) 2003-2010, 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef SCAN_H +#define SCAN_H + +int wpa_supplicant_enabled_networks(struct wpa_config *conf); +void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); +void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s); +void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, + int scanning); +struct wpa_driver_scan_params; +int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params); +struct wpa_scan_results * +wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, + struct scan_info *info, int new_scan); +int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s); +const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, + u32 vendor_type); +struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, + u32 vendor_type); + +#endif /* SCAN_H */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 30c94e489..de76672da 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -28,6 +28,7 @@ #include "notify.h" #include "blacklist.h" #include "bss.h" +#include "scan.h" #include "sme.h" void sme_authenticate(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 7e56bb70f..ec60ebc89 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -45,6 +45,7 @@ #include "notify.h" #include "bgscan.h" #include "bss.h" +#include "scan.h" const char *wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" @@ -1566,56 +1567,6 @@ int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level, } -/** - * wpa_supplicant_get_scan_results - Get scan results - * @wpa_s: Pointer to wpa_supplicant data - * @info: Information about what was scanned or %NULL if not available - * @new_scan: Whether a new scan was performed - * Returns: Scan results, %NULL on failure - * - * This function request the current scan results from the driver and updates - * the local BSS list wpa_s->bss. The caller is responsible for freeing the - * results with wpa_scan_results_free(). - */ -struct wpa_scan_results * -wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, - struct scan_info *info, int new_scan) -{ - struct wpa_scan_results *scan_res; - size_t i; - - if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) - scan_res = ieee80211_sta_get_scan_results(wpa_s); - else - scan_res = wpa_drv_get_scan_results2(wpa_s); - if (scan_res == NULL) { - wpa_printf(MSG_DEBUG, "Failed to get scan results"); - return NULL; - } - - wpa_scan_sort_results(scan_res); - - wpa_bss_update_start(wpa_s); - for (i = 0; i < scan_res->num; i++) - wpa_bss_update_scan_res(wpa_s, scan_res->res[i]); - wpa_bss_update_end(wpa_s, info, new_scan); - - return scan_res; -} - - -int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) -{ - struct wpa_scan_results *scan_res; - scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); - if (scan_res == NULL) - return -1; - wpa_scan_results_free(scan_res); - - return 0; -} - - /** * wpa_supplicant_get_ssid - Get a pointer to the current network structure * @wpa_s: Pointer to wpa_supplicant data diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 677925f66..936684c43 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -444,10 +444,6 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s); -struct wpa_scan_results * -wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, - struct scan_info *info, int new_scan); -int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s); void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr); void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, int sec, int usec); @@ -490,16 +486,6 @@ void wpa_supplicant_terminate_proc(struct wpa_global *global); void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, const u8 *buf, size_t len); -/* scan.c */ -int wpa_supplicant_enabled_networks(struct wpa_config *conf); -void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); -void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s); -void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, - int scanning); -struct wpa_driver_scan_params; -int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, - struct wpa_driver_scan_params *params); - /* events.c */ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s); diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index dad73b777..3fa85a11b 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -31,6 +31,7 @@ #include "wpas_glue.h" #include "wps_supplicant.h" #include "bss.h" +#include "scan.h" #ifndef CONFIG_NO_CONFIG_BLOBS diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index bdc0bd170..fa0123aeb 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -31,6 +31,7 @@ #include "notify.h" #include "blacklist.h" #include "bss.h" +#include "scan.h" #include "wps_supplicant.h"