[PATCH 3/3] Enable wildcards (*) in BSSID lists
Stefan Tomanek
stefan.tomanek
Mon Dec 15 04:24:43 PST 2014
In many context it seems suitable not just to enumerate a group of mac
addresses, but to use wildcards (ca:ff:ee:*:*:*).
This change expands the data structures used by mac lists to include a mask
indicating the significant (non-masked) portions of an address.
Signed-off-by: Stefan Tomanek <stefan.tomanek at wertarbyte.de>
---
src/utils/common.c | 54 ++++++++++++++++++++++++++++++++------
src/utils/common.h | 3 +++
wpa_supplicant/config.c | 22 +++++++++-------
wpa_supplicant/events.c | 15 +++++++++--
wpa_supplicant/wpa_supplicant.conf | 4 +--
5 files changed, 76 insertions(+), 22 deletions(-)
diff --git a/src/utils/common.c b/src/utils/common.c
index 422b476..243e2d8 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -44,18 +44,39 @@ int hex2byte(const char *hex)
*/
int hwaddr_aton(const char *txt, u8 *addr)
{
+ u8 mask[ETH_ALEN];
+ return hwaddr_wildcard_aton(txt, addr, mask, 0);
+}
+
+/**
+ * hwaddr_wildcard_aton - Convert ASCII string with wildcards to MAC address (colon-delimited format)
+ * @txt: MAC address as a string (e.g., "00:11:22:33:*:*")
+ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
+ * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes)
+ * @wildcard: Flag to indicate whether wildcards are allowed
+ * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
+ */
+int hwaddr_wildcard_aton(const char *txt, u8 *addr, u8 *mask, u8 wildcard)
+{
int i;
for (i = 0; i < 6; i++) {
- int a, b;
+ int a = 0;
+ int b = 0;
- a = hex2num(*txt++);
- if (a < 0)
- return -1;
- b = hex2num(*txt++);
- if (b < 0)
- return -1;
- *addr++ = (a << 4) | b;
+ if (wildcard && *txt == '*') {
+ mask[i] = 0x00;
+ txt++;
+ } else {
+ mask[i] = 0xFF;
+ a = hex2num(*txt++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*txt++);
+ if (b < 0)
+ return -1;
+ }
+ addr[i] = (a << 4) | b;
if (i < 5 && *txt++ != ':')
return -1;
}
@@ -143,6 +164,23 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len)
return 0;
}
+size_t hwaddr_mask_txt(char *buf, u8 *addr, u8 *mask) {
+ size_t i;
+ char *pos = buf;
+ for (i = 0; i < ETH_ALEN; i++) {
+ if (!mask[i]) {
+ *pos++ = '*';
+ } else {
+ u8 n = sprintf(pos, "%02x", addr[i]);
+ pos += n;
+ }
+ if (i < 5) {
+ *pos++ = ':';
+ }
+ }
+ *pos = '\0';
+ return pos - buf;
+}
/**
* inc_byte_array - Increment arbitrary length byte array by one
diff --git a/src/utils/common.h b/src/utils/common.h
index 70d76a9..c96d70b 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -471,6 +471,7 @@ typedef u64 __bitwise le64;
#endif /* __must_check */
int hwaddr_aton(const char *txt, u8 *addr);
+int hwaddr_wildcard_aton(const char *txt, u8 *addr, u8 *mask, u8 wildcards);
int hwaddr_compact_aton(const char *txt, u8 *addr);
int hwaddr_aton2(const char *txt, u8 *addr);
int hex2byte(const char *hex);
@@ -482,6 +483,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);
+size_t hwaddr_mask_txt(char *buf, u8 *addr, 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 62e2948..163bfaa 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -238,10 +238,11 @@ static int wpa_config_parse_addr_list(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value,
u8 **list, size_t *num, char *name,
- u8 abort_on_error)
+ u8 abort_on_error, u8 wildcards)
{
const char *pos;
u8 *buf, *n, addr[ETH_ALEN];
+ u8 mask[ETH_ALEN];
size_t count;
buf = NULL;
@@ -252,7 +253,7 @@ static int wpa_config_parse_addr_list(const struct parse_data *data,
while (*pos == ' ')
pos++;
- if (hwaddr_aton(pos, addr)) {
+ if (hwaddr_wildcard_aton(pos, addr, mask, wildcards)) {
if (abort_on_error || count == 0) {
wpa_printf(MSG_ERROR, "Line %d: Invalid "
"%s address '%s'.",
@@ -266,14 +267,15 @@ static int wpa_config_parse_addr_list(const struct parse_data *data,
"truncated %s address '%s'",
line, name, pos);
} else {
- n = os_realloc_array(buf, count + 1, ETH_ALEN);
+ n = os_realloc_array(buf, count + 1, 2*ETH_ALEN);
if (n == NULL) {
os_free(buf);
return -1;
}
buf = n;
- os_memmove(buf + ETH_ALEN, buf, count * ETH_ALEN);
+ os_memmove(buf + 2*ETH_ALEN, buf, count * 2*ETH_ALEN);
os_memcpy(buf, addr, ETH_ALEN);
+ os_memcpy(buf + ETH_ALEN, mask, ETH_ALEN);
count++;
wpa_hexdump(MSG_MSGDUMP, name,
addr, ETH_ALEN);
@@ -308,9 +310,9 @@ static char * wpa_config_write_addr_list(const struct parse_data *data,
end = value + 20 * (*num);
for (i = (*num); i > 0; i--) {
- res = os_snprintf(pos, end - pos, MACSTR " ",
- MAC2STR(*list +
- (i - 1) * ETH_ALEN));
+ u8 *a = *list + (i-1) * 2*ETH_ALEN;
+ u8 *m = *list + (i-1) * 2*ETH_ALEN + ETH_ALEN;
+ res = hwaddr_mask_txt(pos, a, m);
if (os_snprintf_error(end - pos, res)) {
os_free(value);
return NULL;
@@ -373,7 +375,7 @@ static char * wpa_config_write_bssid(const struct parse_data *data,
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, ssid, line, value, &ssid->bssid_blacklist, &ssid->num_bssid_blacklist, "bssid_blacklist", 1);
+ return wpa_config_parse_addr_list(data, ssid, line, value, &ssid->bssid_blacklist, &ssid->num_bssid_blacklist, "bssid_blacklist", 1, 1);
}
#ifndef NO_CONFIG_WRITE
@@ -388,7 +390,7 @@ static char * wpa_config_write_bssid_blacklist(const struct parse_data *data,
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, ssid, line, value, &ssid->bssid_whitelist, &ssid->num_bssid_whitelist, "bssid_whitelist", 1);
+ return wpa_config_parse_addr_list(data, ssid, line, value, &ssid->bssid_whitelist, &ssid->num_bssid_whitelist, "bssid_whitelist", 1, 1);
}
#ifndef NO_CONFIG_WRITE
@@ -1573,7 +1575,7 @@ static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
{
- return wpa_config_parse_addr_list(data, ssid, line, value, &ssid->p2p_client_list, &ssid->num_p2p_clients, "p2p_client_list", 0);
+ return wpa_config_parse_addr_list(data, ssid, line, value, &ssid->p2p_client_list, &ssid->num_p2p_clients, "p2p_client_list", 0, 0);
}
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 3a01d23..0dae38c 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -705,11 +705,22 @@ static int bss_is_ess(struct wpa_bss *bss)
IEEE80211_CAP_ESS);
}
+static int match_mac_mask(u8 *addrA, u8 *addrB, u8 *mask) {
+ size_t i;
+ for (i = 0; i < ETH_ALEN; i++) {
+ if ((addrA[i] & mask[i]) != (addrB[i] & mask[i])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
static int addr_in_list(u8 *addr, u8 *list, size_t num) {
size_t i;
for (i = 0; i < num; i++) {
- u8 *a = list + (i*ETH_ALEN);
- if (os_memcmp(a, addr, ETH_ALEN) == 0) {
+ u8 *a = list + (i*ETH_ALEN*2);
+ u8 *m = list + (i*ETH_ALEN*2) + ETH_ALEN;
+ if (match_mac_mask(a, addr, m)) {
return 1;
}
}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 4ed7865..8595028 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1436,11 +1436,11 @@ network={
}
# Example configuration limiting AP selection to a specific set of APs;
-# any other AP will be ignored for this network entry
+# any other AP not matching the wildcard will be ignored for this network entry
network={
ssid="example"
psk="very secret passphrase"
- bssid_whitelist=ca:fe:ba:be:d0:0d de:ad:be:ef:00:00
+ bssid_whitelist=ca:fe:ba:be:*:*
}
# Example config file that will only scan on channel 36.
--
2.1.1
More information about the Hostap
mailing list