[PATCH 25/35] NAN: Support matching filters
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Mon Oct 20 05:28:00 PDT 2025
Add support for matching tx/rx filters.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
src/common/nan_de.c | 199 ++++++++++++++++++++++++++++++++++++--------
src/common/nan_de.h | 14 ++++
2 files changed, 179 insertions(+), 34 deletions(-)
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
index 50931b22d0..b9208fc89c 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -66,6 +66,10 @@ struct nan_de_service {
bool is_p2p;
bool is_pr;
bool sync;
+
+ /* Filters */
+ struct wpabuf *matching_filter_tx;
+ struct wpabuf *matching_filter_rx;
};
struct nan_de {
@@ -128,6 +132,8 @@ static void nan_de_service_free(struct nan_de_service *srv)
os_free(srv->service_name);
wpabuf_free(srv->ssi);
wpabuf_free(srv->elems);
+ wpabuf_free(srv->matching_filter_tx);
+ wpabuf_free(srv->matching_filter_rx);
os_free(srv->freq_list);
os_free(srv);
}
@@ -245,6 +251,11 @@ static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
/* Service Descriptor attribute */
sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
+ if (srv->matching_filter_tx && wpabuf_len(srv->matching_filter_tx)) {
+ sda_len += wpabuf_len(srv->matching_filter_tx) + 1;
+ ctrl |= NAN_SRV_CTRL_MATCHING_FILTER;
+ }
+
len += NAN_ATTR_HDR_LEN + sda_len;
/* Service Descriptor Extension attribute */
@@ -269,6 +280,11 @@ static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
wpabuf_put_u8(buf, req_instance_id); /* Requestor Instance ID */
wpabuf_put_u8(buf, ctrl);
+ if (ctrl & NAN_SRV_CTRL_MATCHING_FILTER) {
+ wpabuf_put_u8(buf, wpabuf_len(srv->matching_filter_tx));
+ wpabuf_put_buf(buf, srv->matching_filter_tx);
+ }
+
/* Service Descriptor Extension attribute */
if (srv->type == NAN_DE_PUBLISH || ssi) {
wpabuf_put_u8(buf, NAN_ATTR_SDEA);
@@ -904,12 +920,115 @@ static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
}
+static bool nan_de_filter_match(struct nan_de_service *srv,
+ const u8 *matching_filter,
+ size_t matching_filter_len)
+{
+ const u8 *spos, *spos_end, *ppos, *ppos_end;
+ const u8 *publish_filter = NULL, *subscribe_filter = NULL;
+ u8 publish_filter_len = 0, subscribe_filter_len = 0;
+
+ wpa_printf(MSG_DEBUG,
+ "NAN: Check matching filter for service id %d type %d",
+ srv->id, srv->type);
+
+ if (srv->type == NAN_DE_PUBLISH) {
+ if (srv->matching_filter_rx) {
+ publish_filter = wpabuf_head_u8(srv->matching_filter_rx);
+ publish_filter_len = wpabuf_len(srv->matching_filter_rx);
+ }
+ subscribe_filter = matching_filter;
+ subscribe_filter_len = matching_filter_len;
+ } else if (srv->type == NAN_DE_SUBSCRIBE) {
+ publish_filter = matching_filter;
+ publish_filter_len = matching_filter_len;
+ if (srv->matching_filter_rx) {
+ subscribe_filter =
+ wpabuf_head_u8(srv->matching_filter_rx);
+ subscribe_filter_len =
+ wpabuf_len(srv->matching_filter_rx);
+ }
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Unsupported service type %d for matching filter",
+ srv->type);
+ return false;
+ }
+
+ if (!subscribe_filter)
+ return true;
+
+ spos = subscribe_filter;
+ spos_end = subscribe_filter + subscribe_filter_len;
+
+ ppos = publish_filter;
+ ppos_end = publish_filter + publish_filter_len;
+
+ wpa_hexdump(MSG_DEBUG, "NAN: subscribe filter",
+ spos, spos_end - spos);
+ if (ppos)
+ wpa_hexdump(MSG_DEBUG, "NAN: publish filter",
+ ppos, ppos_end - ppos);
+
+ while (spos < spos_end) {
+ u8 slen, plen = 0;
+
+ slen = *spos++;
+
+ /* Invalid filter length - do not match */
+ if (slen > spos_end - spos)
+ return false;
+
+ /* Read publish filter */
+ if (ppos) {
+ plen = *ppos++;
+ if (ppos + plen > ppos_end)
+ return false;
+ }
+
+ if (slen > 0) {
+ if (!ppos)
+ return false;
+
+ /* for non zero filters, compare */
+ if (plen &&
+ (plen != slen || os_memcmp(spos, ppos, plen)))
+ return false;
+
+ /* filter matches */
+ }
+
+ spos += slen;
+
+ /*
+ * If ppos is NULL we can still have match if the
+ * subscribe filter is <0><0>...
+ */
+ if (!ppos)
+ continue;
+
+ ppos += plen;
+
+ /* Publish filter is over */
+ if (ppos >= ppos_end && spos < spos_end)
+ return false;
+ }
+
+ return true;
+}
+
+
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
const u8 *peer_addr, const u8 *a3, u8 instance_id,
+ const u8 *matching_filter,
+ size_t matching_filter_len,
u8 req_instance_id, u16 sdea_control,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len)
{
+ if (!nan_de_filter_match(srv, matching_filter, matching_filter_len))
+ return;
+
/* Skip USD logic */
if (srv->sync)
goto send_event;
@@ -946,40 +1065,6 @@ send_event:
}
-static bool nan_de_filter_match(struct nan_de_service *srv,
- const u8 *matching_filter,
- size_t matching_filter_len)
-{
- const u8 *pos, *end;
-
- /* Since we do not currently support matching_filter_rx values for the
- * local Publish function, any matching filter with at least one
- * <length,value> pair with length larger than zero implies a mismatch.
- */
-
- if (!matching_filter)
- return true;
-
- pos = matching_filter;
- end = matching_filter + matching_filter_len;
-
- while (pos < end) {
- u8 len;
-
- len = *pos++;
- if (len > end - pos)
- break;
- if (len) {
- /* A non-empty Matching Filter entry: no match since
- * there is no local matching_filter_rx. */
- return false;
- }
- }
-
- return true;
-}
-
-
static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
const u8 *peer_addr, const u8 *a3,
u8 instance_id,
@@ -1187,6 +1272,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
switch (type) {
case NAN_SRV_CTRL_PUBLISH:
nan_de_rx_publish(de, srv, peer_addr, a3, instance_id,
+ matching_filter,
+ matching_filter_len,
req_instance_id,
sdea_control, srv_proto_type,
ssi, ssi_len);
@@ -1379,6 +1466,28 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
goto fail;
}
+ if (params->match_filter_rx) {
+ srv->matching_filter_rx =
+ wpabuf_parse_bin(params->match_filter_rx);
+ if (!srv->matching_filter_rx ||
+ wpabuf_len(srv->matching_filter_rx) > 255) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to parse rx matching filter");
+ goto fail;
+ }
+ }
+
+ if (params->match_filter_tx) {
+ srv->matching_filter_tx =
+ wpabuf_parse_bin(params->match_filter_tx);
+ if (!srv->matching_filter_tx ||
+ wpabuf_len(srv->matching_filter_tx) > 255) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to parse tx matching filter");
+ goto fail;
+ }
+ }
+
srv->sync = params->sync;
/* Prepare for single and multi-channel states; starting with
@@ -1541,6 +1650,28 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
goto fail;
}
+ if (params->match_filter_rx) {
+ srv->matching_filter_rx =
+ wpabuf_parse_bin(params->match_filter_rx);
+ if (!srv->matching_filter_rx ||
+ wpabuf_len(srv->matching_filter_rx) > 255) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to parse rx matching filter");
+ goto fail;
+ }
+ }
+
+ if (params->match_filter_tx) {
+ srv->matching_filter_tx =
+ wpabuf_parse_bin(params->match_filter_tx);
+ if (!srv->matching_filter_tx ||
+ wpabuf_len(srv->matching_filter_tx) > 255) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to parse tx matching filter");
+ goto fail;
+ }
+ }
+
wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
subscribe_id, service_name ? service_name : "Ranging");
srv->id = subscribe_id;
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index 4b360907e2..837db4ef02 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -121,6 +121,13 @@ struct nan_publish_params {
/* Synchronized discovery */
bool sync;
+
+ /*
+ * Null-terminated string containing the hex-encoded
+ * representation of the matching filters.
+ */
+ const char *match_filter_tx;
+ const char *match_filter_rx;
};
/* Returns -1 on failure or >0 publish_id */
@@ -160,6 +167,13 @@ struct nan_subscribe_params {
/* Synchronized discovery */
bool sync;
+
+ /*
+ * Null-terminated string containing the hex-encoded
+ * representation of the matching filters.
+ */
+ const char *match_filter_tx;
+ const char *match_filter_rx;
};
/* Returns -1 on failure or >0 subscribe_id */
--
2.49.0
More information about the Hostap
mailing list