1 /* 2 * hostapd / IEEE 802.11 Management 3 * Copyright (c) 2002-2024, Jouni Malinen <j@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 hostapd_eid_timeout_interval(u8 * pos,u8 type,u32 value)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 hostapd_eid_assoc_comeback_time(struct hostapd_data * hapd,struct sta_info * sta,u8 * eid)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 */ ieee802_11_send_sa_query_req(struct hostapd_data * hapd,const u8 * addr,const u8 * trans_id)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 ieee802_11_send_sa_query_resp(struct hostapd_data * hapd,const u8 * sa,const u8 * trans_id)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 ieee802_11_sa_query_action(struct hostapd_data * hapd,const struct ieee80211_mgmt * mgmt,size_t len)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 hostapd_ext_capab_byte(struct hostapd_data * hapd,u8 * pos,int idx,bool mbssid_complete)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 case 12: /* Bits 96-103 */ 480 if (hapd->iconf->peer_to_peer_twt) 481 *pos |= 0x10; /* Bit 100 - Peer to Peer TWT */ 482 if (hapd->conf->known_sta_identification) 483 *pos |= 0x40; /* Bit 102 - Known STA Identification 484 * Enabled */ 485 break; 486 case 13: /* Bits 104-111 */ 487 if (hapd->iconf->channel_usage) 488 *pos |= 0x01; /* Bit 104 - Channel Usage support */ 489 break; 490 } 491 } 492 493 hostapd_eid_ext_capab(struct hostapd_data * hapd,u8 * eid,bool mbssid_complete)494 u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid, 495 bool mbssid_complete) 496 { 497 u8 *pos = eid; 498 u8 len = EXT_CAPA_MAX_LEN, i; 499 500 if (len < hapd->iface->extended_capa_len) 501 len = hapd->iface->extended_capa_len; 502 503 *pos++ = WLAN_EID_EXT_CAPAB; 504 *pos++ = len; 505 for (i = 0; i < len; i++, pos++) { 506 hostapd_ext_capab_byte(hapd, pos, i, mbssid_complete); 507 508 if (i < hapd->iface->extended_capa_len) { 509 *pos &= ~hapd->iface->extended_capa_mask[i]; 510 *pos |= hapd->iface->extended_capa[i]; 511 } 512 513 if (i < EXT_CAPA_MAX_LEN) { 514 *pos &= ~hapd->conf->ext_capa_mask[i]; 515 *pos |= hapd->conf->ext_capa[i]; 516 } 517 518 /* Clear bits 83 and 22 if EMA and MBSSID are not enabled 519 * otherwise association fails with some clients */ 520 if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED) 521 *pos &= ~0x08; 522 if (i == 2 && !hapd->iconf->mbssid) 523 *pos &= ~0x40; 524 } 525 526 while (len > 0 && eid[1 + len] == 0) { 527 len--; 528 eid[1] = len; 529 } 530 if (len == 0) 531 return eid; 532 533 return eid + 2 + len; 534 } 535 536 hostapd_eid_qos_map_set(struct hostapd_data * hapd,u8 * eid)537 u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid) 538 { 539 u8 *pos = eid; 540 u8 len = hapd->conf->qos_map_set_len; 541 542 if (!len) 543 return eid; 544 545 *pos++ = WLAN_EID_QOS_MAP_SET; 546 *pos++ = len; 547 os_memcpy(pos, hapd->conf->qos_map_set, len); 548 pos += len; 549 550 return pos; 551 } 552 553 hostapd_eid_interworking(struct hostapd_data * hapd,u8 * eid)554 u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) 555 { 556 u8 *pos = eid; 557 #ifdef CONFIG_INTERWORKING 558 u8 *len; 559 560 if (!hapd->conf->interworking) 561 return eid; 562 563 *pos++ = WLAN_EID_INTERWORKING; 564 len = pos++; 565 566 *pos = hapd->conf->access_network_type; 567 if (hapd->conf->internet) 568 *pos |= INTERWORKING_ANO_INTERNET; 569 if (hapd->conf->asra) 570 *pos |= INTERWORKING_ANO_ASRA; 571 if (hapd->conf->esr) 572 *pos |= INTERWORKING_ANO_ESR; 573 if (hapd->conf->uesa) 574 *pos |= INTERWORKING_ANO_UESA; 575 pos++; 576 577 if (hapd->conf->venue_info_set) { 578 *pos++ = hapd->conf->venue_group; 579 *pos++ = hapd->conf->venue_type; 580 } 581 582 if (!is_zero_ether_addr(hapd->conf->hessid)) { 583 os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 584 pos += ETH_ALEN; 585 } 586 587 *len = pos - len - 1; 588 #endif /* CONFIG_INTERWORKING */ 589 590 return pos; 591 } 592 593 hostapd_eid_adv_proto(struct hostapd_data * hapd,u8 * eid)594 u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid) 595 { 596 u8 *pos = eid; 597 #ifdef CONFIG_INTERWORKING 598 599 /* TODO: Separate configuration for ANQP? */ 600 if (!hapd->conf->interworking) 601 return eid; 602 603 *pos++ = WLAN_EID_ADV_PROTO; 604 *pos++ = 2; 605 *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */ 606 *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL; 607 #endif /* CONFIG_INTERWORKING */ 608 609 return pos; 610 } 611 612 hostapd_eid_roaming_consortium(struct hostapd_data * hapd,u8 * eid)613 u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) 614 { 615 u8 *pos = eid; 616 #ifdef CONFIG_INTERWORKING 617 u8 *len; 618 unsigned int i, count; 619 620 if (!hapd->conf->interworking || 621 hapd->conf->roaming_consortium == NULL || 622 hapd->conf->roaming_consortium_count == 0) 623 return eid; 624 625 *pos++ = WLAN_EID_ROAMING_CONSORTIUM; 626 len = pos++; 627 628 /* Number of ANQP OIs (in addition to the max 3 listed here) */ 629 if (hapd->conf->roaming_consortium_count > 3 + 255) 630 *pos++ = 255; 631 else if (hapd->conf->roaming_consortium_count > 3) 632 *pos++ = hapd->conf->roaming_consortium_count - 3; 633 else 634 *pos++ = 0; 635 636 /* OU #1 and #2 Lengths */ 637 *pos = hapd->conf->roaming_consortium[0].len; 638 if (hapd->conf->roaming_consortium_count > 1) 639 *pos |= hapd->conf->roaming_consortium[1].len << 4; 640 pos++; 641 642 if (hapd->conf->roaming_consortium_count > 3) 643 count = 3; 644 else 645 count = hapd->conf->roaming_consortium_count; 646 647 for (i = 0; i < count; i++) { 648 os_memcpy(pos, hapd->conf->roaming_consortium[i].oi, 649 hapd->conf->roaming_consortium[i].len); 650 pos += hapd->conf->roaming_consortium[i].len; 651 } 652 653 *len = pos - len - 1; 654 #endif /* CONFIG_INTERWORKING */ 655 656 return pos; 657 } 658 659 hostapd_eid_time_adv(struct hostapd_data * hapd,u8 * eid)660 u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) 661 { 662 if (hapd->conf->time_advertisement != 2) 663 return eid; 664 665 if (hapd->time_adv == NULL && 666 hostapd_update_time_adv(hapd) < 0) 667 return eid; 668 669 if (hapd->time_adv == NULL) 670 return eid; 671 672 os_memcpy(eid, wpabuf_head(hapd->time_adv), 673 wpabuf_len(hapd->time_adv)); 674 eid += wpabuf_len(hapd->time_adv); 675 676 return eid; 677 } 678 679 hostapd_eid_time_zone(struct hostapd_data * hapd,u8 * eid)680 u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) 681 { 682 size_t len; 683 684 if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone) 685 return eid; 686 687 len = os_strlen(hapd->conf->time_zone); 688 689 *eid++ = WLAN_EID_TIME_ZONE; 690 *eid++ = len; 691 os_memcpy(eid, hapd->conf->time_zone, len); 692 eid += len; 693 694 return eid; 695 } 696 697 hostapd_update_time_adv(struct hostapd_data * hapd)698 int hostapd_update_time_adv(struct hostapd_data *hapd) 699 { 700 const int elen = 2 + 1 + 10 + 5 + 1; 701 struct os_time t; 702 struct os_tm tm; 703 u8 *pos; 704 705 if (hapd->conf->time_advertisement != 2) 706 return 0; 707 708 if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) 709 return -1; 710 711 if (!hapd->time_adv) { 712 hapd->time_adv = wpabuf_alloc(elen); 713 if (hapd->time_adv == NULL) 714 return -1; 715 pos = wpabuf_put(hapd->time_adv, elen); 716 } else 717 pos = wpabuf_mhead_u8(hapd->time_adv); 718 719 *pos++ = WLAN_EID_TIME_ADVERTISEMENT; 720 *pos++ = 1 + 10 + 5 + 1; 721 722 *pos++ = 2; /* UTC time at which the TSF timer is 0 */ 723 724 /* Time Value at TSF 0 */ 725 /* FIX: need to calculate this based on the current TSF value */ 726 WPA_PUT_LE16(pos, tm.year); /* Year */ 727 pos += 2; 728 *pos++ = tm.month; /* Month */ 729 *pos++ = tm.day; /* Day of month */ 730 *pos++ = tm.hour; /* Hours */ 731 *pos++ = tm.min; /* Minutes */ 732 *pos++ = tm.sec; /* Seconds */ 733 WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ 734 pos += 2; 735 *pos++ = 0; /* Reserved */ 736 737 /* Time Error */ 738 /* TODO: fill in an estimate on the error */ 739 *pos++ = 0; 740 *pos++ = 0; 741 *pos++ = 0; 742 *pos++ = 0; 743 *pos++ = 0; 744 745 *pos++ = hapd->time_update_counter++; 746 747 return 0; 748 } 749 750 hostapd_eid_bss_max_idle_period(struct hostapd_data * hapd,u8 * eid,u16 value)751 u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid, 752 u16 value) 753 { 754 u8 *pos = eid; 755 756 #ifdef CONFIG_WNM_AP 757 if (hapd->conf->ap_max_inactivity > 0 && 758 hapd->conf->bss_max_idle) { 759 unsigned int val; 760 *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD; 761 *pos++ = 3; 762 val = hapd->conf->ap_max_inactivity; 763 if (val > 68000) 764 val = 68000; 765 val *= 1000; 766 val /= 1024; 767 if (val == 0) 768 val = 1; 769 if (val > 65535) 770 val = 65535; 771 if (value) 772 val = value; 773 WPA_PUT_LE16(pos, val); 774 pos += 2; 775 /* Set the Protected Keep-Alive Required bit based on 776 * configuration */ 777 *pos++ = hapd->conf->bss_max_idle == 2 ? BIT(0) : 0x00; 778 } 779 #endif /* CONFIG_WNM_AP */ 780 781 return pos; 782 } 783 784 785 #ifdef CONFIG_MBO 786 hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data * hapd,u8 * eid,size_t len,int delta)787 u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, 788 size_t len, int delta) 789 { 790 u8 mbo[4]; 791 792 mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT; 793 mbo[1] = 2; 794 /* Delta RSSI */ 795 mbo[2] = delta; 796 /* Retry delay */ 797 mbo[3] = hapd->iconf->rssi_reject_assoc_timeout; 798 799 return eid + mbo_add_ie(eid, len, mbo, 4); 800 } 801 802 hostapd_eid_mbo(struct hostapd_data * hapd,u8 * eid,size_t len)803 u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) 804 { 805 u8 mbo[9], *mbo_pos = mbo; 806 u8 *pos = eid; 807 808 if (!hapd->conf->mbo_enabled && 809 !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) 810 return eid; 811 812 if (hapd->conf->mbo_enabled) { 813 *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; 814 *mbo_pos++ = 1; 815 /* Not Cellular aware */ 816 *mbo_pos++ = 0; 817 } 818 819 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { 820 *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW; 821 *mbo_pos++ = 1; 822 *mbo_pos++ = hapd->mbo_assoc_disallow; 823 } 824 825 if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { 826 u8 ctrl; 827 828 ctrl = OCE_RELEASE; 829 if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) 830 ctrl |= OCE_IS_STA_CFON; 831 832 *mbo_pos++ = OCE_ATTR_ID_CAPA_IND; 833 *mbo_pos++ = 1; 834 *mbo_pos++ = ctrl; 835 } 836 837 pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo); 838 839 return pos; 840 } 841 842 hostapd_mbo_ie_len(struct hostapd_data * hapd)843 u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) 844 { 845 u8 len; 846 847 if (!hapd->conf->mbo_enabled && 848 !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) 849 return 0; 850 851 /* 852 * MBO IE header (6) + Capability Indication attribute (3) + 853 * Association Disallowed attribute (3) = 12 854 */ 855 len = 6; 856 if (hapd->conf->mbo_enabled) 857 len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0); 858 859 /* OCE capability indication attribute (3) */ 860 if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) 861 len += 3; 862 863 return len; 864 } 865 866 #endif /* CONFIG_MBO */ 867 868 869 #ifdef CONFIG_OWE hostapd_eid_owe_trans_enabled(struct hostapd_data * hapd)870 static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd) 871 { 872 return hapd->conf->owe_transition_ssid_len > 0 && 873 !is_zero_ether_addr(hapd->conf->owe_transition_bssid); 874 } 875 #endif /* CONFIG_OWE */ 876 877 hostapd_eid_owe_trans_len(struct hostapd_data * hapd)878 size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd) 879 { 880 #ifdef CONFIG_OWE 881 if (!hostapd_eid_owe_trans_enabled(hapd)) 882 return 0; 883 return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len; 884 #else /* CONFIG_OWE */ 885 return 0; 886 #endif /* CONFIG_OWE */ 887 } 888 889 hostapd_eid_owe_trans(struct hostapd_data * hapd,u8 * eid,size_t len)890 u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, 891 size_t len) 892 { 893 #ifdef CONFIG_OWE 894 u8 *pos = eid; 895 size_t elen; 896 897 if (hapd->conf->owe_transition_ifname[0] && 898 !hostapd_eid_owe_trans_enabled(hapd)) 899 hostapd_owe_trans_get_info(hapd); 900 901 if (!hostapd_eid_owe_trans_enabled(hapd)) 902 return pos; 903 904 elen = hostapd_eid_owe_trans_len(hapd); 905 if (len < elen) { 906 wpa_printf(MSG_DEBUG, 907 "OWE: Not enough room in the buffer for OWE IE"); 908 return pos; 909 } 910 911 *pos++ = WLAN_EID_VENDOR_SPECIFIC; 912 *pos++ = elen - 2; 913 WPA_PUT_BE24(pos, OUI_WFA); 914 pos += 3; 915 *pos++ = OWE_OUI_TYPE; 916 os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN); 917 pos += ETH_ALEN; 918 *pos++ = hapd->conf->owe_transition_ssid_len; 919 os_memcpy(pos, hapd->conf->owe_transition_ssid, 920 hapd->conf->owe_transition_ssid_len); 921 pos += hapd->conf->owe_transition_ssid_len; 922 923 return pos; 924 #else /* CONFIG_OWE */ 925 return eid; 926 #endif /* CONFIG_OWE */ 927 } 928 929 hostapd_eid_dpp_cc_len(struct hostapd_data * hapd)930 size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd) 931 { 932 #ifdef CONFIG_DPP2 933 if (hostapd_dpp_configurator_connectivity(hapd)) 934 return 6; 935 #endif /* CONFIG_DPP2 */ 936 return 0; 937 } 938 939 hostapd_eid_dpp_cc(struct hostapd_data * hapd,u8 * eid,size_t len)940 u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len) 941 { 942 u8 *pos = eid; 943 944 #ifdef CONFIG_DPP2 945 if (!hostapd_dpp_configurator_connectivity(hapd) || len < 6) 946 return pos; 947 948 *pos++ = WLAN_EID_VENDOR_SPECIFIC; 949 *pos++ = 4; 950 WPA_PUT_BE24(pos, OUI_WFA); 951 pos += 3; 952 *pos++ = DPP_CC_OUI_TYPE; 953 #endif /* CONFIG_DPP2 */ 954 955 return pos; 956 } 957 958 ap_copy_sta_supp_op_classes(struct sta_info * sta,const u8 * supp_op_classes,size_t supp_op_classes_len)959 void ap_copy_sta_supp_op_classes(struct sta_info *sta, 960 const u8 *supp_op_classes, 961 size_t supp_op_classes_len) 962 { 963 if (!supp_op_classes) 964 return; 965 os_free(sta->supp_op_classes); 966 sta->supp_op_classes = os_malloc(1 + supp_op_classes_len); 967 if (!sta->supp_op_classes) 968 return; 969 970 sta->supp_op_classes[0] = supp_op_classes_len; 971 os_memcpy(sta->supp_op_classes + 1, supp_op_classes, 972 supp_op_classes_len); 973 } 974 975 hostapd_eid_fils_indic(struct hostapd_data * hapd,u8 * eid,int hessid)976 u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) 977 { 978 u8 *pos = eid; 979 #ifdef CONFIG_FILS 980 u8 *len; 981 u16 fils_info = 0; 982 size_t realms; 983 struct fils_realm *realm; 984 985 if (!(hapd->conf->wpa & WPA_PROTO_RSN) || 986 !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) 987 return pos; 988 989 realms = dl_list_len(&hapd->conf->fils_realms); 990 if (realms > 7) 991 realms = 7; /* 3 bit count field limits this to max 7 */ 992 993 *pos++ = WLAN_EID_FILS_INDICATION; 994 len = pos++; 995 /* TODO: B0..B2: Number of Public Key Identifiers */ 996 if (hapd->conf->erp_domain) { 997 /* B3..B5: Number of Realm Identifiers */ 998 fils_info |= realms << 3; 999 } 1000 /* TODO: B6: FILS IP Address Configuration */ 1001 if (hapd->conf->fils_cache_id_set) 1002 fils_info |= BIT(7); 1003 if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) 1004 fils_info |= BIT(8); /* HESSID Included */ 1005 /* FILS Shared Key Authentication without PFS Supported */ 1006 fils_info |= BIT(9); 1007 if (hapd->conf->fils_dh_group) { 1008 /* FILS Shared Key Authentication with PFS Supported */ 1009 fils_info |= BIT(10); 1010 } 1011 /* TODO: B11: FILS Public Key Authentication Supported */ 1012 /* B12..B15: Reserved */ 1013 WPA_PUT_LE16(pos, fils_info); 1014 pos += 2; 1015 if (hapd->conf->fils_cache_id_set) { 1016 os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN); 1017 pos += FILS_CACHE_ID_LEN; 1018 } 1019 if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) { 1020 os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 1021 pos += ETH_ALEN; 1022 } 1023 1024 dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, 1025 list) { 1026 if (realms == 0) 1027 break; 1028 realms--; 1029 os_memcpy(pos, realm->hash, 2); 1030 pos += 2; 1031 } 1032 *len = pos - len - 1; 1033 #endif /* CONFIG_FILS */ 1034 1035 return pos; 1036 } 1037 1038 1039 #ifdef CONFIG_OCV get_tx_parameters(struct sta_info * sta,int ap_max_chanwidth,int ap_seg1_idx,int * bandwidth,int * seg1_idx)1040 int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, 1041 int ap_seg1_idx, int *bandwidth, int *seg1_idx) 1042 { 1043 int ht_40mhz = 0; 1044 int vht_80p80 = 0; 1045 int requested_bw; 1046 1047 if (sta->ht_capabilities) 1048 ht_40mhz = !!(le_to_host16(sta->ht_capabilities-> 1049 ht_capabilities_info) & 1050 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); 1051 1052 if (sta->vht_operation) { 1053 struct ieee80211_vht_operation *oper = sta->vht_operation; 1054 1055 /* 1056 * If a VHT Operation element was present, use it to determine 1057 * the supported channel bandwidth. 1058 */ 1059 if (oper->vht_op_info_chwidth == CHANWIDTH_USE_HT) { 1060 requested_bw = ht_40mhz ? 40 : 20; 1061 } else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0) { 1062 requested_bw = 80; 1063 } else { 1064 int diff; 1065 1066 requested_bw = 160; 1067 diff = abs((int) 1068 oper->vht_op_info_chan_center_freq_seg0_idx - 1069 (int) 1070 oper->vht_op_info_chan_center_freq_seg1_idx); 1071 vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx 1072 != 0 && diff > 16; 1073 } 1074 } else if (sta->vht_capabilities) { 1075 struct ieee80211_vht_capabilities *capab; 1076 int vht_chanwidth; 1077 1078 capab = sta->vht_capabilities; 1079 1080 /* 1081 * If only the VHT Capabilities element is present (e.g., for 1082 * normal clients), use it to determine the supported channel 1083 * bandwidth. 1084 */ 1085 vht_chanwidth = le_to_host32(capab->vht_capabilities_info) & 1086 VHT_CAP_SUPP_CHAN_WIDTH_MASK; 1087 vht_80p80 = le_to_host32(capab->vht_capabilities_info) & 1088 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 1089 1090 /* TODO: Also take into account Extended NSS BW Support field */ 1091 requested_bw = vht_chanwidth ? 160 : 80; 1092 } else { 1093 requested_bw = ht_40mhz ? 40 : 20; 1094 } 1095 1096 *bandwidth = requested_bw < ap_max_chanwidth ? 1097 requested_bw : ap_max_chanwidth; 1098 1099 *seg1_idx = 0; 1100 if (ap_seg1_idx && vht_80p80) 1101 *seg1_idx = ap_seg1_idx; 1102 1103 return 0; 1104 } 1105 #endif /* CONFIG_OCV */ 1106 1107 hostapd_eid_rsnxe(struct hostapd_data * hapd,u8 * eid,size_t len)1108 u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) 1109 { 1110 u8 *pos = eid; 1111 bool sae_pk = false; 1112 u32 capab = 0, tmp; 1113 size_t flen; 1114 1115 if (!(hapd->conf->wpa & WPA_PROTO_RSN)) 1116 return eid; 1117 1118 #ifdef CONFIG_SAE_PK 1119 sae_pk = hostapd_sae_pk_in_use(hapd->conf); 1120 #endif /* CONFIG_SAE_PK */ 1121 1122 if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && 1123 (hapd->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT || 1124 hapd->conf->sae_pwe == SAE_PWE_BOTH || 1125 hostapd_sae_pw_id_in_use(hapd->conf) || sae_pk || 1126 wpa_key_mgmt_sae_ext_key(hapd->conf->wpa_key_mgmt)) && 1127 hapd->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK) { 1128 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); 1129 #ifdef CONFIG_SAE_PK 1130 if (sae_pk) 1131 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK); 1132 #endif /* CONFIG_SAE_PK */ 1133 } 1134 1135 if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_AP) 1136 capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF); 1137 if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_AP) 1138 capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT); 1139 if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP) 1140 capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR); 1141 if (hapd->conf->ssid_protection) 1142 capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION); 1143 if ((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU) && 1144 hapd->conf->spp_amsdu) 1145 capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU); 1146 1147 if (!capab) 1148 return eid; /* no supported extended RSN capabilities */ 1149 tmp = capab; 1150 flen = 0; 1151 while (tmp) { 1152 flen++; 1153 tmp >>= 8; 1154 } 1155 1156 if (len < 2 + flen) 1157 return eid; /* no supported extended RSN capabilities */ 1158 capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ 1159 1160 *pos++ = WLAN_EID_RSNX; 1161 *pos++ = flen; 1162 while (capab) { 1163 *pos++ = capab & 0xff; 1164 capab >>= 8; 1165 } 1166 1167 return pos; 1168 } 1169 1170 check_ext_capab(struct hostapd_data * hapd,struct sta_info * sta,const u8 * ext_capab_ie,size_t ext_capab_ie_len)1171 u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, 1172 const u8 *ext_capab_ie, size_t ext_capab_ie_len) 1173 { 1174 /* check for QoS Map support */ 1175 if (ext_capab_ie_len >= 5) { 1176 if (ext_capab_ie[4] & 0x01) 1177 sta->qos_map_enabled = 1; 1178 } 1179 1180 if (ext_capab_ie_len > 0) { 1181 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2)); 1182 os_free(sta->ext_capability); 1183 sta->ext_capability = os_malloc(1 + ext_capab_ie_len); 1184 if (sta->ext_capability) { 1185 sta->ext_capability[0] = ext_capab_ie_len; 1186 os_memcpy(sta->ext_capability + 1, ext_capab_ie, 1187 ext_capab_ie_len); 1188 } 1189 } 1190 1191 return WLAN_STATUS_SUCCESS; 1192 } 1193 1194 hostapd_ml_get_assoc_sta(struct hostapd_data * hapd,struct sta_info * sta,struct hostapd_data ** assoc_hapd)1195 struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd, 1196 struct sta_info *sta, 1197 struct hostapd_data **assoc_hapd) 1198 { 1199 #ifdef CONFIG_IEEE80211BE 1200 struct hostapd_data *other_hapd = NULL; 1201 struct sta_info *tmp_sta; 1202 1203 if (!ap_sta_is_mld(hapd, sta)) 1204 return NULL; 1205 1206 *assoc_hapd = hapd; 1207 1208 /* The station is the one on which the association was performed */ 1209 if (sta->mld_assoc_link_id == hapd->mld_link_id) 1210 return sta; 1211 1212 other_hapd = hostapd_mld_get_link_bss(hapd, sta->mld_assoc_link_id); 1213 if (!other_hapd) { 1214 wpa_printf(MSG_DEBUG, "MLD: No link match for link_id=%u", 1215 sta->mld_assoc_link_id); 1216 return sta; 1217 } 1218 1219 /* 1220 * Iterate over the stations and find the one with the matching link ID 1221 * and association ID. 1222 */ 1223 for (tmp_sta = other_hapd->sta_list; tmp_sta; tmp_sta = tmp_sta->next) { 1224 if (tmp_sta->mld_assoc_link_id == sta->mld_assoc_link_id && 1225 tmp_sta->aid == sta->aid) { 1226 *assoc_hapd = other_hapd; 1227 return tmp_sta; 1228 } 1229 } 1230 #endif /* CONFIG_IEEE80211BE */ 1231 1232 return sta; 1233 } 1234 1235 hostapd_get_ht_vht_twt_responder(struct hostapd_data * hapd)1236 bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd) 1237 { 1238 return hapd->iconf->ht_vht_twt_responder && 1239 ((hapd->iconf->ieee80211n && !hapd->conf->disable_11n) || 1240 (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)) && 1241 (hapd->iface->drv_flags2 & 1242 WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER); 1243 } 1244 1245 hostapd_wfa_gen_capab(struct hostapd_data * hapd,struct sta_info * sta,const u8 * capab,size_t len)1246 static void hostapd_wfa_gen_capab(struct hostapd_data *hapd, 1247 struct sta_info *sta, 1248 const u8 *capab, size_t len) 1249 { 1250 char *hex; 1251 size_t buflen; 1252 1253 wpa_printf(MSG_DEBUG, 1254 "WFA: Received indication of generational capabilities from " 1255 MACSTR, MAC2STR(sta->addr)); 1256 wpa_hexdump(MSG_DEBUG, "WFA: Generational Capabilities", capab, len); 1257 1258 buflen = 2 * len + 1; 1259 hex = os_zalloc(buflen); 1260 if (!hex) 1261 return; 1262 wpa_snprintf_hex(hex, buflen, capab, len); 1263 wpa_msg(hapd->msg_ctx, MSG_INFO, WFA_GEN_CAPAB_RX MACSTR " %s", 1264 MAC2STR(sta->addr), hex); 1265 os_free(hex); 1266 } 1267 1268 hostapd_wfa_capab(struct hostapd_data * hapd,struct sta_info * sta,const u8 * pos,const u8 * end)1269 void hostapd_wfa_capab(struct hostapd_data *hapd, struct sta_info *sta, 1270 const u8 *pos, const u8 *end) 1271 { 1272 u8 capab_len; 1273 const u8 *gen_capa; 1274 1275 if (end - pos < 1) 1276 return; 1277 capab_len = *pos++; 1278 if (capab_len > end - pos) 1279 return; 1280 pos += capab_len; /* skip the Capabilities field */ 1281 1282 /* Wi-Fi Alliance Capabilities attributes use a header that is similar 1283 * to the one used in Information Elements. */ 1284 gen_capa = get_ie(pos, end - pos, WFA_CAPA_ATTR_GENERATIONAL_CAPAB); 1285 if (gen_capa) 1286 hostapd_wfa_gen_capab(hapd, sta, gen_capa + 2, gen_capa[1]); 1287 } 1288