|
@@ -0,0 +1,141 @@
|
|
|
+Modified algorithm for generating BSSIDs. Always set locally
|
|
|
+administered bit. Calculate the mask after calculating the
|
|
|
+BSSIDs. This eliminates the "Invalid BSSID mask" caused when
|
|
|
+addr & mask != addr.
|
|
|
+
|
|
|
+Signed-off-by: Bill Jordan <bjordan <at> rajant.com>
|
|
|
+---
|
|
|
+Taken from http://permalink.gmane.org/gmane.linux.drivers.hostap/22207
|
|
|
+---
|
|
|
+ src/ap/hostapd.c | 74 ++++++------------------------------------------------
|
|
|
+ 1 files changed, 8 insertions(+), 66 deletions(-)
|
|
|
+
|
|
|
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
|
|
|
+index f4517f8..1dc6b66 100644
|
|
|
+--- a/src/ap/hostapd.c
|
|
|
|
|
|
+@@ -360,70 +360,26 @@ static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
|
|
|
+ {
|
|
|
+ u8 mask[ETH_ALEN] = { 0 };
|
|
|
+ struct hostapd_data *hapd = iface->bss[0];
|
|
|
+- unsigned int i = iface->conf->num_bss, bits = 0, j;
|
|
|
++ unsigned int i, j;
|
|
|
+ int res;
|
|
|
+- int auto_addr = 0;
|
|
|
+
|
|
|
+ if (hostapd_drv_none(hapd))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Generate BSSID mask that is large enough to cover the BSSIDs. */
|
|
|
+
|
|
|
+- /* Determine the bits necessary to cover the number of BSSIDs. */
|
|
|
+- for (i--; i; i >>= 1)
|
|
|
+- bits++;
|
|
|
+-
|
|
|
+ /* Determine the bits necessary to any configured BSSIDs,
|
|
|
+ if they are higher than the number of BSSIDs. */
|
|
|
+ for (j = 0; j < iface->conf->num_bss; j++) {
|
|
|
+- if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) {
|
|
|
+- if (j)
|
|
|
+- auto_addr++;
|
|
|
+- continue;
|
|
|
+- }
|
|
|
+-
|
|
|
+ for (i = 0; i < ETH_ALEN; i++) {
|
|
|
+ mask[i] |=
|
|
|
+- iface->conf->bss[j].bssid[i] ^
|
|
|
++ iface->bss[j]->conf->bssid[i] ^
|
|
|
+ hapd->own_addr[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+- if (!auto_addr)
|
|
|
+- goto skip_mask_ext;
|
|
|
+-
|
|
|
+- for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
|
|
|
+- ;
|
|
|
+- j = 0;
|
|
|
+- if (i < ETH_ALEN) {
|
|
|
+- j = (5 - i) * 8;
|
|
|
+-
|
|
|
+- while (mask[i] != 0) {
|
|
|
+- mask[i] >>= 1;
|
|
|
+- j++;
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (bits < j)
|
|
|
+- bits = j;
|
|
|
+-
|
|
|
+- if (bits > 40) {
|
|
|
+- wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
|
|
|
+- bits);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+-
|
|
|
+- os_memset(mask, 0xff, ETH_ALEN);
|
|
|
+- j = bits / 8;
|
|
|
+- for (i = 5; i > 5 - j; i--)
|
|
|
+- mask[i] = 0;
|
|
|
+- j = bits % 8;
|
|
|
+- while (j--)
|
|
|
+- mask[i] <<= 1;
|
|
|
+-
|
|
|
+-skip_mask_ext:
|
|
|
+- wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
|
|
|
+- (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
|
|
|
++ wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR ,
|
|
|
++ (unsigned long) iface->conf->num_bss, MAC2STR(mask));
|
|
|
+
|
|
|
+ res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
|
|
|
+ if (res == 0)
|
|
|
+@@ -436,21 +392,6 @@ skip_mask_ext:
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+- if (!auto_addr)
|
|
|
+- return 0;
|
|
|
+-
|
|
|
+- for (i = 0; i < ETH_ALEN; i++) {
|
|
|
+- if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
|
|
|
+- wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
|
|
|
+- " for start address " MACSTR ".",
|
|
|
+- MAC2STR(mask), MAC2STR(hapd->own_addr));
|
|
|
+- wpa_printf(MSG_ERROR, "Start address must be the "
|
|
|
+- "first address in the block (i.e., addr "
|
|
|
+- "AND mask == addr).");
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -492,6 +433,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|
|
+ if (!first) {
|
|
|
+ if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
|
|
|
+ /* Allocate the next available BSSID. */
|
|
|
++ hapd->own_addr[0] |= 2; /* locally administered address */
|
|
|
+ do {
|
|
|
+ inc_byte_array(hapd->own_addr, ETH_ALEN);
|
|
|
+ } while (mac_in_conf(hapd->iconf, hapd->own_addr));
|
|
|
+@@ -672,9 +614,6 @@ static int setup_interface(struct hostapd_iface *iface)
|
|
|
+ iface->bss[i]->drv_priv = hapd->drv_priv;
|
|
|
+ }
|
|
|
+
|
|
|
+- if (hostapd_validate_bssid_configuration(iface))
|
|
|
+- return -1;
|
|
|
+-
|
|
|
+ if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
|
|
|
+ os_memcpy(country, hapd->iconf->country, 3);
|
|
|
+ country[3] = '\0';
|
|
|
+@@ -774,6 +713,9 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
|
|
|
+ prev_addr = hapd->own_addr;
|
|
|
+ }
|
|
|
+
|
|
|
++ if (hostapd_validate_bssid_configuration(iface))
|
|
|
++ return -1;
|
|
|
++
|
|
|
+ hostapd_tx_queue_params(iface);
|
|
|
+
|
|
|
+ ap_list_init(iface);
|