diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index e07035737..8925705a3 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -368,6 +368,50 @@ static char * wpa_config_write_bssid(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +static int wpa_config_parse_bssid_blacklist(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->bssid_blacklist, + &ssid->num_bssid_blacklist, + "bssid_blacklist", 1); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_blacklist(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->bssid_blacklist, + ssid->num_bssid_blacklist, + "bssid_blacklist"); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_bssid_whitelist(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->bssid_whitelist, + &ssid->num_bssid_whitelist, + "bssid_whitelist", 1); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_whitelist(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->bssid_whitelist, + ssid->num_bssid_whitelist, + "bssid_whitelist"); +} +#endif /* NO_CONFIG_WRITE */ + + static int wpa_config_parse_psk(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) @@ -1744,6 +1788,8 @@ static const struct parse_data ssid_fields[] = { { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, { INT_RANGE(scan_ssid, 0, 1) }, { FUNC(bssid) }, + { FUNC(bssid_blacklist) }, + { FUNC(bssid_whitelist) }, { FUNC_KEY(psk) }, { FUNC(proto) }, { FUNC(key_mgmt) }, diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 18ce67fc9..f744895a3 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -131,6 +131,18 @@ struct wpa_ssid { */ u8 bssid[ETH_ALEN]; + /** + * bssid_blacklist - List of inacceptable BSSIDs + */ + u8 *bssid_blacklist; + size_t num_bssid_blacklist; + + /** + * bssid_blacklist - List of acceptable BSSIDs + */ + u8 *bssid_whitelist; + size_t num_bssid_whitelist; + /** * bssid_set - Whether BSSID is configured for this network */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 7f90393fa..4dd9bc611 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -698,6 +698,20 @@ static int bss_is_ess(struct wpa_bss *bss) } +static int addr_in_list(const u8 *addr, const u8 *list, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) { + const u8 *a = list + (i * ETH_ALEN); + + if (os_memcmp(a, addr, ETH_ALEN) == 0) + return 1; + } + return 0; +} + + static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_bss *bss, struct wpa_ssid *group, @@ -822,6 +836,24 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, continue; } + /* check blacklist */ + if (ssid->num_bssid_blacklist && + addr_in_list(bss->bssid, ssid->bssid_blacklist, + ssid->num_bssid_blacklist)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID blacklisted"); + continue; + } + + /* if there is a whitelist, only accept those APs */ + if (ssid->num_bssid_whitelist && + !addr_in_list(bss->bssid, ssid->bssid_whitelist, + ssid->num_bssid_whitelist)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID not in whitelist"); + continue; + } + if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) continue; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index e78c0dd99..4b2c3cc0e 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1431,6 +1431,21 @@ network={ key_mgmt=NONE } +# Example configuration blacklisting two APs - these will be ignored +# for this network. +network={ + ssid="example" + psk="very secret passphrase" + bssid_blacklist=02:11:22:33:44:55 02:22:aa:44:55:66 +} + +# Example configuration limiting AP selection to a specific set of APs; +# any other AP will be ignored for this network entry. +network={ + ssid="example" + psk="very secret passphrase" + bssid_whitelist=02:55:ae:bc:de:f0 02:88:77:66:55:44 +} # Example config file that will only scan on channel 36. freq_list=5180