xref: /freebsd/contrib/wpa/src/nan/nan_ndl.c (revision 71e72c9e91c4b8007a4292e09669e8b549c29e97)
1 /*
2  * Wi-Fi Aware - NAN Data link
3  * Copyright (C) 2025 Intel Corporation
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 #include "common.h"
11 #include "utils/bitfield.h"
12 #include "common/ieee802_11_common.h"
13 #include "nan_i.h"
14 
15 
16 struct ndl_attr_params {
17 	u8 dialog_token;
18 	u8 type;
19 	u8 status;
20 	u8 reason;
21 	enum nan_ndl_setup_reason setup_reason;
22 
23 	u16 max_idle_period;
24 	u8 min_slots;
25 	u16 max_latency;
26 
27 	u8 ndc_id[ETH_ALEN];
28 	const u8 *ndc_sched;
29 	u16 ndc_sched_len;
30 
31 	const u8 *immut_sched; u16 immut_sched_len;
32 };
33 
34 
nan_ndl_state_str(enum nan_ndl_state state)35 static const char * nan_ndl_state_str(enum nan_ndl_state state)
36 {
37 #define C2S(x) case x: return #x;
38 	switch (state) {
39 	C2S(NAN_NDL_STATE_NONE)
40 	C2S(NAN_NDL_STATE_START)
41 	C2S(NAN_NDL_STATE_REQ_SENT)
42 	C2S(NAN_NDL_STATE_REQ_RECV)
43 	C2S(NAN_NDL_STATE_RES_SENT)
44 	C2S(NAN_NDL_STATE_RES_RECV)
45 	C2S(NAN_NDL_STATE_CON_SENT)
46 	C2S(NAN_NDL_STATE_CON_RECV)
47 	C2S(NAN_NDL_STATE_DONE)
48 	default:
49 		return "Invalid NAN NDL state";
50 	}
51 }
52 
53 
nan_ndl_set_state(struct nan_data * nan,struct nan_ndl * ndl,enum nan_ndl_state state)54 static void nan_ndl_set_state(struct nan_data *nan, struct nan_ndl *ndl,
55 			      enum nan_ndl_state state)
56 {
57 	wpa_printf(MSG_DEBUG, "NAN: NDL: State %s (%u) --> %s (%u)",
58 		   nan_ndl_state_str(ndl->state), ndl->state,
59 		   nan_ndl_state_str(state), state);
60 
61 	ndl->state = state;
62 }
63 
64 
nan_ndl_time_bitmap_print(struct nan_data * nan,struct nan_time_bitmap * tbm,const char * type)65 static void nan_ndl_time_bitmap_print(struct nan_data *nan,
66 				      struct nan_time_bitmap *tbm,
67 				      const char *type)
68 {
69 	if (!tbm->len)
70 		return;
71 
72 	wpa_printf(MSG_DEBUG,
73 		   "channel sched: %s: dur=%u, per=%u, off=%u, len=%u",
74 		   type, tbm->duration, tbm->period, tbm->offset, tbm->len);
75 
76 	wpa_printf(MSG_DEBUG, "bitmap[0:3]: 0x%x:0x%x:0x%x:0x%x",
77 		   tbm->bitmap[0], tbm->bitmap[1],
78 		   tbm->bitmap[2], tbm->bitmap[3]);
79 }
80 
81 
nan_ndl_chan_sched_print(struct nan_data * nan,size_t idx,struct nan_chan_schedule * cs)82 static void nan_ndl_chan_sched_print(struct nan_data *nan, size_t idx,
83 				     struct nan_chan_schedule *cs)
84 {
85 	wpa_printf(MSG_DEBUG, "NAN: sched: index=%zu, map_id=%u",
86 		   idx, cs->map_id);
87 
88 	wpa_printf(MSG_DEBUG,
89 		   "channel sched: chan: freq=%u, c1=%d, c2=%d, bandwidth=%d",
90 		   cs->chan.freq, cs->chan.center_freq1, cs->chan.center_freq2,
91 		   cs->chan.bandwidth);
92 
93 	nan_ndl_time_bitmap_print(nan, &cs->committed, "committed");
94 	nan_ndl_time_bitmap_print(nan, &cs->conditional, "conditional");
95 }
96 
97 
nan_ndl_sched_print(struct nan_data * nan,struct nan_schedule * sched)98 static void nan_ndl_sched_print(struct nan_data *nan,
99 				struct nan_schedule *sched)
100 {
101 	size_t i;
102 
103 	wpa_printf(MSG_DEBUG,
104 		   "NAN: sched: map_ids=0x%x, n_chans=%u, seq_id=%u",
105 		   sched->map_ids_bitmap,
106 		   sched->n_chans, sched->sequence_id);
107 
108 	for (i = 0; i < sched->n_chans; i++)
109 		nan_ndl_chan_sched_print(nan, i, &sched->chans[i]);
110 }
111 
112 
nan_ndl_clear(struct nan_data * nan,struct nan_peer * peer)113 static void nan_ndl_clear(struct nan_data *nan, struct nan_peer *peer)
114 {
115 	struct nan_ndl *ndl = peer->ndl;
116 
117 	wpa_printf(MSG_DEBUG,
118 		   "NAN: NDL: Clear info for peer=" MACSTR " state=%s (%u)",
119 		   MAC2STR(peer->nmi_addr),
120 		   nan_ndl_state_str(peer->ndl->state), peer->ndl->state);
121 
122 	nan_clear_peer_schedule(nan, peer);
123 
124 	os_free(ndl->ndc_sched);
125 	ndl->ndc_sched = NULL;
126 	ndl->ndc_sched_len = 0;
127 
128 	os_free(ndl->immut_sched);
129 	ndl->immut_sched = NULL;
130 	ndl->immut_sched_len = 0;
131 
132 	ndl->dialog_token = 0;
133 	ndl->max_idle_period = 0;
134 
135 	os_memset(ndl->ndc_id, 0, sizeof(ndl->ndc_id));
136 
137 	ndl->peer_qos.max_latency = NAN_QOS_MAX_LATENCY_NO_PREF;
138 	ndl->local_qos.max_latency = NAN_QOS_MAX_LATENCY_NO_PREF;
139 
140 	ndl->setup_reason = NAN_NDL_SETUP_REASON_NONE;
141 }
142 
143 
144 /*
145  * nan_ndl_reset - Reset the NDL state
146  *
147  * @nan: NAN module context from nan_init()
148  * @peer: The peer that requires NDL setup reset
149  */
nan_ndl_reset(struct nan_data * nan,struct nan_peer * peer)150 void nan_ndl_reset(struct nan_data *nan, struct nan_peer *peer)
151 {
152 	wpa_printf(MSG_DEBUG, "NAN: NDL: Reset state for peer=" MACSTR,
153 		   MAC2STR(peer->nmi_addr));
154 
155 	if (!peer->ndl) {
156 		wpa_printf(MSG_DEBUG, "NAN: NDL: Reset: no NDL");
157 		return;
158 	}
159 
160 	nan_ndl_clear(nan, peer);
161 
162 	os_free(peer->ndl);
163 	peer->ndl = NULL;
164 }
165 
166 
nan_ndl_alloc(struct nan_data * nan)167 static struct nan_ndl * nan_ndl_alloc(struct nan_data *nan)
168 {
169 	struct nan_ndl *ndl;
170 
171 	wpa_printf(MSG_DEBUG, "NAN: NDL: Allocating a new NDL");
172 
173 	ndl = os_zalloc(sizeof(struct nan_ndl));
174 	if (!ndl) {
175 		wpa_printf(MSG_INFO, "NAN: NDL: Failed to allocate NDL");
176 		return NULL;
177 	}
178 
179 	ndl->status = NAN_NDL_STATUS_ACCEPTED;
180 	ndl->reason = NAN_REASON_RESERVED;
181 
182 	ndl->local_qos.min_slots = NAN_QOS_MIN_SLOTS_NO_PREF;
183 	ndl->local_qos.max_latency = NAN_QOS_MAX_LATENCY_NO_PREF;
184 
185 	ndl->peer_qos.min_slots = NAN_QOS_MIN_SLOTS_NO_PREF;
186 	ndl->peer_qos.max_latency = NAN_QOS_MAX_LATENCY_NO_PREF;
187 
188 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_NONE);
189 
190 	return ndl;
191 }
192 
193 
nan_ndl_validate_peer_avail(struct nan_data * nan,struct nan_peer * peer)194 bool nan_ndl_validate_peer_avail(struct nan_data *nan, struct nan_peer *peer)
195 {
196 	struct nan_ndl *ndl = peer->ndl;
197 	bool ret;
198 
199 	/* First, validate if immutable is covered by the availability map */
200 	ret = nan_sched_covered_by_avail_entries(nan, &peer->info.avail_entries,
201 						 ndl->immut_sched,
202 						 ndl->immut_sched_len);
203 	if (!ret) {
204 		wpa_printf(MSG_DEBUG,
205 			   "NAN: Peer avail: Immutable is not covered by avail");
206 		peer->ndl->reason = NAN_REASON_IMMUTABLE_UNACCEPTABLE;
207 		return ret;
208 	}
209 
210 	/* Now validate NDC schedule is covered by the availability map */
211 	ret = nan_sched_covered_by_avail_entries(nan, &peer->info.avail_entries,
212 						 ndl->ndc_sched,
213 						 ndl->ndc_sched_len);
214 	if (!ret) {
215 		wpa_printf(MSG_DEBUG,
216 			   "NAN: Peer avail: NDC is not covered by avail");
217 		peer->ndl->reason = NAN_REASON_NDL_UNACCEPTABLE;
218 		return ret;
219 	}
220 
221 	wpa_printf(MSG_DEBUG,
222 		   "NAN: NDL: Peer NDC and immutable are covered by avail");
223 
224 	return ret;
225 }
226 
227 
228 /**
229  * enum nan_ndl_ver - Verdict of comparing local availability to given schedule
230  * @NAN_NDL_VER_SCHED_SUBSET_OF_LOCAL: The schedule is a subset of the local one
231  * @NAN_NDL_VER_SCHED_SUPERSET_OF_LOCAL: The schedule is a superset of the local
232  *     one
233  * @NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL: The schedule is identical to the local
234  * @NAN_NDL_VER_SCHED_NONE: None of the above. This means that there was no
235  *     match or an error occurred.
236  */
237 enum nan_ndl_ver {
238 	NAN_NDL_VER_SCHED_SUBSET_OF_LOCAL,
239 	NAN_NDL_VER_SCHED_SUPERSET_OF_LOCAL,
240 	NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL,
241 	NAN_NDL_VER_SCHED_NONE,
242 };
243 
244 
245 /*
246  * nan_ndl_match_sched_vs_common - Compare the given schedule to the common
247  * availability of the local device and the peer device, comparing channel
248  * configuration and bitmap.
249  *
250  * @nan: NAN module context from nan_init()
251  * @avail_entries: Peer availability entries
252  * @sched: A byte array with 0 or more &struct nan_sched_entry entries
253  * @sched_len: Length of the &sched array
254  * @common_bf: Bitfield representing the intersection of local and peer
255  *     availability
256  * @op_class: Local operating class
257  * @cbm: Local channel bitmap
258  *
259  * Returns one of enum nan_ndl_ver. In case of on an error
260  * NAN_NDL_VER_SCHED_NONE is returned.
261  *
262  * The function first verifies that the given schedule is covered by the peer
263  * availability. Then, the function verifies that the schedule is covered by
264  * the common availability between local and peer.
265  *
266  * The function can (and should be used) to check the schedule constraints of
267  * an NDC schedule and/or immutable schedule.
268  *
269  * Note: In case that &sched is NULL or &sched_len is 0, returns
270  * NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL, meaning no constraints.
271  */
272 static enum nan_ndl_ver
nan_ndl_match_sched_vs_common(struct nan_data * nan,struct dl_list * avail_entries,const u8 * sched,size_t sched_len,const struct bitfield * common_bf,u8 op_class,u16 cbm)273 nan_ndl_match_sched_vs_common(struct nan_data *nan,
274 			      struct dl_list *avail_entries,
275 			      const u8 *sched, size_t sched_len,
276 			      const struct bitfield *common_bf,
277 			      u8 op_class, u16 cbm)
278 {
279 	struct dl_list sched_entries;
280 	struct bitfield *sched_bf;
281 	u8 map_id;
282 	enum nan_ndl_ver verdict;
283 	int ret;
284 	enum nan_reason reason;
285 
286 	/* No constraints */
287 	if (!sched || !sched_len)
288 		return NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL;
289 
290 	/* Convert the schedule entries to availability entries  */
291 	ret = nan_sched_entries_to_avail_entries(nan, &sched_entries,
292 						 sched, sched_len);
293 	if (ret)
294 		return NAN_NDL_VER_SCHED_NONE;
295 
296 	/* Convert the schedule availability entries to map ID and bitfield */
297 	sched_bf = nan_sched_to_bf(nan, &sched_entries, &map_id, &reason);
298 	nan_flush_avail_entries(&sched_entries);
299 
300 	/*
301 	 * Now that the schedule is represented as a bitfield and the map ID is
302 	 * obtained, compare these against the peer availability entries and
303 	 * channel configuration. A successful match means that the schedule is
304 	 * covered by the peer availability entries for the given channel.
305 	 */
306 	ret = nan_sched_bf_covered_by_avail_entries_and_chan(
307 		nan, avail_entries, sched_bf, map_id, op_class, cbm);
308 	if (ret) {
309 		int ret2;
310 
311 		/*
312 		 * After validating the schedule against the peer availability,
313 		 * match the peer availability with the local one.
314 		 */
315 		ret = bitfield_is_subset(common_bf, sched_bf);
316 		ret2 = bitfield_is_subset(sched_bf, common_bf);
317 
318 		if (ret < 0 || ret2 < 0)
319 			verdict = NAN_NDL_VER_SCHED_NONE;
320 		else if (ret == 1 && ret2 == 1)
321 			verdict = NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL;
322 		else if (ret == 1)
323 			verdict = NAN_NDL_VER_SCHED_SUBSET_OF_LOCAL;
324 		else
325 			verdict = NAN_NDL_VER_SCHED_SUPERSET_OF_LOCAL;
326 	} else {
327 		verdict = NAN_NDL_VER_SCHED_NONE;
328 	}
329 
330 	bitfield_free(sched_bf);
331 	return verdict;
332 }
333 
334 
nan_ndl_meets_qos(struct nan_data * nan,const struct nan_peer * peer,const struct bitfield * common_bf)335 bool nan_ndl_meets_qos(struct nan_data *nan, const struct nan_peer *peer,
336 		       const struct bitfield *common_bf)
337 {
338 	size_t size, max_latency, i;
339 	u16 crbs;
340 
341 	/* No QoS requirements */
342 	if (peer->ndl->peer_qos.min_slots == NAN_QOS_MIN_SLOTS_NO_PREF &&
343 	    peer->ndl->peer_qos.max_latency == NAN_QOS_MAX_LATENCY_NO_PREF) {
344 		wpa_printf(MSG_DEBUG, "NAN: No QoS requirements from peer");
345 		return true;
346 	}
347 
348 	size = bitfield_size(common_bf);
349 
350 	/*
351 	 * The common map covers an entire 8192 period with 16 TU slots. For
352 	 * minimal time slots need to only consider the first 32 slots
353 	 */
354 	for (i = 0, crbs = 0, max_latency = 0; i < size; i++) {
355 		if (bitfield_is_set(common_bf, i)) {
356 			if (i < 32)
357 				crbs++;
358 
359 			max_latency = 0;
360 		} else if (peer->ndl->peer_qos.max_latency !=
361 			   NAN_QOS_MAX_LATENCY_NO_PREF) {
362 			max_latency++;
363 			if (max_latency > peer->ndl->peer_qos.max_latency) {
364 				wpa_printf(MSG_DEBUG,
365 					   "NAN: Failed to meet max latency");
366 				return false;
367 			}
368 		}
369 	}
370 
371 	if (peer->ndl->peer_qos.min_slots != NAN_QOS_MIN_SLOTS_NO_PREF &&
372 	    peer->ndl->peer_qos.min_slots >= crbs) {
373 		wpa_printf(MSG_DEBUG, "NAN: Failed to meet min slots");
374 		return false;
375 	}
376 
377 	return true;
378 }
379 
380 
nan_ndl_determine_status(struct nan_data * nan,struct nan_peer * peer,bool can_counter,enum nan_reason * reason)381 static enum nan_ndl_status nan_ndl_determine_status(struct nan_data *nan,
382 						    struct nan_peer *peer,
383 						    bool can_counter,
384 						    enum nan_reason *reason)
385 {
386 	struct nan_schedule *sched = &nan->sched;
387 	struct bitfield *common_bf = NULL, *ndc_bf = NULL, *track_ndc_bf = NULL;
388 	enum nan_ndl_ver verdict;
389 	size_t i;
390 	int ret;
391 
392 	*reason = NAN_REASON_RESERVED;
393 
394 	ndc_bf = nan_tbm_to_bf(nan, &sched->ndc);
395 	if (!ndc_bf) {
396 		wpa_printf(MSG_DEBUG,
397 			   "NAN: NDL: Failed to build NDC bitfield from schedule");
398 
399 		*reason = NAN_REASON_UNSPECIFIED_REASON;
400 		return NAN_NDL_STATUS_REJECTED;
401 	}
402 
403 	track_ndc_bf = bitfield_alloc(bitfield_size(ndc_bf));
404 	if (!track_ndc_bf) {
405 		wpa_printf(MSG_DEBUG,
406 			   "NAN: NDL: Failed to allocate bitfield for tracking NDC");
407 
408 		bitfield_free(ndc_bf);
409 		*reason = NAN_REASON_UNSPECIFIED_REASON;
410 		return NAN_NDL_STATUS_REJECTED;
411 	}
412 
413 	/*
414 	 * Iterate over all the channels included in the local schedule. For
415 	 * each channel, convert the committed and conditional slots to a
416 	 * bitfield object and extract the operating class and channel bitmap.
417 	 *
418 	 * Using the operating class and channel bitmap find the peer
419 	 * availability on that channel and intersect it with the local one:
420 	 *
421 	 * - Accumulate the intersection of the NDC bitmap with the bitmap of
422 	 *   all channels with the same map ID as the NDC, so that whether the
423 	 *   NDC is covered by the local availability can be verified later.
424 	 * - Accumulate the intersection of local and peer availability for
425 	 *   all channels, so that the QoS requirements can be verified later.
426 	 */
427 	wpa_printf(MSG_DEBUG, "NAN: NDL: n_chans=%u, ndc_map_id=%u",
428 		   sched->n_chans, sched->ndc_map_id);
429 
430 	for (i = 0; i < sched->n_chans; i++) {
431 		struct bitfield *own_chan_bf = NULL, *peer_chan_bf = NULL;
432 		u16 cbm, pri_cbm;
433 		u8 map_id, op_class;
434 
435 		/* Convert the schedule for the current channel to bitfield */
436 		ret = nan_convert_chan_sched_to_bf(nan, &sched->chans[i],
437 						   &own_chan_bf, &map_id,
438 						   &op_class, &cbm, &pri_cbm);
439 		if (ret) {
440 			wpa_printf(MSG_DEBUG,
441 				   "NAN: NDL: Failed to convert chan sched to bitfield");
442 
443 			*reason = NAN_REASON_UNSPECIFIED_REASON;
444 			ret = NAN_NDL_STATUS_REJECTED;
445 			goto out;
446 		}
447 
448 		if (sched->ndc_map_id == map_id) {
449 			struct bitfield *tmp = bitfield_dup(ndc_bf);
450 
451 			if (tmp) {
452 				bitfield_intersect_in_place(tmp, own_chan_bf);
453 				bitfield_union_in_place(track_ndc_bf, tmp);
454 				bitfield_free(tmp);
455 			}
456 		}
457 
458 		/* Get the peer availability for the current channel */
459 		peer_chan_bf = nan_avail_entries_to_bf(
460 			nan, &peer->info.avail_entries,
461 			op_class, cbm, pri_cbm);
462 		if (!peer_chan_bf) {
463 			bitfield_free(own_chan_bf);
464 			continue;
465 		}
466 
467 		ret = bitfield_intersect_in_place(own_chan_bf, peer_chan_bf);
468 		bitfield_free(peer_chan_bf);
469 		peer_chan_bf = NULL;
470 
471 		if (ret < 0) {
472 			wpa_printf(MSG_DEBUG,
473 				   "NAN: NDL: Failed to intersect own and peer chan bitfields");
474 
475 			bitfield_free(own_chan_bf);
476 
477 			*reason = NAN_REASON_INVALID_AVAILABILITY;
478 			ret = NAN_NDL_STATUS_REJECTED;
479 			goto out;
480 		}
481 
482 		/*
483 		 * Accumulate schedule common for the local and peer device, so
484 		 * it can later be used to verify QoS requirements, etc.
485 		 */
486 		if (common_bf) {
487 			ret = bitfield_union_in_place(common_bf, own_chan_bf);
488 			if (ret) {
489 				wpa_printf(MSG_DEBUG,
490 					   "NAN: NDL: Failed to unify own chan bitfields");
491 
492 				bitfield_free(own_chan_bf);
493 
494 				*reason = NAN_REASON_UNSPECIFIED_REASON;
495 				ret = NAN_NDL_STATUS_REJECTED;
496 				goto out;
497 			}
498 		} else {
499 			common_bf = bitfield_dup(own_chan_bf);
500 			if (!common_bf) {
501 				wpa_printf(MSG_DEBUG,
502 					   "NAN: NDL: Failed to dup own chan bitfield");
503 
504 				bitfield_free(own_chan_bf);
505 
506 				*reason = NAN_REASON_UNSPECIFIED_REASON;
507 				ret = NAN_NDL_STATUS_REJECTED;
508 				goto out;
509 			}
510 		}
511 
512 		bitfield_free(own_chan_bf);
513 		own_chan_bf = NULL;
514 	}
515 
516 	if (!common_bf) {
517 		wpa_printf(MSG_DEBUG,
518 			   "NAN: NDL: No common availability between local and peer");
519 
520 		*reason = NAN_REASON_INVALID_AVAILABILITY;
521 		ret = NAN_NDL_STATUS_CONTINUED;
522 		goto out;
523 	}
524 
525 	/*
526 	 * Verify that the schedule NDC bitmap is covered by the local
527 	 * availability for the map used for the NDC.
528 	 */
529 	if (!bitfield_is_subset(ndc_bf, track_ndc_bf)) {
530 		wpa_printf(MSG_DEBUG,
531 			   "NAN: NDL: NDC bitmap is not covered by local availability on NDC channel");
532 
533 		*reason = NAN_REASON_UNSPECIFIED_REASON;
534 		ret = NAN_NDL_STATUS_REJECTED;
535 		goto out;
536 	}
537 
538 	bitfield_free(ndc_bf);
539 	ndc_bf = track_ndc_bf;
540 	track_ndc_bf = NULL;
541 
542 	/*
543 	 * In case the peer included an immutable schedule, the immutable
544 	 * schedule must be covered by the common schedule. If not, reject.
545 	 */
546 	verdict = nan_ndl_match_sched_vs_common(nan,
547 						&peer->info.avail_entries,
548 						peer->ndl->immut_sched,
549 						peer->ndl->immut_sched_len,
550 						common_bf, 0, 0);
551 	if (verdict != NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL &&
552 	    verdict != NAN_NDL_VER_SCHED_SUBSET_OF_LOCAL) {
553 		wpa_printf(MSG_DEBUG,
554 			   "NAN: Schedule does not cover immutable. Reject");
555 
556 		*reason = NAN_REASON_IMMUTABLE_UNACCEPTABLE;
557 		ret = NAN_NDL_STATUS_REJECTED;
558 		goto out;
559 	}
560 
561 	/*
562 	 * In case the peer included an NDC, check if it is identical to
563 	 * the locally generated one.
564 	 *
565 	 * Note: The list of peer availability entries needs to be iterated
566 	 * again, as the NDC map ID must also be matched.
567 	 */
568 	verdict = nan_ndl_match_sched_vs_common(nan, &peer->info.avail_entries,
569 						peer->ndl->ndc_sched,
570 						peer->ndl->ndc_sched_len,
571 						ndc_bf, 0, 0);
572 	if (verdict != NAN_NDL_VER_SCHED_IDENTICAL_OF_LOCAL) {
573 		wpa_printf(MSG_DEBUG,
574 			   "NAN: Response NDC does not match req NDC");
575 
576 		*reason = NAN_REASON_INVALID_AVAILABILITY;
577 		ret = NAN_NDL_STATUS_CONTINUED;
578 		goto out;
579 	}
580 
581 	if (nan_ndl_meets_qos(nan, peer, common_bf)) {
582 		wpa_printf(MSG_DEBUG, "NAN: NDL QoS requirements met. Accept");
583 		ret = NAN_NDL_STATUS_ACCEPTED;
584 	} else {
585 		wpa_printf(MSG_DEBUG, "NAN: NDL QoS requirements not met");
586 		*reason = NAN_REASON_QOS_UNACCEPTABLE;
587 		ret = NAN_NDL_STATUS_CONTINUED;
588 	}
589 
590 out:
591 	bitfield_free(common_bf);
592 	bitfield_free(ndc_bf);
593 	bitfield_free(track_ndc_bf);
594 
595 	wpa_printf(MSG_DEBUG,
596 		   "NAN: NDL: Response status=%s (%u)",
597 		   ret == NAN_NDL_STATUS_ACCEPTED ? "ACCEPTED" :
598 		   ret == NAN_NDL_STATUS_CONTINUED ? "CONTINUED" :
599 		   "REJECTED",
600 		   ret);
601 
602 	if (ret == NAN_NDL_STATUS_CONTINUED && !can_counter) {
603 		wpa_printf(MSG_DEBUG,
604 			   "NAN: Cannot counter, change verdict to REJECTED");
605 		ret = NAN_NDL_STATUS_REJECTED;
606 	}
607 
608 	return ret;
609 }
610 
611 
612 /*
613  * nan_ndl_setup - Handle NDL setup either as an initiator or a responder
614  *
615  * @nan: NAN module context from nan_init()
616  * @peer: The peer for which the NDL is being setup
617  * @params: NDP setup request parameters
618  * @dialog_token: Dialog token to be used for the NDL setup messages. Should be
619  *      used for a new NDL only.
620  * Returns: 0 on success, negative on failure.
621 
622  * It is possible that an NDL with the peer already exists in which case it
623  * would be reused. Otherwise, new NDL establishment will be started.
624  */
nan_ndl_setup(struct nan_data * nan,struct nan_peer * peer,const struct nan_ndp_params * params,u8 dialog_token)625 int nan_ndl_setup(struct nan_data *nan, struct nan_peer *peer,
626 		  const struct nan_ndp_params *params,
627 		  u8 dialog_token)
628 {
629 	struct nan_ndl *ndl;
630 	enum nan_reason reason;
631 
632 	if (!peer->ndl) {
633 		if (params->type != NAN_NDP_ACTION_REQ) {
634 			wpa_printf(MSG_DEBUG,
635 				   "NAN: NDL: Invalid action; expecting request");
636 			return -1;
637 		}
638 
639 		peer->ndl = nan_ndl_alloc(nan);
640 		if (!peer->ndl)
641 			return -1;
642 
643 		ndl = peer->ndl;
644 	} else {
645 		ndl = peer->ndl;
646 
647 		ndl->send_naf_on_error = 0;
648 
649 		wpa_printf(MSG_DEBUG,
650 			   "NAN: NDL: peer=" MACSTR ". state=%s (%u)",
651 			   MAC2STR(peer->nmi_addr),
652 			   nan_ndl_state_str(ndl->state),
653 			   ndl->state);
654 
655 		if (ndl->state == NAN_NDL_STATE_DONE) {
656 			wpa_printf(MSG_DEBUG,
657 				   "NAN: NDL: Already established");
658 			return 0;
659 		}
660 
661 		if (!((params->type == NAN_NDP_ACTION_RESP &&
662 		       ndl->state == NAN_NDL_STATE_REQ_RECV) ||
663 		      (params->type == NAN_NDP_ACTION_CONF &&
664 		       ndl->state == NAN_NDL_STATE_RES_RECV))) {
665 			wpa_printf(MSG_DEBUG,
666 				   "NAN: NDL: Invalid action type=%u, state=%u",
667 				   params->type, ndl->state);
668 			return -1;
669 		}
670 
671 		if (params->u.resp.status == NAN_NDP_STATUS_REJECTED) {
672 			reason = params->u.resp.reason_code;
673 			goto out_fail;
674 		}
675 	}
676 
677 	if (!params->sched_valid) {
678 		wpa_printf(MSG_DEBUG, "NAN: NDL: no valid schedule");
679 		reason = NAN_REASON_INVALID_PARAMETERS;
680 		goto out_fail;
681 	}
682 
683 	wpabuf_free(nan->sched.elems);
684 	os_memcpy(&nan->sched, &params->sched, sizeof(nan->sched));
685 	nan_ndl_sched_print(nan, &nan->sched);
686 
687 	/* Copy elems buffer */
688 	if (params->sched.elems) {
689 		nan->sched.elems =
690 			wpabuf_alloc_copy(wpabuf_head(params->sched.elems),
691 					  wpabuf_len(params->sched.elems));
692 		if (!nan->sched.elems) {
693 			reason = NAN_REASON_UNSPECIFIED_REASON;
694 			goto out_fail;
695 		}
696 	}
697 
698 	nan_ndl_sched_print(nan, &nan->sched);
699 
700 	if (is_zero_ether_addr(ndl->ndc_id)) {
701 		if (os_get_random(ndl->ndc_id, ETH_ALEN) < 0) {
702 			reason = NAN_REASON_UNSPECIFIED_REASON;
703 			goto out_fail;
704 		}
705 		wpa_printf(MSG_DEBUG,
706 			   "NAN: NDL: generated NDC ID " MACSTR,
707 			   MAC2STR(ndl->ndc_id));
708 	}
709 
710 	ndl->local_qos.min_slots = params->qos.min_slots;
711 	ndl->local_qos.max_latency = params->qos.max_latency;
712 
713 	if (ndl->state == NAN_NDL_STATE_NONE) {
714 		ndl->dialog_token = dialog_token;
715 		nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_START);
716 		ndl->status = NAN_NDL_STATUS_CONTINUED;
717 	} else {
718 		ndl->status = nan_ndl_determine_status(nan, peer,
719 						       ndl->state ==
720 						       NAN_NDL_STATE_REQ_RECV,
721 						       &reason);
722 		if (ndl->status == NAN_NDL_STATUS_REJECTED)
723 			goto out_fail;
724 	}
725 
726 	ndl->setup_reason = NAN_NDL_SETUP_REASON_NDP;
727 
728 	wpa_printf(MSG_DEBUG,
729 		   "NAN: NDL: success: state=%s (%u). Dialog token=%u",
730 		   nan_ndl_state_str(ndl->state), ndl->state,
731 		   ndl->dialog_token);
732 
733 	return 0;
734 
735 out_fail:
736 	wpa_printf(MSG_DEBUG, "NAN: NDL: Failed. reason=%u", reason);
737 	if (ndl->state == NAN_NDL_STATE_REQ_RECV ||
738 	    ndl->state == NAN_NDL_STATE_RES_RECV) {
739 		ndl->status = NAN_NDL_STATUS_REJECTED;
740 		ndl->reason = reason;
741 		ndl->send_naf_on_error = 1;
742 
743 		/*
744 		 * Do not modify the state. Full cleanup will be done on Tx
745 		 * status handling.
746 		 */
747 	} else {
748 		nan_ndl_clear(nan, peer);
749 	}
750 
751 	return -1;
752 }
753 
754 
755 /**
756  * nan_ndl_setup_failure - Indicate failure during NDL setup
757  * @nan: NAN module context from nan_init()
758  * @peer: NAN peer
759  * @reason: Failure reason
760  * @reset_state: Reset the NDL state if true.
761  */
nan_ndl_setup_failure(struct nan_data * nan,struct nan_peer * peer,enum nan_reason reason,bool reset_state)762 void nan_ndl_setup_failure(struct nan_data *nan, struct nan_peer *peer,
763 			   enum nan_reason reason, bool reset_state)
764 {
765 	struct nan_ndl *ndl = peer->ndl;
766 
767 	wpa_printf(MSG_DEBUG,
768 		   "NAN: NDL: Setup failure: peer " MACSTR
769 		   ". state=%s (%u). reason=%u",
770 		   MAC2STR(peer->nmi_addr), nan_ndl_state_str(ndl->state),
771 		   ndl->state, reason);
772 
773 	if (reset_state) {
774 		nan_ndl_reset(nan, peer);
775 	} else {
776 		ndl->status = NAN_NDL_STATUS_REJECTED;
777 		ndl->reason = reason;
778 	}
779 }
780 
781 
nan_ndl_parse_ndc_attr(struct nan_data * nan,const struct ieee80211_ndc * ndc_attr,u16 ndc_attr_len,u8 * ndc_id,const u8 ** ndc_schedule,u16 * ndc_schedule_len)782 static int nan_ndl_parse_ndc_attr(struct nan_data *nan,
783 				  const struct ieee80211_ndc *ndc_attr,
784 				  u16 ndc_attr_len, u8 *ndc_id,
785 				  const u8 **ndc_schedule,
786 				  u16 *ndc_schedule_len)
787 {
788 	u16 ext_ndc_len;
789 
790 	/* Consider only the selected NDC */
791 	if (!(ndc_attr->ctrl & NAN_NDC_CTRL_SELECTED))
792 		return -1;
793 
794 	if (ndc_attr_len < sizeof(*ndc_attr))
795 		return -1;
796 	ext_ndc_len = ndc_attr_len - sizeof(*ndc_attr);
797 
798 	if (ext_ndc_len <= sizeof(struct nan_sched_entry)) {
799 		wpa_printf(MSG_DEBUG, "NAN: NDL: Request with invalid len=%u",
800 			   ndc_attr_len);
801 		return -1;
802 	}
803 
804 	os_memcpy(ndc_id, ndc_attr->ndc_id, sizeof(ndc_attr->ndc_id));
805 	*ndc_schedule_len = ext_ndc_len;
806 	*ndc_schedule = (const u8 *) (ndc_attr + 1);
807 
808 	wpa_printf(MSG_DEBUG, "NAN: NDL: ndc_id=" MACSTR " schedule_len=%u",
809 		   MAC2STR(ndc_id), *ndc_schedule_len);
810 	return 0;
811 }
812 
813 
nan_ndl_parse_qos_attr(struct nan_data * nan,const struct ieee80211_nan_qos * qos_attr,u16 qos_attr_len,u8 * min_slots,u16 * max_latency)814 static int nan_ndl_parse_qos_attr(struct nan_data *nan,
815 				  const struct ieee80211_nan_qos *qos_attr,
816 				  u16 qos_attr_len,
817 				  u8 *min_slots, u16 *max_latency)
818 {
819 	*min_slots = qos_attr->min_slots;
820 	*max_latency = le_to_host16(qos_attr->max_latency);
821 
822 	wpa_printf(MSG_DEBUG, "NAN: QoS attr: min_slots=%u, max_latency=%u",
823 		   *min_slots, *max_latency);
824 	return 0;
825 }
826 
827 
nan_ndl_attr_handle_req(struct nan_data * nan,struct nan_peer * peer,const struct ndl_attr_params * params)828 static int nan_ndl_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
829 				   const struct ndl_attr_params *params)
830 {
831 	struct nan_ndl *ndl;
832 	int ret;
833 
834 	wpa_printf(MSG_DEBUG, "NAN: NDL: Handle request");
835 
836 	if (peer->ndl) {
837 		wpa_printf(MSG_DEBUG,
838 			   "NAN: NDL: Request while another establishment is ongoing");
839 		return -1;
840 	}
841 
842 	if (params->status != NAN_NDL_STATUS_CONTINUED) {
843 		wpa_printf(MSG_DEBUG,
844 			   "NAN: NDL: Request with invalid status=%u",
845 			   params->status);
846 		return -1;
847 	}
848 
849 	peer->ndl = nan_ndl_alloc(nan);
850 	if (!peer->ndl)
851 		return -1;
852 
853 	ndl = peer->ndl;
854 
855 	ndl->status = NAN_NDL_STATUS_CONTINUED;
856 
857 	ndl->dialog_token = params->dialog_token;
858 	ndl->max_idle_period = params->max_idle_period;
859 	ndl->setup_reason = params->setup_reason;
860 
861 	if (!is_zero_ether_addr(params->ndc_id)) {
862 		os_memcpy(ndl->ndc_id, params->ndc_id, sizeof(ndl->ndc_id));
863 
864 		if (params->ndc_sched && params->ndc_sched_len) {
865 			os_free(ndl->ndc_sched);
866 			ndl->ndc_sched_len = 0;
867 
868 			ndl->ndc_sched = os_memdup(params->ndc_sched,
869 						   params->ndc_sched_len);
870 			if (!ndl->ndc_sched) {
871 				wpa_printf(MSG_INFO,
872 					   "NAN: NDL: Failed to copy NDC schedule");
873 				goto fail;
874 			}
875 
876 			ndl->ndc_sched_len = params->ndc_sched_len;
877 		}
878 	}
879 
880 	ndl->peer_qos.min_slots = params->min_slots;
881 	ndl->peer_qos.max_latency = params->max_latency;
882 
883 	if (params->immut_sched && params->immut_sched_len) {
884 		ndl->immut_sched = os_memdup(params->immut_sched,
885 					     params->immut_sched_len);
886 		if (!ndl->immut_sched) {
887 			wpa_printf(MSG_INFO,
888 				   "NAN: NDL: Failed to copy immutable schedule");
889 			goto fail;
890 		}
891 		ndl->immut_sched_len = params->immut_sched_len;
892 	}
893 
894 	ret = nan_ndl_validate_peer_avail(nan, peer);
895 	if (!ret) {
896 		ndl->status = NAN_NDL_STATUS_REJECTED;
897 		ndl->send_naf_on_error = 1;
898 	}
899 
900 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_REQ_RECV);
901 
902 	wpa_printf(MSG_DEBUG, "NAN: NDL: Handle request done");
903 	return 0;
904 
905 fail:
906 	nan_ndl_reset(nan, peer);
907 	return -1;
908 }
909 
910 
nan_ndl_attr_handle_resp(struct nan_data * nan,struct nan_peer * peer,const struct ndl_attr_params * params)911 static int nan_ndl_attr_handle_resp(struct nan_data *nan, struct nan_peer *peer,
912 				    const struct ndl_attr_params *params)
913 {
914 	struct nan_ndl *ndl = peer->ndl;
915 	int ret;
916 
917 	wpa_printf(MSG_DEBUG, "NAN: NDL: Handle response");
918 
919 	if (!ndl) {
920 		wpa_printf(MSG_DEBUG, "NAN: NDL: Unexpected response");
921 		return -1;
922 	}
923 
924 	if (ndl->state != NAN_NDL_STATE_REQ_SENT) {
925 		if (ndl->state != NAN_NDL_STATE_START) {
926 			wpa_printf(MSG_DEBUG,
927 				   "NAN: NDL: Response while state=%s (%u)",
928 				   nan_ndl_state_str(ndl->state), ndl->state);
929 			return -1;
930 		}
931 
932 		/*
933 		 * Due to races with the driver, it is possible that the
934 		 * response is received before an ACK is indicated. Allow the
935 		 * processing of the attribute, and if all parameters are OK,
936 		 * fast forward the state machine below.
937 		 */
938 		wpa_printf(MSG_DEBUG,
939 			   "NAN: NDL: Response received before Tx status");
940 	}
941 
942 	ndl->send_naf_on_error = 0;
943 	ndl->status = params->status;
944 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_RES_RECV);
945 
946 	if (ndl->dialog_token != params->dialog_token) {
947 		wpa_printf(MSG_DEBUG,
948 			   "NAN: NDL: Resp: Invalid dialog token (%u != %u)",
949 			   ndl->dialog_token, params->dialog_token);
950 		return -1;
951 	}
952 
953 	if (params->status != NAN_NDL_STATUS_CONTINUED &&
954 	    params->status != NAN_NDL_STATUS_ACCEPTED) {
955 		wpa_printf(MSG_DEBUG,
956 			   "NAN: NDL: Resp: Rejected. status=%u, reason=%u",
957 			   params->status, params->reason);
958 
959 		ndl->reason = params->reason;
960 		ndl->status = NAN_NDL_STATUS_REJECTED;
961 		return 0;
962 	}
963 
964 	if (is_zero_ether_addr(params->ndc_id)) {
965 		wpa_printf(MSG_DEBUG, "NAN: NDL: Response without NDC");
966 		return -1;
967 	}
968 
969 	if (os_memcmp(ndl->ndc_id, params->ndc_id, sizeof(ndl->ndc_id)) != 0) {
970 		wpa_printf(MSG_DEBUG, "NAN: NDL: Resp: ndc_id changed");
971 		os_memcpy(ndl->ndc_id, params->ndc_id, sizeof(ndl->ndc_id));
972 	}
973 
974 	ndl->max_idle_period = params->max_idle_period;
975 	ndl->peer_qos.min_slots = params->min_slots;
976 	ndl->peer_qos.max_latency = params->max_latency;
977 
978 	/* TODO: validate that in case an ACCEPTED NDL and an NDC, the NDC
979 	 * schedule is covered by the local device committed availability.
980 	 */
981 	if (params->ndc_sched && params->ndc_sched_len) {
982 		os_free(ndl->ndc_sched);
983 		ndl->ndc_sched_len = 0;
984 
985 		ndl->ndc_sched = os_memdup(params->ndc_sched,
986 					   params->ndc_sched_len);
987 		if (!ndl->ndc_sched) {
988 			wpa_printf(MSG_INFO,
989 				   "NAN: NDL: Resp: Failed to allocate NDC schedule");
990 			ret = -1;
991 			goto fail;
992 		}
993 
994 		ndl->ndc_sched_len = params->ndc_sched_len;
995 	}
996 
997 	if (params->immut_sched && params->immut_sched_len) {
998 		if (params->status == NAN_NDL_STATUS_ACCEPTED) {
999 			wpa_printf(MSG_DEBUG,
1000 				   "NAN: NDL: Resp: Immutable not allowed with status == accept");
1001 			return -1;
1002 		}
1003 
1004 		os_free(ndl->immut_sched);
1005 		ndl->immut_sched_len = 0;
1006 		ndl->immut_sched = os_memdup(params->immut_sched,
1007 					     params->immut_sched_len);
1008 		if (!ndl->immut_sched) {
1009 			wpa_printf(MSG_INFO,
1010 				   "NAN: NDL: Resp: fail allocate immutable schedule");
1011 			ret = -1;
1012 			goto fail;
1013 		}
1014 		ndl->immut_sched_len = params->immut_sched_len;
1015 	}
1016 
1017 	ret = nan_ndl_validate_peer_avail(nan, peer);
1018 	if (!ret)
1019 		goto fail;
1020 
1021 	wpa_printf(MSG_DEBUG, "NAN: NDL: Resp: status=%u", params->status);
1022 
1023 	ndl->status = params->status;
1024 	if (params->status == NAN_NDL_STATUS_ACCEPTED)
1025 		nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_DONE);
1026 
1027 	return 0;
1028 
1029 fail:
1030 	nan_ndl_clear(nan, peer);
1031 	ndl->status = NAN_NDL_STATUS_REJECTED;
1032 	ndl->reason = NAN_REASON_RESOURCE_LIMITATION;
1033 	ndl->send_naf_on_error = 1;
1034 	return ret;
1035 }
1036 
1037 
nan_ndl_attr_handle_conf(struct nan_data * nan,struct nan_peer * peer,const struct ndl_attr_params * params)1038 static int nan_ndl_attr_handle_conf(struct nan_data *nan, struct nan_peer *peer,
1039 				    const struct ndl_attr_params *params)
1040 {
1041 	struct nan_ndl *ndl = peer->ndl;
1042 	int ret;
1043 
1044 	if (!ndl) {
1045 		wpa_printf(MSG_DEBUG, "NAN: NDL: Confirm without an NDL");
1046 		return -1;
1047 	}
1048 
1049 	if (ndl->state != NAN_NDL_STATE_RES_SENT) {
1050 		wpa_printf(MSG_DEBUG,
1051 			   "NAN: NDL: Confirm while not expecting one");
1052 
1053 		if (ndl->state != NAN_NDL_STATE_REQ_RECV ||
1054 		    ndl->status != NAN_NDL_STATUS_CONTINUED)
1055 			return -1;
1056 
1057 		/*
1058 		 * Due to races with the driver, it is possible that the
1059 		 * response is received before an ACK is indicated. Allow the
1060 		 * processing of the attribute, and if all parameters are OK,
1061 		 * fast forward the state machine below.
1062 		 */
1063 		wpa_printf(MSG_DEBUG,
1064 			   "NAN: NDL: Confirm received before Tx status");
1065 	}
1066 
1067 	ndl->send_naf_on_error = 0;
1068 	ndl->status = params->status;
1069 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_CON_RECV);
1070 
1071 	if (params->status != NAN_NDL_STATUS_ACCEPTED) {
1072 		wpa_printf(MSG_DEBUG,
1073 			   "NAN: NDL: Confirm was not accepted. status=%u, reason=%u",
1074 			   params->status, params->reason);
1075 		ndl->status = NAN_NDL_STATUS_REJECTED;
1076 		ndl->reason = params->reason;
1077 		return 0;
1078 	}
1079 
1080 	if (ndl->dialog_token != params->dialog_token) {
1081 		wpa_printf(MSG_DEBUG,
1082 			   "NAN: NDL: Confirm with invalid dialog token (%u != %u)",
1083 			   ndl->dialog_token, params->dialog_token);
1084 		return -1;
1085 	}
1086 
1087 	if (!is_zero_ether_addr(params->ndc_id) &&
1088 	    os_memcmp(ndl->ndc_id, params->ndc_id, sizeof(ndl->ndc_id)) != 0) {
1089 		wpa_printf(MSG_DEBUG, "NAN: NDL: Confirm: ndc_id changed");
1090 		os_memcpy(ndl->ndc_id, params->ndc_id, sizeof(ndl->ndc_id));
1091 	}
1092 
1093 	ndl->max_idle_period = params->max_idle_period;
1094 	ndl->peer_qos.min_slots = params->min_slots;
1095 	ndl->peer_qos.max_latency = params->max_latency;
1096 
1097 	/* TODO: validate that the NDC schedule is covered by the local device
1098 	 * committed availability.
1099 	 */
1100 	if (params->ndc_sched && params->ndc_sched_len) {
1101 		os_free(ndl->ndc_sched);
1102 		ndl->ndc_sched_len = 0;
1103 
1104 		ndl->ndc_sched = os_memdup(params->ndc_sched,
1105 					   params->ndc_sched_len);
1106 		if (!ndl->ndc_sched) {
1107 			wpa_printf(MSG_INFO,
1108 				   "NAN: NDL: Failed to allocate NDC schedule");
1109 			ret = -1;
1110 			goto fail;
1111 		}
1112 		ndl->ndc_sched_len = params->ndc_sched_len;
1113 	}
1114 
1115 	/* TODO: validate that the immutable schedule is covered by the local
1116 	 * device committed availability.
1117 	 */
1118 	if (params->immut_sched && params->immut_sched_len) {
1119 		os_free(ndl->immut_sched);
1120 		ndl->immut_sched_len = 0;
1121 
1122 		ndl->immut_sched = os_memdup(params->immut_sched,
1123 					     params->immut_sched_len);
1124 		if (!ndl->immut_sched) {
1125 			wpa_printf(MSG_INFO,
1126 				   "NAN: NDL: Failed to allocate immutable schedule");
1127 			ret = -1;
1128 			goto fail;
1129 		}
1130 		ndl->immut_sched_len = params->immut_sched_len;
1131 	}
1132 
1133 	ret = nan_ndl_validate_peer_avail(nan, peer);
1134 	if (!ret)
1135 		goto fail;
1136 
1137 	nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_DONE);
1138 	return 0;
1139 
1140 fail:
1141 	ndl->reason = NAN_REASON_RESOURCE_LIMITATION;
1142 	ndl->send_naf_on_error = 1;
1143 	return ret;
1144 }
1145 
1146 
1147 /*
1148  * nan_ndl_handle_ndl_attr - Handle NDL attribute and update local state
1149  *
1150  * @nan: NAN module context from nan_init()
1151  * @peer: The peer from which the original message was received
1152  * @msg: Parsed NAN Action frame
1153  * Returns: 0 on success, negative on failure to parse the attributes etc.
1154  *
1155  * As part of the NDL attribute handling, the function also parses NDC and QoS
1156  * attributes.
1157  */
nan_ndl_handle_ndl_attr(struct nan_data * nan,struct nan_peer * peer,struct nan_msg * msg)1158 int nan_ndl_handle_ndl_attr(struct nan_data *nan, struct nan_peer *peer,
1159 			    struct nan_msg *msg)
1160 {
1161 	const struct ieee80211_ndl *ndl_attr;
1162 	const u8 *ndl_attr_ext;
1163 	struct ndl_attr_params params;
1164 	u16 ndl_attr_len, ndl_attr_ext_len;
1165 	u16 control;
1166 	u8 ctrl_setup_reason;
1167 	u8 ndc_ok;
1168 	int ret;
1169 
1170 	os_memset(&params, 0, sizeof(params));
1171 
1172 	if (!msg || !peer)
1173 		return -1;
1174 
1175 	/*
1176 	 * It is possible that we receive a confirm NAF before the TX status
1177 	 * of the previous NAF was processed. If NDL was accepted, the confirm
1178 	 * would not include the NDL attribute, thus fast forward to state
1179 	 * "done" here.
1180 	 */
1181 	if (msg->oui_subtype == NAN_SUBTYPE_DATA_PATH_CONFIRM &&
1182 	    peer->ndl &&
1183 	    peer->ndl->state == NAN_NDL_STATE_REQ_RECV &&
1184 	    peer->ndl->status == NAN_NDL_STATUS_ACCEPTED) {
1185 		wpa_printf(MSG_DEBUG,
1186 			   "NAN: NDL is accepted - fast forward to state done");
1187 		nan_ndl_set_state(nan, peer->ndl, NAN_NDL_STATE_DONE);
1188 	}
1189 
1190 	if (peer->ndl && peer->ndl->state == NAN_NDL_STATE_DONE) {
1191 		wpa_printf(MSG_DEBUG, "NAN: NDL: NDL already done");
1192 		return 0;
1193 	}
1194 
1195 	if (!msg->attrs.ndl)
1196 		return 0;
1197 
1198 	ndl_attr = (const struct ieee80211_ndl *) msg->attrs.ndl;
1199 	ndl_attr_len = msg->attrs.ndl_len;
1200 	if (ndl_attr_len < sizeof(struct ieee80211_ndl))
1201 		return -1;
1202 
1203 	ndl_attr_ext = (const u8 *) (ndl_attr + 1);
1204 	ndl_attr_ext_len = ndl_attr_len - sizeof(struct ieee80211_ndl);
1205 
1206 	params.type = BITS(ndl_attr->type_and_status, NAN_NDL_TYPE_MASK,
1207 			   NAN_NDL_TYPE_POS);
1208 
1209 	params.status = BITS(ndl_attr->type_and_status, NAN_NDL_STATUS_MASK,
1210 			     NAN_NDL_STATUS_POS);
1211 	params.reason = ndl_attr->reason_code;
1212 	control = le_to_host16(ndl_attr->ctrl);
1213 
1214 	if (peer->ndl)
1215 		wpa_printf(MSG_DEBUG,
1216 			   "NAN: NDL: curr: state=%s (%d), status=%d",
1217 			   nan_ndl_state_str(peer->ndl->state),
1218 			   peer->ndl->state, peer->ndl->status);
1219 	else
1220 		wpa_printf(MSG_DEBUG, "NAN: NDL: NDL does not exist");
1221 
1222 	params.dialog_token = ndl_attr->dialog_token;
1223 
1224 	wpa_printf(MSG_DEBUG,
1225 		   "NAN: NDL: dialog=%u, type=0x%x, status=0x%x, ctrl=0x%x",
1226 		   params.dialog_token, params.type, params.status, control);
1227 
1228 	if (control & NAN_NDL_CTRL_PEER_ID_PRESENT) {
1229 		if (ndl_attr_ext_len < 1) {
1230 			wpa_printf(MSG_DEBUG,
1231 				   "NAN: NDL: Request with invalid len=%u, control=0x%x",
1232 				   ndl_attr_len, control);
1233 			return -1;
1234 		}
1235 
1236 		/*
1237 		 * Peer ID is no longer used. It is considered as reserved in
1238 		 * Wi-Fi Aware Specification v4.0, Table 105 (NDL attribute
1239 		 * format). Just skip it.
1240 		 */
1241 		ndl_attr_ext++;
1242 		ndl_attr_ext_len--;
1243 	}
1244 
1245 	if (control & NAN_NDL_CTRL_MAX_IDLE_PERIOD_PRESENT) {
1246 		if (ndl_attr_ext_len < 2) {
1247 			wpa_printf(MSG_DEBUG,
1248 				   "NAN: NDL: Request with invalid len=%u, control=0x%x",
1249 				   ndl_attr_len, control);
1250 			return -1;
1251 		}
1252 
1253 		params.max_idle_period = WPA_GET_LE16(ndl_attr_ext);
1254 		ndl_attr_ext += 2;
1255 		ndl_attr_ext_len -= 2;
1256 
1257 		wpa_printf(MSG_DEBUG, "NAN: NDL: max_idle_period=%u",
1258 			   params.max_idle_period);
1259 	}
1260 
1261 	ndc_ok = 1;
1262 	if (control & NAN_NDL_CTRL_NDC_ATTR_PRESENT) {
1263 		struct nan_attrs_entry *n;
1264 
1265 		ret = -1;
1266 		dl_list_for_each(n, &msg->attrs.ndc, struct nan_attrs_entry,
1267 				 list) {
1268 			ret = nan_ndl_parse_ndc_attr(
1269 				nan, (const struct ieee80211_ndc *) n->ptr,
1270 				n->len, params.ndc_id,
1271 				&params.ndc_sched, &params.ndc_sched_len);
1272 			if (!ret)
1273 				break;
1274 		}
1275 
1276 		if (ret)
1277 			ndc_ok = 0;
1278 	} else if (params.type == NAN_NDL_TYPE_RESPONSE) {
1279 		ndc_ok = 0;
1280 	}
1281 
1282 	if (!ndc_ok && params.status != NAN_NDL_STATUS_REJECTED) {
1283 		wpa_printf(MSG_DEBUG, "NAN: NDL: Missing valid selected NDC");
1284 		return -1;
1285 	}
1286 
1287 	params.min_slots = NAN_QOS_MIN_SLOTS_NO_PREF;
1288 	params.max_latency = NAN_QOS_MAX_LATENCY_NO_PREF;
1289 	if (control & NAN_NDL_CTRL_NDL_QOS_ATTR_PRESENT) {
1290 		if (!msg->attrs.ndl_qos) {
1291 			wpa_printf(MSG_DEBUG,
1292 				   "NAN: NDL QoS attribute not present but control flag is set");
1293 			return -1;
1294 		}
1295 		ret = nan_ndl_parse_qos_attr(
1296 			nan,
1297 			(const struct ieee80211_nan_qos *) msg->attrs.ndl_qos,
1298 			msg->attrs.ndl_qos_len, &params.min_slots,
1299 			&params.max_latency);
1300 		if (ret)
1301 			return ret;
1302 	}
1303 
1304 	if (control & NAN_NDL_CTRL_IMMUT_SCHED_PRESENT) {
1305 		if (ndl_attr_ext_len <= sizeof(struct nan_sched_entry)) {
1306 			wpa_printf(MSG_DEBUG,
1307 				   "NAN: NDL: Request with invalid len=%u, control=0x%x",
1308 				ndl_attr_len, control);
1309 			return -1;
1310 		}
1311 
1312 		params.immut_sched = ndl_attr_ext;
1313 		params.immut_sched_len = ndl_attr_ext_len;
1314 	}
1315 
1316 	ctrl_setup_reason = BITS(control, NAN_NDL_CTRL_NDL_SETUP_REASON_MASK,
1317 				 NAN_NDL_CTRL_NDL_SETUP_REASON_POS);
1318 	if (ctrl_setup_reason == NAN_NDL_CTRL_NDL_SETUP_REASON_NDP) {
1319 		params.setup_reason = NAN_NDL_SETUP_REASON_NDP;
1320 	} else {
1321 		wpa_printf(MSG_DEBUG,
1322 			   "NAN: NDL: Unknown setup reason. Assume NDP");
1323 		params.setup_reason = NAN_NDL_SETUP_REASON_NDP;
1324 	}
1325 
1326 	wpa_printf(MSG_DEBUG,
1327 		   "NAN: NDL: max_idle_period=%u, immutable len=%u",
1328 		   params.max_idle_period, params.immut_sched_len);
1329 
1330 	switch (params.type) {
1331 	case NAN_NDL_TYPE_REQUEST:
1332 		return nan_ndl_attr_handle_req(nan, peer, &params);
1333 	case NAN_NDL_TYPE_RESPONSE:
1334 		return nan_ndl_attr_handle_resp(nan, peer, &params);
1335 	case NAN_NDL_TYPE_CONFIRM:
1336 		return nan_ndl_attr_handle_conf(nan, peer, &params);
1337 	default:
1338 		return -1;
1339 	}
1340 }
1341 
1342 
1343 /**
1344  * nan_ndl_add_avail_attrs - Add availability attributes
1345  * @nan: NAN module context from nan_init()
1346  * @peer: NAN peer for NDL establishment
1347  * @buf: Frame buffer to which the attribute would be added
1348  * Returns: 0 on success, negative on failure
1349  *
1350  * An availability attribute is added for each map (identified by map ID) in the
1351  * NDL schedule. Each attribute holds an availability entry for committed slots
1352  * and an availability entry for conditional slots.
1353  */
nan_ndl_add_avail_attrs(struct nan_data * nan,const struct nan_peer * peer,struct wpabuf * buf)1354 int nan_ndl_add_avail_attrs(struct nan_data *nan, const struct nan_peer *peer,
1355 			    struct wpabuf *buf)
1356 {
1357 	struct nan_schedule *sched;
1358 	u8 type_for_conditional = NAN_AVAIL_ENTRY_CTRL_TYPE_COND;
1359 
1360 	if (!peer || !peer->ndl)
1361 		return -1;
1362 
1363 	sched = &nan->sched;
1364 
1365 	wpa_printf(MSG_DEBUG,
1366 		   "NAN: NDL: Add Avail attribute. state=%s, status=%u",
1367 		   nan_ndl_state_str(peer->ndl->state), peer->ndl->status);
1368 
1369 	if (sched->n_chans < 1) {
1370 		if (peer->ndl->status == NAN_NDL_STATUS_REJECTED) {
1371 			wpa_printf(MSG_DEBUG,
1372 				   "NAN: NDL: Rejected. Not adding availability attributes");
1373 			return 0;
1374 		}
1375 
1376 		wpa_printf(MSG_DEBUG,
1377 			   "NAN: NDL: Cannot build availability without channels");
1378 		return -1;
1379 	}
1380 
1381 	/* In case the NDL exchange was complete successfully, consider the
1382 	 * conditional entries as committed, as this is expected by the spec.
1383 	 */
1384 	if (peer->ndl->status == NAN_NDL_STATUS_ACCEPTED) {
1385 		wpa_printf(MSG_DEBUG,
1386 			   "NAN: NDL: Add conditional entry as committed");
1387 		type_for_conditional = NAN_AVAIL_ENTRY_CTRL_TYPE_COMMITTED;
1388 	}
1389 
1390 	return nan_add_avail_attrs(nan, sched->sequence_id,
1391 				   sched->map_ids_bitmap,
1392 				   type_for_conditional,
1393 				   sched->n_chans, sched->chans, buf, true);
1394 }
1395 
1396 
1397 /**
1398  * nan_ndl_add_ndl_attr - Add NDL attribute to frame
1399  * @nan: NAN module context from nan_init()
1400  * @peer: NAN peer for NDL establishment
1401  * @buf: Frame buffer to which the attribute would be added
1402  * Returns: 0 on success, negative on failure.
1403  */
nan_ndl_add_ndl_attr(struct nan_data * nan,const struct nan_peer * peer,struct wpabuf * buf)1404 int nan_ndl_add_ndl_attr(struct nan_data *nan, const struct nan_peer *peer,
1405 			 struct wpabuf *buf)
1406 {
1407 	struct nan_ndl *ndl;
1408 	struct nan_schedule *sched = &nan->sched;
1409 	u16 ndl_ctrl = 0;
1410 	u8 *len_ptr;
1411 	u8 type;
1412 
1413 	if (!peer || !peer->ndl)
1414 		return -1;
1415 
1416 	ndl = peer->ndl;
1417 
1418 	wpa_printf(MSG_DEBUG, "NAN: Add NDL attribute. state=%s, status=%u",
1419 		   nan_ndl_state_str(ndl->state), ndl->status);
1420 
1421 	if (nan->cfg->max_ndl_idle_period) {
1422 		wpa_printf(MSG_DEBUG, "NAN: NDL: max idle period=%u",
1423 			   nan->cfg->max_ndl_idle_period);
1424 
1425 		ndl_ctrl |= NAN_NDL_CTRL_MAX_IDLE_PERIOD_PRESENT;
1426 	}
1427 
1428 	switch (ndl->state) {
1429 	case NAN_NDL_STATE_NONE:
1430 	case NAN_NDL_STATE_REQ_SENT:
1431 	case NAN_NDL_STATE_RES_SENT:
1432 	case NAN_NDL_STATE_CON_SENT:
1433 	default:
1434 		return -1;
1435 	case NAN_NDL_STATE_START:
1436 		type = NAN_NDL_TYPE_REQUEST;
1437 		if (sched->ndc.len)
1438 			ndl_ctrl |= NAN_NDL_CTRL_NDC_ATTR_PRESENT;
1439 		break;
1440 	case NAN_NDL_STATE_REQ_RECV:
1441 		type = NAN_NDL_TYPE_RESPONSE;
1442 		if (sched->ndc.len &&
1443 		    ndl->status != NAN_NDL_STATUS_REJECTED)
1444 			ndl_ctrl |= NAN_NDL_CTRL_NDC_ATTR_PRESENT;
1445 		break;
1446 	case NAN_NDL_STATE_RES_RECV:
1447 		type = NAN_NDL_TYPE_CONFIRM;
1448 		if (sched->ndc.len &&
1449 		    ndl->status != NAN_NDL_STATUS_REJECTED)
1450 			ndl_ctrl |= NAN_NDL_CTRL_NDC_ATTR_PRESENT;
1451 		break;
1452 	case NAN_NDL_STATE_DONE:
1453 		wpa_printf(MSG_DEBUG,
1454 			   "NAN: NDL: Done. Not adding NDL attribute");
1455 		return 0;
1456 	}
1457 
1458 	/* QoS attribute is going to be added */
1459 	if (ndl->local_qos.max_latency != NAN_QOS_MAX_LATENCY_NO_PREF ||
1460 	    ndl->local_qos.min_slots != NAN_QOS_MIN_SLOTS_NO_PREF)
1461 		ndl_ctrl |= NAN_NDL_CTRL_NDL_QOS_ATTR_PRESENT;
1462 
1463 	wpabuf_put_u8(buf, NAN_ATTR_NDL);
1464 	len_ptr = wpabuf_put(buf, 2);
1465 
1466 	wpabuf_put_u8(buf, ndl->dialog_token);
1467 	wpabuf_put_u8(buf, type | (ndl->status << NAN_NDL_STATUS_POS));
1468 	wpabuf_put_u8(buf, ndl->reason);
1469 	wpabuf_put_u8(buf, ndl_ctrl);
1470 
1471 	if (nan->cfg->max_ndl_idle_period)
1472 		wpabuf_put_le16(buf, nan->cfg->max_ndl_idle_period);
1473 
1474 	WPA_PUT_LE16(len_ptr, (u8 *) wpabuf_put(buf, 0) - len_ptr - 2);
1475 
1476 	return 0;
1477 }
1478 
1479 
1480 /**
1481  * nan_ndl_add_ndc_attr - Add NDC attribute to frame
1482  * @nan: NAN module context from nan_init()
1483  * @peer: NAN peer for NDL establishment
1484  * @buf: Frame buffer to which the attribute would be added
1485  * Returns: 0 on success, negative on failure.
1486  */
nan_ndl_add_ndc_attr(struct nan_data * nan,const struct nan_peer * peer,struct wpabuf * buf)1487 int nan_ndl_add_ndc_attr(struct nan_data *nan, const struct nan_peer *peer,
1488 			 struct wpabuf *buf)
1489 {
1490 	struct nan_ndl *ndl;
1491 	struct nan_schedule *sched = &nan->sched;
1492 	u8 ndc_ctrl = NAN_NDC_CTRL_SELECTED;
1493 	u16 sched_entry_ctrl = 0;
1494 
1495 	if (!peer || !peer->ndl)
1496 		return -1;
1497 
1498 	ndl = peer->ndl;
1499 
1500 	if (ndl->state != NAN_NDL_STATE_START &&
1501 	    ndl->state != NAN_NDL_STATE_REQ_RECV &&
1502 	    ndl->state != NAN_NDL_STATE_RES_RECV)
1503 		return 0;
1504 
1505 	wpa_printf(MSG_DEBUG, "NAN: Add NDC attribute. state=%s, status=%u",
1506 		   nan_ndl_state_str(ndl->state), ndl->status);
1507 
1508 	/* NDC attribute is optional in case of reject */
1509 	if (ndl->status == NAN_NDL_STATUS_REJECTED)
1510 		return 0;
1511 
1512 	/*
1513 	 * NDC attribute for NDP Request is optional. In all other cases it is
1514 	 * mandatory
1515 	 */
1516 	if (!sched->ndc.len) {
1517 		if (ndl->state != NAN_NDL_STATE_START) {
1518 			wpa_printf(MSG_DEBUG, "NAN: NDL: No NDC to add");
1519 			return -1;
1520 		}
1521 
1522 		return 0;
1523 	}
1524 
1525 	wpabuf_put_u8(buf, NAN_ATTR_NDC);
1526 	wpabuf_put_le16(buf, sizeof(struct ieee80211_ndc) +
1527 			sizeof(struct nan_sched_entry) +
1528 			sched->ndc.len);
1529 
1530 	wpabuf_put_data(buf, ndl->ndc_id, sizeof(ndl->ndc_id));
1531 	wpabuf_put_u8(buf, ndc_ctrl);
1532 
1533 	/* Add the schedule entry */
1534 	wpabuf_put_u8(buf, sched->ndc_map_id);
1535 
1536 	sched_entry_ctrl |= sched->ndc.duration <<
1537 		NAN_TIME_BM_CTRL_BIT_DURATION_POS;
1538 	sched_entry_ctrl |= sched->ndc.period <<
1539 		NAN_TIME_BM_CTRL_PERIOD_POS;
1540 	sched_entry_ctrl |= sched->ndc.offset <<
1541 		NAN_TIME_BM_CTRL_START_OFFSET_POS;
1542 
1543 	wpabuf_put_le16(buf, sched_entry_ctrl);
1544 
1545 	/* Add the time bitmap */
1546 	wpabuf_put_u8(buf, sched->ndc.len);
1547 	wpabuf_put_data(buf, sched->ndc.bitmap, sched->ndc.len);
1548 
1549 	return 0;
1550 }
1551 
1552 
1553 /**
1554  * nan_ndl_add_qos_attr - Add QOS attribute to frame
1555  * @nan: NAN module context from nan_init()
1556  * @peer: NAN peer for NDL establishment
1557  * @buf: Frame buffer to which the attribute would be added
1558  * Returns: 0 on success, negative on failure.
1559  */
nan_ndl_add_qos_attr(struct nan_data * nan,const struct nan_peer * peer,struct wpabuf * buf)1560 int nan_ndl_add_qos_attr(struct nan_data *nan,
1561 			 const struct nan_peer *peer,
1562 			 struct wpabuf *buf)
1563 {
1564 	struct nan_ndl *ndl;
1565 
1566 	if (!peer || !peer->ndl)
1567 		return -1;
1568 
1569 	ndl = peer->ndl;
1570 
1571 	wpa_printf(MSG_DEBUG, "NAN: Add QoS attribute. state=%s, status=%u",
1572 		   nan_ndl_state_str(ndl->state), ndl->status);
1573 
1574 	switch (ndl->state) {
1575 	case NAN_NDL_STATE_START:
1576 	case NAN_NDL_STATE_REQ_RECV:
1577 	case NAN_NDL_STATE_RES_RECV:
1578 		break;
1579 	case NAN_NDL_STATE_NONE:
1580 	case NAN_NDL_STATE_REQ_SENT:
1581 	case NAN_NDL_STATE_RES_SENT:
1582 	case NAN_NDL_STATE_CON_SENT:
1583 	case NAN_NDL_STATE_CON_RECV:
1584 	case NAN_NDL_STATE_DONE:
1585 	default:
1586 		return 0;
1587 	}
1588 
1589 	if (ndl->local_qos.max_latency == NAN_QOS_MAX_LATENCY_NO_PREF &&
1590 	    ndl->local_qos.min_slots == NAN_QOS_MIN_SLOTS_NO_PREF)
1591 		return 0;
1592 
1593 	wpabuf_put_u8(buf, NAN_ATTR_NDL_QOS);
1594 	wpabuf_put_le16(buf, sizeof(struct ieee80211_nan_qos));
1595 	wpabuf_put_u8(buf, ndl->local_qos.min_slots);
1596 	wpabuf_put_le16(buf, ndl->local_qos.max_latency);
1597 
1598 	return 0;
1599 }
1600 
1601 
1602 /**
1603  * nan_ndl_naf_sent - Indicate a NAF has been sent
1604  * @nan: NAN module context from nan_init()
1605  * @peer: The peer with whom the NDL is being setup
1606  * @subtype: The NAN OUI subtype
1607  *
1608  * A notification indicating to the NDL state machine that a NAF was sent, so
1609  * the NDL state machine can update its state.
1610  *
1611  * In case the NDL setup negotiation is successfully done, the final schedule
1612  * is applied and the NDL is active. If the negotiation is done and failed, the
1613  * NDL state is reset.
1614  */
nan_ndl_naf_sent(struct nan_data * nan,struct nan_peer * peer,enum nan_subtype subtype)1615 int nan_ndl_naf_sent(struct nan_data *nan, struct nan_peer *peer,
1616 		     enum nan_subtype subtype)
1617 {
1618 	struct nan_ndl *ndl;
1619 
1620 	if (!peer || !peer->ndl)
1621 		return -1;
1622 
1623 	ndl = peer->ndl;
1624 
1625 	if (ndl->state == NAN_NDL_STATE_DONE)
1626 		return 0;
1627 
1628 	wpa_printf(MSG_DEBUG,
1629 		   "NAN: NDL: Tx done with peer=" MACSTR " state=%s, status=%u",
1630 		   MAC2STR(peer->nmi_addr), nan_ndl_state_str(ndl->state),
1631 		   ndl->status);
1632 
1633 	/* Note: Due to races between the Tx status and Rx path, it is possible
1634 	 * that the Tx status is received after the peer response was already
1635 	 * processed (which can result with another frame being sent). In such a
1636 	 * case the logic above fast-forwards the state, and the transitions
1637 	 * here need to take this into consideration.
1638 	 */
1639 	switch (ndl->state) {
1640 	case NAN_NDL_STATE_START:
1641 		if (subtype != NAN_SUBTYPE_DATA_PATH_REQUEST)
1642 			return 0;
1643 		if (ndl->status != NAN_NDL_STATUS_CONTINUED) {
1644 			wpa_printf(MSG_DEBUG,
1645 				   "NAN: NDL: Tx sent: invalid continue status");
1646 			return -1;
1647 		}
1648 		nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_REQ_SENT);
1649 		return 0;
1650 	case NAN_NDL_STATE_REQ_RECV:
1651 		if (subtype != NAN_SUBTYPE_DATA_PATH_RESPONSE)
1652 			return 0;
1653 		if (ndl->status == NAN_NDL_STATUS_CONTINUED) {
1654 			nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_RES_SENT);
1655 			return 0;
1656 		}
1657 		break;
1658 	case NAN_NDL_STATE_RES_RECV:
1659 		if (subtype != NAN_SUBTYPE_DATA_PATH_CONFIRM)
1660 			return 0;
1661 		if (ndl->status == NAN_NDL_STATUS_CONTINUED) {
1662 			wpa_printf(MSG_DEBUG,
1663 				   "NAN: NDL: Tx sent: invalid continue status");
1664 			return -1;
1665 		}
1666 		break;
1667 	case NAN_NDL_STATE_CON_RECV:
1668 	case NAN_NDL_STATE_REQ_SENT:
1669 	case NAN_NDL_STATE_RES_SENT:
1670 	case NAN_NDL_STATE_CON_SENT:
1671 	case NAN_NDL_STATE_DONE:
1672 	default:
1673 		wpa_printf(MSG_DEBUG, "NAN: NDL: Tx sent: unexpected state %d",
1674 			   ndl->state);
1675 		return 0;
1676 	}
1677 
1678 	if (ndl->status == NAN_NDL_STATUS_ACCEPTED) {
1679 		wpa_printf(MSG_DEBUG, "NAN: NDL: Schedule setup success");
1680 		nan_ndl_set_state(nan, ndl, NAN_NDL_STATE_DONE);
1681 		return 0;
1682 	}
1683 
1684 	/* NDL is rejected and NAF already sent. Higher layer is expected to
1685 	 * handle it.
1686 	 */
1687 	return 0;
1688 }
1689 
1690 
1691 /*
1692  * nan_ndl_add_elem_container_attr - Add NAN element container attribute
1693  *
1694  * @nan: NAN module context from nan_init()
1695  * @peer: The peer with whom the NDL is being setup
1696  * @buf: wpabuf to which the attribute is added
1697  */
nan_ndl_add_elem_container_attr(const struct nan_data * nan,const struct nan_peer * peer,struct wpabuf * buf)1698 void nan_ndl_add_elem_container_attr(const struct nan_data *nan,
1699 				     const struct nan_peer *peer,
1700 				     struct wpabuf *buf)
1701 {
1702 	const struct nan_ndl *ndl;
1703 
1704 	if (!peer || !peer->ndl || !nan->sched.elems)
1705 		return;
1706 
1707 	ndl = peer->ndl;
1708 
1709 	wpa_printf(MSG_DEBUG, "NAN: Add element container. state=%s, status=%u",
1710 		   nan_ndl_state_str(ndl->state), ndl->status);
1711 
1712 	if (peer->ndl->status == NAN_NDL_STATUS_REJECTED)
1713 		return;
1714 
1715 	/* Element container is expected only in NDP request/response */
1716 	if (ndl->state != NAN_NDL_STATE_START &&
1717 	    ndl->state != NAN_NDL_STATE_REQ_RECV)
1718 		return;
1719 
1720 	wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
1721 	wpabuf_put_le16(buf, 1 + wpabuf_len(nan->sched.elems));
1722 	wpabuf_put_u8(buf, 0);
1723 	wpabuf_put_buf(buf, nan->sched.elems);
1724 }
1725