From a7c152d6b8065e3b2c3c0b3562e8a22e53d60f2e Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 27 Jul 2021 16:42:20 -0700 Subject: [PATCH] RNR: Add data from neighbor database Include data from the existing neighbor database in the Reduced Neighbor Report element in Beacon frames if the configuration option 'rnr' is enabled for the BSS. Signed-off-by: John Crispin Signed-off-by: Muna Sinada Co-developed-by: Aloka Dixit Signed-off-by: Aloka Dixit --- src/ap/ieee802_11.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ src/ap/ieee802_11.h | 2 + 2 files changed, 127 insertions(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 71fbefc8e..52df06d29 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -7071,4 +7071,129 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) return eid; } + +static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd, + size_t *current_len) +{ + struct hostapd_neighbor_entry *nr; + size_t total_len = 0, len = *current_len; + + 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; + + /* Start a new element */ + if (!len || + len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) { + len = RNR_HEADER_LEN; + total_len += RNR_HEADER_LEN; + } + + len += RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN; + total_len += RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN; + } + + *current_len = len; + return total_len; +} + + +size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type) +{ + size_t total_len = 0, current_len = 0; + + switch (type) { + case WLAN_FC_STYPE_BEACON: + if (hapd->conf->rnr) + total_len += hostapd_eid_nr_db_len(hapd, ¤t_len); + break; + + default: + break; + } + + return total_len; +} + + +static u8 * hostapd_eid_nr_db(struct hostapd_data *hapd, u8 *eid, + size_t *current_len) +{ + struct hostapd_neighbor_entry *nr; + size_t len = *current_len; + u8 *size_offset = (eid - 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; + + /* Start a new element */ + if (!len || + len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) { + *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT; + size_offset = eid++; + len = RNR_HEADER_LEN; + } + + /* TBTT Information Header subfield (2 octets) */ + *eid++ = 0; + /* TBTT Information Length */ + *eid++ = RNR_TBTT_INFO_LEN; + /* Operating Class */ + *eid++ = wpabuf_head_u8(nr->nr)[10]; + /* Channel Number */ + *eid++ = wpabuf_head_u8(nr->nr)[11]; + len += RNR_TBTT_HEADER_LEN; + /* TBTT Information Set */ + /* TBTT Information field */ + /* Neighbor AP TBTT Offset */ + *eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN; + /* BSSID */ + os_memcpy(eid, nr->bssid, ETH_ALEN); + eid += ETH_ALEN; + /* Short SSID */ + os_memcpy(eid, &nr->short_ssid, 4); + eid += 4; + /* BSS parameters */ + *eid++ = nr->bss_parameters; + /* 20 MHz PSD */ + *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1; + len += RNR_TBTT_INFO_LEN; + *size_offset = (eid - size_offset) - 1; + } + + *current_len = len; + return eid; +} + + +u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type) +{ + u8 *eid_start = eid; + size_t current_len = 0; + + switch (type) { + case WLAN_FC_STYPE_BEACON: + if (hapd->conf->rnr) + eid = hostapd_eid_nr_db(hapd, eid, ¤t_len); + break; + + default: + return eid_start; + } + + if (eid == eid_start + 2) + return eid_start; + + return eid; +} + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index ea8c60846..c59ad5e38 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -194,5 +194,7 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, void auth_sae_process_commit(void *eloop_ctx, void *user_ctx); u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len); +size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type); +u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type); #endif /* IEEE802_11_H */