|
@@ -0,0 +1,649 @@
|
|
|
+Add network specific BSSID black and white lists
|
|
|
+
|
|
|
+This change adds the configuration options "bssid_whitelist" and
|
|
|
+"bssid_blacklist" used to limit the AP selection of a network to a
|
|
|
+specified (finite) set or discard certain APs.
|
|
|
+
|
|
|
+This can be useful for environments where multiple networks operate
|
|
|
+using the same SSID and roaming between those is not desired. It is also
|
|
|
+useful to ignore a faulty or otherwise unwanted AP.
|
|
|
+
|
|
|
+In many applications it is useful not just to enumerate a group of well
|
|
|
+known access points, but to use a address/mask notation to match an
|
|
|
+entire set of addresses (ca:ff:ee:00:00:00/ff:ff:ff:00:00:00).
|
|
|
+
|
|
|
+This change expands the data structures used by MAC lists to include a
|
|
|
+mask indicating the significant (non-masked) portions of an address and
|
|
|
+extends the list parser to recognize mask suffixes.
|
|
|
+
|
|
|
+Signed-off-by: Stefan Tomanek <[email protected]>
|
|
|
+---
|
|
|
+ src/utils/common.c | 86 ++++++++++++--
|
|
|
+ src/utils/common.h | 3 +
|
|
|
+ wpa_supplicant/config.c | 223 ++++++++++++++++++++++++-------------
|
|
|
+ wpa_supplicant/config_ssid.h | 12 ++
|
|
|
+ wpa_supplicant/events.c | 45 ++++++++
|
|
|
+ wpa_supplicant/p2p_supplicant.c | 40 ++++---
|
|
|
+ wpa_supplicant/wpa_supplicant.conf | 15 +++
|
|
|
+ 7 files changed, 323 insertions(+), 101 deletions(-)
|
|
|
+
|
|
|
+diff --git a/src/utils/common.c b/src/utils/common.c
|
|
|
+index 9902004..dd6e4aa 100644
|
|
|
+--- a/src/utils/common.c
|
|
|
++++ b/src/utils/common.c
|
|
|
+@@ -36,6 +36,25 @@ int hex2byte(const char *hex)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++static const char * hwaddr_parse(const char *txt, u8 *addr)
|
|
|
++{
|
|
|
++ size_t i;
|
|
|
++
|
|
|
++ for (i = 0; i < ETH_ALEN; i++) {
|
|
|
++ int a;
|
|
|
++
|
|
|
++ a = hex2byte(txt);
|
|
|
++ if (a < 0)
|
|
|
++ return NULL;
|
|
|
++ txt += 2;
|
|
|
++ addr[i] = a;
|
|
|
++ if (i < ETH_ALEN - 1 && *txt++ != ':')
|
|
|
++ return NULL;
|
|
|
++ }
|
|
|
++ return txt;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+ /**
|
|
|
+ * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
|
|
|
+ * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
|
|
|
+@@ -44,25 +63,46 @@ int hex2byte(const char *hex)
|
|
|
+ */
|
|
|
+ int hwaddr_aton(const char *txt, u8 *addr)
|
|
|
+ {
|
|
|
+- int i;
|
|
|
++ return hwaddr_parse(txt, addr) ? 0 : -1;
|
|
|
++}
|
|
|
+
|
|
|
+- for (i = 0; i < 6; i++) {
|
|
|
+- int a, b;
|
|
|
+
|
|
|
+- a = hex2num(*txt++);
|
|
|
+- if (a < 0)
|
|
|
+- return -1;
|
|
|
+- b = hex2num(*txt++);
|
|
|
+- if (b < 0)
|
|
|
+- return -1;
|
|
|
+- *addr++ = (a << 4) | b;
|
|
|
+- if (i < 5 && *txt++ != ':')
|
|
|
++/**
|
|
|
++ * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format)
|
|
|
++ * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00")
|
|
|
++ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
|
|
|
++ * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes)
|
|
|
++ * @maskable: Flag to indicate whether a mask is allowed
|
|
|
++ * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
|
|
|
++ */
|
|
|
++int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable)
|
|
|
++{
|
|
|
++ const char *r;
|
|
|
++
|
|
|
++ /* parse address part */
|
|
|
++ r = hwaddr_parse(txt, addr);
|
|
|
++ if (!r)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ /* check for optional mask */
|
|
|
++ if (*r == '\0' || isspace(*r)) {
|
|
|
++ /* no mask specified, assume default */
|
|
|
++ os_memset(mask, 0xff, ETH_ALEN);
|
|
|
++ } else if (maskable && *r == '/') {
|
|
|
++ /* mask specified and allowed */
|
|
|
++ r = hwaddr_parse(r + 1, mask);
|
|
|
++ /* parser error? */
|
|
|
++ if (!r)
|
|
|
+ return -1;
|
|
|
++ } else {
|
|
|
++ /* mask specified but not allowed or trailing garbage */
|
|
|
++ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
++
|
|
|
+ /**
|
|
|
+ * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format)
|
|
|
+ * @txt: MAC address as a string (e.g., "001122334455")
|
|
|
+@@ -144,6 +184,30 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask)
|
|
|
++{
|
|
|
++ size_t i;
|
|
|
++ int print_mask = 0;
|
|
|
++ int res;
|
|
|
++
|
|
|
++ for (i = 0; i < ETH_ALEN; i++) {
|
|
|
++ if (mask[i] != 0xff) {
|
|
|
++ print_mask = 1;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ if (print_mask)
|
|
|
++ res = os_snprintf(buf, len, MACSTR "/" MACSTR,
|
|
|
++ MAC2STR(addr), MAC2STR(mask));
|
|
|
++ else
|
|
|
++ res = os_snprintf(buf, len, MACSTR, MAC2STR(addr));
|
|
|
++ if (os_snprintf_error(len, res))
|
|
|
++ return -1;
|
|
|
++ return res;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+ /**
|
|
|
+ * inc_byte_array - Increment arbitrary length byte array by one
|
|
|
+ * @counter: Pointer to byte array
|
|
|
+diff --git a/src/utils/common.h b/src/utils/common.h
|
|
|
+index 14d9ad1..1127074 100644
|
|
|
+--- a/src/utils/common.h
|
|
|
++++ b/src/utils/common.h
|
|
|
+@@ -468,6 +468,7 @@ typedef u64 __bitwise le64;
|
|
|
+ #endif /* __must_check */
|
|
|
+
|
|
|
+ int hwaddr_aton(const char *txt, u8 *addr);
|
|
|
++int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable);
|
|
|
+ int hwaddr_compact_aton(const char *txt, u8 *addr);
|
|
|
+ int hwaddr_aton2(const char *txt, u8 *addr);
|
|
|
+ int hex2byte(const char *hex);
|
|
|
+@@ -478,6 +479,8 @@ int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
|
|
|
+ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
|
|
|
+ size_t len);
|
|
|
+
|
|
|
++int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
|
|
|
++
|
|
|
+ #ifdef CONFIG_NATIVE_WINDOWS
|
|
|
+ void wpa_unicode2ascii_inplace(TCHAR *str);
|
|
|
+ TCHAR * wpa_strdup_tchar(const char *str);
|
|
|
+diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
|
|
|
+index 8d1e1e0..7f742cb 100644
|
|
|
+--- a/wpa_supplicant/config.c
|
|
|
++++ b/wpa_supplicant/config.c
|
|
|
+@@ -235,6 +235,99 @@ static char * wpa_config_write_int(const struct parse_data *data,
|
|
|
+ #endif /* NO_CONFIG_WRITE */
|
|
|
+
|
|
|
+
|
|
|
++static int wpa_config_parse_addr_list(const struct parse_data *data,
|
|
|
++ int line, const char *value,
|
|
|
++ u8 **list, size_t *num, char *name,
|
|
|
++ u8 abort_on_error, u8 masked)
|
|
|
++{
|
|
|
++ const char *pos;
|
|
|
++ u8 *buf, *n, addr[2 * ETH_ALEN];
|
|
|
++ size_t count;
|
|
|
++
|
|
|
++ buf = NULL;
|
|
|
++ count = 0;
|
|
|
++
|
|
|
++ pos = value;
|
|
|
++ while (pos && *pos) {
|
|
|
++ while (*pos == ' ')
|
|
|
++ pos++;
|
|
|
++
|
|
|
++ if (hwaddr_masked_aton(pos, addr, &addr[ETH_ALEN], masked)) {
|
|
|
++ if (abort_on_error || count == 0) {
|
|
|
++ wpa_printf(MSG_ERROR,
|
|
|
++ "Line %d: Invalid %s address '%s'",
|
|
|
++ line, name, value);
|
|
|
++ os_free(buf);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ /* continue anyway since this could have been from a
|
|
|
++ * truncated configuration file line */
|
|
|
++ wpa_printf(MSG_INFO,
|
|
|
++ "Line %d: Ignore likely truncated %s address '%s'",
|
|
|
++ line, name, pos);
|
|
|
++ } else {
|
|
|
++ n = os_realloc_array(buf, count + 1, 2 * ETH_ALEN);
|
|
|
++ if (n == NULL) {
|
|
|
++ os_free(buf);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ buf = n;
|
|
|
++ os_memmove(buf + 2 * ETH_ALEN, buf,
|
|
|
++ count * 2 * ETH_ALEN);
|
|
|
++ os_memcpy(buf, addr, 2 * ETH_ALEN);
|
|
|
++ count++;
|
|
|
++ wpa_printf(MSG_MSGDUMP,
|
|
|
++ "%s: addr=" MACSTR " mask=" MACSTR,
|
|
|
++ name, MAC2STR(addr),
|
|
|
++ MAC2STR(&addr[ETH_ALEN]));
|
|
|
++ }
|
|
|
++
|
|
|
++ pos = os_strchr(pos, ' ');
|
|
|
++ }
|
|
|
++
|
|
|
++ os_free(*list);
|
|
|
++ *list = buf;
|
|
|
++ *num = count;
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++#ifndef NO_CONFIG_WRITE
|
|
|
++static char * wpa_config_write_addr_list(const struct parse_data *data,
|
|
|
++ const u8 *list, size_t num, char *name)
|
|
|
++{
|
|
|
++ char *value, *end, *pos;
|
|
|
++ int res;
|
|
|
++ size_t i;
|
|
|
++
|
|
|
++ if (list == NULL || num == 0)
|
|
|
++ return NULL;
|
|
|
++
|
|
|
++ value = os_malloc(2 * 20 * num);
|
|
|
++ if (value == NULL)
|
|
|
++ return NULL;
|
|
|
++ pos = value;
|
|
|
++ end = value + 2 * 20 * num;
|
|
|
++
|
|
|
++ for (i = num; i > 0; i--) {
|
|
|
++ const u8 *a = list + (i - 1) * 2 * ETH_ALEN;
|
|
|
++ const u8 *m = a + ETH_ALEN;
|
|
|
++
|
|
|
++ if (i < num)
|
|
|
++ *pos++ = ' ';
|
|
|
++ res = hwaddr_mask_txt(pos, end - pos, a, m);
|
|
|
++ if (res < 0) {
|
|
|
++ os_free(value);
|
|
|
++ return NULL;
|
|
|
++ }
|
|
|
++ pos += res;
|
|
|
++ }
|
|
|
++
|
|
|
++ return value;
|
|
|
++}
|
|
|
++#endif /* NO_CONFIG_WRITE */
|
|
|
++
|
|
|
+ static int wpa_config_parse_bssid(const struct parse_data *data,
|
|
|
+ struct wpa_ssid *ssid, int line,
|
|
|
+ const char *value)
|
|
|
+@@ -280,6 +373,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, 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, 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)
|
|
|
+@@ -1435,53 +1572,10 @@ static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
|
|
|
+ struct wpa_ssid *ssid, int line,
|
|
|
+ const char *value)
|
|
|
+ {
|
|
|
+- const char *pos;
|
|
|
+- u8 *buf, *n, addr[ETH_ALEN];
|
|
|
+- size_t count;
|
|
|
+-
|
|
|
+- buf = NULL;
|
|
|
+- count = 0;
|
|
|
+-
|
|
|
+- pos = value;
|
|
|
+- while (pos && *pos) {
|
|
|
+- while (*pos == ' ')
|
|
|
+- pos++;
|
|
|
+-
|
|
|
+- if (hwaddr_aton(pos, addr)) {
|
|
|
+- if (count == 0) {
|
|
|
+- wpa_printf(MSG_ERROR, "Line %d: Invalid "
|
|
|
+- "p2p_client_list address '%s'.",
|
|
|
+- line, value);
|
|
|
+- os_free(buf);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+- /* continue anyway since this could have been from a
|
|
|
+- * truncated configuration file line */
|
|
|
+- wpa_printf(MSG_INFO, "Line %d: Ignore likely "
|
|
|
+- "truncated p2p_client_list address '%s'",
|
|
|
+- line, pos);
|
|
|
+- } else {
|
|
|
+- n = os_realloc_array(buf, count + 1, ETH_ALEN);
|
|
|
+- if (n == NULL) {
|
|
|
+- os_free(buf);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+- buf = n;
|
|
|
+- os_memmove(buf + ETH_ALEN, buf, count * ETH_ALEN);
|
|
|
+- os_memcpy(buf, addr, ETH_ALEN);
|
|
|
+- count++;
|
|
|
+- wpa_hexdump(MSG_MSGDUMP, "p2p_client_list",
|
|
|
+- addr, ETH_ALEN);
|
|
|
+- }
|
|
|
+-
|
|
|
+- pos = os_strchr(pos, ' ');
|
|
|
+- }
|
|
|
+-
|
|
|
+- os_free(ssid->p2p_client_list);
|
|
|
+- ssid->p2p_client_list = buf;
|
|
|
+- ssid->num_p2p_clients = count;
|
|
|
+-
|
|
|
+- return 0;
|
|
|
++ return wpa_config_parse_addr_list(data, line, value,
|
|
|
++ &ssid->p2p_client_list,
|
|
|
++ &ssid->num_p2p_clients,
|
|
|
++ "p2p_client_list", 0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+@@ -1489,34 +1583,9 @@ static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
|
|
|
+ static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
|
|
|
+ struct wpa_ssid *ssid)
|
|
|
+ {
|
|
|
+- char *value, *end, *pos;
|
|
|
+- int res;
|
|
|
+- size_t i;
|
|
|
+-
|
|
|
+- if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0)
|
|
|
+- return NULL;
|
|
|
+-
|
|
|
+- value = os_malloc(20 * ssid->num_p2p_clients);
|
|
|
+- if (value == NULL)
|
|
|
+- return NULL;
|
|
|
+- pos = value;
|
|
|
+- end = value + 20 * ssid->num_p2p_clients;
|
|
|
+-
|
|
|
+- for (i = ssid->num_p2p_clients; i > 0; i--) {
|
|
|
+- res = os_snprintf(pos, end - pos, MACSTR " ",
|
|
|
+- MAC2STR(ssid->p2p_client_list +
|
|
|
+- (i - 1) * ETH_ALEN));
|
|
|
+- if (res < 0 || res >= end - pos) {
|
|
|
+- os_free(value);
|
|
|
+- return NULL;
|
|
|
+- }
|
|
|
+- pos += res;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (pos > value)
|
|
|
+- pos[-1] = '\0';
|
|
|
+-
|
|
|
+- return value;
|
|
|
++ return wpa_config_write_addr_list(data, ssid->p2p_client_list,
|
|
|
++ ssid->num_p2p_clients,
|
|
|
++ "p2p_client_list");
|
|
|
+ }
|
|
|
+ #endif /* NO_CONFIG_WRITE */
|
|
|
+
|
|
|
+@@ -1667,6 +1736,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) },
|
|
|
+@@ -1971,6 +2042,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
|
|
|
+ os_free(ssid->freq_list);
|
|
|
+ os_free(ssid->bgscan);
|
|
|
+ os_free(ssid->p2p_client_list);
|
|
|
++ os_free(ssid->bssid_blacklist);
|
|
|
++ os_free(ssid->bssid_whitelist);
|
|
|
+ #ifdef CONFIG_HT_OVERRIDES
|
|
|
+ os_free(ssid->ht_mcs);
|
|
|
+ #endif /* CONFIG_HT_OVERRIDES */
|
|
|
+diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
|
|
|
+index a4910d0..7443207 100644
|
|
|
+--- a/wpa_supplicant/config_ssid.h
|
|
|
++++ b/wpa_supplicant/config_ssid.h
|
|
|
+@@ -128,6 +128,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
|
|
|
+ */
|
|
|
+ int bssid_set;
|
|
|
+diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
|
|
|
+index 6761c1a..855653c 100644
|
|
|
+--- a/wpa_supplicant/events.c
|
|
|
++++ b/wpa_supplicant/events.c
|
|
|
+@@ -703,6 +703,33 @@ static int bss_is_ess(struct wpa_bss *bss)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++static int match_mac_mask(const u8 *addr_a, const u8 *addr_b, const u8 *mask)
|
|
|
++{
|
|
|
++ size_t i;
|
|
|
++
|
|
|
++ for (i = 0; i < ETH_ALEN; i++) {
|
|
|
++ if ((addr_a[i] & mask[i]) != (addr_b[i] & mask[i]))
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++ return 1;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++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 * 2;
|
|
|
++ const u8 *m = a + ETH_ALEN;
|
|
|
++
|
|
|
++ if (match_mac_mask(a, addr, m))
|
|
|
++ 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,
|
|
|
+@@ -827,6 +854,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/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
|
|
|
+index 8cd43df..60dcb5d 100644
|
|
|
+--- a/wpa_supplicant/p2p_supplicant.c
|
|
|
++++ b/wpa_supplicant/p2p_supplicant.c
|
|
|
+@@ -831,7 +831,7 @@ static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s,
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
|
|
|
+- if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, addr,
|
|
|
++ if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN, addr,
|
|
|
+ ETH_ALEN) != 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+@@ -839,32 +839,42 @@ static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s,
|
|
|
+ return; /* already the most recent entry */
|
|
|
+
|
|
|
+ /* move the entry to mark it most recent */
|
|
|
+- os_memmove(s->p2p_client_list + i * ETH_ALEN,
|
|
|
+- s->p2p_client_list + (i + 1) * ETH_ALEN,
|
|
|
+- (s->num_p2p_clients - i - 1) * ETH_ALEN);
|
|
|
++ os_memmove(s->p2p_client_list + i * 2 * ETH_ALEN,
|
|
|
++ s->p2p_client_list + (i + 1) * 2 * ETH_ALEN,
|
|
|
++ (s->num_p2p_clients - i - 1) * 2 * ETH_ALEN);
|
|
|
+ os_memcpy(s->p2p_client_list +
|
|
|
+- (s->num_p2p_clients - 1) * ETH_ALEN, addr, ETH_ALEN);
|
|
|
++ (s->num_p2p_clients - 1) * 2 * ETH_ALEN, addr,
|
|
|
++ ETH_ALEN);
|
|
|
++ os_memset(s->p2p_client_list +
|
|
|
++ (s->num_p2p_clients - 1) * 2 * ETH_ALEN + ETH_ALEN,
|
|
|
++ 0xff, ETH_ALEN);
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found && s->num_p2p_clients < P2P_MAX_STORED_CLIENTS) {
|
|
|
+ n = os_realloc_array(s->p2p_client_list,
|
|
|
+- s->num_p2p_clients + 1, ETH_ALEN);
|
|
|
++ s->num_p2p_clients + 1, 2 * ETH_ALEN);
|
|
|
+ if (n == NULL)
|
|
|
+ return;
|
|
|
+- os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN);
|
|
|
++ os_memcpy(n + s->num_p2p_clients * 2 * ETH_ALEN, addr,
|
|
|
++ ETH_ALEN);
|
|
|
++ os_memset(n + s->num_p2p_clients * 2 * ETH_ALEN + ETH_ALEN,
|
|
|
++ 0xff, ETH_ALEN);
|
|
|
+ s->p2p_client_list = n;
|
|
|
+ s->num_p2p_clients++;
|
|
|
+ } else if (!found && s->p2p_client_list) {
|
|
|
+ /* Not enough room for an additional entry - drop the oldest
|
|
|
+ * entry */
|
|
|
+ os_memmove(s->p2p_client_list,
|
|
|
+- s->p2p_client_list + ETH_ALEN,
|
|
|
+- (s->num_p2p_clients - 1) * ETH_ALEN);
|
|
|
++ s->p2p_client_list + 2 * ETH_ALEN,
|
|
|
++ (s->num_p2p_clients - 1) * 2 * ETH_ALEN);
|
|
|
+ os_memcpy(s->p2p_client_list +
|
|
|
+- (s->num_p2p_clients - 1) * ETH_ALEN,
|
|
|
++ (s->num_p2p_clients - 1) * 2 * ETH_ALEN,
|
|
|
+ addr, ETH_ALEN);
|
|
|
++ os_memset(s->p2p_client_list +
|
|
|
++ (s->num_p2p_clients - 1) * 2 * ETH_ALEN + ETH_ALEN,
|
|
|
++ 0xff, ETH_ALEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (wpa_s->parent->conf->update_config &&
|
|
|
+@@ -3276,7 +3286,7 @@ static void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s,
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
|
|
|
+- if (os_memcmp(ssid->p2p_client_list + i * ETH_ALEN, peer,
|
|
|
++ if (os_memcmp(ssid->p2p_client_list + i * 2 * ETH_ALEN, peer,
|
|
|
+ ETH_ALEN) == 0)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+@@ -3296,9 +3306,9 @@ static void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s,
|
|
|
+ "group %d client list%s",
|
|
|
+ MAC2STR(peer), ssid->id,
|
|
|
+ inv ? " due to invitation result" : "");
|
|
|
+- os_memmove(ssid->p2p_client_list + i * ETH_ALEN,
|
|
|
+- ssid->p2p_client_list + (i + 1) * ETH_ALEN,
|
|
|
+- (ssid->num_p2p_clients - i - 1) * ETH_ALEN);
|
|
|
++ os_memmove(ssid->p2p_client_list + i * 2 * ETH_ALEN,
|
|
|
++ ssid->p2p_client_list + (i + 1) * 2 * ETH_ALEN,
|
|
|
++ (ssid->num_p2p_clients - i - 1) * 2 * ETH_ALEN);
|
|
|
+ ssid->num_p2p_clients--;
|
|
|
+ if (wpa_s->parent->conf->update_config &&
|
|
|
+ wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
|
|
|
+@@ -6925,7 +6935,7 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
|
|
|
+ if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
|
|
|
+ continue;
|
|
|
+ for (i = 0; i < s->num_p2p_clients; i++) {
|
|
|
+- if (os_memcmp(s->p2p_client_list + i * ETH_ALEN,
|
|
|
++ if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
|
|
|
+ addr, ETH_ALEN) == 0)
|
|
|
+ return s; /* peer is P2P client in persistent
|
|
|
+ * group */
|
|
|
+diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
|
|
|
+index 0e8a28a..4bc08db 100644
|
|
|
+--- a/wpa_supplicant/wpa_supplicant.conf
|
|
|
++++ b/wpa_supplicant/wpa_supplicant.conf
|
|
|
+@@ -1408,6 +1408,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 not matching the masked address will be ignored.
|
|
|
++network={
|
|
|
++ ssid="example"
|
|
|
++ psk="very secret passphrase"
|
|
|
++ bssid_whitelist=02:55:ae:bc:00:00/ff:ff:ff:ff:00:00 00:00:77:66:55:44/00:00:ff:ff:ff:ff
|
|
|
++}
|
|
|
+
|
|
|
+ # Example config file that will only scan on channel 36.
|
|
|
+ freq_list=5180
|
|
|
+--
|
|
|
+2.1.3
|
|
|
+
|