Signed-off-by: Peddolla Harshavardhan Reddy <peddolla@xxxxxxxxxxxxxxxx> --- 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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap