Home | History | Annotate | Line # | Download | only in ap
      1 /*
      2  * hostapd / IEEE 802.11 Management
      3  * Copyright (c) 2002-2024, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "utils/includes.h"
     10 
     11 #include "utils/common.h"
     12 #include "common/ieee802_11_defs.h"
     13 #include "common/ocv.h"
     14 #include "common/wpa_ctrl.h"
     15 #include "hostapd.h"
     16 #include "sta_info.h"
     17 #include "ap_config.h"
     18 #include "ap_drv_ops.h"
     19 #include "wpa_auth.h"
     20 #include "dpp_hostapd.h"
     21 #include "ieee802_11.h"
     22 
     23 
     24 static u8 * hostapd_eid_timeout_interval(u8 *pos, u8 type, u32 value)
     25 {
     26 	*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
     27 	*pos++ = 5;
     28 	*pos++ = type;
     29 	WPA_PUT_LE32(pos, value);
     30 	pos += 4;
     31 
     32 	return pos;
     33 }
     34 
     35 
     36 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
     37 				     struct sta_info *sta, u8 *eid)
     38 {
     39 	u32 timeout, tu;
     40 	struct os_reltime now, passed;
     41 	u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
     42 
     43 	os_get_reltime(&now);
     44 	os_reltime_sub(&now, &sta->sa_query_start, &passed);
     45 	tu = (passed.sec * 1000000 + passed.usec) / 1024;
     46 	if (hapd->conf->assoc_sa_query_max_timeout > tu)
     47 		timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
     48 	else
     49 		timeout = 0;
     50 	if (timeout < hapd->conf->assoc_sa_query_max_timeout)
     51 		timeout++; /* add some extra time for local timers */
     52 
     53 #ifdef CONFIG_TESTING_OPTIONS
     54 	if (hapd->conf->test_assoc_comeback_type != -1)
     55 		type = hapd->conf->test_assoc_comeback_type;
     56 #endif /* CONFIG_TESTING_OPTIONS */
     57 	return hostapd_eid_timeout_interval(eid, type, timeout);
     58 }
     59 
     60 
     61 /* MLME-SAQuery.request */
     62 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
     63 				  const u8 *addr, const u8 *trans_id)
     64 {
     65 #if defined(CONFIG_OCV) || defined(CONFIG_IEEE80211BE)
     66 	struct sta_info *sta = ap_get_sta(hapd, addr);
     67 #endif /* CONFIG_OCV || CONFIG_IEEE80211BE */
     68 	struct ieee80211_mgmt *mgmt;
     69 	u8 *oci_ie = NULL;
     70 	u8 oci_ie_len = 0;
     71 	u8 *end;
     72 	const u8 *own_addr = hapd->own_addr;
     73 
     74 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
     75 		   MACSTR, MAC2STR(addr));
     76 	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
     77 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
     78 
     79 #ifdef CONFIG_OCV
     80 	if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
     81 		struct wpa_channel_info ci;
     82 
     83 		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
     84 			wpa_printf(MSG_WARNING,
     85 				   "Failed to get channel info for OCI element in SA Query Request");
     86 			return;
     87 		}
     88 #ifdef CONFIG_TESTING_OPTIONS
     89 		if (hapd->conf->oci_freq_override_saquery_req) {
     90 			wpa_printf(MSG_INFO,
     91 				   "TEST: Override OCI frequency %d -> %u MHz",
     92 				   ci.frequency,
     93 				   hapd->conf->oci_freq_override_saquery_req);
     94 			ci.frequency =
     95 				hapd->conf->oci_freq_override_saquery_req;
     96 		}
     97 #endif /* CONFIG_TESTING_OPTIONS */
     98 
     99 		oci_ie_len = OCV_OCI_EXTENDED_LEN;
    100 		oci_ie = os_zalloc(oci_ie_len);
    101 		if (!oci_ie) {
    102 			wpa_printf(MSG_WARNING,
    103 				   "Failed to allocate buffer for OCI element in SA Query Request");
    104 			return;
    105 		}
    106 
    107 		if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
    108 			os_free(oci_ie);
    109 			return;
    110 		}
    111 	}
    112 #endif /* CONFIG_OCV */
    113 
    114 	mgmt = os_zalloc(sizeof(*mgmt) + oci_ie_len);
    115 	if (!mgmt) {
    116 		wpa_printf(MSG_DEBUG,
    117 			   "Failed to allocate buffer for SA Query Response frame");
    118 		os_free(oci_ie);
    119 		return;
    120 	}
    121 
    122 #ifdef CONFIG_IEEE80211BE
    123 	if (ap_sta_is_mld(hapd, sta))
    124 		own_addr = hapd->mld->mld_addr;
    125 #endif /* CONFIG_IEEE80211BE */
    126 
    127 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    128 					   WLAN_FC_STYPE_ACTION);
    129 	os_memcpy(mgmt->da, addr, ETH_ALEN);
    130 	os_memcpy(mgmt->sa, own_addr, ETH_ALEN);
    131 	os_memcpy(mgmt->bssid, own_addr, ETH_ALEN);
    132 	mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
    133 	mgmt->u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
    134 	os_memcpy(mgmt->u.action.u.sa_query_req.trans_id, trans_id,
    135 		  WLAN_SA_QUERY_TR_ID_LEN);
    136 	end = mgmt->u.action.u.sa_query_req.variable;
    137 #ifdef CONFIG_OCV
    138 	if (oci_ie_len > 0) {
    139 		os_memcpy(end, oci_ie, oci_ie_len);
    140 		end += oci_ie_len;
    141 	}
    142 #endif /* CONFIG_OCV */
    143 	if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0, NULL, 0, 0)
    144 	    < 0)
    145 		wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed");
    146 
    147 	os_free(mgmt);
    148 	os_free(oci_ie);
    149 }
    150 
    151 
    152 static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
    153 					  const u8 *sa, const u8 *trans_id)
    154 {
    155 	struct sta_info *sta;
    156 	struct ieee80211_mgmt *resp;
    157 	u8 *oci_ie = NULL;
    158 	u8 oci_ie_len = 0;
    159 	u8 *end;
    160 	const u8 *own_addr = hapd->own_addr;
    161 
    162 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
    163 		   MACSTR, MAC2STR(sa));
    164 	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
    165 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
    166 
    167 	sta = ap_get_sta(hapd, sa);
    168 	if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
    169 		wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
    170 			   "from unassociated STA " MACSTR, MAC2STR(sa));
    171 		return;
    172 	}
    173 
    174 #ifdef CONFIG_OCV
    175 	if (wpa_auth_uses_ocv(sta->wpa_sm)) {
    176 		struct wpa_channel_info ci;
    177 
    178 		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
    179 			wpa_printf(MSG_WARNING,
    180 				   "Failed to get channel info for OCI element in SA Query Response");
    181 			return;
    182 		}
    183 #ifdef CONFIG_TESTING_OPTIONS
    184 		if (hapd->conf->oci_freq_override_saquery_resp) {
    185 			wpa_printf(MSG_INFO,
    186 				   "TEST: Override OCI frequency %d -> %u MHz",
    187 				   ci.frequency,
    188 				   hapd->conf->oci_freq_override_saquery_resp);
    189 			ci.frequency =
    190 				hapd->conf->oci_freq_override_saquery_resp;
    191 		}
    192 #endif /* CONFIG_TESTING_OPTIONS */
    193 
    194 		oci_ie_len = OCV_OCI_EXTENDED_LEN;
    195 		oci_ie = os_zalloc(oci_ie_len);
    196 		if (!oci_ie) {
    197 			wpa_printf(MSG_WARNING,
    198 				   "Failed to allocate buffer for for OCI element in SA Query Response");
    199 			return;
    200 		}
    201 
    202 		if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
    203 			os_free(oci_ie);
    204 			return;
    205 		}
    206 	}
    207 #endif /* CONFIG_OCV */
    208 
    209 	resp = os_zalloc(sizeof(*resp) + oci_ie_len);
    210 	if (!resp) {
    211 		wpa_printf(MSG_DEBUG,
    212 			   "Failed to allocate buffer for SA Query Response frame");
    213 		os_free(oci_ie);
    214 		return;
    215 	}
    216 
    217 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
    218 		   MACSTR, MAC2STR(sa));
    219 
    220 #ifdef CONFIG_IEEE80211BE
    221 	if (ap_sta_is_mld(hapd, sta))
    222 		own_addr = hapd->mld->mld_addr;
    223 #endif /* CONFIG_IEEE80211BE */
    224 
    225 	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    226 					   WLAN_FC_STYPE_ACTION);
    227 	os_memcpy(resp->da, sa, ETH_ALEN);
    228 	os_memcpy(resp->sa, own_addr, ETH_ALEN);
    229 	os_memcpy(resp->bssid, own_addr, ETH_ALEN);
    230 	resp->u.action.category = WLAN_ACTION_SA_QUERY;
    231 	resp->u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
    232 	os_memcpy(resp->u.action.u.sa_query_req.trans_id, trans_id,
    233 		  WLAN_SA_QUERY_TR_ID_LEN);
    234 	end = resp->u.action.u.sa_query_req.variable;
    235 #ifdef CONFIG_OCV
    236 	if (oci_ie_len > 0) {
    237 		os_memcpy(end, oci_ie, oci_ie_len);
    238 		end += oci_ie_len;
    239 	}
    240 #endif /* CONFIG_OCV */
    241 	if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0, NULL, 0, 0)
    242 	    < 0)
    243 		wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed");
    244 
    245 	os_free(resp);
    246 	os_free(oci_ie);
    247 }
    248 
    249 
    250 void ieee802_11_sa_query_action(struct hostapd_data *hapd,
    251 				const struct ieee80211_mgmt *mgmt,
    252 				size_t len)
    253 {
    254 	struct sta_info *sta;
    255 	int i;
    256 	const u8 *sa = mgmt->sa;
    257 	const u8 action_type = mgmt->u.action.u.sa_query_resp.action;
    258 	const u8 *trans_id = mgmt->u.action.u.sa_query_resp.trans_id;
    259 
    260 	if (((const u8 *) mgmt) + len <
    261 	    mgmt->u.action.u.sa_query_resp.variable) {
    262 		wpa_printf(MSG_DEBUG,
    263 			   "IEEE 802.11: Too short SA Query Action frame (len=%lu)",
    264 			   (unsigned long) len);
    265 		return;
    266 	}
    267 	if (is_multicast_ether_addr(mgmt->da)) {
    268 		wpa_printf(MSG_DEBUG,
    269 			   "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
    270 			   MAC2STR(mgmt->da), MAC2STR(mgmt->sa));
    271 		return;
    272 	}
    273 
    274 	sta = ap_get_sta(hapd, sa);
    275 
    276 #ifdef CONFIG_OCV
    277 	if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
    278 		struct ieee802_11_elems elems;
    279 		struct wpa_channel_info ci;
    280 		int tx_chanwidth;
    281 		int tx_seg1_idx;
    282 		size_t ies_len;
    283 		const u8 *ies;
    284 
    285 		ies = mgmt->u.action.u.sa_query_resp.variable;
    286 		ies_len = len - (ies - (u8 *) mgmt);
    287 		if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) ==
    288 		    ParseFailed) {
    289 			wpa_printf(MSG_DEBUG,
    290 				   "SA Query: Failed to parse elements");
    291 			return;
    292 		}
    293 
    294 		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
    295 			wpa_printf(MSG_WARNING,
    296 				   "Failed to get channel info to validate received OCI in SA Query Action frame");
    297 			return;
    298 		}
    299 
    300 		if (get_sta_tx_parameters(sta->wpa_sm,
    301 					  channel_width_to_int(ci.chanwidth),
    302 					  ci.seg1_idx, &tx_chanwidth,
    303 					  &tx_seg1_idx) < 0)
    304 			return;
    305 
    306 		if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
    307 					 tx_chanwidth, tx_seg1_idx) !=
    308 		    OCI_SUCCESS) {
    309 			wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr="
    310 				MACSTR " frame=saquery%s error=%s",
    311 				MAC2STR(sa),
    312 				action_type == WLAN_SA_QUERY_REQUEST ?
    313 				"req" : "resp", ocv_errorstr);
    314 			return;
    315 		}
    316 	}
    317 #endif /* CONFIG_OCV */
    318 
    319 	if (action_type == WLAN_SA_QUERY_REQUEST) {
    320 		if (sta)
    321 			sta->post_csa_sa_query = 0;
    322 		ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
    323 		return;
    324 	}
    325 
    326 	if (action_type != WLAN_SA_QUERY_RESPONSE) {
    327 		wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
    328 			   "Action %d", action_type);
    329 		return;
    330 	}
    331 
    332 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
    333 		   MACSTR, MAC2STR(sa));
    334 	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
    335 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
    336 
    337 	/* MLME-SAQuery.confirm */
    338 
    339 	if (sta == NULL || sta->sa_query_trans_id == NULL) {
    340 		wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
    341 			   "pending SA Query request found");
    342 		return;
    343 	}
    344 
    345 	for (i = 0; i < sta->sa_query_count; i++) {
    346 		if (os_memcmp(sta->sa_query_trans_id +
    347 			      i * WLAN_SA_QUERY_TR_ID_LEN,
    348 			      trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
    349 			break;
    350 	}
    351 
    352 	if (i >= sta->sa_query_count) {
    353 		wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
    354 			   "transaction identifier found");
    355 		return;
    356 	}
    357 
    358 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
    359 		       HOSTAPD_LEVEL_DEBUG,
    360 		       "Reply to pending SA Query received");
    361 	ap_sta_stop_sa_query(hapd, sta);
    362 }
    363 
    364 
    365 static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx,
    366 				   bool mbssid_complete)
    367 {
    368 	*pos = 0x00;
    369 
    370 	switch (idx) {
    371 	case 0: /* Bits 0-7 */
    372 		if (hapd->iconf->obss_interval)
    373 			*pos |= 0x01; /* Bit 0 - Coexistence management */
    374 		if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)
    375 			*pos |= 0x04; /* Bit 2 - Extended Channel Switching */
    376 		break;
    377 	case 1: /* Bits 8-15 */
    378 		if (hapd->conf->proxy_arp)
    379 			*pos |= 0x10; /* Bit 12 - Proxy ARP */
    380 		if (hapd->conf->coloc_intf_reporting) {
    381 			/* Bit 13 - Collocated Interference Reporting */
    382 			*pos |= 0x20;
    383 		}
    384 		break;
    385 	case 2: /* Bits 16-23 */
    386 		if (hapd->conf->wnm_sleep_mode)
    387 			*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
    388 		if (hapd->conf->bss_transition)
    389 			*pos |= 0x08; /* Bit 19 - BSS Transition */
    390 		if (hapd->iconf->mbssid)
    391 			*pos |= 0x40; /* Bit 22 - Multiple BSSID */
    392 		break;
    393 	case 3: /* Bits 24-31 */
    394 #ifdef CONFIG_WNM_AP
    395 		*pos |= 0x02; /* Bit 25 - SSID List */
    396 #endif /* CONFIG_WNM_AP */
    397 		if (hapd->conf->time_advertisement == 2)
    398 			*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
    399 		if (hapd->conf->interworking)
    400 			*pos |= 0x80; /* Bit 31 - Interworking */
    401 		break;
    402 	case 4: /* Bits 32-39 */
    403 		if (hapd->conf->qos_map_set_len)
    404 			*pos |= 0x01; /* Bit 32 - QoS Map */
    405 		if (hapd->conf->tdls & TDLS_PROHIBIT)
    406 			*pos |= 0x40; /* Bit 38 - TDLS Prohibited */
    407 		if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) {
    408 			/* Bit 39 - TDLS Channel Switching Prohibited */
    409 			*pos |= 0x80;
    410 		}
    411 		break;
    412 	case 5: /* Bits 40-47 */
    413 #ifdef CONFIG_HS20
    414 		if (hapd->conf->hs20)
    415 			*pos |= 0x40; /* Bit 46 - WNM-Notification */
    416 #endif /* CONFIG_HS20 */
    417 #ifdef CONFIG_MBO
    418 		if (hapd->conf->mbo_enabled)
    419 			*pos |= 0x40; /* Bit 46 - WNM-Notification */
    420 #endif /* CONFIG_MBO */
    421 		break;
    422 	case 6: /* Bits 48-55 */
    423 		if (hapd->conf->ssid.utf8_ssid)
    424 			*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
    425 		break;
    426 	case 7: /* Bits 56-63 */
    427 		break;
    428 	case 8: /* Bits 64-71 */
    429 		if (hapd->conf->ftm_responder)
    430 			*pos |= 0x40; /* Bit 70 - FTM responder */
    431 		if (hapd->conf->ftm_initiator)
    432 			*pos |= 0x80; /* Bit 71 - FTM initiator */
    433 		break;
    434 	case 9: /* Bits 72-79 */
    435 #ifdef CONFIG_FILS
    436 		if ((hapd->conf->wpa & WPA_PROTO_RSN) &&
    437 		    wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
    438 			*pos |= 0x01;
    439 #endif /* CONFIG_FILS */
    440 #ifdef CONFIG_IEEE80211AX
    441 		if (hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
    442 			*pos |= 0x40; /* Bit 78 - TWT responder */
    443 #endif /* CONFIG_IEEE80211AX */
    444 		if (hostapd_get_ht_vht_twt_responder(hapd))
    445 			*pos |= 0x40; /* Bit 78 - TWT responder */
    446 		break;
    447 	case 10: /* Bits 80-87 */
    448 #ifdef CONFIG_SAE
    449 		if (hapd->conf->wpa &&
    450 		    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
    451 			int in_use = hostapd_sae_pw_id_in_use(hapd->conf);
    452 
    453 			if (in_use)
    454 				*pos |= 0x02; /* Bit 81 - SAE Password
    455 					       * Identifiers In Use */
    456 			if (in_use == 2)
    457 				*pos |= 0x04; /* Bit 82 - SAE Password
    458 					       * Identifiers Used Exclusively */
    459 		}
    460 #endif /* CONFIG_SAE */
    461 		if (hapd->conf->beacon_prot &&
    462 		    (hapd->iface->drv_flags &
    463 		     WPA_DRIVER_FLAGS_BEACON_PROTECTION))
    464 			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
    465 		if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
    466 			*pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
    467 		if (mbssid_complete)
    468 			*pos |= 0x01; /* Bit 80 - Complete List of NonTxBSSID
    469 				       * Profiles */
    470 		break;
    471 	case 11: /* Bits 88-95 */
    472 #ifdef CONFIG_SAE_PK
    473 		if (hapd->conf->wpa &&
    474 		    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
    475 		    hostapd_sae_pk_exclusively(hapd->conf))
    476 			*pos |= 0x01; /* Bit 88 - SAE PK Exclusively */
    477 #endif /* CONFIG_SAE_PK */
    478 		break;
    479 	}
    480 }
    481 
    482 
    483 u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid,
    484 			   bool mbssid_complete)
    485 {
    486 	u8 *pos = eid;
    487 	u8 len = EXT_CAPA_MAX_LEN, i;
    488 
    489 	if (len < hapd->iface->extended_capa_len)
    490 		len = hapd->iface->extended_capa_len;
    491 
    492 	*pos++ = WLAN_EID_EXT_CAPAB;
    493 	*pos++ = len;
    494 	for (i = 0; i < len; i++, pos++) {
    495 		hostapd_ext_capab_byte(hapd, pos, i, mbssid_complete);
    496 
    497 		if (i < hapd->iface->extended_capa_len) {
    498 			*pos &= ~hapd->iface->extended_capa_mask[i];
    499 			*pos |= hapd->iface->extended_capa[i];
    500 		}
    501 
    502 		if (i < EXT_CAPA_MAX_LEN) {
    503 			*pos &= ~hapd->conf->ext_capa_mask[i];
    504 			*pos |= hapd->conf->ext_capa[i];
    505 		}
    506 
    507 		/* Clear bits 83 and 22 if EMA and MBSSID are not enabled
    508 		 * otherwise association fails with some clients */
    509 		if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
    510 			*pos &= ~0x08;
    511 		if (i == 2 && !hapd->iconf->mbssid)
    512 			*pos &= ~0x40;
    513 	}
    514 
    515 	while (len > 0 && eid[1 + len] == 0) {
    516 		len--;
    517 		eid[1] = len;
    518 	}
    519 	if (len == 0)
    520 		return eid;
    521 
    522 	return eid + 2 + len;
    523 }
    524 
    525 
    526 u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid)
    527 {
    528 	u8 *pos = eid;
    529 	u8 len = hapd->conf->qos_map_set_len;
    530 
    531 	if (!len)
    532 		return eid;
    533 
    534 	*pos++ = WLAN_EID_QOS_MAP_SET;
    535 	*pos++ = len;
    536 	os_memcpy(pos, hapd->conf->qos_map_set, len);
    537 	pos += len;
    538 
    539 	return pos;
    540 }
    541 
    542 
    543 u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
    544 {
    545 	u8 *pos = eid;
    546 #ifdef CONFIG_INTERWORKING
    547 	u8 *len;
    548 
    549 	if (!hapd->conf->interworking)
    550 		return eid;
    551 
    552 	*pos++ = WLAN_EID_INTERWORKING;
    553 	len = pos++;
    554 
    555 	*pos = hapd->conf->access_network_type;
    556 	if (hapd->conf->internet)
    557 		*pos |= INTERWORKING_ANO_INTERNET;
    558 	if (hapd->conf->asra)
    559 		*pos |= INTERWORKING_ANO_ASRA;
    560 	if (hapd->conf->esr)
    561 		*pos |= INTERWORKING_ANO_ESR;
    562 	if (hapd->conf->uesa)
    563 		*pos |= INTERWORKING_ANO_UESA;
    564 	pos++;
    565 
    566 	if (hapd->conf->venue_info_set) {
    567 		*pos++ = hapd->conf->venue_group;
    568 		*pos++ = hapd->conf->venue_type;
    569 	}
    570 
    571 	if (!is_zero_ether_addr(hapd->conf->hessid)) {
    572 		os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
    573 		pos += ETH_ALEN;
    574 	}
    575 
    576 	*len = pos - len - 1;
    577 #endif /* CONFIG_INTERWORKING */
    578 
    579 	return pos;
    580 }
    581 
    582 
    583 u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid)
    584 {
    585 	u8 *pos = eid;
    586 #ifdef CONFIG_INTERWORKING
    587 
    588 	/* TODO: Separate configuration for ANQP? */
    589 	if (!hapd->conf->interworking)
    590 		return eid;
    591 
    592 	*pos++ = WLAN_EID_ADV_PROTO;
    593 	*pos++ = 2;
    594 	*pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */
    595 	*pos++ = ACCESS_NETWORK_QUERY_PROTOCOL;
    596 #endif /* CONFIG_INTERWORKING */
    597 
    598 	return pos;
    599 }
    600 
    601 
    602 u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid)
    603 {
    604 	u8 *pos = eid;
    605 #ifdef CONFIG_INTERWORKING
    606 	u8 *len;
    607 	unsigned int i, count;
    608 
    609 	if (!hapd->conf->interworking ||
    610 	    hapd->conf->roaming_consortium == NULL ||
    611 	    hapd->conf->roaming_consortium_count == 0)
    612 		return eid;
    613 
    614 	*pos++ = WLAN_EID_ROAMING_CONSORTIUM;
    615 	len = pos++;
    616 
    617 	/* Number of ANQP OIs (in addition to the max 3 listed here) */
    618 	if (hapd->conf->roaming_consortium_count > 3 + 255)
    619 		*pos++ = 255;
    620 	else if (hapd->conf->roaming_consortium_count > 3)
    621 		*pos++ = hapd->conf->roaming_consortium_count - 3;
    622 	else
    623 		*pos++ = 0;
    624 
    625 	/* OU #1 and #2 Lengths */
    626 	*pos = hapd->conf->roaming_consortium[0].len;
    627 	if (hapd->conf->roaming_consortium_count > 1)
    628 		*pos |= hapd->conf->roaming_consortium[1].len << 4;
    629 	pos++;
    630 
    631 	if (hapd->conf->roaming_consortium_count > 3)
    632 		count = 3;
    633 	else
    634 		count = hapd->conf->roaming_consortium_count;
    635 
    636 	for (i = 0; i < count; i++) {
    637 		os_memcpy(pos, hapd->conf->roaming_consortium[i].oi,
    638 			  hapd->conf->roaming_consortium[i].len);
    639 		pos += hapd->conf->roaming_consortium[i].len;
    640 	}
    641 
    642 	*len = pos - len - 1;
    643 #endif /* CONFIG_INTERWORKING */
    644 
    645 	return pos;
    646 }
    647 
    648 
    649 u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid)
    650 {
    651 	if (hapd->conf->time_advertisement != 2)
    652 		return eid;
    653 
    654 	if (hapd->time_adv == NULL &&
    655 	    hostapd_update_time_adv(hapd) < 0)
    656 		return eid;
    657 
    658 	if (hapd->time_adv == NULL)
    659 		return eid;
    660 
    661 	os_memcpy(eid, wpabuf_head(hapd->time_adv),
    662 		  wpabuf_len(hapd->time_adv));
    663 	eid += wpabuf_len(hapd->time_adv);
    664 
    665 	return eid;
    666 }
    667 
    668 
    669 u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
    670 {
    671 	size_t len;
    672 
    673 	if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone)
    674 		return eid;
    675 
    676 	len = os_strlen(hapd->conf->time_zone);
    677 
    678 	*eid++ = WLAN_EID_TIME_ZONE;
    679 	*eid++ = len;
    680 	os_memcpy(eid, hapd->conf->time_zone, len);
    681 	eid += len;
    682 
    683 	return eid;
    684 }
    685 
    686 
    687 int hostapd_update_time_adv(struct hostapd_data *hapd)
    688 {
    689 	const int elen = 2 + 1 + 10 + 5 + 1;
    690 	struct os_time t;
    691 	struct os_tm tm;
    692 	u8 *pos;
    693 
    694 	if (hapd->conf->time_advertisement != 2)
    695 		return 0;
    696 
    697 	if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0)
    698 		return -1;
    699 
    700 	if (!hapd->time_adv) {
    701 		hapd->time_adv = wpabuf_alloc(elen);
    702 		if (hapd->time_adv == NULL)
    703 			return -1;
    704 		pos = wpabuf_put(hapd->time_adv, elen);
    705 	} else
    706 		pos = wpabuf_mhead_u8(hapd->time_adv);
    707 
    708 	*pos++ = WLAN_EID_TIME_ADVERTISEMENT;
    709 	*pos++ = 1 + 10 + 5 + 1;
    710 
    711 	*pos++ = 2; /* UTC time at which the TSF timer is 0 */
    712 
    713 	/* Time Value at TSF 0 */
    714 	/* FIX: need to calculate this based on the current TSF value */
    715 	WPA_PUT_LE16(pos, tm.year); /* Year */
    716 	pos += 2;
    717 	*pos++ = tm.month; /* Month */
    718 	*pos++ = tm.day; /* Day of month */
    719 	*pos++ = tm.hour; /* Hours */
    720 	*pos++ = tm.min; /* Minutes */
    721 	*pos++ = tm.sec; /* Seconds */
    722 	WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */
    723 	pos += 2;
    724 	*pos++ = 0; /* Reserved */
    725 
    726 	/* Time Error */
    727 	/* TODO: fill in an estimate on the error */
    728 	*pos++ = 0;
    729 	*pos++ = 0;
    730 	*pos++ = 0;
    731 	*pos++ = 0;
    732 	*pos++ = 0;
    733 
    734 	*pos++ = hapd->time_update_counter++;
    735 
    736 	return 0;
    737 }
    738 
    739 
    740 u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid,
    741 				     u16 value)
    742 {
    743 	u8 *pos = eid;
    744 
    745 #ifdef CONFIG_WNM_AP
    746 	if (hapd->conf->ap_max_inactivity > 0 &&
    747 	    hapd->conf->bss_max_idle) {
    748 		unsigned int val;
    749 		*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
    750 		*pos++ = 3;
    751 		val = hapd->conf->ap_max_inactivity;
    752 		if (val > 68000)
    753 			val = 68000;
    754 		val *= 1000;
    755 		val /= 1024;
    756 		if (val == 0)
    757 			val = 1;
    758 		if (val > 65535)
    759 			val = 65535;
    760 		if (value)
    761 			val = value;
    762 		WPA_PUT_LE16(pos, val);
    763 		pos += 2;
    764 		/* Set the Protected Keep-Alive Required bit based on
    765 		 * configuration */
    766 		*pos++ = hapd->conf->bss_max_idle == 2 ? BIT(0) : 0x00;
    767 	}
    768 #endif /* CONFIG_WNM_AP */
    769 
    770 	return pos;
    771 }
    772 
    773 
    774 #ifdef CONFIG_MBO
    775 
    776 u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid,
    777 				    size_t len, int delta)
    778 {
    779 	u8 mbo[4];
    780 
    781 	mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT;
    782 	mbo[1] = 2;
    783 	/* Delta RSSI */
    784 	mbo[2] = delta;
    785 	/* Retry delay */
    786 	mbo[3] = hapd->iconf->rssi_reject_assoc_timeout;
    787 
    788 	return eid + mbo_add_ie(eid, len, mbo, 4);
    789 }
    790 
    791 
    792 u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
    793 {
    794 	u8 mbo[9], *mbo_pos = mbo;
    795 	u8 *pos = eid;
    796 
    797 	if (!hapd->conf->mbo_enabled &&
    798 	    !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
    799 		return eid;
    800 
    801 	if (hapd->conf->mbo_enabled) {
    802 		*mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
    803 		*mbo_pos++ = 1;
    804 		/* Not Cellular aware */
    805 		*mbo_pos++ = 0;
    806 	}
    807 
    808 	if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
    809 		*mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW;
    810 		*mbo_pos++ = 1;
    811 		*mbo_pos++ = hapd->mbo_assoc_disallow;
    812 	}
    813 
    814 	if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
    815 		u8 ctrl;
    816 
    817 		ctrl = OCE_RELEASE;
    818 		if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
    819 			ctrl |= OCE_IS_STA_CFON;
    820 
    821 		*mbo_pos++ = OCE_ATTR_ID_CAPA_IND;
    822 		*mbo_pos++ = 1;
    823 		*mbo_pos++ = ctrl;
    824 	}
    825 
    826 	pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo);
    827 
    828 	return pos;
    829 }
    830 
    831 
    832 u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
    833 {
    834 	u8 len;
    835 
    836 	if (!hapd->conf->mbo_enabled &&
    837 	    !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
    838 		return 0;
    839 
    840 	/*
    841 	 * MBO IE header (6) + Capability Indication attribute (3) +
    842 	 * Association Disallowed attribute (3) = 12
    843 	 */
    844 	len = 6;
    845 	if (hapd->conf->mbo_enabled)
    846 		len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
    847 
    848 	/* OCE capability indication attribute (3) */
    849 	if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd))
    850 		len += 3;
    851 
    852 	return len;
    853 }
    854 
    855 #endif /* CONFIG_MBO */
    856 
    857 
    858 #ifdef CONFIG_OWE
    859 static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd)
    860 {
    861 	return hapd->conf->owe_transition_ssid_len > 0 &&
    862 		!is_zero_ether_addr(hapd->conf->owe_transition_bssid);
    863 }
    864 #endif /* CONFIG_OWE */
    865 
    866 
    867 size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd)
    868 {
    869 #ifdef CONFIG_OWE
    870 	if (!hostapd_eid_owe_trans_enabled(hapd))
    871 		return 0;
    872 	return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len;
    873 #else /* CONFIG_OWE */
    874 	return 0;
    875 #endif /* CONFIG_OWE */
    876 }
    877 
    878 
    879 u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid,
    880 				  size_t len)
    881 {
    882 #ifdef CONFIG_OWE
    883 	u8 *pos = eid;
    884 	size_t elen;
    885 
    886 	if (hapd->conf->owe_transition_ifname[0] &&
    887 	    !hostapd_eid_owe_trans_enabled(hapd))
    888 		hostapd_owe_trans_get_info(hapd);
    889 
    890 	if (!hostapd_eid_owe_trans_enabled(hapd))
    891 		return pos;
    892 
    893 	elen = hostapd_eid_owe_trans_len(hapd);
    894 	if (len < elen) {
    895 		wpa_printf(MSG_DEBUG,
    896 			   "OWE: Not enough room in the buffer for OWE IE");
    897 		return pos;
    898 	}
    899 
    900 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
    901 	*pos++ = elen - 2;
    902 	WPA_PUT_BE24(pos, OUI_WFA);
    903 	pos += 3;
    904 	*pos++ = OWE_OUI_TYPE;
    905 	os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN);
    906 	pos += ETH_ALEN;
    907 	*pos++ = hapd->conf->owe_transition_ssid_len;
    908 	os_memcpy(pos, hapd->conf->owe_transition_ssid,
    909 		  hapd->conf->owe_transition_ssid_len);
    910 	pos += hapd->conf->owe_transition_ssid_len;
    911 
    912 	return pos;
    913 #else /* CONFIG_OWE */
    914 	return eid;
    915 #endif /* CONFIG_OWE */
    916 }
    917 
    918 
    919 size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd)
    920 {
    921 #ifdef CONFIG_DPP2
    922 	if (hostapd_dpp_configurator_connectivity(hapd))
    923 		return 6;
    924 #endif /* CONFIG_DPP2 */
    925 	return 0;
    926 }
    927 
    928 
    929 u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len)
    930 {
    931 	u8 *pos = eid;
    932 
    933 #ifdef CONFIG_DPP2
    934 	if (!hostapd_dpp_configurator_connectivity(hapd) || len < 6)
    935 		return pos;
    936 
    937 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
    938 	*pos++ = 4;
    939 	WPA_PUT_BE24(pos, OUI_WFA);
    940 	pos += 3;
    941 	*pos++ = DPP_CC_OUI_TYPE;
    942 #endif /* CONFIG_DPP2 */
    943 
    944 	return pos;
    945 }
    946 
    947 
    948 void ap_copy_sta_supp_op_classes(struct sta_info *sta,
    949 				 const u8 *supp_op_classes,
    950 				 size_t supp_op_classes_len)
    951 {
    952 	if (!supp_op_classes)
    953 		return;
    954 	os_free(sta->supp_op_classes);
    955 	sta->supp_op_classes = os_malloc(1 + supp_op_classes_len);
    956 	if (!sta->supp_op_classes)
    957 		return;
    958 
    959 	sta->supp_op_classes[0] = supp_op_classes_len;
    960 	os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
    961 		  supp_op_classes_len);
    962 }
    963 
    964 
    965 u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid)
    966 {
    967 	u8 *pos = eid;
    968 #ifdef CONFIG_FILS
    969 	u8 *len;
    970 	u16 fils_info = 0;
    971 	size_t realms;
    972 	struct fils_realm *realm;
    973 
    974 	if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
    975 	    !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
    976 		return pos;
    977 
    978 	realms = dl_list_len(&hapd->conf->fils_realms);
    979 	if (realms > 7)
    980 		realms = 7; /* 3 bit count field limits this to max 7 */
    981 
    982 	*pos++ = WLAN_EID_FILS_INDICATION;
    983 	len = pos++;
    984 	/* TODO: B0..B2: Number of Public Key Identifiers */
    985 	if (hapd->conf->erp_domain) {
    986 		/* B3..B5: Number of Realm Identifiers */
    987 		fils_info |= realms << 3;
    988 	}
    989 	/* TODO: B6: FILS IP Address Configuration */
    990 	if (hapd->conf->fils_cache_id_set)
    991 		fils_info |= BIT(7);
    992 	if (hessid && !is_zero_ether_addr(hapd->conf->hessid))
    993 		fils_info |= BIT(8); /* HESSID Included */
    994 	/* FILS Shared Key Authentication without PFS Supported */
    995 	fils_info |= BIT(9);
    996 	if (hapd->conf->fils_dh_group) {
    997 		/* FILS Shared Key Authentication with PFS Supported */
    998 		fils_info |= BIT(10);
    999 	}
   1000 	/* TODO: B11: FILS Public Key Authentication Supported */
   1001 	/* B12..B15: Reserved */
   1002 	WPA_PUT_LE16(pos, fils_info);
   1003 	pos += 2;
   1004 	if (hapd->conf->fils_cache_id_set) {
   1005 		os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN);
   1006 		pos += FILS_CACHE_ID_LEN;
   1007 	}
   1008 	if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) {
   1009 		os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
   1010 		pos += ETH_ALEN;
   1011 	}
   1012 
   1013 	dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm,
   1014 			 list) {
   1015 		if (realms == 0)
   1016 			break;
   1017 		realms--;
   1018 		os_memcpy(pos, realm->hash, 2);
   1019 		pos += 2;
   1020 	}
   1021 	*len = pos - len - 1;
   1022 #endif /* CONFIG_FILS */
   1023 
   1024 	return pos;
   1025 }
   1026 
   1027 
   1028 #ifdef CONFIG_OCV
   1029 int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
   1030 		      int ap_seg1_idx, int *bandwidth, int *seg1_idx)
   1031 {
   1032 	int ht_40mhz = 0;
   1033 	int vht_80p80 = 0;
   1034 	int requested_bw;
   1035 
   1036 	if (sta->ht_capabilities)
   1037 		ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info &
   1038 			      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
   1039 
   1040 	if (sta->vht_operation) {
   1041 		struct ieee80211_vht_operation *oper = sta->vht_operation;
   1042 
   1043 		/*
   1044 		 * If a VHT Operation element was present, use it to determine
   1045 		 * the supported channel bandwidth.
   1046 		 */
   1047 		if (oper->vht_op_info_chwidth == CHANWIDTH_USE_HT) {
   1048 			requested_bw = ht_40mhz ? 40 : 20;
   1049 		} else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0) {
   1050 			requested_bw = 80;
   1051 		} else {
   1052 			int diff;
   1053 
   1054 			requested_bw = 160;
   1055 			diff = abs((int)
   1056 				   oper->vht_op_info_chan_center_freq_seg0_idx -
   1057 				   (int)
   1058 				   oper->vht_op_info_chan_center_freq_seg1_idx);
   1059 			vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx
   1060 				!= 0 &&	diff > 16;
   1061 		}
   1062 	} else if (sta->vht_capabilities) {
   1063 		struct ieee80211_vht_capabilities *capab;
   1064 		int vht_chanwidth;
   1065 
   1066 		capab = sta->vht_capabilities;
   1067 
   1068 		/*
   1069 		 * If only the VHT Capabilities element is present (e.g., for
   1070 		 * normal clients), use it to determine the supported channel
   1071 		 * bandwidth.
   1072 		 */
   1073 		vht_chanwidth = capab->vht_capabilities_info &
   1074 			VHT_CAP_SUPP_CHAN_WIDTH_MASK;
   1075 		vht_80p80 = capab->vht_capabilities_info &
   1076 			VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
   1077 
   1078 		/* TODO: Also take into account Extended NSS BW Support field */
   1079 		requested_bw = vht_chanwidth ? 160 : 80;
   1080 	} else {
   1081 		requested_bw = ht_40mhz ? 40 : 20;
   1082 	}
   1083 
   1084 	*bandwidth = requested_bw < ap_max_chanwidth ?
   1085 		requested_bw : ap_max_chanwidth;
   1086 
   1087 	*seg1_idx = 0;
   1088 	if (ap_seg1_idx && vht_80p80)
   1089 		*seg1_idx = ap_seg1_idx;
   1090 
   1091 	return 0;
   1092 }
   1093 #endif /* CONFIG_OCV */
   1094 
   1095 
   1096 u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
   1097 {
   1098 	u8 *pos = eid;
   1099 	bool sae_pk = false;
   1100 	u32 capab = 0, tmp;
   1101 	size_t flen;
   1102 
   1103 	if (!(hapd->conf->wpa & WPA_PROTO_RSN))
   1104 		return eid;
   1105 
   1106 #ifdef CONFIG_SAE_PK
   1107 	sae_pk = hostapd_sae_pk_in_use(hapd->conf);
   1108 #endif /* CONFIG_SAE_PK */
   1109 
   1110 	if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
   1111 	    (hapd->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
   1112 	     hapd->conf->sae_pwe == SAE_PWE_BOTH ||
   1113 	     hostapd_sae_pw_id_in_use(hapd->conf) || sae_pk ||
   1114 	     wpa_key_mgmt_sae_ext_key(hapd->conf->wpa_key_mgmt)) &&
   1115 	    hapd->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK) {
   1116 		capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
   1117 #ifdef CONFIG_SAE_PK
   1118 		if (sae_pk)
   1119 			capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
   1120 #endif /* CONFIG_SAE_PK */
   1121 	}
   1122 
   1123 	if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_AP)
   1124 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
   1125 	if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_AP)
   1126 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
   1127 	if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP)
   1128 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
   1129 	if (hapd->conf->ssid_protection)
   1130 		capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
   1131 
   1132 	if (!capab)
   1133 		return eid; /* no supported extended RSN capabilities */
   1134 	tmp = capab;
   1135 	flen = 0;
   1136 	while (tmp) {
   1137 		flen++;
   1138 		tmp >>= 8;
   1139 	}
   1140 
   1141 	if (len < 2 + flen)
   1142 		return eid; /* no supported extended RSN capabilities */
   1143 	capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
   1144 
   1145 	*pos++ = WLAN_EID_RSNX;
   1146 	*pos++ = flen;
   1147 	while (capab) {
   1148 		*pos++ = capab & 0xff;
   1149 		capab >>= 8;
   1150 	}
   1151 
   1152 	return pos;
   1153 }
   1154 
   1155 
   1156 u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
   1157 		    const u8 *ext_capab_ie, size_t ext_capab_ie_len)
   1158 {
   1159 	/* check for QoS Map support */
   1160 	if (ext_capab_ie_len >= 5) {
   1161 		if (ext_capab_ie[4] & 0x01)
   1162 			sta->qos_map_enabled = 1;
   1163 	}
   1164 
   1165 	if (ext_capab_ie_len > 0) {
   1166 		sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
   1167 		os_free(sta->ext_capability);
   1168 		sta->ext_capability = os_malloc(1 + ext_capab_ie_len);
   1169 		if (sta->ext_capability) {
   1170 			sta->ext_capability[0] = ext_capab_ie_len;
   1171 			os_memcpy(sta->ext_capability + 1, ext_capab_ie,
   1172 				  ext_capab_ie_len);
   1173 		}
   1174 	}
   1175 
   1176 	return WLAN_STATUS_SUCCESS;
   1177 }
   1178 
   1179 
   1180 struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
   1181 					   struct sta_info *sta,
   1182 					   struct hostapd_data **assoc_hapd)
   1183 {
   1184 #ifdef CONFIG_IEEE80211BE
   1185 	struct hostapd_data *other_hapd = NULL;
   1186 	struct sta_info *tmp_sta;
   1187 
   1188 	if (!ap_sta_is_mld(hapd, sta))
   1189 		return NULL;
   1190 
   1191 	*assoc_hapd = hapd;
   1192 
   1193 	/* The station is the one on which the association was performed */
   1194 	if (sta->mld_assoc_link_id == hapd->mld_link_id)
   1195 		return sta;
   1196 
   1197 	other_hapd = hostapd_mld_get_link_bss(hapd, sta->mld_assoc_link_id);
   1198 	if (!other_hapd) {
   1199 		wpa_printf(MSG_DEBUG, "MLD: No link match for link_id=%u",
   1200 			   sta->mld_assoc_link_id);
   1201 		return sta;
   1202 	}
   1203 
   1204 	/*
   1205 	 * Iterate over the stations and find the one with the matching link ID
   1206 	 * and association ID.
   1207 	 */
   1208 	for (tmp_sta = other_hapd->sta_list; tmp_sta; tmp_sta = tmp_sta->next) {
   1209 		if (tmp_sta->mld_assoc_link_id == sta->mld_assoc_link_id &&
   1210 		    tmp_sta->aid == sta->aid) {
   1211 			*assoc_hapd = other_hapd;
   1212 			return tmp_sta;
   1213 		}
   1214 	}
   1215 #endif /* CONFIG_IEEE80211BE */
   1216 
   1217 	return sta;
   1218 }
   1219 
   1220 
   1221 bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd)
   1222 {
   1223 	return hapd->iconf->ht_vht_twt_responder &&
   1224 		((hapd->iconf->ieee80211n && !hapd->conf->disable_11n) ||
   1225 		 (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)) &&
   1226 		(hapd->iface->drv_flags2 &
   1227 		 WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER);
   1228 }
   1229