mesh: Make BSSBasicRateSet configurable

STAs that have different BSSBasicRateSet cannot connect to each other
as per IEEE 802.11s-2011 9.6.0c1:

"A mesh STA shall not establish a mesh peering with a mesh STA using a
different BSSBasicRateSet."

Make BSSBasicRateSet configurable to improve interoperability with other
stations.

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
This commit is contained in:
Masashi Honma 2014-09-01 00:23:38 -04:00 committed by Jouni Malinen
parent 603a3f34c4
commit 2b2bb5a8b9
4 changed files with 72 additions and 12 deletions

View file

@ -1617,7 +1617,31 @@ static int wpa_config_parse_mesh_ht_mode(const struct parse_data *data,
}
static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
{
int *rates = wpa_config_parse_int_array(value);
if (rates == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'",
line, value);
return -1;
}
if (rates[0] == 0) {
os_free(rates);
rates = NULL;
}
os_free(ssid->mesh_basic_rates);
ssid->mesh_basic_rates = rates;
return 0;
}
#ifndef NO_CONFIG_WRITE
static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data,
struct wpa_ssid *ssid)
{
@ -1643,6 +1667,13 @@ static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data,
return val ? os_strdup(val) : NULL;
}
static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
struct wpa_ssid *ssid)
{
return wpa_config_write_freqs(data, ssid->mesh_basic_rates);
}
#endif /* NO_CONFIG_WRITE */
#endif /* CONFIG_MESH */
@ -1819,6 +1850,7 @@ static const struct parse_data ssid_fields[] = {
{ INT_RANGE(frequency, 0, 65000) },
#ifdef CONFIG_MESH
{ FUNC(mesh_ht_mode) },
{ FUNC(mesh_basic_rates) },
#endif /* CONFIG_MESH */
{ INT(wpa_ptk_rekey) },
{ STR(bgscan) },
@ -2049,6 +2081,9 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
#ifdef CONFIG_HT_OVERRIDES
os_free(ssid->ht_mcs);
#endif /* CONFIG_HT_OVERRIDES */
#ifdef CONFIG_MESH
os_free(ssid->mesh_basic_rates);
#endif /* CONFIG_MESH */
while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
list))) {
dl_list_del(&psk->list);

View file

@ -743,7 +743,10 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(update_identifier);
#endif /* CONFIG_HS20 */
write_int(f, "mac_addr", ssid->mac_addr, -1);
#ifdef CONFIG_MESH
STR(mesh_ht_mode);
STR(mesh_basic_rates);
#endif /* CONFIG_MESH */
#undef STR
#undef INT

View file

@ -413,6 +413,12 @@ struct wpa_ssid {
*/
int mesh_ht_mode;
/**
* mesh_basic_rates - BSS Basic rate set for mesh network
*
*/
int *mesh_basic_rates;
int ht40;
int vht;

View file

@ -122,6 +122,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
size_t len;
int rate_len;
if (!wpa_s->conf->user_mpm) {
/* not much for us to do here */
@ -186,19 +187,34 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
goto out_free;
}
/*
* XXX: Hack! This is so an MPM which correctly sets the ERP mandatory
* rates as BSSBasicRateSet doesn't reject us. We could add a new
* hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but this is way easier. This
* also makes our BSSBasicRateSet advertised in Beacon frames match the
* one in peering frames, sigh.
*/
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
conf->basic_rates = os_malloc(sizeof(basic_rates_erp));
if (!conf->basic_rates)
if (ssid->mesh_basic_rates == NULL) {
/*
* XXX: Hack! This is so an MPM which correctly sets the ERP
* mandatory rates as BSSBasicRateSet doesn't reject us. We
* could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but
* this is way easier. This also makes our BSSBasicRateSet
* advertised in beacons match the one in peering frames, sigh.
*/
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
conf->basic_rates = os_malloc(sizeof(basic_rates_erp));
if (!conf->basic_rates)
goto out_free;
os_memcpy(conf->basic_rates, basic_rates_erp,
sizeof(basic_rates_erp));
}
} else {
rate_len = 0;
while (1) {
if (ssid->mesh_basic_rates[rate_len] < 1)
break;
rate_len++;
}
conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
if (conf->basic_rates == NULL)
goto out_free;
os_memcpy(conf->basic_rates, basic_rates_erp,
sizeof(basic_rates_erp));
os_memcpy(conf->basic_rates, ssid->mesh_basic_rates,
rate_len * sizeof(int));
conf->basic_rates[rate_len] = -1;
}
if (hostapd_setup_interface(ifmsh)) {