From 2b2bb5a8b987f3921f32dd9e76c351496ce6ff15 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 1 Sep 2014 00:23:38 -0400 Subject: [PATCH] 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 --- wpa_supplicant/config.c | 35 +++++++++++++++++++++++++++++++ wpa_supplicant/config_file.c | 3 +++ wpa_supplicant/config_ssid.h | 6 ++++++ wpa_supplicant/mesh.c | 40 +++++++++++++++++++++++++----------- 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 9e261ba75..c948c5fc9 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -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); diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 852140f94..6c55cfc67 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -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 diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 85d976c39..b1c2fd8aa 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -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; diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 3ebf0584e..1ff8dac34 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -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)) {