[RFC PATCH 18/34] Add PR IE with capabilities and operation mode in PASN auth1 frame
Peddolla Harshavardhan Reddy
peddolla at qti.qualcomm.com
Thu May 15 00:17:41 PDT 2025
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
src/common/proximity_ranging.c | 138 ++++++++++++++++++++++++++++++++-
src/common/proximity_ranging.h | 12 +++
2 files changed, 149 insertions(+), 1 deletion(-)
diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index f136fe06f..4826b085c 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -427,6 +427,30 @@ static int pr_validate_dira(struct pr_data *pr, struct pr_device *dev,
}
+#ifdef CONFIG_PASN
+
+static void pr_copy_channels(struct pr_channels *dst,
+ const struct pr_channels *src, bool allow_6ghz)
+{
+ size_t i, j;
+
+ if (allow_6ghz) {
+ os_memcpy(dst, src, sizeof(struct pr_channels));
+ return;
+ }
+
+ for (i = 0, j = 0; i < src->reg_classes; i++) {
+ if (is_6ghz_op_class(src->reg_class[i].reg_class))
+ continue;
+ os_memcpy(&dst->reg_class[j], &src->reg_class[i],
+ sizeof(struct pr_reg_class));
+ j++;
+ }
+ dst->reg_classes = j;
+}
+
+#endif /* CONFIG_PASN */
+
static void pr_buf_add_channel_list(struct wpabuf *buf, const char *country,
struct pr_channels *chan)
{
@@ -995,6 +1019,103 @@ void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
#ifdef CONFIG_PASN
+static void pr_buf_add_operation_mode(struct wpabuf *buf,
+ struct operation_mode *mode)
+{
+ u8 *len;
+
+ wpabuf_put_u8(buf, PR_ATTR_OPERATION_MODE);
+ /* Length to be filled */
+ len = wpabuf_put(buf, 2);
+
+ wpabuf_put_u8(buf, mode->protocol_type);
+ wpabuf_put_u8(buf, mode->role);
+ pr_buf_add_channel_list(buf, mode->country, &mode->channels);
+
+ /* Update attribute length */
+ WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
+ wpa_hexdump(MSG_DEBUG, "PR: * Operation Mode",
+ len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
+}
+
+
+static int pr_prepare_pasn_pr_ie(struct pr_data *pr, struct wpabuf *extra_ies,
+ bool add_dira, u8 ranging_role,
+ u8 ranging_type, int forced_pr_freq)
+{
+ u32 ie_type;
+ struct wpabuf *buf, *buf2;
+ struct pr_dira dira;
+ struct pr_capabilities pr_caps;
+ struct edca_capabilities edca_caps;
+ struct ntb_capabilities ntb_caps;
+ struct operation_mode op_mode;
+ struct pr_channels op_channels;
+ u8 forced_op_class = 0, forced_op_channel = 0;
+ enum hostapd_hw_mode hw_mode;
+
+ buf = wpabuf_alloc(1000);
+ if (!buf)
+ return -1;
+
+ pr_get_ranging_capabilities(pr, &pr_caps);
+ pr_buf_add_ranging_capa_info(buf, &pr_caps);
+
+ if (ranging_type & PR_EDCA_BASED_RANGING) {
+ pr_get_edca_capabilities(pr, &edca_caps);
+ pr_buf_add_edca_capa_info(buf, &edca_caps);
+ pr_copy_channels(&op_channels, &edca_caps.channels, false);
+ } else if (ranging_type & PR_NTB_OPEN_BASED_RANGING ||
+ ranging_type & PR_NTB_SECURE_LTF_BASED_RANGING) {
+ pr_get_ntb_capabilities(pr, &ntb_caps);
+ pr_buf_add_ntb_capa_info(buf, &ntb_caps);
+ pr_copy_channels(&op_channels, &ntb_caps.channels, false);
+ }
+
+ os_memset(&op_mode, 0, sizeof(struct operation_mode));
+ op_mode.role = ranging_role;
+ op_mode.protocol_type = ranging_type;
+ os_memcpy(op_mode.country, pr->cfg->country, 3);
+
+ if (forced_pr_freq) {
+ hw_mode = ieee80211_freq_to_channel_ext(forced_pr_freq, 0, 0,
+ &forced_op_class,
+ &forced_op_channel);
+ if (hw_mode == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_DEBUG, "PR: Invalid PR freq received");
+ wpabuf_free(buf);
+ return -1;
+ }
+
+ op_mode.channels.reg_classes = 1;
+ op_mode.channels.reg_class[0].channels = 1;
+ op_mode.channels.reg_class[0].channel[0] = forced_op_channel;
+ op_mode.channels.reg_class[0].reg_class = forced_op_class;
+ } else {
+ pr_copy_channels(&op_mode.channels, &op_channels, false);
+ }
+
+ pr_buf_add_operation_mode(buf, &op_mode);
+
+ /* PR Device Identity Resolution attribute */
+ if (!pr_derive_dira(pr, &dira))
+ pr_buf_add_dira(buf, &dira);
+
+ ie_type = (OUI_WFA << 8) | PR_OUI_TYPE;
+ buf2 = pr_encaps_ie(buf, ie_type);
+ wpabuf_free(buf);
+
+ if (wpabuf_tailroom(extra_ies) < wpabuf_len(buf2)) {
+ wpa_printf(MSG_ERROR,
+ "Not enough room for PR IE in PASN Frame");
+ wpabuf_free(buf2);
+ return -1;
+ }
+ wpabuf_put_buf(extra_ies, buf2);
+ wpabuf_free(buf2);
+
+ return 0;
+}
static struct wpabuf * pr_pasn_generate_rsnxe(struct pr_data *pr, int akmp)
@@ -1216,6 +1337,20 @@ int pr_initiate_pasn_auth(struct pr_data *pr, const u8 *addr, int freq,
}
pasn = dev->pasn;
+ extra_ies = wpabuf_alloc(1500);
+ if (!extra_ies)
+ return -1;
+
+ if (pr_prepare_pasn_pr_ie(pr, extra_ies, false, ranging_role,
+ ranging_type, forced_pr_freq)) {
+ wpa_printf(MSG_ERROR, "Failed to prepare PASN extra elements");
+ ret = -1;
+ goto out;
+ }
+
+ pasn_set_extra_ies(dev->pasn, wpabuf_head_u8(extra_ies),
+ wpabuf_len(extra_ies));
+
if (auth_mode == PR_PASN_AUTH_MODE_PMK) {
ret = wpa_pasn_verify(pasn, pasn->own_addr, pasn->peer_addr,
pasn->bssid, pasn->akmp, pasn->cipher,
@@ -1229,7 +1364,8 @@ int pr_initiate_pasn_auth(struct pr_data *pr, const u8 *addr, int freq,
}
if (ret)
wpa_printf(MSG_ERROR, "PR: Failed to start PASN");
-
+out:
+ wpabuf_free(extra_ies);
return ret;
}
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 780df8033..a55b55298 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -382,6 +382,18 @@ struct pr_dira {
size_t tag_len;
};
+struct operation_mode {
+ /* Bit map for Ranging Protocol type */
+ u8 protocol_type;
+
+ /* Bit map for Role-ISTA/RSTA */
+ u8 role;
+
+ char country[3];
+
+ struct pr_channels channels;
+};
+
struct pr_data * pr_init(const struct pr_config *cfg);
void pr_deinit(struct pr_data *pr);
void pr_clear_dev_iks(struct pr_data *pr);
--
2.34.1
More information about the Hostap
mailing list