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, ¶ms->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(¶ms, 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 ¶ms.ndc_sched, ¶ms.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, ¶ms.min_slots,
1299 ¶ms.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, ¶ms);
1333 case NAN_NDL_TYPE_RESPONSE:
1334 return nan_ndl_attr_handle_resp(nan, peer, ¶ms);
1335 case NAN_NDL_TYPE_CONFIRM:
1336 return nan_ndl_attr_handle_conf(nan, peer, ¶ms);
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