[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