[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