From: Ben Greear <greearb@xxxxxxxxxxxxxxx> Now supplicant can deal with beacons containing multiple TBTT elements. This lets MLO connections be attempted against TPLINK be800 AP. This also includes a good bit of logging changes, including conversion to wpa_dbg so that wlan name is seen in the logs. Signed-off-by: Ben Greear <greearb@xxxxxxxxxxxxxxx> --- src/common/ieee802_11_common.c | 42 +++++++++ src/common/ieee802_11_common.h | 2 + wpa_supplicant/bss.c | 18 ++++ wpa_supplicant/bss.h | 1 + wpa_supplicant/sme.c | 167 ++++++++++++++++++++------------- 5 files changed, 163 insertions(+), 67 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 8ccb24d22..74d225f7e 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1118,6 +1118,20 @@ int ieee802_11_ie_count(const u8 *ies, size_t ies_len) return count; } +void ieee802_11_ie_print(const u8 *ies, size_t ies_len) +{ + const struct element *elem; + + if (ies == NULL) { + wpa_printf(MSG_ERROR, "ie-print: ies == NULL"); + return; + } + + for_each_element(elem, ies, ies_len) + wpa_printf(MSG_ERROR, "ie-print: id: %d (0x%x) datalen: %d", + elem->id, elem->id, elem->datalen); +} + struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type) @@ -2498,6 +2512,34 @@ const u8 * get_ie(const u8 *ies, size_t len, u8 eid) return NULL; } +/** + * get_ie - Fetch a specified information element from IEs buffer + * @ies: Information elements buffer + * @len: Information elements buffer length + * @eid: Information element identifier (WLAN_EID_*) + * @nth: Return the nth element of the requested type (2 returns the second) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the nth matching information element in the IEs + * buffer or %NULL in case the element is not found. + */ +const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth) +{ + const struct element *elem; + int sofar = 0; + + if (!ies) + return NULL; + + for_each_element_id(elem, eid, ies, len) { + if ((sofar + 1) == nth) + return &elem->id; + sofar++; + } + + return NULL; +} + /** * get_ie_ext - Fetch a specified extended information element from IEs buffer diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index ef95c3591..9b2e2eb8b 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -198,6 +198,7 @@ ParseRes ieee802_11_parse_link_assoc_req(const u8 *start, size_t len, struct wpabuf *mlbuf, u8 link_id, bool show_errors); int ieee802_11_ie_count(const u8 *ies, size_t ies_len); +void ieee802_11_ie_print(const u8 *ies, size_t ies_len); struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type); struct ieee80211_hdr; @@ -262,6 +263,7 @@ extern const struct oper_class_map global_op_class[]; extern size_t global_op_class_size; const u8 * get_ie(const u8 *ies, size_t len, u8 eid); +const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth); const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext); const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type); diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 3b1646dd2..cfd107082 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -477,6 +477,9 @@ static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); wpa_bss_set_hessid(bss); + wpa_dbg(wpa_s, MSG_DEBUG, "wpa-bss-add, ies:\n"); + ieee802_11_ie_print(wpa_bss_ie_ptr(bss), bss->ie_len); + os_memset(bss->mld_addr, 0, ETH_ALEN); ml_ie = wpa_scan_get_ml_ie(res, MULTI_LINK_CONTROL_TYPE_BASIC); if (ml_ie) { @@ -1194,6 +1197,21 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) return get_ie(wpa_bss_ie_ptr(bss), bss->ie_len, ie); } +/** + * wpa_bss_get_ie_nth - Fetch a specified information element from a BSS entry + * @bss: BSS table entry + * @ie: Information element identitifier (WLAN_EID_*) + * @nth: Return the nth element of the requested type (2 returns the second) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the nth matching information element in the BSS + * entry. + */ +const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth) +{ + return get_ie_nth(wpa_bss_ie_ptr(bss), bss->ie_len, ie, nth); +} + /** * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 611da8844..4580e7981 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -160,6 +160,7 @@ struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); +const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth); const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index acb6981d9..ef054949e 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -400,6 +400,7 @@ static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT | BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA); bool ret = false; + int rnr_idx = 0; if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO)) return false; @@ -463,77 +464,107 @@ static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, ETH_ALEN); wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq; - wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u", + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u", MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id); wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id); - rnr_ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT); - if (!rnr_ie) { - wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RNR element"); - ret = true; - goto out; - } + /* Search for multiple neigh report IEs. */ + while (true) { + rnr_ie = wpa_bss_get_ie_nth(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT, ++rnr_idx); + if (!rnr_ie) { + ret = true; + if (rnr_idx == 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RNR element"); + goto out; + } + break; + } - rnr_ie_len = rnr_ie[1]; - pos = rnr_ie + 2; + rnr_ie_len = rnr_ie[1]; + pos = rnr_ie + 2; - while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) { - const struct ieee80211_neighbor_ap_info *ap_info = - (const struct ieee80211_neighbor_ap_info *) pos; - const u8 *data = ap_info->data; - size_t len = sizeof(struct ieee80211_neighbor_ap_info) + - ap_info->tbtt_info_len; + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: rnr-id-len: %d", + rnr_ie_len); - wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u", - ap_info->op_class, ap_info->channel); + while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) { + const struct ieee80211_neighbor_ap_info *ap_info = + (const struct ieee80211_neighbor_ap_info *) pos; + const u8 *data = ap_info->data; /* start of tbtt elements */ + const u8 tbtt_count = ap_info->tbtt_info_hdr >> 4; + size_t len = ap_info->tbtt_info_len * (tbtt_count + 1) + + sizeof(struct ieee80211_neighbor_ap_info); + int tbti; - if (len > rnr_ie_len) - break; + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: rnr-idx: %d op_class=%u, channel=%u len: %d rnr_ie_len: %d tbtt_info_len: %d", + rnr_idx - 1, ap_info->op_class, ap_info->channel, (int)len, rnr_ie_len, + ap_info->tbtt_info_len); - if (ap_info->tbtt_info_len < 16) { - rnr_ie_len -= len; - pos += len; - continue; - } + if (len > rnr_ie_len) + break; - data += 13; + if (ap_info->tbtt_info_len < 16) { + rnr_ie_len -= len; + pos += len; + continue; + } - wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u", - *data, *(data + 1) & 0xF); + for (tbti = 0; tbti <= tbtt_count; tbti++) { + const u8* bssid = data + 1; /* one byte into the tbtt object */ - if (*data) { - wpa_printf(MSG_DEBUG, - "MLD: Reported link not part of MLD"); - } else { - struct wpa_bss *neigh_bss = - wpa_bss_get_bssid(wpa_s, ap_info->data + 1); - u8 link_id = *(data + 1) & 0xF; - - if (neigh_bss) { - if (wpa_scan_res_match(wpa_s, 0, neigh_bss, - wpa_s->current_ssid, - 1, 0)) { - wpa_s->valid_links |= BIT(link_id); - os_memcpy(wpa_s->links[link_id].bssid, - ap_info->data + 1, ETH_ALEN); - wpa_s->links[link_id].freq = - neigh_bss->freq; + data += 13; /* advance to mld parameters */ + + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: tbtt idx: %d mld ID=%u, link ID=%u data: 0x%lx bssid=" MACSTR, + tbti, *data, *(data + 1) & 0xF, (unsigned long)data, + MAC2STR(bssid)); + + if (*data) { + wpa_dbg(wpa_s, MSG_DEBUG, + "MLD: Reported link not part of MLD"); } else { - wpa_printf(MSG_DEBUG, - "MLD: Neighbor doesn't match current SSID - skip link"); + struct wpa_bss *neigh_bss = + wpa_bss_get_bssid(wpa_s, bssid); + u8 link_id = *(data + 1) & 0xF; + + /* Intel radios won't scan 6e at first. Would need to force + * the radio to scan multiple times to fix that limitations. + */ + if (neigh_bss) { + u8 bss_params = *(data + (1 + 6 + 4 - 13)); + if (((bss_params & 0x2) /* same ssid */ + && (bss_params & (1<<6))) || /* co-located AP */ + wpa_scan_res_match(wpa_s, 0, neigh_bss, + wpa_s->current_ssid, + 1, 0)) { + wpa_s->valid_links |= BIT(link_id); + wpa_dbg(wpa_s, MSG_DEBUG, + "MLD: adding link id: %d valid_links: 0x%x", + link_id, wpa_s->valid_links); + os_memcpy(wpa_s->links[link_id].bssid, + bssid, ETH_ALEN); + if (neigh_bss) + wpa_s->links[link_id].freq = + neigh_bss->freq; + else + wpa_s->links[link_id].freq = 0; + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "MLD: Neighbor doesn't match current SSID - skip link"); + } + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "MLD: Neighbor not found in scan"); + } } - } else { - wpa_printf(MSG_DEBUG, - "MLD: Neighbor not found in scan"); - } - } + data += (ap_info->tbtt_info_len - 13); /* consume rest of tbtt */ + }/* for all tbtt */ - rnr_ie_len -= len; - pos += len; - } + rnr_ie_len -= len; + pos += len; + }/* while more neigh info */ + }/* for all neigh report IEs */ - wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links); for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { if (!(wpa_s->valid_links & BIT(i))) @@ -561,10 +592,11 @@ static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s, if (!wpa_s->valid_links) return; + wpa_dbg(wpa_s, MSG_DEBUG, "sme-ml-auth, parsing auth elements"); if (ieee802_11_parse_elems(data->auth.ies + ie_offset, data->auth.ies_len - ie_offset, &elems, 0) == ParseFailed) { - wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements"); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed parsing elements"); goto out; } @@ -584,17 +616,17 @@ static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s, if (!mld_addr) goto out; - wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr)); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr)); if (os_memcmp(wpa_s->ap_mld_addr, mld_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected " - MACSTR ")", MAC2STR(wpa_s->ap_mld_addr)); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Unexpected MLD address (expected " + MACSTR ")", MAC2STR(wpa_s->ap_mld_addr)); goto out; } return; out: - wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state"); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Authentication - clearing MLD state"); wpas_reset_mlo_info(wpa_s); } @@ -1652,14 +1684,15 @@ static int sme_external_ml_auth(struct wpa_supplicant *wpa_s, struct ieee802_11_elems elems; const u8 *mld_addr; + wpa_dbg(wpa_s, MSG_DEBUG, "external-ml-auth, parsing auth elements"); if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset, &elems, 0) == ParseFailed) { - wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements"); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed parsing elements"); return -1; } if (!elems.basic_mle || !elems.basic_mle_len) { - wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication"); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element in authentication"); if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ || status_code == WLAN_STATUS_SUCCESS || status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || @@ -1672,17 +1705,17 @@ static int sme_external_ml_auth(struct wpa_supplicant *wpa_s, mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len); if (!mld_addr) { - wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element"); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No MLD address in ML element"); return -1; } - wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr)); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr)); if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected " - MACSTR ")", - MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr)); + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Unexpected MLD address (expected " + MACSTR ")", + MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr)); return -1; } -- 2.40.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap