[RFC 24/34] NAN: Support matching filters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add support for matching tx/rx filters.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@xxxxxxxxx>
---
 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 c21164b463..b688517bb5 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -65,6 +65,10 @@ struct nan_de_service {
 	unsigned int next_publish_duration;
 	bool is_p2p;
 	bool sync;
+
+	/* Filters */
+	struct wpabuf *matching_filter_tx;
+	struct wpabuf *matching_filter_rx;
 };
 
 struct nan_de {
@@ -127,6 +131,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);
 }
@@ -244,6 +250,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 */
@@ -268,6 +279,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);
@@ -893,12 +909,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;
@@ -935,40 +1054,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,
@@ -1240,6 +1325,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);
@@ -1419,6 +1506,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
@@ -1567,6 +1676,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);
 	srv->id = subscribe_id;
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index 78bc9348fe..5c2ee6419f 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -113,6 +113,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 */
@@ -149,6 +156,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


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux