From bb9ff477c009507d5728e0cc262a93ce1d3a06a5 Mon Sep 17 00:00:00 2001 From: Rameshkumar Sundaram Date: Tue, 16 Jan 2024 09:44:09 +0530 Subject: [PATCH] hostapd: add ML probing support for MBSSID For beacon Add ML IE for Non-tx profie inside MBSSID non-tx bss profile sub element if it is an MLD. For Probe repsonse Solicited MLD APs MLE should be added in the frame body of the multi-link probe response, whose location is outside of the Multiple BSSID element carried in the frame. The AP MLD ID Present subfield of the Presence Bitmap subfield of the Basic Multi-Link element shall be set to 1. The AP MLD ID subfield of the Common Info field of the Basic Multi-Link element shall be present, and shall be set to the same value as the BSSID Index subfield of the Multiple-BSSID Index element carried in the Nontransmitted BSSID Profile subelement of the Multiple BSSID element. Parse MLD ID from ML probe request and redirect the frame to the NON-TX BSS corresponding to MLD ID Signed-off-by: Rameshkumar Sundaram Signed-off-by: Yuvarani V --- src/ap/beacon.c | 39 ++++++++++++++---------- src/ap/ieee802_11.c | 54 +++++++++++++++++++--------------- src/ap/ieee802_11.h | 11 +++---- src/ap/ieee802_11_eht.c | 4 +-- src/ap/wpa_auth_glue.c | 4 ++- src/common/ieee802_11_common.c | 9 ++++-- src/common/ieee802_11_common.h | 2 +- 7 files changed, 74 insertions(+), 49 deletions(-) --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -533,7 +533,7 @@ ieee802_11_build_ap_params_mbssid(struct else params->mbssid_tx_iface_linkid = -1; len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count, - NULL, 0, &rnr_len); + NULL, 0, &rnr_len, false); if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED && elem_count > iface->ema_max_periodicity)) goto fail; @@ -558,7 +558,7 @@ ieee802_11_build_ap_params_mbssid(struct end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON, elem_count, elem_offset, NULL, 0, rnr_elem, - &rnr_elem_count, rnr_elem_offset, rnr_len); + &rnr_elem_count, rnr_elem_offset, rnr_len, false); params->mbssid_tx_iface = tx_bss->conf->iface; params->mbssid_index = hostapd_mbssid_get_bss_index(hapd); @@ -970,7 +970,7 @@ static u8 * hostapd_gen_probe_resp(struc * and 1024 for ML probe resp */ if (hapd->conf->mld_ap) { - if (ml_probe) { + if (hapd_probed == hapd && ml_probe) { buflen += 1024; } else { buflen += 256; @@ -985,13 +985,13 @@ static u8 * hostapd_gen_probe_resp(struc if (hapd_probed != hapd && hapd_probed->conf->mld_ap && ml_probe) buflen += hostapd_eid_eht_basic_ml_len(hapd_probed, - NULL, true); + hapd->partner_links, true); } #endif /* CONFIG_IEEE80211BE */ - buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL, - known_bss, known_bss_len, NULL); + buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, NULL, + known_bss, known_bss_len, NULL, ml_probe); buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP, true); buflen += hostapd_mbo_ie_len(hapd); buflen += hostapd_eid_owe_trans_len(hapd); @@ -1073,9 +1073,9 @@ static u8 * hostapd_gen_probe_resp(struc pos = hostapd_get_rsne(hapd, pos, epos - pos); pos = hostapd_eid_bss_load(hapd, pos, epos - pos); - pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0, + pos = hostapd_eid_mbssid(hapd_probed, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0, NULL, known_bss, known_bss_len, NULL, NULL, - NULL, 0); + NULL, 0, ml_probe); pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); pos = hostapd_get_mde(hapd, pos, epos - pos); @@ -1171,7 +1171,7 @@ static u8 * hostapd_gen_probe_resp(struc if (hapd_probed != hapd && hapd_probed->conf->mld_ap && ml_probe) pos = hostapd_eid_eht_basic_ml(hapd_probed, pos, - NULL, true); + hapd_probed->partner_links, true); } #endif /* CONFIG_IEEE80211BE */ @@ -1451,7 +1451,9 @@ void handle_probe_req(struct hostapd_dat .elems = &elems, }; bool ml_probe = false; + struct hostapd_data *hapd_probed = hapd; struct wpabuf *mlbuf = NULL; + u8 mld_id = 0; if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && ssi_signal < hapd->iconf->rssi_ignore_probe_request) @@ -1691,12 +1693,24 @@ void handle_probe_req(struct hostapd_dat #ifdef CONFIG_IEEE80211BE mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_PROBE_REQ); - if (mlbuf && ieee802_11_parse_ml_probe_req(mlbuf)) { + if (hapd->conf->mld_ap && mlbuf && ieee802_11_parse_ml_probe_req(mlbuf, &mld_id)) { ml_probe = true; + /* MLD ID Probing */ + if ((hapd == hostapd_mbssid_get_tx_bss(hapd)) && mld_id) { + if (mld_id < hapd->iface->num_bss) + hapd_probed = hapd->iface->bss[mld_id]; + else { + wpa_printf(MSG_INFO, + "Ignore Probe Request from " MACSTR + " since No Matched Non-tx vap found for BSSID Index %d", + MAC2STR(mgmt->sa), mld_id); + return; + } + } } wpabuf_free(mlbuf); #endif - resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL, + resp = hostapd_gen_probe_resp(hapd_probed, mgmt, elems.p2p != NULL, &resp_len, elems.mbssid_known_bss, elems.mbssid_known_bss_len, ml_probe); if (resp == NULL) --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -8389,12 +8389,13 @@ static bool mbssid_known_bss(unsigned in } -static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd, +static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd_probed, u32 frame_type, size_t *bss_index, const u8 *known_bss, - size_t known_bss_len) + size_t known_bss_len, + bool ml_probe) { - struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); + struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd_probed); size_t len, i, tx_xrate_len; /* Element ID: 1 octet @@ -8408,8 +8409,8 @@ static size_t hostapd_eid_mbssid_elem_le len = 1; hostapd_eid_ext_supp_rates(tx_bss, NULL, &tx_xrate_len); - for (i = *bss_index; i < hapd->iface->num_bss; i++) { - struct hostapd_data *bss = hapd->iface->bss[i]; + for (i = *bss_index; i < tx_bss->iface->num_bss; i++) { + struct hostapd_data *bss = tx_bss->iface->bss[i]; const u8 *auth, *rsn = NULL, *rsnx = NULL; size_t nontx_profile_len, auth_len, xrate_len; u8 ie_count = 0, ext_ie_count = 0; @@ -8430,7 +8431,7 @@ static size_t hostapd_eid_mbssid_elem_le if (!bss->conf->ignore_broadcast_ssid || bss->conf->ignore_broadcast_ssid == 2 || - (frame_type == WLAN_FC_STYPE_PROBE_RESP && bss == hapd)) + (frame_type == WLAN_FC_STYPE_PROBE_RESP && bss == hapd_probed)) nontx_profile_len += bss->conf->ssid.ssid_len; if (frame_type == WLAN_FC_STYPE_BEACON) @@ -8456,9 +8457,11 @@ static size_t hostapd_eid_mbssid_elem_le else if (tx_xrate_len) ext_ie_count++; +#ifdef CONFIG_IEEE80211BE /* For ML Probe resp, solicited hapd's MLE will be in the frame body */ - if (bss->conf->mld_ap && (bss != hapd || frame_type != WLAN_FC_STYPE_PROBE_RESP)) + if (bss->conf->mld_ap && (bss != hapd_probed || !ml_probe)) nontx_profile_len += hostapd_eid_eht_basic_ml_len(bss, NULL, true); +#endif /* CONFIG_IEEE80211BE */ if (ie_count || ext_ie_count) { /* Element ID, Length and Element ID Extension (3 octets) @@ -8489,11 +8492,12 @@ static size_t hostapd_eid_mbssid_elem_le } -size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, +size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd_probed, u32 frame_type, u8 *elem_count, const u8 *known_bss, - size_t known_bss_len, size_t *rnr_len) + size_t known_bss_len, size_t *rnr_len, bool ml_probe) { size_t len = 0, bss_index = 1; + struct hostapd_data *hapd = hostapd_mbssid_get_tx_bss(hapd_probed); if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || (frame_type != WLAN_FC_STYPE_BEACON && @@ -8512,9 +8516,9 @@ size_t hostapd_eid_mbssid_len(struct hos while (bss_index < hapd->iface->num_bss) { size_t rnr_count = bss_index; - len += hostapd_eid_mbssid_elem_len(hapd, frame_type, + len += hostapd_eid_mbssid_elem_len(hapd_probed, frame_type, &bss_index, known_bss, - known_bss_len); + known_bss_len, ml_probe); if (frame_type == WLAN_FC_STYPE_BEACON) *elem_count += 1; @@ -8541,12 +8545,13 @@ size_t hostapd_eid_mbssid_len(struct hos } -static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end, +static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd_probed, u8 *eid, u8 *end, u32 frame_type, u8 max_bssid_indicator, size_t *bss_index, u8 elem_count, - const u8 *known_bss, size_t known_bss_len) + const u8 *known_bss, size_t known_bss_len, + bool ml_probe) { - struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); + struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd_probed); size_t i, tx_xrate_len; u8 *eid_len_offset, *max_bssid_indicator_offset; @@ -8555,8 +8560,8 @@ static u8 * hostapd_eid_mbssid_elem(stru eid_len_offset = eid++; max_bssid_indicator_offset = eid++; - for (i = *bss_index; i < hapd->iface->num_bss; i++) { - struct hostapd_data *bss = hapd->iface->bss[i]; + for (i = *bss_index; i < tx_bss->iface->num_bss; i++) { + struct hostapd_data *bss = tx_bss->iface->bss[i]; struct hostapd_bss_config *conf; u8 *eid_len_pos, *nontx_bss_start = eid; const u8 *auth, *rsn = NULL, *rsnx = NULL; @@ -8585,7 +8590,7 @@ static u8 * hostapd_eid_mbssid_elem(stru *eid++ = WLAN_EID_SSID; if (!conf->ignore_broadcast_ssid || - (frame_type == WLAN_FC_STYPE_PROBE_RESP && bss == hapd)) { + (frame_type == WLAN_FC_STYPE_PROBE_RESP && bss == hapd_probed)) { *eid++ = conf->ssid.ssid_len; os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len); eid += conf->ssid.ssid_len; @@ -8601,7 +8606,7 @@ static u8 * hostapd_eid_mbssid_elem(stru if (frame_type == WLAN_FC_STYPE_BEACON) { *eid++ = 3; *eid++ = i; /* BSSID Index */ - if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED && + if (tx_bss->iconf->mbssid == ENHANCED_MBSSID_ENABLED && (conf->dtim_period % elem_count)) conf->dtim_period = elem_count; *eid++ = conf->dtim_period; @@ -8634,9 +8639,11 @@ static u8 * hostapd_eid_mbssid_elem(stru non_inherit_ie[ie_count++] = WLAN_EID_RSNX; if (tx_xrate_len && !xrate_len) non_inherit_ext_ie[ext_ie_count++] = WLAN_EID_EXT_SUPP_RATES; +#ifdef CONFIG_IEEE80211BE /* For ML Probe resp, solicited hapd's MLE will be in the frame body */ - if (bss->conf->mld_ap && (bss != hapd || frame_type != WLAN_FC_STYPE_PROBE_RESP)) + if (bss->conf->mld_ap && (bss != hapd_probed || !ml_probe)) eid = hostapd_eid_eht_basic_ml(bss, eid, NULL, true); +#endif /* CONFIG_IEEE80211BE */ if (ie_count || ext_ie_count) { *eid++ = WLAN_EID_EXTENSION; non_inherit_eid_len_offset = eid++; @@ -8674,15 +8681,16 @@ static u8 * hostapd_eid_mbssid_elem(stru } -u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, +u8 * hostapd_eid_mbssid(struct hostapd_data *hapd_probed, u8 *eid, u8 *end, unsigned int frame_stype, u8 elem_count, u8 **elem_offset, const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid, - u8 *rnr_count, u8 **rnr_offset, size_t rnr_len) + u8 *rnr_count, u8 **rnr_offset, size_t rnr_len, bool ml_probe) { size_t bss_index = 1, cur_len = 0; u8 elem_index = 0, *rnr_start_eid = rnr_eid; bool add_rnr; + struct hostapd_data *hapd = hostapd_mbssid_get_tx_bss(hapd_probed); if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || (frame_stype != WLAN_FC_STYPE_BEACON && @@ -8712,10 +8720,10 @@ u8 * hostapd_eid_mbssid(struct hostapd_d elem_offset[elem_index] = eid; elem_index = elem_index + 1; } - eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_stype, + eid = hostapd_eid_mbssid_elem(hapd_probed, eid, end, frame_stype, hostapd_max_bssid_indicator(hapd), &bss_index, elem_count, - known_bss, known_bss_len); + known_bss, known_bss_len, ml_probe); if (add_rnr) { struct mbssid_ie_profiles skip_profiles = { --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -103,7 +103,7 @@ void hostapd_get_eht_capab(struct hostap u8 * hostapd_eid_eht_basic_ml(struct hostapd_data *hapd, u8 *eid, struct mld_link_info *link_info, bool include_mld_id); size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd, - struct sta_info *info, bool include_mld_id); + struct mld_link_info *info, bool include_mld_id); struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd); const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, @@ -259,14 +259,15 @@ u16 copy_sta_eht_240mhz_capab(struct hos enum ieee80211_op_mode opmode, const u8 *eht_240mhz_capab, size_t eht_240mhz_len); void ru_punct_update_bw(u16 bitmap, u8 pri_chan, enum oper_chan_width *width, u8 *seg0, u8 *seg1); -size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, +size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd_probed, u32 frame_type, u8 *elem_count, const u8 *known_bss, - size_t known_bss_len, size_t *rnr_len); -u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, + size_t known_bss_len, size_t *rnr_len, + bool ml_probe); +u8 * hostapd_eid_mbssid(struct hostapd_data *hapd_probed, u8 *eid, u8 *end, unsigned int frame_stype, u8 elem_count, u8 **elem_offset, const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid, - u8 *rnr_count, u8 **rnr_offset, size_t rnr_len); + u8 *rnr_count, u8 **rnr_offset, size_t rnr_len, bool ml_probe); u16 hostapd_critical_update_capab(struct hostapd_data *hapd); void punct_update_legacy_bw(u16 bitmap, u8 pri_chan, enum oper_chan_width *width, u8 *seg0, u8 *seg1); --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -830,7 +830,7 @@ out: * parameters change counter (1) */ size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd, - struct sta_info *info, + struct mld_link_info *info, bool include_mld_id) { int link_id; @@ -857,7 +857,7 @@ size_t hostapd_eid_eht_basic_ml_len(stru /* Add link info for the other links */ for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) { - struct mld_link_info *link = &info->mld_info.links[link_id]; + struct mld_link_info *link = &info[link_id]; struct hostapd_data *link_bss; size_t sta_prof_len = MLE_STA_INFO_LENGTH + link->resp_sta_profile_len; --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -975,28 +975,42 @@ void ieee802_11_elems_clear_ext_ids(stru } } - -bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf) +bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf, u8 *mld_id) { const struct ieee80211_eht_ml *ml; const u8 *pos; - size_t len; + size_t len, cmn_info_len; u16 ml_control; pos = wpabuf_head(mlbuf); len = wpabuf_len(mlbuf); /* Must have control and common info length */ - if (len < sizeof(*ml) + 1 || len < sizeof(*ml) + pos[sizeof(*ml)]) + if (len < sizeof(*ml) + 1 || len < sizeof(*ml) + pos[sizeof(*ml)]) { + wpa_printf(MSG_DEBUG, "MLD: ML probe request with invalid length"); return false; + } ml = (const struct ieee80211_eht_ml *) pos; ml_control = le_to_host16(ml->ml_control); if ((ml_control & MULTI_LINK_CONTROL_TYPE_MASK) != - MULTI_LINK_CONTROL_TYPE_PROBE_REQ) + MULTI_LINK_CONTROL_TYPE_PROBE_REQ) { + wpa_printf(MSG_DEBUG, "MLD: not an ML probe req"); return false; + } + cmn_info_len = pos; + pos += sizeof(ml->ml_control); + if (ml_control & EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID) { + if (cmn_info_len < 2) { + wpa_printf(MSG_DEBUG, + "MLD: ML probe req too short for MLD ID"); + return false; + } + if (mld_id != NULL) + *mld_id = *(pos + 1); + } /* TODO parse the ML probe request and send response accordingly * Currently if ML probe request is sent, we support sending all * link's profile in the ML probe response --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -193,7 +193,7 @@ void ieee802_11_elems_clear_ids(struct i const u8 *ids, size_t num); void ieee802_11_elems_clear_ext_ids(struct ieee802_11_elems *elems, const u8 *ids, size_t num); -bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf); +bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf, u8 *mld_id); ParseRes ieee802_11_parse_link_assoc_req(const u8 *start, size_t len, struct ieee802_11_elems *elems, struct wpabuf *mlbuf,