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

Peddolla Harshavardhan Reddy peddolla at qti.qualcomm.com
Thu May 15 00:17:34 PDT 2025


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 f5fe438bf..ae4c0e7a8 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -520,17 +520,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 85c1b1a5e..84535a8b6 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -207,6 +207,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