1 /*
2 * Wi-Fi Aware - NAN Data Path
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 "nan_i.h"
12
13
nan_ndp_state_str(enum nan_ndp_state state)14 static const char * nan_ndp_state_str(enum nan_ndp_state state)
15 {
16 #define C2S(x) case x: return #x;
17 switch (state) {
18 C2S(NAN_NDP_STATE_NONE)
19 C2S(NAN_NDP_STATE_START)
20 C2S(NAN_NDP_STATE_REQ_SENT)
21 C2S(NAN_NDP_STATE_REQ_RECV)
22 C2S(NAN_NDP_STATE_RES_SENT)
23 C2S(NAN_NDP_STATE_RES_RECV)
24 C2S(NAN_NDP_STATE_CON_SENT)
25 C2S(NAN_NDP_STATE_CON_RECV)
26 C2S(NAN_NDP_STATE_DONE)
27 default:
28 return "Invalid NAN NDP state";
29 }
30 }
31
32
nan_ndp_set_state(struct nan_data * nan,struct nan_ndp_setup * ndp_setup,enum nan_ndp_state state)33 static void nan_ndp_set_state(struct nan_data *nan,
34 struct nan_ndp_setup *ndp_setup,
35 enum nan_ndp_state state)
36 {
37 wpa_printf(MSG_DEBUG,
38 "NAN: NDP: state: %s (%u) --> %s (%u)",
39 nan_ndp_state_str(ndp_setup->state),
40 ndp_setup->state, nan_ndp_state_str(state),
41 state);
42
43 ndp_setup->state = state;
44 }
45
46
47 static struct nan_ndp *
nan_ndp_alloc(struct nan_data * nan,struct nan_peer * peer,u8 initiator,u8 * init_ndi,u8 ndp_id,u8 min_slots,u16 max_latency)48 nan_ndp_alloc(struct nan_data *nan, struct nan_peer *peer,
49 u8 initiator, u8 *init_ndi, u8 ndp_id, u8 min_slots,
50 u16 max_latency)
51 {
52 struct nan_ndp *ndp = os_zalloc(sizeof(*ndp));
53
54 if (!ndp)
55 return NULL;
56
57 ndp->peer = peer;
58 ndp->initiator = initiator;
59 ndp->ndp_id = ndp_id;
60
61 os_memcpy(ndp->init_ndi, init_ndi, sizeof(ndp->init_ndi));
62
63 ndp->qos.min_slots = min_slots;
64 ndp->qos.max_latency = max_latency;
65
66 return ndp;
67 }
68
69
nan_ndp_ssi(struct nan_data * nan,struct nan_ndp_setup * ndp_setup,const u8 * ssi,u16 ssi_len)70 static int nan_ndp_ssi(struct nan_data *nan, struct nan_ndp_setup *ndp_setup,
71 const u8 *ssi, u16 ssi_len)
72 {
73 os_free(ndp_setup->ssi);
74 ndp_setup->ssi = NULL;
75 ndp_setup->ssi_len = 0;
76
77 if (!ssi || !ssi_len)
78 return 0;
79
80 ndp_setup->ssi = os_memdup(ssi, ssi_len);
81 if (!ndp_setup->ssi) {
82 wpa_printf(MSG_INFO, "NAN: NDP: Failed to allocate NDP ssi");
83 return -1;
84 }
85
86 ndp_setup->ssi_len = ssi_len;
87 return 0;
88 }
89
90
91 /**
92 * nan_ndp_setup_req - Start handling of NDP setup request
93 * @nan: NAN module context from nan_init()
94 * @peer: The peer to initiate the NDP setup with
95 * @params: NDP setup request parameters
96 * Returns: 0 on success, negative on failure
97 *
98 * On successful request, the data structures would be ready to
99 * continue the NDP establishment.
100 */
nan_ndp_setup_req(struct nan_data * nan,struct nan_peer * peer,struct nan_ndp_params * params)101 int nan_ndp_setup_req(struct nan_data *nan, struct nan_peer *peer,
102 struct nan_ndp_params *params)
103 {
104 int ret;
105
106 if (peer->ndp_setup.ndp) {
107 wpa_printf(MSG_DEBUG, "NAN: NDP: already WIP with peer");
108 return -1;
109 }
110
111 peer->ndp_setup.ndp = nan_ndp_alloc(nan, peer, 1,
112 params->ndp_id.init_ndi,
113 params->ndp_id.id,
114 params->qos.min_slots,
115 params->qos.max_latency);
116 if (!peer->ndp_setup.ndp) {
117 wpa_printf(MSG_DEBUG, "NAN: NDP: Failed allocation");
118 return -1;
119 }
120
121 peer->ndp_setup.dialog_token = nan_get_next_dialog_token(nan);
122 peer->ndp_setup.publish_inst_id = params->u.req.publish_inst_id;
123 os_memcpy(peer->ndp_setup.service_id, params->u.req.service_id,
124 NAN_SERVICE_ID_LEN);
125
126 /* Require confirmation for all locally initiated NDPs */
127 peer->ndp_setup.conf_req = 1;
128
129 /* Store service specific information */
130 ret = nan_ndp_ssi(nan, &peer->ndp_setup, params->ssi, params->ssi_len);
131 if (ret) {
132 os_free(peer->ndp_setup.ndp);
133 peer->ndp_setup.ndp = NULL;
134 return ret;
135 }
136
137 nan_sec_reset(nan, &peer->ndp_setup.sec);
138
139 if (params->sec.csid) {
140 peer->ndp_setup.sec.i_csid = params->sec.csid;
141 os_memcpy(peer->ndp_setup.sec.pmk, params->sec.pmk, PMK_LEN);
142
143 peer->ndp_setup.sec.present = true;
144 peer->ndp_setup.sec.valid = true;
145
146 peer->ndp_setup.sec.i_instance_id =
147 peer->ndp_setup.publish_inst_id;
148
149 os_memcpy(&peer->ndp_setup.sec.local_gtk, ¶ms->sec.gtk,
150 sizeof(peer->ndp_setup.sec.local_gtk));
151 }
152
153 if (params->interface_id) {
154 wpa_printf(MSG_DEBUG,
155 "NAN: NDP setup request with local interface id");
156
157 os_memcpy(peer->ndp_setup.local_interface_id,
158 params->interface_id,
159 NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
160
161 peer->ndp_setup.local_interface_id_valid = true;
162 }
163
164 nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_START);
165 peer->ndp_setup.status = NAN_NDP_STATUS_CONTINUED;
166 return 0;
167 }
168
169
170 /**
171 * nan_ndp_setup_resp - Handle higher layer response for an NDP request
172 * @nan: NAN module context from nan_init()
173 * @peer: Peer that originated the NDP setup request
174 * @params: NDP setup parameters
175 * Returns: 0 on success, negative on failure
176 *
177 * The response status can be either ACCEPTED or REJECTED. The internal logic of
178 * the NDP state machine adjusts its own state according to the response status
179 * and its internal state.
180 */
nan_ndp_setup_resp(struct nan_data * nan,struct nan_peer * peer,struct nan_ndp_params * params)181 int nan_ndp_setup_resp(struct nan_data *nan, struct nan_peer *peer,
182 struct nan_ndp_params *params)
183 {
184 int ret;
185
186 if (!peer->ndp_setup.ndp ||
187 peer->ndp_setup.ndp->ndp_id != params->ndp_id.id ||
188 !ether_addr_equal(peer->ndp_setup.ndp->init_ndi,
189 params->ndp_id.init_ndi)) {
190 wpa_printf(MSG_DEBUG,
191 "NAN: NDP: No matching NDP found for NDP response");
192 return -1;
193 }
194
195 if (peer->ndp_setup.state != NAN_NDP_STATE_REQ_RECV) {
196 wpa_printf(MSG_DEBUG,
197 "NAN: NDP: Unexpected state for response");
198 return -1;
199 }
200
201 if (params->u.resp.status != NAN_NDP_STATUS_ACCEPTED &&
202 params->u.resp.status != NAN_NDP_STATUS_REJECTED) {
203 wpa_printf(MSG_DEBUG,
204 "NAN: NDP: Unexpected response status=%u",
205 params->u.resp.status);
206 return -1;
207 }
208
209 peer->ndp_setup.status = params->u.resp.status;
210 peer->ndp_setup.reason = params->u.resp.reason_code;
211
212 if (peer->ndp_setup.status == NAN_NDP_STATUS_ACCEPTED) {
213 if (peer->ndp_setup.conf_req)
214 peer->ndp_setup.status = NAN_NDP_STATUS_CONTINUED;
215
216 os_memcpy(peer->ndp_setup.ndp->resp_ndi,
217 params->u.resp.resp_ndi, ETH_ALEN);
218
219 if (!peer->ndp_setup.sec.present && params->sec.csid) {
220 wpa_printf(MSG_DEBUG,
221 "NAN: NDP: Security not requested by peer");
222 return -1;
223 }
224
225 if (peer->ndp_setup.sec.present) {
226 if (params->sec.csid != peer->ndp_setup.sec.i_csid) {
227 wpa_printf(MSG_DEBUG,
228 "NAN: NDP: Different cipher suite specified.");
229 return -1;
230 }
231
232 peer->ndp_setup.sec.r_csid = params->sec.csid;
233 os_memcpy(peer->ndp_setup.sec.pmk, params->sec.pmk,
234 PMK_LEN);
235 os_memcpy(&peer->ndp_setup.sec.local_gtk,
236 ¶ms->sec.gtk,
237 sizeof(peer->ndp_setup.sec.local_gtk));
238
239 ret = nan_sec_init_resp(nan, peer);
240 if (ret) {
241 wpa_printf(MSG_DEBUG,
242 "NAN: NDP: Failed to init responder security");
243
244 peer->ndp_setup.status =
245 NAN_NDP_STATUS_REJECTED;
246 peer->ndp_setup.reason =
247 NAN_REASON_INVALID_PARAMETERS;
248 return 0;
249 }
250
251 peer->ndp_setup.status = NAN_NDP_STATUS_CONTINUED;
252 }
253 }
254
255 /* Store service specific information */
256 ret = nan_ndp_ssi(nan, &peer->ndp_setup, params->ssi, params->ssi_len);
257 if (ret)
258 return ret;
259
260 if (params->interface_id) {
261 wpa_printf(MSG_DEBUG,
262 "NAN: NDP setup response with local interface id");
263
264 os_memcpy(peer->ndp_setup.local_interface_id,
265 params->interface_id,
266 NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
267
268 peer->ndp_setup.local_interface_id_valid = true;
269 }
270
271 return 0;
272 }
273
274
nan_ndp_attr_handle_tlvs(struct nan_data * nan,struct nan_peer * peer,const u8 * tlvs,u16 tlvs_len)275 static int nan_ndp_attr_handle_tlvs(struct nan_data *nan,
276 struct nan_peer *peer,
277 const u8 *tlvs, u16 tlvs_len)
278 {
279 wpa_printf(MSG_DEBUG, "NAN: NDP: Handle NDPE TLVs len=%u", tlvs_len);
280
281 while (tlvs_len > 3) {
282 u8 tlv_type = tlvs[0];
283 u16 tlv_len = WPA_GET_LE16(tlvs + 1);
284 const u8 *tlv_data = tlvs + 3;
285 int ret;
286
287 if (tlv_len + 3 > tlvs_len) {
288 wpa_printf(MSG_DEBUG,
289 "NAN: NDP: Invalid TLV len=%u for type=%u",
290 tlv_len, tlv_type);
291 return -1;
292 }
293
294 switch (tlv_type) {
295 case NAN_NDPE_TLV_IPV6_LINK_LOCAL:
296 if (tlv_len != NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN) {
297 wpa_printf(MSG_DEBUG,
298 "NAN: NDP: req: Invalid interface ID tlv len=%u",
299 tlv_len);
300 break;
301 }
302
303 peer->ndp_setup.peer_interface_id_valid = true;
304 os_memcpy(peer->ndp_setup.peer_interface_id, tlv_data,
305 NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
306 break;
307 case NAN_NDPE_TLV_SRV_INFO:
308 wpa_printf(MSG_DEBUG,
309 "NAN: NDP: Handle NDP service specific information");
310
311 if (tlv_len >= 4 && WPA_GET_BE24(tlv_data) == OUI_WFA &&
312 tlv_data[3] == NAN_SRV_PROTO_GENERIC)
313 ret = nan_ndp_ssi(nan, &peer->ndp_setup,
314 tlv_data + 4, tlv_len - 4);
315 else
316 ret = nan_ndp_ssi(nan, &peer->ndp_setup,
317 tlv_data, tlv_len);
318 if (ret)
319 wpa_printf(MSG_DEBUG,
320 "NAN: NDP: Failed to save ssi - continue");
321 break;
322 default:
323 wpa_printf(MSG_DEBUG, "NAN: NDP: unknown TLV type=%u",
324 tlv_type);
325 break;
326 }
327
328 tlvs += 3 + tlv_len;
329 tlvs_len -= 3 + tlv_len;
330 }
331
332 if (tlvs_len) {
333 wpa_printf(MSG_DEBUG,
334 "NAN: NDP: TLV parsing ended with %u left octets",
335 tlvs_len);
336 return -1;
337 }
338
339 return 0;
340 }
341
342
nan_ndp_attr_handle_req(struct nan_data * nan,struct nan_peer * peer,struct ieee80211_ndp * ndp_attr,u16 ndp_len,u8 status,bool ndpe)343 static int nan_ndp_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
344 struct ieee80211_ndp *ndp_attr, u16 ndp_len,
345 u8 status, bool ndpe)
346 {
347 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
348 u16 exp_len = sizeof(struct ieee80211_ndp);
349 u8 publish_inst_id;
350
351 if (ndp_setup->ndp) {
352 wpa_printf(MSG_DEBUG,
353 "NAN: NDP: req: While already WIP with peer");
354 return -1;
355 }
356
357 if (!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_PUBLISH_ID_PRESENT)) {
358 wpa_printf(MSG_DEBUG,
359 "NAN: NDP: req: Without publish ID");
360 return -1;
361 }
362
363 exp_len++;
364 if (ndp_len < exp_len) {
365 wpa_printf(MSG_DEBUG,
366 "NAN: NDP: req: Length too short: ndp_len=%u, exp_len=%u",
367 ndp_len, exp_len);
368 return -1;
369 }
370
371 publish_inst_id = *ndp_attr->optional;
372 if (!nan_publish_instance_id_valid(nan, publish_inst_id,
373 ndp_setup->service_id)) {
374 wpa_printf(MSG_DEBUG,
375 "NAN: NDP: req: Invalid publish instance ID=%u",
376 publish_inst_id);
377 return -1;
378 }
379
380 /* Note: The QoS setting should be set in the response. */
381 ndp_setup->ndp = nan_ndp_alloc(nan, peer, 0,
382 ndp_attr->initiator_ndi,
383 ndp_attr->ndp_id,
384 NAN_QOS_MIN_SLOTS_NO_PREF,
385 NAN_QOS_MAX_LATENCY_NO_PREF);
386 if (!ndp_setup->ndp)
387 return -1;
388
389 nan_sec_reset(nan, &peer->ndp_setup.sec);
390 nan_ndp_set_state(nan, ndp_setup, NAN_NDP_STATE_REQ_RECV);
391
392 ndp_setup->status = NAN_NDP_STATUS_CONTINUED;
393 ndp_setup->conf_req =
394 !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_CONFIRM_REQUIRED);
395 ndp_setup->dialog_token = ndp_attr->dialog_token;
396 ndp_setup->publish_inst_id = publish_inst_id;
397 ndp_setup->sec.present =
398 !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
399
400 /* Handle service specific information */
401 ndp_len -= exp_len;
402
403 if (!ndpe && (ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SPEC_INFO_PRESENT) &&
404 ndp_len) {
405 int ret;
406
407 wpa_printf(MSG_DEBUG,
408 "NAN: NDP: req: Handle NDP service specific information");
409
410 ret = nan_ndp_ssi(nan, &peer->ndp_setup,
411 (const u8 *) ndp_attr->optional + 1,
412 ndp_len);
413 if (ret)
414 wpa_printf(MSG_DEBUG,
415 "NAN: NDP: req: Failed to save ssi. continue");
416 return ret;
417 }
418
419 if (ndpe)
420 return nan_ndp_attr_handle_tlvs(nan, peer,
421 ndp_attr->optional + 1,
422 ndp_len);
423
424 return 0;
425 }
426
427
nan_ndp_attr_handle_res(struct nan_data * nan,struct nan_peer * peer,struct ieee80211_ndp * ndp_attr,u16 ndp_len,u8 status,bool ndpe)428 static int nan_ndp_attr_handle_res(struct nan_data *nan, struct nan_peer *peer,
429 struct ieee80211_ndp *ndp_attr, u16 ndp_len,
430 u8 status, bool ndpe)
431 {
432 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
433 u16 opt_len;
434 bool sec_present;
435
436 if (!ndp_setup->ndp) {
437 wpa_printf(MSG_DEBUG,
438 "NAN: NDP: resp: While no NDP WIP with peer");
439 return -1;
440 }
441
442 if (ndp_setup->state != NAN_NDP_STATE_REQ_SENT) {
443 wpa_printf(MSG_DEBUG,
444 "NAN: NDP: resp: While not expecting one");
445
446 if (ndp_setup->state != NAN_NDP_STATE_START)
447 return -1;
448
449 /*
450 * Due to races with the driver, it is possible that the
451 * response is received before an ACK is indicated. Allow the
452 * processing of the attribute, and if all parameters are OK,
453 * fast forward the state machine below.
454 */
455 wpa_printf(MSG_DEBUG,
456 "NAN: NDP: resp: Received before Tx status.");
457 }
458
459 if (ndp_attr->ndp_ctrl & NAN_NDP_CTRL_PUBLISH_ID_PRESENT) {
460 wpa_printf(MSG_DEBUG,
461 "NAN: NDP: resp: Unexpected publish ID");
462 return -1;
463 }
464
465 opt_len = 0;
466 if (status == NAN_NDP_STATUS_CONTINUED ||
467 status == NAN_NDP_STATUS_ACCEPTED) {
468 if (!(ndp_attr->ndp_ctrl &
469 NAN_NDP_CTRL_RESPONDER_NDI_PRESENT)) {
470 wpa_printf(MSG_DEBUG,
471 "NAN: NDP: resp: without responder NDI");
472 return -1;
473 }
474 opt_len += ETH_ALEN;
475 }
476
477 if (ndp_len < (sizeof(struct ieee80211_ndp) + opt_len)) {
478 wpa_printf(MSG_DEBUG, "NAN: NDP: resp: Length too short");
479 return -1;
480 }
481
482 if (ndp_setup->ndp->ndp_id != ndp_attr->ndp_id ||
483 ndp_setup->dialog_token != ndp_attr->dialog_token ||
484 !ether_addr_equal(ndp_setup->ndp->init_ndi,
485 ndp_attr->initiator_ndi)) {
486 wpa_printf(MSG_DEBUG,
487 "NAN: NDP: resp: Invalid NDP ID, dialog token or addr");
488 return -1;
489 }
490
491 if (ndp_setup->state == NAN_NDP_STATE_START) {
492 wpa_printf(MSG_DEBUG,
493 "NAN: NDP: resp: Continue though no TX status yet.");
494 nan_ndp_set_state(nan, &peer->ndp_setup,
495 NAN_NDP_STATE_REQ_SENT);
496 }
497
498 ndp_setup->status = status;
499
500 if (status == NAN_NDP_STATUS_REJECTED) {
501 ndp_setup->reason = ndp_attr->reason_code;
502 nan_ndp_set_state(nan, &peer->ndp_setup,
503 NAN_NDP_STATE_DONE);
504 goto store_ssi;
505 }
506
507 sec_present = !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
508 if (ndp_setup->sec.present != sec_present) {
509 wpa_printf(MSG_DEBUG,
510 "NAN: NDP: Security present mismatch");
511 return -1;
512 }
513
514 if ((sec_present || ndp_setup->conf_req) &&
515 status != NAN_NDP_STATUS_CONTINUED) {
516 wpa_printf(MSG_DEBUG,
517 "NAN: NDP: Security present or confirm required and status != continued");
518 return -1;
519 }
520
521 if (status == NAN_NDP_STATUS_ACCEPTED)
522 nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_DONE);
523 else
524 nan_ndp_set_state(nan, &peer->ndp_setup,
525 NAN_NDP_STATE_RES_RECV);
526
527 os_memcpy(ndp_setup->ndp->resp_ndi, &ndp_attr->optional[0],
528 sizeof(ndp_setup->ndp->resp_ndi));
529
530 /*
531 * In case that security is not configured, move the status to accepted.
532 * The state machine would transition to the 'done' state after the
533 * confirm is acked.
534 * TODO: Once security is configured, need to validate the security must
535 * be present.
536 */
537 if (!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT))
538 ndp_setup->status = NAN_NDP_STATUS_ACCEPTED;
539
540 store_ssi:
541 /* Handle service specific information */
542 ndp_len -= sizeof(struct ieee80211_ndp) + opt_len;
543 if (!ndpe && (ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SPEC_INFO_PRESENT) &&
544 ndp_len) {
545 int ret;
546
547 wpa_printf(MSG_DEBUG, "NAN: NDP: resp: Handle NDP ssi");
548 ret = nan_ndp_ssi(nan, &peer->ndp_setup,
549 ndp_attr->optional + opt_len, ndp_len);
550 if (ret)
551 wpa_printf(MSG_DEBUG,
552 "NAN: NDP: resp: Failed to save ssi. continue");
553 return ret;
554 }
555
556 if (ndpe)
557 return nan_ndp_attr_handle_tlvs(nan, peer,
558 ndp_attr->optional + opt_len,
559 ndp_len);
560
561 return 0;
562 }
563
564
nan_ndp_attr_handle_confirm(struct nan_data * nan,struct nan_peer * peer,struct ieee80211_ndp * ndp_attr,u8 status)565 static int nan_ndp_attr_handle_confirm(struct nan_data *nan,
566 struct nan_peer *peer,
567 struct ieee80211_ndp *ndp_attr,
568 u8 status)
569 {
570 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
571 bool sec_present;
572
573 if (!ndp_setup->ndp) {
574 wpa_printf(MSG_DEBUG,
575 "NAN: NDP: Received confirm while no NDP WIP with peer");
576 return -1;
577 }
578
579 if (ndp_setup->state != NAN_NDP_STATE_RES_SENT) {
580 wpa_printf(MSG_DEBUG,
581 "NAN: NDP: confirm: While not expecting one");
582
583 if (ndp_setup->state != NAN_NDP_STATE_REQ_RECV ||
584 ndp_setup->status != NAN_NDP_STATUS_CONTINUED)
585 return -1;
586
587 /*
588 * Due to races with the driver, it is possible that the
589 * confirm is received before an ACK is indicated. Allow the
590 * processing of the attribute, and if all parameters are OK,
591 * fast forward the state machine below.
592 */
593 wpa_printf(MSG_DEBUG,
594 "NAN: NDP: Confirm received before Tx status");
595 }
596
597 if (ndp_setup->ndp->ndp_id != ndp_attr->ndp_id ||
598 ndp_setup->dialog_token != ndp_attr->dialog_token ||
599 !ether_addr_equal(ndp_setup->ndp->init_ndi,
600 ndp_attr->initiator_ndi)) {
601 wpa_printf(MSG_DEBUG,
602 "NAN: NDP: confirm: Invalid NDP ID, dialog token or init ID");
603 return -1;
604 }
605
606 sec_present = !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
607 if (ndp_setup->sec.present != sec_present) {
608 wpa_printf(MSG_DEBUG,
609 "NAN: NDP: confirm: Security present mismatch");
610 return -1;
611 }
612
613 if (sec_present && status != NAN_NDP_STATUS_CONTINUED) {
614 wpa_printf(MSG_DEBUG,
615 "NAN: NDP: confirm: status != continued with security");
616 return -1;
617 }
618
619 if (ndp_setup->state == NAN_NDP_STATE_REQ_RECV) {
620 wpa_printf(MSG_DEBUG,
621 "NAN: NDP: confirm: Continue though no TX status yet.");
622 nan_ndp_set_state(nan, &peer->ndp_setup,
623 NAN_NDP_STATE_RES_SENT);
624 }
625
626 ndp_setup->status = status;
627
628 if (sec_present)
629 nan_ndp_set_state(nan, &peer->ndp_setup,
630 NAN_NDP_STATE_CON_RECV);
631 else
632 nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_DONE);
633
634 return 0;
635 }
636
637
nan_ndp_find_ndp(struct nan_peer * peer,u8 ndp_id,const u8 * init_ndi)638 static struct nan_ndp * nan_ndp_find_ndp(struct nan_peer *peer,
639 u8 ndp_id, const u8 *init_ndi)
640 {
641 struct nan_ndp *pndp;
642
643 dl_list_for_each(pndp, &peer->ndps, struct nan_ndp, list) {
644 if (pndp->ndp_id == ndp_id &&
645 ether_addr_equal(pndp->init_ndi, init_ndi))
646 return pndp;
647 }
648
649 return NULL;
650 }
651
652
nan_ndp_attr_sec_install(struct nan_data * nan,struct nan_peer * peer,const struct ieee80211_ndp * ndp_attr,u8 status)653 static int nan_ndp_attr_sec_install(struct nan_data *nan, struct nan_peer *peer,
654 const struct ieee80211_ndp *ndp_attr,
655 u8 status)
656 {
657 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
658 bool sec_present;
659
660 if (!ndp_setup->ndp) {
661 wpa_printf(MSG_DEBUG,
662 "NAN: NDP: sec install while no NDP WIP with peer");
663 return -1;
664 }
665
666 if (ndp_setup->state != NAN_NDP_STATE_CON_SENT) {
667 wpa_printf(MSG_DEBUG,
668 "NAN: NDP: sec install while not expecting one");
669
670 if (ndp_setup->state != NAN_NDP_STATE_RES_RECV ||
671 ndp_setup->status != NAN_NDP_STATUS_CONTINUED)
672 return -1;
673
674 /* Due to races with the driver, it is possible that the
675 * install is received before an ACK is indicated. Allow the
676 * processing of the attribute, and if all parameters are OK,
677 * fast forward the state machine below.
678 */
679 wpa_printf(MSG_DEBUG,
680 "NAN: NDP: sec install received before Tx status.");
681 }
682
683 if (ndp_setup->ndp->ndp_id != ndp_attr->ndp_id ||
684 ndp_setup->dialog_token != ndp_attr->dialog_token ||
685 !ether_addr_equal(ndp_setup->ndp->init_ndi,
686 ndp_attr->initiator_ndi)) {
687 wpa_printf(MSG_DEBUG,
688 "NAN: NDP: sec install: Invalid NDP parameters");
689 return -1;
690 }
691
692 sec_present = !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
693 if (ndp_setup->sec.present != sec_present) {
694 wpa_printf(MSG_DEBUG,
695 "NAN: NDP: sec install: Security present mismatch");
696 return -1;
697 }
698
699 if (status != NAN_NDP_STATUS_ACCEPTED) {
700 wpa_printf(MSG_DEBUG,
701 "NAN: NDP: sec install: status != ACCEPTED");
702 return -1;
703 }
704
705 nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_DONE);
706 return 0;
707 }
708
709
nan_ndp_attr_handle_term(struct nan_data * nan,struct nan_peer * peer,struct ieee80211_ndp * ndp_attr,u8 status)710 static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
711 struct ieee80211_ndp *ndp_attr, u8 status)
712 {
713 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
714 struct nan_ndp_id ndp_id;
715 const u8 *local_ndi, *peer_ndi;
716 struct nan_ndp *pndp;
717
718 wpa_printf(MSG_DEBUG,
719 "NAN: NDP: Termination peer=" MACSTR " ndp_id=%u, init_ndi="
720 MACSTR,
721 MAC2STR(peer->nmi_addr), ndp_attr->ndp_id,
722 MAC2STR(ndp_attr->initiator_ndi));
723
724 /*
725 * This should not really happen, but just in case, terminate the
726 * establishment. Since the NDP establishment is not yet done, the NDP
727 * is not added to the list of NDPs, so just reject the establishment.
728 */
729 if (ndp_setup->ndp && ndp_setup->ndp->ndp_id == ndp_attr->ndp_id &&
730 ether_addr_equal(ndp_setup->ndp->init_ndi,
731 ndp_attr->initiator_ndi)) {
732 wpa_printf(MSG_DEBUG,
733 "NAN: NDP: Termination while NDP is in progress");
734
735 nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_DONE);
736 ndp_setup->status = NAN_NDP_STATUS_REJECTED;
737 ndp_setup->reason = NAN_REASON_UNSPECIFIED_REASON;
738 return 0;
739 }
740
741 /* Find the NDP in the list of active NDPs */
742 pndp = nan_ndp_find_ndp(peer, ndp_attr->ndp_id,
743 ndp_attr->initiator_ndi);
744 if (!pndp) {
745 wpa_printf(MSG_DEBUG,
746 "NAN: NDP: Termination but NDP does not exist");
747 return 1;
748 }
749
750 wpa_printf(MSG_DEBUG, "NAN: NDP: Terminating");
751
752 os_memcpy(ndp_id.peer_nmi, peer->nmi_addr, ETH_ALEN);
753 os_memcpy(ndp_id.init_ndi, pndp->init_ndi, ETH_ALEN);
754 ndp_id.id = pndp->ndp_id;
755
756 if (pndp->initiator) {
757 local_ndi = pndp->init_ndi;
758 peer_ndi = pndp->resp_ndi;
759 } else {
760 local_ndi = pndp->resp_ndi;
761 peer_ndi = pndp->init_ndi;
762 }
763
764 /*
765 * Remove the NDP from the list of active NDPs before calling
766 * nan_ndp_terminated() as the function checks the list of NDPs to
767 * determine if the NDL should be reset as well. Free the NDP only after
768 * the call as the NDI addresses are still referenced.
769 */
770 dl_list_del(&pndp->list);
771
772 nan_ndp_terminated(nan, peer, &ndp_id, local_ndi, peer_ndi,
773 ndp_attr->reason_code, pndp->gtk_id);
774
775 os_free(pndp);
776
777 /* Indicate that no further processing is needed */
778 return 1;
779 }
780
781
782 /**
783 * nan_ndp_handle_ndp_attr - Handle NDP attribute and update local state
784 * @nan: NAN module context from nan_init()
785 * @peer: The peer from which the original message was received
786 * @msg: Parsed NAN Action frame
787 * Returns: 0 on success processing indicating that processing can continue; 1
788 * in case of successful processing but no further processing is needed;
789 * negative on failure.
790 */
nan_ndp_handle_ndp_attr(struct nan_data * nan,struct nan_peer * peer,struct nan_msg * msg)791 int nan_ndp_handle_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
792 struct nan_msg *msg)
793 {
794 struct ieee80211_ndp *ndp_attr = NULL;
795 size_t ndp_attr_len = 0;
796 bool ndpe_supported;
797 u8 type, status;
798 int ret;
799
800 if (!msg || !peer || (!msg->attrs.ndp && !msg->attrs.ndpe))
801 return -1;
802
803 ndpe_supported = nan_is_ndpe_supported(nan, peer);
804 wpa_printf(MSG_DEBUG,
805 "NAN: NDP: Handle NDP attribute. ndpe_supported=%u",
806 ndpe_supported);
807
808 /*
809 * The NDP attribute and the NDPE attribute are very similar in
810 * structure so handle them in the same way where possible.
811 */
812 if (ndpe_supported) {
813 ndp_attr = (struct ieee80211_ndp *) msg->attrs.ndpe;
814 ndp_attr_len = msg->attrs.ndpe_len;
815 }
816
817 if (!ndp_attr || !ndp_attr_len) {
818 ndp_attr = (struct ieee80211_ndp *) msg->attrs.ndp;
819 ndp_attr_len = msg->attrs.ndp_len;
820 ndpe_supported = false;
821 if (!ndp_attr || !ndp_attr_len)
822 return -1;
823 }
824
825 type = BITS(ndp_attr->type_and_status, NAN_NDP_TYPE_MASK,
826 NAN_NDP_TYPE_POS);
827 status = BITS(ndp_attr->type_and_status, NAN_NDP_STATUS_MASK,
828 NAN_NDP_STATUS_POS);
829
830 if (peer->ndp_setup.ndp) {
831 wpa_printf(MSG_DEBUG,
832 "NAN: NDP: attr: state=%s (%d), status=%d",
833 nan_ndp_state_str(peer->ndp_setup.state),
834 peer->ndp_setup.state,
835 peer->ndp_setup.status);
836 } else {
837 wpa_printf(MSG_DEBUG, "NAN: NDP: attr: no active NDP setup");
838 }
839
840 wpa_printf(MSG_DEBUG, "NAN: NDP: attr: type=0x%x, status=0x%x",
841 type, status);
842
843 switch (type) {
844 case NAN_NDP_TYPE_REQUEST:
845 ret = nan_ndp_attr_handle_req(nan, peer, ndp_attr,
846 ndp_attr_len, status,
847 ndpe_supported);
848 break;
849 case NAN_NDP_TYPE_RESPONSE:
850 ret = nan_ndp_attr_handle_res(nan, peer, ndp_attr,
851 ndp_attr_len, status,
852 ndpe_supported);
853 break;
854 case NAN_NDP_TYPE_CONFIRM:
855 ret = nan_ndp_attr_handle_confirm(nan, peer, ndp_attr, status);
856 break;
857 case NAN_NDP_TYPE_SECURITY_INSTALL:
858 ret = nan_ndp_attr_sec_install(nan, peer, ndp_attr, status);
859 break;
860 case NAN_NDP_TYPE_TERMINATE:
861 return nan_ndp_attr_handle_term(nan, peer, ndp_attr, status);
862 default:
863 return -1;
864 }
865
866 /* Error or no security.. We are done. */
867 if (ret || !peer->ndp_setup.sec.present ||
868 peer->ndp_setup.status == NAN_NDP_STATUS_REJECTED)
869 return ret;
870
871 ret = nan_sec_rx(nan, peer, msg);
872 if (ret)
873 return ret;
874
875 /* Processing of confirm is successful, so to the overall status is
876 * success. */
877 if (type == NAN_NDP_TYPE_CONFIRM)
878 peer->ndp_setup.status = NAN_NDP_STATUS_ACCEPTED;
879
880 return 0;
881 }
882
883
884 /**
885 * nan_ndp_add_ndp_attr - Add NDP attribute to frame
886 * @nan: NAN module context from nan_init()
887 * @peer: The peer to which the NAF should be sent
888 * @buf: wpabuf to which the attribute would be added
889 * Returns: 0 on success, negative on failure
890 */
nan_ndp_add_ndp_attr(struct nan_data * nan,struct nan_peer * peer,struct wpabuf * buf)891 int nan_ndp_add_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
892 struct wpabuf *buf)
893 {
894 struct nan_ndp_setup *ndp_setup;
895 u8 type, ndp_ctrl = 0;
896 u8 *len_ptr;
897 bool ndpe_supported;
898 bool add_srv_info = false;
899
900 if (!peer || !peer->ndp_setup.ndp)
901 return -1;
902
903 ndpe_supported = nan_is_ndpe_supported(nan, peer);
904 ndp_setup = &peer->ndp_setup;
905
906 switch (ndp_setup->state) {
907 case NAN_NDP_STATE_START:
908 type = NAN_NDP_TYPE_REQUEST;
909 ndp_ctrl = NAN_NDP_CTRL_PUBLISH_ID_PRESENT;
910 if (ndp_setup->conf_req)
911 ndp_ctrl |= NAN_NDP_CTRL_CONFIRM_REQUIRED;
912 if (ndp_setup->ssi && ndp_setup->ssi_len) {
913 add_srv_info = true;
914 if (!ndpe_supported)
915 ndp_ctrl |= NAN_NDP_CTRL_SPEC_INFO_PRESENT;
916 }
917 break;
918 case NAN_NDP_STATE_REQ_RECV:
919 type = NAN_NDP_TYPE_RESPONSE;
920 if (ndp_setup->status != NAN_NDP_STATUS_REJECTED)
921 ndp_ctrl |= NAN_NDP_CTRL_RESPONDER_NDI_PRESENT;
922 if (ndp_setup->ssi && ndp_setup->ssi_len) {
923 add_srv_info = true;
924 if (!ndpe_supported)
925 ndp_ctrl |= NAN_NDP_CTRL_SPEC_INFO_PRESENT;
926 }
927 break;
928 case NAN_NDP_STATE_RES_RECV:
929 type = NAN_NDP_TYPE_CONFIRM;
930 break;
931 case NAN_NDP_STATE_CON_RECV:
932 /* TODO: Integrate NDP security flows */
933 type = NAN_NDP_TYPE_SECURITY_INSTALL;
934 break;
935 case NAN_NDP_STATE_NONE:
936 case NAN_NDP_STATE_DONE:
937 if (ndp_setup->status == NAN_NDP_STATUS_REJECTED)
938 type = NAN_NDP_TYPE_TERMINATE;
939 else
940 return -1;
941 break;
942 case NAN_NDP_STATE_REQ_SENT:
943 case NAN_NDP_STATE_RES_SENT:
944 case NAN_NDP_STATE_CON_SENT:
945 default:
946 return 0;
947 }
948
949 if (ndp_setup->sec.present)
950 ndp_ctrl |= NAN_NDP_CTRL_SECURITY_PRESENT;
951
952 /*
953 * The NDP attribute and the NDPE attribute are very similar in
954 * structure so handle them in the same way where possible.
955 */
956 if (ndpe_supported)
957 wpabuf_put_u8(buf, NAN_ATTR_NDP_EXT);
958 else
959 wpabuf_put_u8(buf, NAN_ATTR_NDP);
960
961 len_ptr = wpabuf_put(buf, 2);
962
963 wpabuf_put_u8(buf, ndp_setup->dialog_token);
964 wpabuf_put_u8(buf, type |
965 (ndp_setup->status << NAN_NDP_STATUS_POS));
966 wpabuf_put_u8(buf, ndp_setup->reason);
967 wpabuf_put_data(buf, ndp_setup->ndp->init_ndi, ETH_ALEN);
968 wpabuf_put_u8(buf, ndp_setup->ndp->ndp_id);
969 wpabuf_put_u8(buf, ndp_ctrl);
970
971 if (ndp_ctrl & NAN_NDP_CTRL_PUBLISH_ID_PRESENT)
972 wpabuf_put_u8(buf, ndp_setup->publish_inst_id);
973
974 if (ndp_ctrl & NAN_NDP_CTRL_RESPONDER_NDI_PRESENT)
975 wpabuf_put_data(buf, ndp_setup->ndp->resp_ndi, ETH_ALEN);
976
977 if (add_srv_info) {
978 if (!ndpe_supported) {
979 wpabuf_put_data(buf, ndp_setup->ssi,
980 ndp_setup->ssi_len);
981 } else {
982 /*
983 * TODO: For the service specific info use the WFA
984 * format. If there is a need to support other vendor
985 * OUIs, this would need to be extended.
986 */
987 wpabuf_put_u8(buf, NAN_NDPE_TLV_SRV_INFO);
988 wpabuf_put_le16(buf, 4 + ndp_setup->ssi_len);
989 wpabuf_put_be24(buf, OUI_WFA);
990 wpabuf_put_u8(buf, NAN_SRV_PROTO_GENERIC);
991 wpabuf_put_data(buf, ndp_setup->ssi,
992 ndp_setup->ssi_len);
993 }
994 }
995
996 if (ndpe_supported && ndp_setup->local_interface_id_valid) {
997 wpabuf_put_u8(buf, NAN_NDPE_TLV_IPV6_LINK_LOCAL);
998 wpabuf_put_le16(buf, NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
999 wpabuf_put_data(buf, ndp_setup->local_interface_id,
1000 NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
1001 }
1002
1003 WPA_PUT_LE16(len_ptr, (u8 *) wpabuf_put(buf, 0) - len_ptr - 2);
1004 return 0;
1005 }
1006
1007
1008 /**
1009 * nan_ndp_setup_reset - Reset the ndp_setup state
1010 * @nan: NAN module context from nan_init()
1011 * @peer: The peer that requires ndp setup reset
1012 */
nan_ndp_setup_reset(struct nan_data * nan,struct nan_peer * peer)1013 void nan_ndp_setup_reset(struct nan_data *nan, struct nan_peer *peer)
1014 {
1015 if (!peer)
1016 return;
1017
1018 os_free(peer->ndp_setup.ssi);
1019 os_free(peer->ndp_setup.ndp);
1020
1021 os_memset(&peer->ndp_setup, 0, sizeof(peer->ndp_setup));
1022 nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_NONE);
1023 }
1024
1025
1026 /**
1027 * nan_ndp_setup_failure - Indicate failure during NDP setup
1028 * @nan: NAN module context from nan_init()
1029 * @peer: The peer from which the original message was received
1030 * @reason: The failure reason
1031 * @reset_state: Reset the NDP state iff equals to true.
1032 */
nan_ndp_setup_failure(struct nan_data * nan,struct nan_peer * peer,enum nan_reason reason,bool reset_state)1033 void nan_ndp_setup_failure(struct nan_data *nan, struct nan_peer *peer,
1034 enum nan_reason reason, bool reset_state)
1035 {
1036 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
1037
1038 wpa_printf(MSG_DEBUG, "NAN: NDP: setup failure: peer " MACSTR
1039 ". state=%s (%u). reason=%u",
1040 MAC2STR(peer->nmi_addr), nan_ndp_state_str(ndp_setup->state),
1041 ndp_setup->state, reason);
1042
1043 if (reset_state) {
1044 nan_ndp_setup_reset(nan, peer);
1045 } else {
1046 ndp_setup->status = NAN_NDP_STATUS_REJECTED;
1047 ndp_setup->reason = reason;
1048 }
1049 }
1050
1051
1052 /**
1053 * nan_ndp_naf_sent - Indicate a NAF has been sent
1054 * @nan: NAN module context from nan_init()
1055 * @peer: The peer with whom the NDP is being setup
1056 * @subtype: The NAN OUI subtype. See &enum nan_subtype
1057 *
1058 * Notification, indicating to the NDP SM to that a NAF was sent, so the
1059 * NDP SM could update its state.
1060 */
nan_ndp_naf_sent(struct nan_data * nan,struct nan_peer * peer,enum nan_subtype subtype)1061 int nan_ndp_naf_sent(struct nan_data *nan, struct nan_peer *peer,
1062 enum nan_subtype subtype)
1063 {
1064 struct nan_ndp_setup *ndp_setup;
1065
1066 if (!peer || !peer->ndp_setup.ndp)
1067 return -1;
1068
1069 ndp_setup = &peer->ndp_setup;
1070
1071 wpa_printf(MSG_DEBUG, "NAN: NDP: Tx done: state=%s (%d), status=%d",
1072 nan_ndp_state_str(ndp_setup->state),
1073 ndp_setup->state, ndp_setup->status);
1074
1075 /*
1076 * Note: Due to races between the Tx status and Rx path, it is possible
1077 * that the Tx status is received after the peer response was already
1078 * processed (which can result with another frame being sent). In such a
1079 * case the logic above fast-forwards the state, and the transitions
1080 * here need to take this into consideration.
1081 */
1082 switch (ndp_setup->state) {
1083 case NAN_NDP_STATE_START:
1084 if (subtype == NAN_SUBTYPE_DATA_PATH_REQUEST)
1085 nan_ndp_set_state(nan, &peer->ndp_setup,
1086 NAN_NDP_STATE_REQ_SENT);
1087 break;
1088 case NAN_NDP_STATE_REQ_RECV:
1089 if (subtype == NAN_SUBTYPE_DATA_PATH_RESPONSE) {
1090 if (ndp_setup->status == NAN_NDP_STATUS_ACCEPTED)
1091 nan_ndp_set_state(nan, &peer->ndp_setup,
1092 NAN_NDP_STATE_DONE);
1093 else
1094 nan_ndp_set_state(nan, &peer->ndp_setup,
1095 NAN_NDP_STATE_RES_SENT);
1096 }
1097 break;
1098 case NAN_NDP_STATE_RES_RECV:
1099 if (subtype == NAN_SUBTYPE_DATA_PATH_CONFIRM) {
1100 if (ndp_setup->status == NAN_NDP_STATUS_ACCEPTED)
1101 nan_ndp_set_state(nan, &peer->ndp_setup,
1102 NAN_NDP_STATE_DONE);
1103 else
1104 nan_ndp_set_state(nan, &peer->ndp_setup,
1105 NAN_NDP_STATE_CON_SENT);
1106 }
1107 break;
1108 case NAN_NDP_STATE_CON_RECV:
1109 if (subtype == NAN_SUBTYPE_DATA_PATH_KEY_INSTALL &&
1110 ndp_setup->status == NAN_NDP_STATUS_ACCEPTED)
1111 nan_ndp_set_state(nan, &peer->ndp_setup,
1112 NAN_NDP_STATE_DONE);
1113 break;
1114 case NAN_NDP_STATE_REQ_SENT:
1115 case NAN_NDP_STATE_RES_SENT:
1116 case NAN_NDP_STATE_CON_SENT:
1117 case NAN_NDP_STATE_DONE:
1118 default:
1119 break;
1120 }
1121
1122 return 0;
1123 }
1124
1125
1126 /*
1127 * nan_ndp_term_req - Handle local NDP termination request
1128 * @nan: NAN module context from nan_init()
1129 * @peer: The peer with whom the NDP is being setup
1130 * @ndp_id: NDP identifier
1131 * Returns: 0 on success, -1 on failure
1132 */
nan_ndp_term_req(struct nan_data * nan,struct nan_peer * peer,struct nan_ndp_id * ndp_id)1133 int nan_ndp_term_req(struct nan_data *nan, struct nan_peer *peer,
1134 struct nan_ndp_id *ndp_id)
1135 {
1136 struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
1137 struct nan_ndp *pndp;
1138
1139 wpa_printf(MSG_DEBUG,
1140 "NAN: NDP: Terminate request with peer=" MACSTR
1141 " ndp_id=%u, init_ndi=" MACSTR,
1142 MAC2STR(peer->nmi_addr), ndp_id->id,
1143 MAC2STR(ndp_id->init_ndi));
1144
1145 if (ndp_setup->ndp) {
1146 if (ndp_setup->ndp->ndp_id == ndp_id->id &&
1147 ether_addr_equal(ndp_setup->ndp->init_ndi,
1148 ndp_id->init_ndi)) {
1149 wpa_printf(MSG_DEBUG,
1150 "NAN: NDP: WIP with peer. Terminate");
1151
1152 nan_ndp_set_state(nan, &peer->ndp_setup,
1153 NAN_NDP_STATE_DONE);
1154 ndp_setup->status = NAN_NDP_STATUS_REJECTED;
1155 ndp_setup->reason = NAN_REASON_UNSPECIFIED_REASON;
1156 return 0;
1157 }
1158
1159 wpa_printf(MSG_DEBUG,
1160 "NAN: NDP: Cannot terminate NDP while NDP establishment is WIP");
1161 return -1;
1162 }
1163
1164 /* Find the NDP in the list of active NDPs */
1165 pndp = nan_ndp_find_ndp(peer, ndp_id->id, ndp_id->init_ndi);
1166 if (!pndp) {
1167 wpa_printf(MSG_DEBUG,
1168 "NAN: NDP: Termination request for unknown NDP");
1169 return -1;
1170 }
1171
1172 /* Remove the NDP from the list and setup data for the termination */
1173 dl_list_del(&pndp->list);
1174
1175 peer->ndp_setup.ndp = pndp;
1176 peer->ndp_setup.status = NAN_NDP_STATUS_REJECTED;
1177 peer->ndp_setup.reason = NAN_REASON_UNSPECIFIED_REASON;
1178 return 0;
1179 }
1180
1181
1182 /**
1183 * nan_ndp_requested_gtk_csid - Get the GTK CSID requested by peer for NDP setup
1184 * @nan: NAN module context from nan_init()
1185 * @ndp_id: NDP identifier
1186 * Returns: The GTK CSID requested by peer, or NAN_CS_NONE if no matching NDP is
1187 * found or GTK is not requested by peer.
1188 */
nan_ndp_requested_gtk_csid(struct nan_data * nan,const struct nan_ndp_id * ndp_id)1189 int nan_ndp_requested_gtk_csid(struct nan_data *nan,
1190 const struct nan_ndp_id *ndp_id)
1191 {
1192 struct nan_peer *peer;
1193
1194 peer = nan_get_peer(nan, ndp_id->peer_nmi);
1195 if (!peer) {
1196 wpa_printf(MSG_DEBUG,
1197 "NAN: NDP: No matching peer found for GTK CSID request");
1198 return NAN_CS_NONE;
1199 }
1200
1201 if (!peer->ndp_setup.ndp ||
1202 peer->ndp_setup.ndp->ndp_id != ndp_id->id ||
1203 !ether_addr_equal(peer->ndp_setup.ndp->init_ndi,
1204 ndp_id->init_ndi)) {
1205 wpa_printf(MSG_DEBUG,
1206 "NAN: NDP: No matching NDP found for GTK CSID request");
1207 return NAN_CS_NONE;
1208 }
1209
1210 if (peer->ndp_setup.state != NAN_NDP_STATE_REQ_RECV)
1211 return NAN_CS_NONE;
1212
1213 return peer->ndp_setup.sec.peer_gtk.csid;
1214 }
1215