Remove src/drivers/scan_helpers.c
[mech_eap.git] / wpa_supplicant / bss.c
index 96ab955..a125ca1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * BSS table
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  *
  * 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
@@ -20,6 +20,7 @@
 #include "drivers/driver.h"
 #include "wpa_supplicant_i.h"
 #include "notify.h"
+#include "scan.h"
 #include "bss.h"
 
 
@@ -65,9 +66,8 @@ static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 }
 
 
-static struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s,
-                                   const u8 *bssid, const u8 *ssid,
-                                   size_t ssid_len)
+struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
+                            const u8 *ssid, size_t ssid_len)
 {
        struct wpa_bss *bss;
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
@@ -149,17 +149,28 @@ static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                bss->ie_len = res->ie_len;
        } else {
                struct wpa_bss *nbss;
+               struct dl_list *prev = bss->list_id.prev;
+               dl_list_del(&bss->list_id);
                nbss = os_realloc(bss, sizeof(*bss) + res->ie_len);
                if (nbss) {
                        bss = nbss;
                        os_memcpy(bss + 1, res + 1, res->ie_len);
                        bss->ie_len = res->ie_len;
                }
+               dl_list_add(prev, &bss->list_id);
        }
        dl_list_add_tail(&wpa_s->bss, &bss->list);
 }
 
 
+static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+{
+       return bss == wpa_s->current_bss ||
+               os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
+               os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0;
+}
+
+
 void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
 {
        wpa_s->bss_update_idx++;
@@ -196,16 +207,60 @@ void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
 }
 
 
-void wpa_bss_update_end(struct wpa_supplicant *wpa_s)
+static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
+                                   const struct scan_info *info)
+{
+       int found;
+       size_t i;
+
+       if (info == NULL)
+               return 1;
+
+       if (info->num_freqs) {
+               found = 0;
+               for (i = 0; i < info->num_freqs; i++) {
+                       if (bss->freq == info->freqs[i]) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found)
+                       return 0;
+       }
+
+       if (info->num_ssids) {
+               found = 0;
+               for (i = 0; i < info->num_ssids; i++) {
+                       const struct wpa_driver_scan_ssid *s = &info->ssids[i];
+                       if ((s->ssid == NULL || s->ssid_len == 0) ||
+                           (s->ssid_len == bss->ssid_len &&
+                            os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
+                            0)) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found)
+                       return 0;
+       }
+
+       return 1;
+}
+
+
+void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
+                       int new_scan)
 {
        struct wpa_bss *bss, *n;
 
-       /* TODO: expire only entries that were on the scanned frequencies/SSIDs
-        * list; need to get info from driver about scanned frequencies and
-        * SSIDs to be able to figure out which entries should be expired based
-        * on this */
+       if (!new_scan)
+               return; /* do not expire entries without new scan */
 
        dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
+               if (wpa_bss_in_use(wpa_s, bss))
+                       continue;
+               if (!wpa_bss_included_in_scan(bss, info))
+                       continue; /* expire only BSSes that were scanned */
                if (bss->last_update_idx < wpa_s->bss_update_idx)
                        bss->scan_miss_count++;
                if (bss->scan_miss_count >= WPA_BSS_EXPIRATION_SCAN_COUNT) {
@@ -230,9 +285,8 @@ static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx)
        t.sec -= WPA_BSS_EXPIRATION_AGE;
 
        dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
-               if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
-                   os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0)
-                       continue; /* do not expire BSSes that are in use */
+               if (wpa_bss_in_use(wpa_s, bss))
+                       continue;
 
                if (os_time_before(&bss->last_update, &t)) {
                        wpa_printf(MSG_DEBUG, "BSS: Expire BSS %u due to age",
@@ -260,6 +314,8 @@ void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
 {
        struct wpa_bss *bss, *n;
        eloop_cancel_timeout(wpa_bss_timeout, wpa_s, NULL);
+       if (wpa_s->bss.next == NULL)
+               return; /* BSS table not yet initialized */
        dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list)
                wpa_bss_remove(wpa_s, bss);
 }
@@ -356,3 +412,25 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
 
        return buf;
 }
+
+
+int wpa_bss_get_max_rate(const struct wpa_bss *bss)
+{
+       int rate = 0;
+       const u8 *ie;
+       int i;
+
+       ie = wpa_bss_get_ie(bss, 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_bss_get_ie(bss, 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;
+}