Add BSSID filter for testing purposes
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 16 Feb 2012 14:30:13 +0000 (16:30 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 16 Feb 2012 14:30:13 +0000 (16:30 +0200)
wpa_supplicant can now be configured to filter out scan results based
on a BSSID filter. Space-separated set of allowed BSSIDs can be set
with wpa_cli set bssid_filter command. Filtering mechanism can be
disabled by setting this variable to an empty list. When set, only
the BSSes that have a matching entry in this list will be accepted
from scan results.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

wpa_supplicant/bss.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/scan.c
wpa_supplicant/scan.h
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index cbed2e0..2a5bb85 100644 (file)
@@ -61,6 +61,8 @@ 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;
+       if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
+               return NULL;
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
                if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
                    bss->ssid_len == ssid_len &&
@@ -526,6 +528,8 @@ struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
                                   const u8 *bssid)
 {
        struct wpa_bss *bss;
+       if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
+               return NULL;
        dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
                if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
                        return bss;
index 2c8fd51..1cdb082 100644 (file)
@@ -114,6 +114,41 @@ static int pno_stop(struct wpa_supplicant *wpa_s)
 }
 
 
+static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
+{
+       char *pos;
+       u8 addr[ETH_ALEN], *filter = NULL, *n;
+       size_t count = 0;
+
+       pos = val;
+       while (pos) {
+               if (*pos == '\0')
+                       break;
+               if (hwaddr_aton(pos, addr))
+                       return -1;
+               n = os_realloc(filter, (count + 1) * ETH_ALEN);
+               if (n == NULL) {
+                       os_free(filter);
+                       return -1;
+               }
+               filter = n;
+               os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
+               count++;
+
+               pos = os_strchr(pos, ' ');
+               if (pos)
+                       pos++;
+       }
+
+       wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
+       os_free(wpa_s->bssid_filter);
+       wpa_s->bssid_filter = filter;
+       wpa_s->bssid_filter_count = count;
+
+       return 0;
+}
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                                         char *cmd)
 {
@@ -241,6 +276,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                }
        } else if (os_strcasecmp(cmd, "ps") == 0) {
                ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
+       } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
+               ret = set_bssid_filter(wpa_s, value);
        } else {
                value[-1] = '=';
                ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
index 7fddb74..5fe3865 100644 (file)
@@ -1235,6 +1235,50 @@ static void dump_scan_res(struct wpa_scan_results *scan_res)
 }
 
 
+int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
+                                     const u8 *bssid)
+{
+       size_t i;
+
+       if (wpa_s->bssid_filter == NULL)
+               return 1;
+
+       for (i = 0; i < wpa_s->bssid_filter_count; i++) {
+               if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
+                             ETH_ALEN) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+
+
+static void filter_scan_res(struct wpa_supplicant *wpa_s,
+                           struct wpa_scan_results *res)
+{
+       size_t i, j;
+
+       if (wpa_s->bssid_filter == NULL)
+               return;
+
+       for (i = 0, j = 0; i < res->num; i++) {
+               if (wpa_supplicant_filter_bssid_match(wpa_s,
+                                                     res->res[i]->bssid)) {
+                       res->res[j++] = res->res[i];
+               } else {
+                       os_free(res->res[i]);
+                       res->res[i] = NULL;
+               }
+       }
+
+       if (res->num != j) {
+               wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
+                          (int) (res->num - j));
+               res->num = j;
+       }
+}
+
+
 /**
  * wpa_supplicant_get_scan_results - Get scan results
  * @wpa_s: Pointer to wpa_supplicant data
@@ -1259,6 +1303,7 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
                wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
                return NULL;
        }
+       filter_scan_res(wpa_s, scan_res);
 
 #ifdef CONFIG_WPS
        if (wpas_wps_in_progress(wpa_s)) {
index b794105..8c83a42 100644 (file)
@@ -32,5 +32,7 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
                                             u32 vendor_type);
 struct wpabuf * wpa_scan_get_vendor_ie_multi_beacon(
        const struct wpa_scan_res *res, u32 vendor_type);
+int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
+                                     const u8 *bssid);
 
 #endif /* SCAN_H */
index eff0459..b58e2fd 100644 (file)
@@ -445,6 +445,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        wpa_s->gas = NULL;
 
        free_hw_features(wpa_s);
+
+       os_free(wpa_s->bssid_filter);
+       wpa_s->bssid_filter = NULL;
 }
 
 
index 8c9f4a8..671bca2 100644 (file)
@@ -280,6 +280,9 @@ struct wpa_supplicant {
        void *drv_priv; /* private data used by driver_ops */
        void *global_drv_priv;
 
+       u8 *bssid_filter;
+       size_t bssid_filter_count;
+
        /* previous scan was wildcard when interleaving between
         * wildcard scans and specific SSID scan when max_ssids=1 */
        int prev_scan_wildcard;