[RFC v2 24/99] NAN: Add validation of peer availability

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Dec 23 03:51:28 PST 2025


From: Ilan Peer <ilan.peer at intel.com>

After processing the NDL related attributes, and before
the flow continues to handle the data, validate that the
availability information is valid:

1. Parse the availability attributes.
2. Validate that the immutable schedule is covered by the
   availability attributes.
3. Validate that the NDC schedule is covered by the
   availability attributes.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/nan/nan_i.h    |  4 ++
 src/nan/nan_ndl.c  | 55 +++++++++++++++++++++++++-
 src/nan/nan_util.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index 90d6cec654..6f3cfdb77b 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -446,4 +446,8 @@ bool nan_sched_covered_by_avail_entry(struct nan_data *nan,
 				      struct nan_avail_entry *avail,
 				      struct bitfield *sched_bf,
 				      u8 map_id);
+int nan_sched_covered_by_avail_entries(struct nan_data *nan,
+				       struct dl_list *avail_entries,
+				       u8 *sched,
+				       u8 sched_len);
 #endif
diff --git a/src/nan/nan_ndl.c b/src/nan/nan_ndl.c
index afca5e55a2..4b43c13077 100644
--- a/src/nan/nan_ndl.c
+++ b/src/nan/nan_ndl.c
@@ -190,6 +190,38 @@ struct nan_ndl *nan_ndl_alloc(struct nan_data *nan)
 }
 
 
+static int nan_ndl_validate_peer_avail(struct nan_data *nan,
+				       struct nan_peer *peer)
+{
+	struct nan_ndl *ndl = peer->ndl;
+	int ret;
+
+	/* first validate if immutable is covered by the availability map */
+	ret = nan_sched_covered_by_avail_entries(nan, &peer->info.avail_entries,
+						 ndl->immut_sched,
+						 ndl->immut_sched_len);
+	if (ret <= 0) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Peer avail: Immutable is not covered by avail");
+		return -1;
+	}
+
+	/* now validate NDC schedule is covered by the availability map */
+	ret = nan_sched_covered_by_avail_entries(nan, &peer->info.avail_entries,
+						 ndl->ndc_sched,
+						 ndl->ndc_sched_len);
+	if (ret <= 0) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Peer avail: NDC is not covered by avail");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "NAN: NDL: peer NDC and immutable are covered by avail");
+	return 0;
+}
+
+
 static enum nan_ndl_status nan_ndl_res_status(struct nan_data *nan,
 					      struct nan_peer *peer)
 {
@@ -399,6 +431,7 @@ static int nan_ndl_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
 				   const struct ndl_attr_params *params)
 {
 	struct nan_ndl *ndl;
+	int ret;
 
 	wpa_printf(MSG_DEBUG, "NAN: NDL: Handle request");
 
@@ -460,6 +493,10 @@ static int nan_ndl_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
 		ndl->immut_sched_len = params->immut_sched_len;
 	}
 
+	ret = nan_ndl_validate_peer_avail(nan, peer);
+	if (!ret)
+		goto fail;
+
 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_REQ_RECV);
 
 	wpa_printf(MSG_DEBUG, "NAN: NDL: Handle request done");
@@ -474,6 +511,7 @@ static int nan_ndl_attr_handle_resp(struct nan_data *nan, struct nan_peer *peer,
 				    const struct ndl_attr_params *params)
 {
 	struct nan_ndl *ndl = peer->ndl;
+	int ret;
 
 	wpa_printf(MSG_DEBUG, "NAN: NDL: Handle response");
 
@@ -548,6 +586,7 @@ static int nan_ndl_attr_handle_resp(struct nan_data *nan, struct nan_peer *peer,
 		if (!ndl->ndc_sched) {
 			wpa_printf(MSG_DEBUG,
 				   "NAN: NDL: Resp: Failed to allocate NDC schedule");
+			ret = -1;
 			goto fail;
 		}
 
@@ -568,11 +607,16 @@ static int nan_ndl_attr_handle_resp(struct nan_data *nan, struct nan_peer *peer,
 		if (!ndl->immut_sched) {
 			wpa_printf(MSG_DEBUG,
 				   "NAN: NDL: Resp: fail allocate immutable schedule");
+			ret = -1;
 			goto fail;
 		}
 		ndl->immut_sched_len = params->immut_sched_len;
 	}
 
+	ret = nan_ndl_validate_peer_avail(nan, peer);
+	if (!ret)
+		goto fail;
+
 	wpa_printf(MSG_DEBUG, "NAN: NDL: Resp: status=%u", params->status);
 
 	ndl->status = params->status;
@@ -585,7 +629,7 @@ fail:
 	ndl->status = NAN_NDL_STATUS_REJECTED;
 	ndl->reason = NAN_REASON_RESOURCE_LIMITATION;
 	ndl->send_naf_on_error = 1;
-	return 0;
+	return ret;
 }
 
 
@@ -593,6 +637,7 @@ static int nan_ndl_attr_handle_conf(struct nan_data *nan, struct nan_peer *peer,
 				    const struct ndl_attr_params *params)
 {
 	struct nan_ndl *ndl = peer->ndl;
+	int ret;
 
 	if (!ndl) {
 		wpa_printf(MSG_DEBUG,
@@ -660,6 +705,7 @@ static int nan_ndl_attr_handle_conf(struct nan_data *nan, struct nan_peer *peer,
 		if (!ndl->ndc_sched) {
 			wpa_printf(MSG_DEBUG,
 				   "NAN: NDL: Failed to allocate NDC schedule");
+			ret = -1;
 			goto fail;
 		}
 		ndl->ndc_sched_len = params->ndc_sched_len;
@@ -677,18 +723,23 @@ static int nan_ndl_attr_handle_conf(struct nan_data *nan, struct nan_peer *peer,
 		if (!ndl->immut_sched) {
 			wpa_printf(MSG_DEBUG,
 				   "NAN: NDL: Failed to allocate immutable schedule");
+			ret = -1;
 			goto fail;
 		}
 		ndl->immut_sched_len = params->immut_sched_len;
 	}
 
+	ret = nan_ndl_validate_peer_avail(nan, peer);
+	if (!ret)
+		goto fail;
+
 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_DONE);
 	return 0;
 
 fail:
 	ndl->reason = NAN_REASON_RESOURCE_LIMITATION;
 	ndl->send_naf_on_error = 1;
-	return -1;
+	return ret;
 }
 
 
diff --git a/src/nan/nan_util.c b/src/nan/nan_util.c
index 946aed0412..ced188fc47 100644
--- a/src/nan/nan_util.c
+++ b/src/nan/nan_util.c
@@ -1135,3 +1135,101 @@ bool nan_sched_covered_by_avail_entry(struct nan_data *nan,
 
 	return ret == 1;
 }
+
+
+static int nan_sched_bf_covered_by_avail_entries(struct nan_data *nan,
+						 struct dl_list *avail_entries,
+						 struct bitfield *sched_bf,
+						 u8 map_id)
+{
+	struct nan_avail_entry *avail;
+	struct bitfield *res_bf = NULL;
+	int ret = 0;
+
+	dl_list_for_each(avail, avail_entries, struct nan_avail_entry,
+			 list) {
+		struct bitfield *avail_bf;
+
+		if (avail->map_id != map_id)
+			continue;
+
+		/* schedule can only be covered by committed/conditional */
+		if (avail->type != NAN_AVAIL_ENTRY_CTRL_TYPE_COMMITTED &&
+		    avail->type != NAN_AVAIL_ENTRY_CTRL_TYPE_COND)
+			continue;
+
+		/* convert the availability entry to bf */
+		avail_bf = nan_tbm_to_bf(nan, &avail->tbm);
+		if (!avail_bf) {
+			ret = -1;
+			goto fail;
+		}
+
+		bitfield_dump(avail_bf, "NAN: Availability entry bitmap");
+		if (!res_bf) {
+			res_bf = avail_bf;
+		} else {
+			struct bitfield *tmp_bf;
+
+			tmp_bf = bitfield_union(res_bf, avail_bf);
+			bitfield_free(avail_bf);
+
+			if (!tmp_bf) {
+				ret = -1;
+				goto fail;
+			}
+
+			bitfield_free(res_bf);
+			res_bf = tmp_bf;
+		}
+	}
+
+	ret = bitfield_is_subset(res_bf, sched_bf);
+fail:
+	wpa_printf(MSG_DEBUG,
+		   "NAN: Is bitfield schedule subset of entries=%d", ret);
+	bitfield_free(res_bf);
+	return ret;
+}
+
+
+/**
+ * nan_sched_covered_by_avail_entries - Check if schedule is covered by the
+ * list of availability attributes
+ *
+ * @nan: NAN module context from nan_init()
+ * @avail_entries: A list of availability entries (see &struct nan_avail_entry)
+ * @sched: An array with 0 or more &struct nan_sched_entry entries
+ * @sched_len: Length of the &sched array
+ * Returns 1 of schedule is covered by the entries; 0 if not and -1 on error
+ */
+int nan_sched_covered_by_avail_entries(struct nan_data *nan,
+				       struct dl_list *avail_entries,
+				       u8 *sched,
+				       u8 sched_len)
+{
+	struct dl_list sched_entries;
+	struct bitfield *sched_bf;
+	u8 map_id;
+	int ret;
+
+	if (!sched || !sched_len)
+		return 1;
+
+	dl_list_init(&sched_entries);
+	ret = nan_sched_entries_to_avail_entries(nan,
+						 &sched_entries,
+						 sched, sched_len);
+
+	sched_bf = nan_sched_to_bf(nan, &sched_entries, &map_id);
+	nan_flush_avail_entries(&sched_entries);
+
+	ret = nan_sched_bf_covered_by_avail_entries(nan, avail_entries,
+						    sched_bf, map_id);
+
+	wpa_printf(MSG_DEBUG,
+		   "NAN: NDC schedule is %s a subset of entries",
+		   ret == 1 ? "" : "NOT");
+	bitfield_free(sched_bf);
+	return ret;
+}
-- 
2.49.0




More information about the Hostap mailing list