1 /*
2 * Wi-Fi Aware - NAN Bootstrap
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/eloop.h"
12 #include "nan_i.h"
13
14 #define NAN_BOOTSTRAP_RETRY_TIMEOUT_US (1 * 1000 * 1000) /* 1 second */
15 #define NAN_BOOTSTRAP_COOKIE_LEN 4
16
17 static void nan_bootstrap_timeout(void *eloop_data, void *user_ctx);
18
19
20 /**
21 * nan_complement_pbm - Get complement pairing bootstrapping method
22 * @pbm: Pairing bootstrapping method
23 * Returns: Complement pairing bootstrapping method
24 */
nan_complement_pbm(u16 pbm)25 static u16 nan_complement_pbm(u16 pbm)
26 {
27 if (pbm == NAN_PBA_METHOD_OPPORTUNISTIC)
28 return NAN_PBA_METHOD_OPPORTUNISTIC;
29 if (pbm == NAN_PBA_METHOD_PIN_DISPLAY)
30 return NAN_PBA_METHOD_PIN_KEYPAD;
31 if (pbm == NAN_PBA_METHOD_PASSPHRASE_DISPLAY)
32 return NAN_PBA_METHOD_PASSPHRASE_KEYPAD;
33 if (pbm == NAN_PBA_METHOD_QR_DISPLAY)
34 return NAN_PBA_METHOD_QR_SCAN;
35 if (pbm == NAN_PBA_METHOD_NFC_TAG)
36 return NAN_PBA_METHOD_NFC_READER;
37 if (pbm == NAN_PBA_METHOD_PIN_KEYPAD)
38 return NAN_PBA_METHOD_PIN_DISPLAY;
39 if (pbm == NAN_PBA_METHOD_PASSPHRASE_KEYPAD)
40 return NAN_PBA_METHOD_PASSPHRASE_DISPLAY;
41 if (pbm == NAN_PBA_METHOD_QR_SCAN)
42 return NAN_PBA_METHOD_QR_DISPLAY;
43 if (pbm == NAN_PBA_METHOD_NFC_READER)
44 return NAN_PBA_METHOD_NFC_TAG;
45 if (pbm == NAN_PBA_METHOD_SERVICE_MANAGED)
46 return NAN_PBA_METHOD_SERVICE_MANAGED;
47 if (pbm == NAN_PBA_METHOD_HANDSHAKE_SKIPPED)
48 return NAN_PBA_METHOD_HANDSHAKE_SKIPPED;
49
50 return 0;
51 }
52
53
54 /**
55 * nan_bootstrap_reset - Reset bootstrap state
56 * @nan: NAN module context from nan_init()
57 * @peer: Peer to reset bootstrap state
58 */
nan_bootstrap_reset(struct nan_data * nan,struct nan_peer * peer)59 void nan_bootstrap_reset(struct nan_data *nan, struct nan_peer *peer)
60 {
61 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: Reset state");
62
63 eloop_cancel_timeout(nan_bootstrap_timeout, nan, peer);
64 os_free(peer->bootstrap.cookie);
65
66 /*
67 * Do not use memset to reset all data to preserve the peer's
68 * supported bootstrap methods and the NPBA buffer if present.
69 */
70 peer->bootstrap.cookie = NULL;
71 peer->bootstrap.cookie_len = 0;
72 peer->bootstrap.initiator = false;
73 peer->bootstrap.dialog_token = 0;
74 peer->bootstrap.requested_pbm = 0;
75 peer->bootstrap.authorized = 0;
76 peer->bootstrap.status = 0;
77 peer->bootstrap.comeback_required = false;
78 peer->bootstrap.in_progress = false;
79 peer->bootstrap.reason_code = 0;
80 peer->bootstrap.handle = -1;
81 peer->bootstrap.req_instance_id = 0;
82 }
83
84
85 /**
86 * nan_bootstrap_build_npba - Build NAN Pairing Bootstrap attribute
87 * @nan: NAN module context from nan_init()
88 * @peer: Peer for which to build the attribute
89 * Returns: The constructed NPBA or %NULL on failure
90 */
nan_bootstrap_build_npba(struct nan_data * nan,struct nan_peer * peer)91 static struct wpabuf * nan_bootstrap_build_npba(struct nan_data *nan,
92 struct nan_peer *peer)
93 {
94 struct wpabuf *buf;
95 u16 pbm = peer->bootstrap.requested_pbm;
96 u8 type_and_status;
97 u8 *len;
98
99 /*
100 * Allocate max possible size: header (3) + Dialog Token (1) + Type and
101 * Status (1) + Reason (1) + Comeback (2 + 1 + Comeback Token) + pbm (2)
102 */
103 buf = wpabuf_alloc(11 + peer->bootstrap.cookie_len);
104 if (!buf)
105 return NULL;
106
107 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: Build NPBA");
108
109 if (peer->bootstrap.initiator) {
110 type_and_status = NAN_PBA_TYPE_RESPONSE;
111 if (peer->bootstrap.status)
112 pbm = 0;
113 } else {
114 type_and_status = NAN_PBA_TYPE_REQUEST;
115 }
116
117 type_and_status |= peer->bootstrap.status << NAN_PBA_STATUS_POS;
118
119 wpabuf_put_u8(buf, NAN_ATTR_NPBA);
120 len = wpabuf_put(buf, 2);
121
122 wpabuf_put_u8(buf, peer->bootstrap.dialog_token);
123 wpabuf_put_u8(buf, type_and_status);
124 wpabuf_put_u8(buf, peer->bootstrap.reason_code);
125
126 if (peer->bootstrap.status == NAN_PBA_STATUS_COMEBACK) {
127 if (peer->bootstrap.initiator)
128 wpabuf_put_le16(buf, peer->bootstrap.comeback_after);
129
130 wpabuf_put_u8(buf, peer->bootstrap.cookie_len);
131 if (peer->bootstrap.cookie)
132 wpabuf_put_data(buf, peer->bootstrap.cookie,
133 peer->bootstrap.cookie_len);
134 }
135
136 wpabuf_put_le16(buf, pbm);
137 WPA_PUT_LE16(len, wpabuf_len(buf) - 3);
138
139 return buf;
140 }
141
142
143 /**
144 * nan_bootstrap_timeout - Bootstrap timeout handler
145 * @eloop_data: NAN module context from nan_init()
146 * @user_ctx: Peer for which the timeout occurred
147 */
nan_bootstrap_timeout(void * eloop_data,void * user_ctx)148 static void nan_bootstrap_timeout(void *eloop_data, void *user_ctx)
149 {
150 struct nan_data *nan = eloop_data;
151 struct nan_peer *peer = user_ctx;
152 struct wpabuf *attr;
153
154 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: timeout. status=%u",
155 peer->bootstrap.status);
156
157 attr = nan_bootstrap_build_npba(nan, peer);
158 if (!attr) {
159 wpa_printf(MSG_DEBUG,
160 "NAN: Bootstrap: Failed to build attribute");
161
162 nan_bootstrap_reset(nan, peer);
163
164 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx, peer->nmi_addr,
165 0, false,
166 NAN_REASON_UNSPECIFIED_REASON,
167 -1, 0);
168 return;
169 }
170
171 if (nan->cfg->transmit_followup(nan->cfg->cb_ctx, peer->nmi_addr, attr,
172 peer->bootstrap.handle,
173 peer->bootstrap.req_instance_id)) {
174 wpa_printf(MSG_DEBUG,
175 "NAN: Bootstrap: Failed to transmit followup");
176
177 nan_bootstrap_reset(nan, peer);
178
179 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx, peer->nmi_addr,
180 0, false,
181 NAN_REASON_UNSPECIFIED_REASON,
182 peer->bootstrap.handle,
183 peer->bootstrap.req_instance_id);
184 }
185
186 wpabuf_free(attr);
187
188 /* If the peer didn't reply, try again */
189 if (peer->bootstrap.status != NAN_PBA_STATUS_COMEBACK)
190 eloop_register_timeout(0, NAN_BOOTSTRAP_RETRY_TIMEOUT_US,
191 nan_bootstrap_timeout, nan, peer);
192 }
193
194
195 /**
196 * nan_bootstrap_handle_rx_request - Process received bootstrap request
197 * @nan: NAN module context from nan_init()
198 * @peer: Peer from which the request was received
199 * @dialog_token: Dialog token from the request
200 * @pbm: Pairing bootstrapping method bitmap from the request
201 * @cookie: Comeback cookie from the request (if any)
202 * @cookie_len: Length of the comeback cookie
203 * @status: Status field from the request
204 * @handle: Follow-up handle
205 * @req_instance_id: Follow-up instance ID
206 * @npba: NPBA from the request
207 * @npba_len: Length of the NPBA
208 */
nan_bootstrap_handle_rx_request(struct nan_data * nan,struct nan_peer * peer,u8 dialog_token,u16 pbm,const u8 * cookie,u8 cookie_len,u8 status,int handle,u8 req_instance_id,const u8 * npba,u16 npba_len)209 static void nan_bootstrap_handle_rx_request(struct nan_data *nan,
210 struct nan_peer *peer,
211 u8 dialog_token, u16 pbm,
212 const u8 *cookie,
213 u8 cookie_len, u8 status,
214 int handle, u8 req_instance_id,
215 const u8 *npba, u16 npba_len)
216 {
217 struct wpabuf *attr = NULL;
218 u16 supported_methods;
219
220 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: RX request");
221
222 if (peer->bootstrap.initiator && peer->bootstrap.comeback_required) {
223 if (status != NAN_PBA_STATUS_COMEBACK) {
224 wpa_printf(MSG_DEBUG,
225 "NAN: Bootstrap: Missing comeback cookie. Ignore");
226 return;
227 }
228
229 if (cookie_len != peer->bootstrap.cookie_len ||
230 !!cookie ^ !!peer->bootstrap.cookie ||
231 (cookie && os_memcmp(cookie, peer->bootstrap.cookie,
232 cookie_len) != 0)) {
233 wpa_printf(MSG_DEBUG,
234 "NAN: Bootstrap: Invalid comeback cookie. Ignore");
235 return;
236 }
237
238 if (dialog_token != peer->bootstrap.dialog_token) {
239 wpa_printf(MSG_DEBUG,
240 "NAN: Bootstrap: Invalid dialog token. Ignore");
241 return;
242 }
243
244 if (handle != peer->bootstrap.handle ||
245 req_instance_id != peer->bootstrap.req_instance_id) {
246 wpa_printf(MSG_DEBUG,
247 "NAN: Bootstrap: Invalid handle or instance ID");
248 return;
249 }
250
251 wpa_printf(MSG_DEBUG,
252 "NAN: Bootstrap: Valid comeback request(pbm=0x%04x) authorized=0x%04x",
253 pbm, peer->bootstrap.authorized);
254
255 if (peer->bootstrap.authorized == nan_complement_pbm(pbm)) {
256 wpa_printf(MSG_DEBUG,
257 "NAN: Bootstrap: Peer bootstrap authorized. Accept.");
258
259 peer->bootstrap.status = NAN_PBA_STATUS_ACCEPTED;
260 peer->bootstrap.reason_code = 0;
261 peer->bootstrap.comeback_required = false;
262 peer->bootstrap.requested_pbm = nan_complement_pbm(pbm);
263 }
264
265 goto send_response;
266 }
267
268 wpa_printf(MSG_DEBUG,
269 "NAN: Bootstrap: New bootstrap request. pbm=0x%04x", pbm);
270
271 nan_bootstrap_reset(nan, peer);
272
273 peer->bootstrap.initiator = true;
274 peer->bootstrap.dialog_token = dialog_token;
275 peer->bootstrap.requested_pbm = nan_complement_pbm(pbm);
276 peer->bootstrap.in_progress = true;
277 peer->bootstrap.handle = handle;
278 peer->bootstrap.req_instance_id = req_instance_id;
279 supported_methods =
280 nan->cfg->get_supported_bootstrap_methods(nan->cfg->cb_ctx,
281 handle);
282
283 if (!(supported_methods & peer->bootstrap.requested_pbm)) {
284 wpa_printf(MSG_DEBUG,
285 "NAN: Bootstrap: No supported bootstrap methods in request");
286
287 peer->bootstrap.status = NAN_PBA_STATUS_REJECTED;
288 peer->bootstrap.reason_code =
289 NAN_REASON_PAIR_BOOTSTRAP_REJECTED;
290 goto send_response;
291 }
292
293 if (peer->bootstrap.requested_pbm &
294 nan->cfg->auto_accept_bootstrap_methods) {
295 peer->bootstrap.authorized = peer->bootstrap.requested_pbm;
296 peer->bootstrap.status = NAN_PBA_STATUS_ACCEPTED;
297 goto send_response;
298 }
299
300 peer->bootstrap.status = NAN_PBA_STATUS_COMEBACK;
301 peer->bootstrap.comeback_required = true;
302 peer->bootstrap.cookie_len = NAN_BOOTSTRAP_COOKIE_LEN;
303 peer->bootstrap.cookie = os_malloc(peer->bootstrap.cookie_len);
304
305 if (peer->bootstrap.cookie) {
306 if (os_get_random(peer->bootstrap.cookie,
307 peer->bootstrap.cookie_len) < 0) {
308 nan_bootstrap_reset(nan, peer);
309 return;
310 }
311 } else {
312 peer->bootstrap.cookie_len = 0;
313 }
314
315 peer->bootstrap.comeback_after = nan->cfg->bootstrap_comeback_timeout;
316
317 if (nan->cfg->bootstrap_request)
318 nan->cfg->bootstrap_request(nan->cfg->cb_ctx, peer->nmi_addr,
319 peer->bootstrap.requested_pbm,
320 handle, req_instance_id);
321
322 send_response:
323 attr = nan_bootstrap_build_npba(nan, peer);
324 if (!attr) {
325 wpa_printf(MSG_DEBUG,
326 "NAN: Bootstrap: Failed to build bootstrap attribute");
327 goto done;
328 }
329
330 if (nan->cfg->transmit_followup(nan->cfg->cb_ctx, peer->nmi_addr, attr,
331 handle, req_instance_id)) {
332 wpa_printf(MSG_DEBUG,
333 "NAN: Bootstrap: Failed to transmit bootstrap followup");
334
335 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx, peer->nmi_addr,
336 0, false,
337 NAN_REASON_UNSPECIFIED_REASON,
338 handle, req_instance_id);
339 goto done;
340 }
341
342 if (peer->bootstrap.status == NAN_PBA_STATUS_COMEBACK) {
343 wpa_printf(MSG_DEBUG,
344 "NAN: Bootstrap: Wait for comeback bootstrap request");
345
346 wpabuf_free(attr);
347 return;
348 }
349
350 if (peer->bootstrap.status == NAN_PBA_STATUS_ACCEPTED) {
351 wpabuf_free(peer->bootstrap.npba);
352 peer->bootstrap.npba = wpabuf_alloc(3 + npba_len);
353 if (peer->bootstrap.npba) {
354 wpabuf_put_u8(peer->bootstrap.npba, NAN_ATTR_NPBA);
355 wpabuf_put_le16(peer->bootstrap.npba, npba_len);
356 wpabuf_put_data(peer->bootstrap.npba, npba, npba_len);
357 } else {
358 wpa_printf(MSG_INFO,
359 "NAN: Bootstrap: Failed to store NPBA");
360 }
361 }
362
363 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx,
364 peer->nmi_addr,
365 peer->bootstrap.requested_pbm,
366 peer->bootstrap.status ==
367 NAN_PBA_STATUS_ACCEPTED,
368 peer->bootstrap.reason_code,
369 peer->bootstrap.handle,
370 peer->bootstrap.req_instance_id);
371 done:
372 wpabuf_free(attr);
373 nan_bootstrap_reset(nan, peer);
374 }
375
376
377 /**
378 * nan_bootstrap_supported - Check if bootstrap operations are supported
379 * @nan: NAN module context from nan_init()
380 * Returns: Whether all required bootstrap operations are supported
381 */
nan_bootstrap_supported(struct nan_data * nan)382 static bool nan_bootstrap_supported(struct nan_data *nan)
383 {
384 return nan->cfg->bootstrap_completed &&
385 nan->cfg->bootstrap_request &&
386 nan->cfg->transmit_followup &&
387 nan->cfg->get_supported_bootstrap_methods;
388 }
389
390
391 /**
392 * nan_bootstrap_handle_rx - Process received bootstrap follow-up
393 * @nan: NAN module context from nan_init()
394 * @peer_nmi: Peer address from which the follow-up was received
395 * @npba: Pointer to the NPBA in the follow-up
396 * @npba_len: Length of the NPBA
397 * @buf: Complete Follow-up frame
398 * @len: Length of the complete Follow-up frame
399 * @handle: Follow up handle
400 * @req_instance_id: Follow-up instance ID
401 * Returns: true if the follow up was processed, false on error
402 */
nan_bootstrap_handle_rx(struct nan_data * nan,const u8 * peer_nmi,const u8 * npba,u16 npba_len,const u8 * buf,size_t len,int handle,u8 req_instance_id)403 bool nan_bootstrap_handle_rx(struct nan_data *nan, const u8 *peer_nmi,
404 const u8 *npba, u16 npba_len,
405 const u8 *buf, size_t len,
406 int handle, u8 req_instance_id)
407 {
408 const u8 *cookie = NULL;
409 u8 dialog_token, type, status, reason_code, cookie_len = 0;
410 u16 pbm, comeback_after = 0;
411 struct nan_peer *peer;
412 const u8 *orig_npba = npba;
413 u16 orig_npba_len = npba_len;
414
415 if (!nan_bootstrap_supported(nan)) {
416 wpa_printf(MSG_DEBUG,
417 "NAN: Bootstrap: Not all bootstrap operations are supported. Ignore");
418 return false;
419 }
420
421 if (npba_len < 3)
422 return false;
423 dialog_token = *npba++;
424 type = *npba & NAN_PBA_TYPE_MASK;
425 status = (*npba++ >> NAN_PBA_STATUS_POS) & NAN_PBA_STATUS_MASK;
426 reason_code = *npba++;
427 npba_len -= 3;
428
429 if (type == NAN_PBA_TYPE_ADVERTISE) {
430 wpa_printf(MSG_DEBUG,
431 "NAN: Bootstrap: type == Advertise. Ignore");
432 return false;
433 }
434
435 if (type != NAN_PBA_TYPE_REQUEST &&
436 type != NAN_PBA_TYPE_RESPONSE) {
437 wpa_printf(MSG_DEBUG,
438 "NAN: Bootstrap: Unknown NPBA type %u", type);
439 return false;
440 }
441
442 if (status == NAN_PBA_STATUS_COMEBACK) {
443 if (type == NAN_PBA_TYPE_RESPONSE) {
444 if (npba_len < 2) {
445 wpa_printf(MSG_DEBUG,
446 "NAN: Bootstrap: Response too short for comeback after");
447 return false;
448 }
449
450 comeback_after = WPA_GET_LE16(npba);
451 npba += 2;
452 npba_len -= 2;
453 }
454
455 if (npba_len < 1) {
456 wpa_printf(MSG_DEBUG,
457 "NAN: Bootstrap: Response too short for comeback cookie length");
458 return false;
459 }
460
461 cookie_len = *npba++;
462 npba_len--;
463 if (cookie_len > npba_len) {
464 wpa_printf(MSG_DEBUG,
465 "NAN: Bootstrap: Comeback field is too long");
466 return false;
467 }
468
469 cookie = npba;
470 npba += cookie_len;
471 npba_len -= cookie_len;
472 }
473
474 if (npba_len < 2) {
475 wpa_printf(MSG_DEBUG,
476 "NAN: Bootstrap: Buffer too short for PBM");
477 return false;
478 }
479
480 pbm = WPA_GET_LE16(npba);
481 peer = nan_get_peer(nan, peer_nmi);
482
483 /* Handle NAN bootstrap request */
484 if (type == NAN_PBA_TYPE_REQUEST) {
485 if (!peer) {
486 nan_add_peer(nan, peer_nmi, buf, len);
487 peer = nan_get_peer(nan, peer_nmi);
488 if (!peer) {
489 wpa_printf(MSG_DEBUG,
490 "NAN: Bootstrap: Failed alloc peer from bootstrap request");
491 return false;
492 }
493 }
494
495 nan_bootstrap_handle_rx_request(nan, peer, dialog_token,
496 pbm, cookie, cookie_len,
497 status, handle,
498 req_instance_id,
499 orig_npba, orig_npba_len);
500 return true;
501 }
502
503 /* Handle NAN bootstrap response */
504 if (!peer || !peer->bootstrap.in_progress ||
505 peer->bootstrap.initiator) {
506 wpa_printf(MSG_DEBUG,
507 "NAN: Bootstrap: Unexpected bootstrap response");
508 return false;
509 }
510
511 if (dialog_token != peer->bootstrap.dialog_token) {
512 wpa_printf(MSG_DEBUG,
513 "NAN: Bootstrap: Response with invalid dialog token. Ignore");
514 return false;
515 }
516
517 if (handle != peer->bootstrap.handle ||
518 req_instance_id != peer->bootstrap.req_instance_id) {
519 wpa_printf(MSG_DEBUG,
520 "NAN: Bootstrap: Response with invalid handle or instance ID. Ignore");
521 return false;
522 }
523
524 peer->bootstrap.status = status;
525 peer->bootstrap.reason_code = reason_code;
526 peer->bootstrap.comeback_required = status == NAN_PBA_STATUS_COMEBACK;
527 peer->bootstrap.comeback_after = comeback_after;
528
529 if (cookie && cookie_len) {
530 os_free(peer->bootstrap.cookie);
531 peer->bootstrap.cookie = os_memdup(cookie, cookie_len);
532 if (!peer->bootstrap.cookie) {
533 nan_bootstrap_reset(nan, peer);
534 return false;
535 }
536 peer->bootstrap.cookie_len = cookie_len;
537 }
538
539 if (status == NAN_PBA_STATUS_ACCEPTED &&
540 nan_complement_pbm(pbm) == peer->bootstrap.requested_pbm) {
541 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: Accepted. Complete.");
542
543 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx,
544 peer->nmi_addr,
545 peer->bootstrap.requested_pbm,
546 true, 0,
547 peer->bootstrap.handle,
548 peer->bootstrap.req_instance_id);
549 nan_bootstrap_reset(nan, peer);
550 } else if (status == NAN_PBA_STATUS_REJECTED) {
551 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: Rejected. Complete");
552
553 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx, peer->nmi_addr,
554 0, false, reason_code,
555 peer->bootstrap.handle,
556 peer->bootstrap.req_instance_id);
557 nan_bootstrap_reset(nan, peer);
558 } else if (status == NAN_PBA_STATUS_COMEBACK) {
559 wpa_printf(MSG_DEBUG,
560 "NAN: Bootstrap: Comeback required. Schedule timeout for %u TU",
561 peer->bootstrap.comeback_after);
562
563 eloop_cancel_timeout(nan_bootstrap_timeout, nan, peer);
564 eloop_register_timeout(peer->bootstrap.comeback_after / 1024,
565 (peer->bootstrap.comeback_after % 1024) *
566 1000,
567 nan_bootstrap_timeout, nan, peer);
568 } else {
569 wpa_printf(MSG_DEBUG,
570 "NAN: Bootstrap: Unknown status=%u. Abort.",
571 status);
572
573 nan->cfg->bootstrap_completed(nan->cfg->cb_ctx, peer->nmi_addr,
574 0, false,
575 NAN_REASON_UNSPECIFIED_REASON,
576 peer->bootstrap.handle,
577 peer->bootstrap.req_instance_id);
578 nan_bootstrap_reset(nan, peer);
579 }
580
581 return true;
582 }
583
584
585 /**
586 * nan_bootstrap_request - Initiate NAN bootstrap request to a peer
587 * @nan: NAN module context from nan_init()
588 * @handle: Follow up handle
589 * @peer_nmi: Peer address to which to send the bootstrap request
590 * @req_instance_id: Follow up instance ID
591 * @pbm: Pairing bootstrapping method bitmap to use
592 * @auth: If true, authorize the bootstrap request for the peer instead of
593 * sending the request
594 * Returns: 0 on success, -1 on failure
595 */
nan_bootstrap_request(struct nan_data * nan,int handle,const u8 * peer_nmi,u8 req_instance_id,u16 pbm,bool auth)596 int nan_bootstrap_request(struct nan_data *nan, int handle,
597 const u8 *peer_nmi, u8 req_instance_id, u16 pbm,
598 bool auth)
599 {
600 struct nan_peer *peer;
601 int ret;
602
603 if (!nan || !nan->nan_started)
604 return -1;
605
606 if (!nan_bootstrap_supported(nan)) {
607 wpa_printf(MSG_DEBUG,
608 "NAN: Bootstrap: Not all bootstrap operations are supported. Ignore");
609 return -1;
610 }
611
612 wpa_printf(MSG_DEBUG,
613 "NAN: Bootstrap: Request bootstrap to peer " MACSTR
614 " pbm=0x%x auth=%d",
615 MAC2STR(peer_nmi), pbm, auth);
616
617 peer = nan_get_peer(nan, peer_nmi);
618 if (!peer) {
619 wpa_printf(MSG_DEBUG,
620 "NAN: Bootstrap: Request for unknown peer");
621 return -1;
622 }
623
624 if (!(pbm & nan->cfg->supported_bootstrap_methods)) {
625 wpa_printf(MSG_DEBUG,
626 "NAN: Bootstrap: Unsupported method=0x%x (local support=0x%x)",
627 pbm, nan->cfg->supported_bootstrap_methods);
628 return -1;
629 }
630
631 if (pbm & (pbm - 1)) {
632 wpa_printf(MSG_DEBUG,
633 "NAN: Bootstrap: Multiple bootstrap methods=0x%x in request",
634 pbm);
635 return -1;
636 }
637
638 if (auth) {
639 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: Authorize request");
640
641 peer->bootstrap.authorized = pbm;
642 return 0;
643 }
644
645 if (peer->bootstrap.in_progress) {
646 wpa_printf(MSG_DEBUG,
647 "NAN: Bootstrap: already in progress with the peer");
648 return -1;
649 }
650
651 if (!(nan_complement_pbm(pbm) & peer->bootstrap.supported_methods)) {
652 wpa_printf(MSG_DEBUG,
653 "NAN: Bootstrap: Peer doesn't support method=0x%x",
654 pbm);
655 return -1;
656 }
657
658 wpa_printf(MSG_DEBUG, "NAN: Prepare bootstrap request");
659
660 nan_bootstrap_reset(nan, peer);
661
662 peer->bootstrap.dialog_token = nan_get_next_dialog_token(nan);
663 peer->bootstrap.requested_pbm = pbm;
664 peer->bootstrap.in_progress = true;
665 peer->bootstrap.handle = handle;
666 peer->bootstrap.req_instance_id = req_instance_id;
667
668 peer->bootstrap.npba = nan_bootstrap_build_npba(nan, peer);
669 if (!peer->bootstrap.npba) {
670 nan_bootstrap_reset(nan, peer);
671 return -1;
672 }
673
674 ret = nan->cfg->transmit_followup(nan->cfg->cb_ctx, peer->nmi_addr,
675 peer->bootstrap.npba, handle,
676 req_instance_id);
677 if (ret) {
678 wpa_printf(MSG_DEBUG,
679 "NAN: Bootstrap: Failed to transmit follow-up");
680
681 nan_bootstrap_reset(nan, peer);
682 return -1;
683 }
684
685 eloop_register_timeout(0, NAN_BOOTSTRAP_RETRY_TIMEOUT_US,
686 nan_bootstrap_timeout, nan, peer);
687 return ret;
688 }
689
690
691 /**
692 * nan_bootstrap_peer_reset - Reset bootstrap state for a peer
693 * @nan: NAN module context from nan_init()
694 * @peer_nmi: Peer address for which to reset the bootstrap state
695 * Returns: 0 on success, -1 on failure
696 */
nan_bootstrap_peer_reset(struct nan_data * nan,const u8 * peer_nmi)697 int nan_bootstrap_peer_reset(struct nan_data *nan, const u8 *peer_nmi)
698 {
699 struct nan_peer *peer;
700
701 if (!nan || !nan->nan_started)
702 return -1;
703
704 peer = nan_get_peer(nan, peer_nmi);
705 if (!peer) {
706 wpa_printf(MSG_DEBUG, "NAN: Bootstrap: Reset for unknown peer");
707 return -1;
708 }
709
710 nan_bootstrap_reset(nan, peer);
711 return 0;
712 }
713
714
715 /**
716 * nan_bootstrap_get_supported_methods - Get supported bootstrap methods for a peer
717 *
718 * @nan: NAN module context from nan_init()
719 * @peer_nmi: Peer address
720 * @supported_methods: Pointer to store the supported methods bitmap
721 * Returns: 0 on success, -1 on failure
722 */
nan_bootstrap_get_supported_methods(struct nan_data * nan,const u8 * peer_nmi,u16 * supported_methods)723 int nan_bootstrap_get_supported_methods(struct nan_data *nan,
724 const u8 *peer_nmi,
725 u16 *supported_methods)
726 {
727 struct nan_peer *peer;
728
729 if (!nan || !nan->nan_started || !supported_methods)
730 return -1;
731
732 peer = nan_get_peer(nan, peer_nmi);
733 if (!peer) {
734 wpa_printf(MSG_DEBUG,
735 "NAN: Bootstrap: Get supported methods for unknown peer");
736 return -1;
737 }
738
739 *supported_methods = peer->bootstrap.supported_methods;
740 return 0;
741 }
742