}
+static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+ struct hostapd_data *reporting_hapd,
+ size_t *current_len)
+{
+ size_t total_len = 0, len = *current_len;
+ int tbtt_count = 0;
+ size_t i, start = 0;
+
+ while (start < hapd->iface->num_bss) {
+ 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;
+ total_len += RNR_TBTT_HEADER_LEN;
+
+ for (i = start; i < hapd->iface->num_bss; i++) {
+ struct hostapd_data *bss = hapd->iface->bss[i];
+
+ if (!bss || !bss->conf || !bss->started)
+ continue;
+
+ if (bss == reporting_hapd ||
+ bss->conf->ignore_broadcast_ssid)
+ continue;
+
+ if (len + RNR_TBTT_INFO_LEN > 255 ||
+ tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+ break;
+
+ len += RNR_TBTT_INFO_LEN;
+ total_len += RNR_TBTT_INFO_LEN;
+ tbtt_count++;
+ }
+ start = i;
+ }
+
+ if (!tbtt_count)
+ total_len = 0;
+ else
+ *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;
case WLAN_FC_STYPE_BEACON:
if (hapd->conf->rnr)
total_len += hostapd_eid_nr_db_len(hapd, ¤t_len);
+ /* fallthrough */
+
+ case WLAN_FC_STYPE_PROBE_RESP:
+ if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+ total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+ ¤t_len);
break;
default:
}
+static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
+ struct hostapd_data *reporting_hapd,
+ u8 *eid, size_t *current_len)
+{
+ struct hostapd_data *bss;
+ struct hostapd_iface *iface = hapd->iface;
+ size_t i, start = 0;
+ size_t len = *current_len;
+ u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1;
+ u8 tbtt_count = 0, op_class, channel, bss_param;
+
+ if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
+ return eid;
+
+ 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;
+
+ while (start < iface->num_bss) {
+ if (!len ||
+ len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+ eid_start = eid;
+ *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
+ size_offset = eid++;
+ len = RNR_HEADER_LEN;
+ tbtt_count = 0;
+ }
+
+ tbtt_count_pos = eid++;
+ *eid++ = RNR_TBTT_INFO_LEN;
+ *eid++ = op_class;
+ *eid++ = hapd->iconf->channel;
+ len += RNR_TBTT_HEADER_LEN;
+
+ for (i = start; i < iface->num_bss; i++) {
+ bss_param = 0;
+ bss = iface->bss[i];
+ if (!bss || !bss->conf || !bss->started)
+ continue;
+
+ if (bss == reporting_hapd ||
+ bss->conf->ignore_broadcast_ssid)
+ continue;
+
+ if (len + RNR_TBTT_INFO_LEN > 255 ||
+ tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+ break;
+
+ *eid++ = RNR_NEIGHBOR_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 |= RNR_BSS_PARAM_SAME_SSID;
+
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ bss->conf->unsol_bcast_probe_resp_interval)
+ bss_param |=
+ RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE;
+
+ bss_param |= RNR_BSS_PARAM_CO_LOCATED;
+
+ *eid++ = bss_param;
+ *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
+ len += RNR_TBTT_INFO_LEN;
+ tbtt_count += 1;
+ }
+
+ start = i;
+ *tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
+ *size_offset = (eid - size_offset) - 1;
+ }
+
+ if (tbtt_count == 0)
+ return eid_start;
+
+ *current_len = len;
+ return eid;
+}
+
+
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
{
u8 *eid_start = eid;
case WLAN_FC_STYPE_BEACON:
if (hapd->conf->rnr)
eid = hostapd_eid_nr_db(hapd, eid, ¤t_len);
+ /* fallthrough */
+
+ case WLAN_FC_STYPE_PROBE_RESP:
+ if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+ eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+ ¤t_len);
break;
default: