From 92dcec1419c26192f860f3d571459429c59c2df9 Mon Sep 17 00:00:00 2001 From: Yuvarani V Date: Mon, 4 Dec 2023 01:29:37 +0530 Subject: [PATCH] hostapd: Add NL attribute to set critical update params Detect Category-1 critical update like CSA, eCSA, CCA element id inclusion and set critical update attribute. Detect Category-2 critical update like EHTOP, HEOP, VHTOP, HTOP, WMM, MU_EDCA and spatial reuse element id modification and set critical update attribute. Signed-off-by: Rathees Kumar R Chinannan Signed-off-by: Yuvarani V --- src/ap/beacon.c | 63 ++++++++++++++++++++++++++++++++++++ src/ap/hostapd.h | 23 +++++++++++++ src/drivers/driver.h | 4 +++ src/drivers/driver_nl80211.c | 22 +++++++++++++ src/drivers/nl80211_copy.h | 18 +++++++++++ 5 files changed, 130 insertions(+) --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -13,6 +13,7 @@ #ifndef CONFIG_NATIVE_WINDOWS #include "utils/common.h" +#include "utils/crc32.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/hw_features_common.h" @@ -2118,6 +2119,31 @@ static u8 * hostapd_fils_discovery(struc #endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211BE +static void hostapd_eid_update_cu_info(struct hostapd_data *hapd, u8 *elemid_modified, + const u8 *eid_pos, size_t eid_len, + enum elemid_cu eid_cu) +{ + u32 hash; + + if (!hapd->conf->mld_ap) + return; + if (!eid_pos || (eid_len == 0) || (eid_len > 255)) + return; + if (eid_cu >= ELEMID_CU_PARAM_MAX) + return; + + hash = ieee80211_crc32(eid_pos, eid_len); + if ((hapd->cu_eid[eid_cu].eid_len != eid_len) || + (hapd->cu_eid[eid_cu].hash != hash)) { + hapd->cu_eid[eid_cu].eid_len = eid_len; + hapd->cu_eid[eid_cu].hash = hash; + *elemid_modified |= BIT(eid_cu); + } +} +#endif + + int ieee802_11_build_ap_params(struct hostapd_data *hapd, struct wpa_driver_ap_params *params) { @@ -2130,6 +2156,8 @@ int ieee802_11_build_ap_params(struct ho u16 capab_info; u8 *pos, *tailpos, *tailend, *csa_pos; bool complete = false; + u8 *startpos; + u8 elemid_modified = 0; #endif /* NEED_AP_MLME */ os_memset(params, 0, sizeof(*params)); @@ -2297,8 +2325,14 @@ int ieee802_11_build_ap_params(struct ho tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); + startpos = tailpos; tailpos = hostapd_eid_ht_operation(hapd, tailpos); +#ifdef CONFIG_IEEE80211BE + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_HTOP); +#endif + if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) { if (ieee802_11_build_ap_params_mbssid(hapd, params)) { os_free(head); @@ -2336,7 +2370,12 @@ int ieee802_11_build_ap_params(struct ho if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac && !is_6ghz_op_class(hapd->iconf->op_class)) { tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0); + startpos = tailpos; tailpos = hostapd_eid_vht_operation(hapd, tailpos); +#ifdef CONFIG_IEEE80211BE + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_VHTOP); +#endif tailpos = hostapd_eid_txpower_envelope(hapd, tailpos); } #endif /* CONFIG_IEEE80211AC */ @@ -2364,16 +2403,31 @@ int ieee802_11_build_ap_params(struct ho tailpos = hostapd_eid_he_capab(hapd, tailpos, IEEE80211_MODE_AP); + startpos = tailpos; tailpos = hostapd_eid_he_operation(hapd, tailpos); +#ifdef CONFIG_IEEE80211BE + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_EXT_HEOP); +#endif /* BSS Color Change Announcement element */ cca_pos = hostapd_eid_cca(hapd, tailpos); if (cca_pos != tailpos) hapd->cca_c_off_beacon = cca_pos - tail - 2; tailpos = cca_pos; + startpos = tailpos; tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); +#ifdef CONFIG_IEEE80211BE + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_SPATIAL_REUSE); +#endif + startpos = tailpos; tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); +#ifdef CONFIG_IEEE80211BE + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_MU_EDCA); +#endif tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos); } #endif /* CONFIG_IEEE80211AX */ @@ -2385,7 +2439,10 @@ int ieee802_11_build_ap_params(struct ho true); tailpos = hostapd_eid_eht_capab(hapd, tailpos, IEEE80211_MODE_AP); + startpos = tailpos; tailpos = hostapd_eid_eht_operation(hapd, tailpos, IEEE80211_MODE_AP); + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_EXT_EHTOP); tailpos = hostapd_eid_vendor_240mhz(hapd, tailpos, IEEE80211_MODE_AP); } #endif /* CONFIG_IEEE80211BE */ @@ -2400,8 +2457,11 @@ int ieee802_11_build_ap_params(struct ho tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos); /* Wi-Fi Alliance WMM */ + startpos = tailpos; tailpos = hostapd_eid_wmm(hapd, tailpos); #ifdef CONFIG_IEEE80211BE + hostapd_eid_update_cu_info(hapd, &elemid_modified, startpos, + tailpos-startpos, ELEMID_CU_PARAM_WMM); tailpos = hostapd_add_scs_cap(tailpos, false, true); #endif #ifdef CONFIG_WPS @@ -2537,6 +2597,9 @@ int ieee802_11_build_ap_params(struct ho params->beacon_tx_mode = hapd->conf->beacon_tx_mode; + if (hapd->conf->mld_ap && elemid_modified) + params->elemid_modified = 1; + #ifdef CONFIG_IEEE80211BE if (hapd->conf->mld_ap && hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -194,6 +194,27 @@ struct rx_critical_param { }; /** + * enum elemid_cu - used for detecting element id modification + * category 2 critical update + */ +enum elemid_cu { + ELEMID_CU_PARAM_EXT_EHTOP = 0, + ELEMID_CU_PARAM_EXT_HEOP, + ELEMID_CU_PARAM_VHTOP, + ELEMID_CU_PARAM_HTOP, + ELEMID_CU_PARAM_WMM, + ELEMID_CU_PARAM_MU_EDCA, + ELEMID_CU_PARAM_SPATIAL_REUSE, + + ELEMID_CU_PARAM_MAX, +}; + +struct elemid_cu_param { + u8 eid_len; + u32 hash; +}; + +/** * struct hostapd_data - hostapd per-BSS data structure */ struct hostapd_data { @@ -505,6 +526,8 @@ struct hostapd_data { #endif /* CONFIG_CTRL_IFACE_UDP */ struct rx_critical_param rx_cu_param; + /*Element ID critical update data*/ + struct elemid_cu_param cu_eid[ELEMID_CU_PARAM_MAX]; #ifdef CONFIG_IEEE80211BE struct hostapd_mld *mld; struct dl_list link; --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1902,6 +1902,10 @@ struct wpa_driver_ap_params { /* Unsolicited broadcast Probe Response data*/ struct unsol_bcast_probe_resp ubpr; + /* critical_update_flag - critical update flag*/ + bool elemid_added; + bool elemid_modified; + /** * allowed_freqs - List of allowed 20 MHz channel center frequencies in * MHz for AP operation. Drivers which support this parameter will --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5063,6 +5063,7 @@ static int wpa_driver_nl80211_set_ap(voi #ifdef CONFIG_MESH struct wpa_driver_mesh_bss_params mesh_params; #endif /* CONFIG_MESH */ + u8 critical_update = 0; if (params->mld_ap) { size_t i; @@ -5399,6 +5400,14 @@ static int wpa_driver_nl80211_set_ap(voi goto fail; #endif /* CONFIG_FILS */ + if (bss->n_links && (params->elemid_added || params->elemid_modified)) { + if (params->elemid_added) + critical_update |= NL80211_CU_ELEMID_ADDED; + if (params->elemid_modified) + critical_update |= NL80211_CU_ELEMID_MODIFIED; + if (nla_put_u8(msg, NL80211_ATTR_SET_CRITICAL_UPDATE, critical_update)) + goto fail; + } if (params->punct_bitmap) { wpa_printf(MSG_DEBUG, "nl80211: Puncturing bitmap=0x%04x", params->punct_bitmap); @@ -11213,6 +11222,7 @@ static int nl80211_switch_channel(void * int ret = -ENOBUFS; int csa_off_len = 0; int i; + u8 critical_update = 0; wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d puncturing_bitmap=0x%04x%s%s%s puncturing bitmap=0x%04x, ru_punct_ofdma=%u)", @@ -11350,6 +11360,12 @@ static int nl80211_switch_channel(void * goto fail; #endif /* CONFIG_IEEE80211AX */ + if (bss->n_links) { + critical_update |= NL80211_CU_ELEMID_ADDED; + if (nla_put_u8(msg, NL80211_ATTR_SET_CRITICAL_UPDATE, critical_update)) + goto fail; + } + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)", @@ -11374,6 +11390,7 @@ static int nl80211_switch_color(void *pr struct nlattr *beacon_cca; struct nl_msg *msg; int ret = -ENOBUFS; + u8 critical_update = 0; wpa_printf(MSG_DEBUG, "nl80211: Color change request (cca_count=%u color=%d)", @@ -11447,6 +11464,11 @@ static int nl80211_switch_color(void *pr goto error; } + if (bss->n_links) { + critical_update |= NL80211_CU_ELEMID_ADDED; + if (nla_put_u8(msg, NL80211_ATTR_SET_CRITICAL_UPDATE, critical_update)) + goto error; + } ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -2842,7 +2842,9 @@ enum nl80211_commands { * @NL80211_ATTR_RXMGMT_CRITICAL_UPDATE: Nested attribute listing the critical * update for each MLD. In each nested item, it contains attributes * defined in &enum nl80211_cu_attrs. - + * @NL80211_ATTR_SET_CRITICAL_UPDATE: set critical update for the bss + * (see &enum nl80211_set_cu). + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3400,6 +3402,7 @@ enum nl80211_attrs { NL80211_ATTR_ADD_MULTI_CHAN, NL80211_ATTR_DEL_MULTI_CHAN, NL80211_ATTR_RXMGMT_CRITICAL_UPDATE, + NL80211_ATTR_SET_CRITICAL_UPDATE, /* add attributes here, update the policy in nl80211.c */ @@ -6061,6 +6064,21 @@ enum plink_actions { NUM_NL80211_PLINK_ACTIONS, }; +/** + * enum nl80211_set_cu - set critical update params + * + * @NL80211_CU_UNSPEC: reserved + * @NL80211_CU_ELEMID_ADDED: Critical update - Element id added + * @NL80211_CU_ELEMID_MODIFIED: Critical update - Element id Modified + * @NUM_NL80211_CUS: number of CU attributes + */ +enum nl80211_set_cu { + NL80211_CU_UNSPEC, + NL80211_CU_ELEMID_ADDED, + NL80211_CU_ELEMID_MODIFIED, + + NUM_NL80211_CUS, +}; #define NL80211_KCK_LEN 16 #define NL80211_KEK_LEN 16