[PATCH 11/34] PR: Add support to parse attributes of ranging IE

Peddolla Harshavardhan Reddy peddolla at qti.qualcomm.com
Thu Jun 19 08:37:04 PDT 2025


Add changes to get the Proximity Ranging IE, and parse this IE
based on the attributes. This IE contains ranging capabilities,
Device identity resolution attribute and such. This is also stored in
a message structure to be processed further.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
 src/common/proximity_ranging.c | 187 +++++++++++++++++++++++++++++++++
 src/common/proximity_ranging.h |  28 +++++
 2 files changed, 215 insertions(+)

diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index ebbacb798..cc8cf0bb6 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -518,17 +518,204 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country)
 }
 
 
+static int pr_parse_attribute(u8 id, const u8 *data, u16 len,
+			      struct pr_message *msg)
+{
+	switch (id) {
+	case PR_ATTR_RANGING_CAPABILITY:
+		if (len < 34) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Too short Capability attribute (length %d)",
+				   len);
+			return -1;
+		}
+		msg->pr_capability = data;
+		msg->pr_capability_len = len;
+		wpa_printf(MSG_ERROR,
+			   "PR: Device Capability: %02x Pasn Type: %02x",
+			   data[0], data[1]);
+		break;
+	case PR_ATTR_EDCA_CAPABILITY:
+		if (len < 11) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Too short EDCA Capability attribute (length %d)",
+				   len);
+			return -1;
+		}
+		msg->edca_capability = data;
+		msg->edca_capability_len = len;
+		wpa_printf(MSG_DEBUG,
+			   "PR: EDCA capable roles %u, capability %u",
+			   data[0], WPA_GET_BE16(data + 1));
+		break;
+	case PR_ATTR_NTB_CAPABILITY:
+		if (len < 13) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Too short NTB capability attribute (length %d)",
+				   len);
+			return -1;
+		}
+		msg->ntb_capability = data;
+		msg->ntb_capability_len = len;
+		wpa_printf(MSG_DEBUG,
+			   "PR: NTB capable roles %u, capabilities %u",
+			   data[0], WPA_GET_BE32(data + 1));
+		break;
+	case PR_ATTR_DEVICE_IDENTITY_RESOLUTION:
+		if (len < 17) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Too short DIRA attribute (length %d)",
+				   len);
+			return -1;
+		}
+		msg->dira = data;
+		msg->dira_len = len;
+		wpa_printf(MSG_DEBUG, "PR: DIRA cipher version %u", data[0]);
+		break;
+	case PR_ATTR_STATUS:
+		if (len != 1) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Invalid status attribute (length %d)",
+				   len);
+			return -1;
+		}
+		msg->status_ie = data;
+		msg->status_ie_len = len;
+		wpa_printf(MSG_DEBUG, "PR: PASN status=%u", data[0]);
+		break;
+	case PR_ATTR_OPERATION_MODE:
+		if (len < 7) {
+			wpa_printf(MSG_ERROR,
+				   "PR: Invalid operation mode attribute (length %d)",
+				   len);
+			return -1;
+		}
+		msg->op_mode = data;
+		msg->op_mode_len = len;
+		break;
+	default:
+		wpa_printf(MSG_DEBUG,
+			   "PR: Skipped unknown attribute %d (length %d)",
+			   id, len);
+		break;
+	}
+
+	return 0;
+}
+
+
+/**
+ * pr_parse_proximity_ranging_ie - Parse Proximity Ranging IE
+ * @buf: Concatenated PR IE(s) payload
+ * @msg: Buffer for returning parsed attributes
+ * Returns: 0 on success, -1 on failure
+ *
+ * Note: Caller is responsible for clearing the msg data structure before
+ * calling this function.
+ */
+static int pr_parse_proximity_ranging_ie(const struct wpabuf *buf,
+					 struct pr_message *msg)
+{
+	const u8 *pos = wpabuf_head_u8(buf);
+	const u8 *end = pos + wpabuf_len(buf);
+
+	wpa_printf(MSG_DEBUG, "PR: Parsing Proximity Ranging IE");
+
+	while (pos < end) {
+		u16 attr_len;
+		u8 id;
+
+		if (end - pos < 3) {
+			wpa_printf(MSG_DEBUG, "PR: Invalid PR attribute");
+			return -1;
+		}
+		id = *pos++;
+		attr_len = WPA_GET_LE16(pos);
+		pos += 2;
+		wpa_printf(MSG_DEBUG, "PR: Attribute %d length %u",
+			   id, attr_len);
+		if (attr_len > end - pos) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: Attribute underflow (len=%u left=%d)",
+				   attr_len, (int) (end - pos));
+			wpa_hexdump(MSG_MSGDUMP, "PR: Data", pos, end - pos);
+			return -1;
+		}
+		if (pr_parse_attribute(id, pos, attr_len, msg))
+			return -1;
+		pos += attr_len;
+	}
+
+	return 0;
+}
+
+
+static void pr_parse_free(struct pr_message *msg)
+{
+	wpabuf_free(msg->pr_attributes);
+	msg->pr_attributes = NULL;
+}
+
+
+/**
+ * pr_parse_ies - Parse PR message IEs
+ * @data: IEs from the message
+ * @len: Length of data buffer in octets
+ * @msg: Buffer for returning parsed attributes
+ * Returns: 0 on success, -1 on failure
+ *
+ * Note: Caller is responsible for clearing the msg data structure before
+ * calling this function.
+ *
+ * Note: Caller must free temporary memory allocations by calling
+ * pr_parse_free() when the parsed data is not needed anymore.
+ */
+static int pr_parse_ies(const u8 *data, size_t len, struct pr_message *msg)
+{
+	struct ieee802_11_elems elems;
+
+	if (ieee802_11_parse_elems(data, len, &elems, true) == ParseFailed)
+		return -1;
+
+	msg->pr_attributes = ieee802_11_vendor_ie_concat(data, len,
+							 PR_IE_VENDOR_TYPE);
+	if (msg->pr_attributes &&
+	    pr_parse_proximity_ranging_ie(msg->pr_attributes, msg)) {
+		wpa_printf(MSG_ERROR, "PR: Failed to parse PR IE data");
+		if (msg->pr_attributes)
+			wpa_hexdump_buf(MSG_MSGDUMP, "PR: PR IE data",
+					msg->pr_attributes);
+		pr_parse_free(msg);
+		return -1;
+	}
+	return 0;
+}
+
+
 void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
 			  const u8 *peer_addr, unsigned int freq)
 {
 	struct pr_device *dev;
+	struct pr_message msg;
+
+	os_memset(&msg, 0, sizeof(msg));
+	os_memcpy(msg.pr_device_addr, peer_addr, ETH_ALEN);
+
+	if (pr_parse_ies(ies, ies_len, &msg)) {
+		wpa_printf(MSG_ERROR, "PR: Failed to parse PR IEs data");
+		pr_parse_free(&msg);
+		return;
+	}
 
 	dev = pr_create_device(pr, peer_addr);
 	if (!dev) {
+		pr_parse_free(&msg);
 		wpa_printf(MSG_ERROR, "PR: Failed to create a device");
 		return;
 	}
 
 	os_get_reltime(&dev->last_seen);
 	dev->listen_freq = freq;
+
+	pr_parse_free(&msg);
 }
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 057ecb79a..3d66a0b67 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -225,6 +225,34 @@ struct pr_device {
 };
 
 
+/**
+ * struct pr_message - Proximity ranging peer information
+ */
+struct pr_message {
+	struct wpabuf *pr_attributes;
+
+	u8 pr_device_addr[ETH_ALEN];
+
+	const u8 *pr_capability;
+	size_t pr_capability_len;
+
+	const u8 *edca_capability;
+	size_t edca_capability_len;
+
+	const u8 *ntb_capability;
+	size_t ntb_capability_len;
+
+	const u8 *dira;
+	size_t dira_len;
+
+	const u8 *status_ie;
+	size_t status_ie_len;
+
+	const u8 *op_mode;
+	size_t op_mode_len;
+};
+
+
 struct pr_config {
 	u8 pasn_type;
 
-- 
2.34.1




More information about the Hostap mailing list