mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 18:01:23 +00:00
405 lines
12 KiB
Diff
405 lines
12 KiB
Diff
From f8217bb43d1157dbd83c1361dd44b66b81bd70b8 Mon Sep 17 00:00:00 2001
|
|
From: Aloka Dixit <alokad@codeaurora.org>
|
|
Date: Thu, 10 Dec 2020 14:12:33 -0800
|
|
Subject: [PATCH 5/9] hostapd: Length checks for reduced neighbor report
|
|
|
|
Maximum length of any RNR element can be 255 bytes.
|
|
This commit adds code to check the length in all RNR related functions
|
|
and creates a new element if required.
|
|
|
|
Additionally, this change modifies some incorrect calculations used for
|
|
for total lengths.
|
|
|
|
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
|
---
|
|
src/ap/ieee802_11.c | 247 +++++++++++++++++++++++------------
|
|
src/common/ieee802_11_defs.h | 2 +
|
|
2 files changed, 166 insertions(+), 83 deletions(-)
|
|
|
|
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
|
|
index 488f02f58f63..953a444a5cd4 100644
|
|
--- a/src/ap/ieee802_11.c
|
|
+++ b/src/ap/ieee802_11.c
|
|
@@ -5985,22 +5985,48 @@ u8 * hostapd_eid_multiple_bssid(struct hostapd_data *hapd,
|
|
|
|
|
|
size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
|
|
- struct hostapd_data *reporting_hapd)
|
|
+ struct hostapd_data *reporting_hapd,
|
|
+ size_t *current_len)
|
|
{
|
|
- size_t len = 0;
|
|
- int i;
|
|
+ size_t total_len = 0;
|
|
+ int i, tbtt_count = 0, start = 0;
|
|
+
|
|
+ while (start < hapd->iface->num_bss) {
|
|
+ if (!(*current_len) ||
|
|
+ ((*current_len + TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH) >
|
|
+ 255)) {
|
|
+ *current_len = RNR_HEADER_LENGTH;
|
|
+ total_len += RNR_HEADER_LENGTH;
|
|
+ }
|
|
|
|
- for (i = 0; i < hapd->iface->num_bss; i++) {
|
|
- if (hapd->iface->bss[i] == reporting_hapd ||
|
|
- hapd->iface->bss[i]->conf->ignore_broadcast_ssid)
|
|
- continue;
|
|
- len += TBTT_INFO_LENGTH;
|
|
+ *current_len += TBTT_HEADER_LENGTH;
|
|
+ total_len += TBTT_HEADER_LENGTH;
|
|
+
|
|
+ for (i = start; i < hapd->iface->num_bss; i++) {
|
|
+ if (hapd->iface->bss[i] == reporting_hapd ||
|
|
+ hapd->conf->ignore_broadcast_ssid)
|
|
+ continue;
|
|
+
|
|
+ if ((*current_len + TBTT_INFO_LENGTH > 255) ||
|
|
+ (tbtt_count >= TBTT_INFO_COUNT_MAX))
|
|
+ break;
|
|
+
|
|
+ *current_len += TBTT_INFO_LENGTH;
|
|
+ total_len += TBTT_INFO_LENGTH;
|
|
+ tbtt_count++;
|
|
+ }
|
|
+ start = i;
|
|
}
|
|
- return len;
|
|
+
|
|
+ if (!tbtt_count)
|
|
+ total_len = 0;
|
|
+
|
|
+ return total_len;
|
|
}
|
|
|
|
|
|
-static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd)
|
|
+static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd,
|
|
+ size_t *current_len)
|
|
{
|
|
struct hostapd_iface *iface;
|
|
size_t len = 0;
|
|
@@ -6015,8 +6041,35 @@ static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd)
|
|
if (iface == hapd->iface || !iface->conf->he_co_locate)
|
|
continue;
|
|
|
|
- len += (TBTT_HEADER_LENGTH +
|
|
- hostapd_eid_rnr_iface_len(iface->bss[0], hapd));
|
|
+ len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
|
|
+ current_len);
|
|
+ }
|
|
+ return len;
|
|
+}
|
|
+
|
|
+
|
|
+static size_t hostapd_eid_neighbor_report_db_len(struct hostapd_data *hapd,
|
|
+ size_t *current_len)
|
|
+{
|
|
+ struct hostapd_neighbor_entry *nr;
|
|
+ size_t len = 0;
|
|
+
|
|
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
|
|
+ list) {
|
|
+ if (!nr->nr || wpabuf_len(nr->nr) < 12)
|
|
+ continue;
|
|
+ if (nr->short_ssid == hapd->conf->ssid.short_ssid)
|
|
+ continue;
|
|
+
|
|
+ if (!*current_len ||
|
|
+ ((*current_len + TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH) >
|
|
+ 255)) {
|
|
+ *current_len = RNR_HEADER_LENGTH;
|
|
+ len += RNR_HEADER_LENGTH;
|
|
+ }
|
|
+
|
|
+ *current_len += (TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH);
|
|
+ len += (TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH);
|
|
}
|
|
return len;
|
|
}
|
|
@@ -6049,23 +6102,21 @@ static bool is_6ghz_colocated(struct hostapd_data *hapd)
|
|
|
|
size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
|
|
{
|
|
- size_t len = 0;
|
|
+ size_t len = 0, current_len = 0;
|
|
|
|
if (hapd->conf->rnr_beacon) {
|
|
if (hapd->iface->num_bss > 1)
|
|
- len += (TBTT_HEADER_LENGTH +
|
|
- hostapd_eid_rnr_iface_len(hapd, hapd));
|
|
+ len += hostapd_eid_rnr_iface_len(hapd, hapd,
|
|
+ ¤t_len);
|
|
|
|
if ((type == WLAN_FC_STYPE_BEACON) &&
|
|
- !dl_list_empty(&hapd->nr_db))
|
|
- len += dl_list_len(&hapd->nr_db) * (TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH);
|
|
+ !dl_list_empty(&hapd->nr_db))
|
|
+ len += hostapd_eid_neighbor_report_db_len(hapd,
|
|
+ ¤t_len);
|
|
}
|
|
|
|
if ((true == is_6ghz_colocated(hapd)) && type != WLAN_FC_STYPE_ACTION)
|
|
- len += hostapd_eid_rnr_colocation_len(hapd);
|
|
-
|
|
- if (len)
|
|
- len += 2; /* Element ID and length */
|
|
+ len += hostapd_eid_rnr_colocation_len(hapd, ¤t_len);
|
|
|
|
return len;
|
|
}
|
|
@@ -6073,72 +6124,95 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
|
|
|
|
static u8 *hostapd_eid_rnr_iface(struct hostapd_data *hapd,
|
|
struct hostapd_data *reporting_hapd,
|
|
- u8 *eid, int *count)
|
|
+ u8 *eid, size_t *current_len)
|
|
{
|
|
- u8 *eid_start = eid, *tbtt_count_pos;
|
|
- u8 tbtt_count = 0;
|
|
- u8 op_class, channel;
|
|
- int i;
|
|
+ u8 *eid_start = eid, *tbtt_count_pos = NULL;
|
|
+ u8 tbtt_count = 0, op_class, channel, bss_param;
|
|
+ u8 *size_offset = (eid - *current_len) + 1;
|
|
+ int i, start = 0;
|
|
+ struct hostapd_data *bss;
|
|
+ struct hostapd_iface *iface = hapd->iface;
|
|
|
|
- if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) ||
|
|
- !hapd->iface->freq)
|
|
+ if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
|
|
return eid;
|
|
|
|
- if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
|
|
+ if (ieee80211_freq_to_channel_ext(iface->freq,
|
|
hapd->iconf->secondary_channel,
|
|
hostapd_get_oper_chwidth(hapd->iconf),
|
|
&op_class, &channel) ==
|
|
NUM_HOSTAPD_MODES)
|
|
return eid;
|
|
|
|
- tbtt_count_pos = eid++;
|
|
- *eid++ = TBTT_INFO_LENGTH;
|
|
- *eid++ = op_class;
|
|
- *eid++ = hapd->iconf->channel;
|
|
- for (i = 0; i < hapd->iface->num_bss; i++) {
|
|
- u8 bss_param = 0;
|
|
+ while (start < iface->num_bss) {
|
|
+ if (!(*current_len) ||
|
|
+ ((*current_len + TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH) >
|
|
+ 255)) {
|
|
+ eid_start = eid;
|
|
+ *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
|
|
+ size_offset = eid++;
|
|
+ *current_len = RNR_HEADER_LENGTH;
|
|
+ tbtt_count = 0;
|
|
+ }
|
|
|
|
- if (hapd->iface->bss[i] == reporting_hapd ||
|
|
- hapd->iface->bss[i]->conf->ignore_broadcast_ssid)
|
|
- continue;
|
|
+ tbtt_count_pos = eid++;
|
|
+ *eid++ = TBTT_INFO_LENGTH;
|
|
+ *eid++ = op_class;
|
|
+ *eid++ = hapd->iconf->channel;
|
|
+ *current_len += TBTT_HEADER_LENGTH;
|
|
|
|
- *eid++ = TBTT_AP_OFFSET_UNKNOWN;
|
|
- os_memcpy(eid, hapd->iface->bss[i]->conf->bssid, ETH_ALEN);
|
|
- eid += 6;
|
|
- os_memcpy(eid, &hapd->iface->bss[i]->conf->ssid.short_ssid, 4);
|
|
- eid += 4;
|
|
- if (hapd->iface->bss[i]->conf->ssid.short_ssid ==
|
|
- reporting_hapd->conf->ssid.short_ssid)
|
|
- bss_param |= TBTT_BSS_PARAM_SAME_SSID;
|
|
-
|
|
- if (hapd->iconf->multiple_bssid && hapd->iface->num_bss > 1) {
|
|
- bss_param |= TBTT_BSS_PARAM_MULTIPLE_BSSID;
|
|
- if (hapd->iface->bss[i] == hostapd_get_primary_bss(hapd->iface->bss[i]))
|
|
- bss_param |= TBTT_BSS_PARAM_TRANSMITTED_BSSID;
|
|
- }
|
|
- if (hapd->iface->bss[i]->iconf->he_co_locate)
|
|
- bss_param |= TBTT_BSS_PARAM_CO_LOCATED;
|
|
+ for (i = start; i < iface->num_bss; i++) {
|
|
+ bss_param = 0;
|
|
+ bss = iface->bss[i];
|
|
|
|
- if (hapd->iface->bss[i]->conf->unsol_bcast_probe_resp_interval)
|
|
- bss_param |= TBTT_BSS_PARAM_20_TU_PROBE_RESP_ACTIVE;
|
|
+ if (bss == reporting_hapd ||
|
|
+ hapd->conf->ignore_broadcast_ssid)
|
|
+ continue;
|
|
|
|
- *eid++ = bss_param;
|
|
- /* Setting 20 MHz PSD */
|
|
- *eid++ = TBTT_PSD_MAX_TXPOWER - 1;
|
|
- *count += 1;
|
|
- tbtt_count++;
|
|
+ if ((*current_len + TBTT_INFO_LENGTH > 255) ||
|
|
+ (tbtt_count >= TBTT_INFO_COUNT_MAX))
|
|
+ break;
|
|
+
|
|
+ *eid++ = TBTT_AP_OFFSET_UNKNOWN;
|
|
+ os_memcpy(eid, bss->conf->bssid, ETH_ALEN);
|
|
+ eid += ETH_ALEN;
|
|
+ os_memcpy(eid, &bss->conf->ssid.short_ssid, 4);
|
|
+ eid += 4;
|
|
+ if (bss->conf->ssid.short_ssid ==
|
|
+ reporting_hapd->conf->ssid.short_ssid)
|
|
+ bss_param |= TBTT_BSS_PARAM_SAME_SSID;
|
|
+
|
|
+ if (hapd->iconf->multiple_bssid &&
|
|
+ (iface->num_bss > 1)) {
|
|
+ bss_param |= TBTT_BSS_PARAM_MULTIPLE_BSSID;
|
|
+ if (bss == hostapd_get_primary_bss(bss))
|
|
+ bss_param |= TBTT_BSS_PARAM_TRANSMITTED_BSSID;
|
|
+ }
|
|
+ if (bss->iconf->he_co_locate)
|
|
+ bss_param |= TBTT_BSS_PARAM_CO_LOCATED;
|
|
+
|
|
+ if (bss->conf->unsol_bcast_probe_resp_interval)
|
|
+ bss_param |= TBTT_BSS_PARAM_20_TU_PROBE_RESP_ACTIVE;
|
|
+
|
|
+ *eid++ = bss_param;
|
|
+ *eid++ = TBTT_PSD_MAX_TXPOWER - 1;
|
|
+ *current_len += TBTT_INFO_LENGTH;
|
|
+ tbtt_count += 1;
|
|
+ }
|
|
+
|
|
+ start = i;
|
|
+ *tbtt_count_pos = TBTT_INFO_COUNT(tbtt_count - 1);
|
|
+ *size_offset = (eid - size_offset) - 1;
|
|
}
|
|
|
|
if (tbtt_count == 0)
|
|
return eid_start;
|
|
|
|
- *tbtt_count_pos = TBTT_INFO_COUNT(tbtt_count - 1);
|
|
return eid;
|
|
}
|
|
|
|
|
|
static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
|
|
- int *count)
|
|
+ size_t *current_len)
|
|
{
|
|
struct hostapd_iface *iface;
|
|
int i;
|
|
@@ -6152,36 +6226,50 @@ static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
|
|
if (iface == hapd->iface || !iface->conf->he_co_locate)
|
|
continue;
|
|
|
|
- eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid, count);
|
|
+ eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
|
|
+ current_len);
|
|
}
|
|
return eid;
|
|
}
|
|
|
|
|
|
static u8 *hostapd_eid_neighbor_report_db(struct hostapd_data *hapd, u8 *eid,
|
|
- int *count)
|
|
+ size_t *current_len)
|
|
{
|
|
struct hostapd_neighbor_entry *nr;
|
|
+ u8 *size_offset = (eid - *current_len) + 1;
|
|
|
|
dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
|
|
list) {
|
|
if (!nr->nr || wpabuf_len(nr->nr) < 12)
|
|
continue;
|
|
+
|
|
if (nr->short_ssid == hapd->conf->ssid.short_ssid)
|
|
continue;
|
|
+
|
|
+ if (!*current_len ||
|
|
+ ((*current_len + TBTT_HEADER_LENGTH + TBTT_INFO_LENGTH) >
|
|
+ 255)) {
|
|
+ *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
|
|
+ size_offset = eid++;
|
|
+ *current_len = RNR_HEADER_LENGTH;
|
|
+ }
|
|
+
|
|
*eid++ = 0;
|
|
*eid++ = TBTT_INFO_LENGTH;
|
|
*eid++ = wpabuf_head_u8(nr->nr)[10];
|
|
*eid++ = wpabuf_head_u8(nr->nr)[11];
|
|
+ *current_len += TBTT_HEADER_LENGTH;
|
|
*eid++ = TBTT_AP_OFFSET_UNKNOWN;
|
|
os_memcpy(eid, nr->bssid, ETH_ALEN);
|
|
- eid += 6;
|
|
+ eid += ETH_ALEN;
|
|
os_memcpy(eid, &nr->short_ssid, 4);
|
|
eid += 4;
|
|
*eid++ = nr->bss_parameters;
|
|
/* setting 20 MHZ PSD */
|
|
*eid++ = TBTT_PSD_MAX_TXPOWER - 1;
|
|
- *count += 1;
|
|
+ *current_len += TBTT_INFO_LENGTH;
|
|
+ *size_offset = (eid - size_offset) - 1;
|
|
}
|
|
|
|
return eid;
|
|
@@ -6190,31 +6278,24 @@ static u8 *hostapd_eid_neighbor_report_db(struct hostapd_data *hapd, u8 *eid,
|
|
|
|
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
|
|
{
|
|
- size_t len = hostapd_eid_rnr_len(hapd, type);
|
|
- int i, count = 0;
|
|
- u8 *size_offset;
|
|
-
|
|
- if (!len)
|
|
- return eid;
|
|
-
|
|
- *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
|
|
- size_offset = eid++;
|
|
+ u8 *eid_start = eid;
|
|
+ size_t current_len = 0;
|
|
|
|
if (hapd->conf->rnr_beacon) {
|
|
if (hapd->iface->num_bss > 1)
|
|
- eid = hostapd_eid_rnr_iface(hapd, hapd, eid, &count);
|
|
+ eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
|
|
+ ¤t_len);
|
|
|
|
if (type == WLAN_FC_STYPE_BEACON)
|
|
- eid = hostapd_eid_neighbor_report_db(hapd, eid, &count);
|
|
+ eid = hostapd_eid_neighbor_report_db(hapd, eid,
|
|
+ ¤t_len);
|
|
}
|
|
|
|
if ((true == is_6ghz_colocated(hapd)) && type != WLAN_FC_STYPE_ACTION)
|
|
- eid = hostapd_eid_rnr_colocation(hapd, eid, &count);
|
|
+ eid = hostapd_eid_rnr_colocation(hapd, eid, ¤t_len);
|
|
|
|
- if (!count)
|
|
- eid -= 2;
|
|
- else
|
|
- *size_offset = (eid - size_offset) - 1;
|
|
+ if (eid == (eid_start + 2))
|
|
+ return eid_start;
|
|
|
|
return eid;
|
|
}
|
|
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
|
|
index 52e2c868e723..ab7f36f39196 100644
|
|
--- a/src/common/ieee802_11_defs.h
|
|
+++ b/src/common/ieee802_11_defs.h
|
|
@@ -2420,10 +2420,12 @@ enum mscs_description_subelem {
|
|
#define FILS_DISCOVERY_MAX_INTERVAL_6GHZ 20
|
|
|
|
/* TBTT Information field defines */
|
|
+#define RNR_HEADER_LENGTH 2
|
|
#define TBTT_HEADER_LENGTH 4
|
|
#define TBTT_INFO_LENGTH 13
|
|
#define TBTT_INFO_FILTERED_NEIGH_AP BIT(2)
|
|
#define TBTT_INFO_COUNT(x) (((x) & 0xf) << 4)
|
|
+#define TBTT_INFO_COUNT_MAX 16
|
|
#define TBTT_AP_OFFSET_UNKNOWN 255
|
|
#define TBTT_BSS_PARAM_OCT_RECOMMENDED BIT(0)
|
|
#define TBTT_BSS_PARAM_SAME_SSID BIT(1)
|
|
--
|
|
2.25.0
|
|
|