diff --git a/package/network/services/hostapd/files/netifd.sh b/package/network/services/hostapd/files/netifd.sh
index 83fb129fe119c5ff9ca3deb3c643624373f74ced..3a64689428d5a3bc529ea89adc7a215c7cc2c543 100644
--- a/package/network/services/hostapd/files/netifd.sh
+++ b/package/network/services/hostapd/files/netifd.sh
@@ -153,6 +153,9 @@ hostapd_common_add_bss_config() {
 	config_add_string macfilter 'macfile:file'
 	config_add_array 'maclist:list(macaddr)'
 
+	config_add_array bssid_blacklist
+	config_add_array bssid_whitelist
+
 	config_add_int mcast_rate
 	config_add_array basic_rate
 	config_add_array supported_rates
@@ -580,6 +583,12 @@ wpa_supplicant_add_network() {
 	[ -n "$bssid" ] && append network_data "bssid=$bssid" "$N$T"
 	[ -n "$beacon_int" ] && append network_data "beacon_int=$beacon_int" "$N$T"
 
+	local bssid_blacklist bssid_whitelist
+	json_get_values bssid_blacklist bssid_blacklist
+	json_get_values bssid_whitelist bssid_whitelist
+
+	[ -n "$bssid_blacklist" ] && append network_data "bssid_blacklist=$bssid_blacklist" "$N$T"
+	[ -n "$bssid_whitelist" ] && append network_data "bssid_whitelist=$bssid_whitelist" "$N$T"
 
 	[ -n "$basic_rate" ] && {
 		local br rate_list=
diff --git a/package/network/services/hostapd/patches/700-Add-os_snprintf_error-helper.patch b/package/network/services/hostapd/patches/700-Add-os_snprintf_error-helper.patch
new file mode 100644
index 0000000000000000000000000000000000000000..51ad1c4d70a8619d2afed090c089017d6828e361
--- /dev/null
+++ b/package/network/services/hostapd/patches/700-Add-os_snprintf_error-helper.patch
@@ -0,0 +1,29 @@
+Add os_snprintf_error() helper
+
+This can be used to check os_snprintf() return value more consistently.
+
+Signed-off-by: Jouni Malinen <j@w1.fi>
+---
+ src/utils/os.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/utils/os.h b/src/utils/os.h
+index b9247d8..77250d6 100644
+--- a/src/utils/os.h
++++ b/src/utils/os.h
+@@ -549,6 +549,12 @@ char * os_strdup(const char *s);
+ #endif /* OS_NO_C_LIB_DEFINES */
+ 
+ 
++static inline int os_snprintf_error(size_t size, int res)
++{
++	return res < 0 || (unsigned int) res >= size;
++}
++
++
+ static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
+ {
+ 	if (size && nmemb > (~(size_t) 0) / size)
+-- 
+2.1.3
+
diff --git a/package/network/services/hostapd/patches/710-Add-network-specific-BSSID-black-and-white-lists.patch b/package/network/services/hostapd/patches/710-Add-network-specific-BSSID-black-and-white-lists.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5b42158a4b7180fc184525145057a3579b9db339
--- /dev/null
+++ b/package/network/services/hostapd/patches/710-Add-network-specific-BSSID-black-and-white-lists.patch
@@ -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 <stefan.tomanek@wertarbyte.de>
+---
+ 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
+