2 * WPA Supplicant - Helper functions for scan result processing
3 * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "drivers/driver.h"
19 #include "ieee802_11_defs.h"
22 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
26 pos = (const u8 *) (res + 1);
27 end = pos + res->ie_len;
29 while (pos + 1 < end) {
30 if (pos + 2 + pos[1] > end)
41 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
46 pos = (const u8 *) (res + 1);
47 end = pos + res->ie_len;
49 while (pos + 1 < end) {
50 if (pos + 2 + pos[1] > end)
52 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
53 vendor_type == WPA_GET_BE32(&pos[2]))
62 int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
68 ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
69 for (i = 0; ie && i < ie[1]; i++) {
70 if ((ie[i + 2] & 0x7f) > rate)
71 rate = ie[i + 2] & 0x7f;
74 ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
75 for (i = 0; ie && i < ie[1]; i++) {
76 if ((ie[i + 2] & 0x7f) > rate)
77 rate = ie[i + 2] & 0x7f;
84 void wpa_scan_results_free(struct wpa_scan_results *res)
91 for (i = 0; i < res->num; i++)
98 /* Compare function for sorting scan results. Return >0 if @b is considered
100 static int wpa_scan_result_compar(const void *a, const void *b)
102 struct wpa_scan_res **_wa = (void *) a;
103 struct wpa_scan_res **_wb = (void *) b;
104 struct wpa_scan_res *wa = *_wa;
105 struct wpa_scan_res *wb = *_wb;
106 int wpa_a, wpa_b, maxrate_a, maxrate_b;
108 /* WPA/WPA2 support preferred */
109 wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
110 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
111 wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
112 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
119 /* privacy support preferred */
120 if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
121 (wb->caps & IEEE80211_CAP_PRIVACY))
123 if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
124 (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
127 /* best/max rate preferred if signal level close enough XXX */
128 maxrate_a = wpa_scan_get_max_rate(wa);
129 maxrate_b = wpa_scan_get_max_rate(wb);
130 if (maxrate_a != maxrate_b && abs(wb->level - wa->level) < 5)
131 return maxrate_b - maxrate_a;
133 /* use freq for channel preference */
135 /* all things being equal, use signal level; if signal levels are
136 * identical, use quality values since some drivers may only report
137 * that value and leave the signal level zero */
138 if (wb->level == wa->level)
139 return wb->qual - wa->qual;
140 return wb->level - wa->level;
144 void wpa_scan_sort_results(struct wpa_scan_results *res)
146 qsort(res->res, res->num, sizeof(struct wpa_scan_res *),
147 wpa_scan_result_compar);