blob: acde4f3b2acdfe4b783b5c7cbf11d627d0a17f5e [file] [log] [blame]
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001/*
2 * NAN Discovery Engine
3 * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "crypto/crypto.h"
14#include "crypto/sha256.h"
15#include "ieee802_11_defs.h"
16#include "nan.h"
17#include "nan_de.h"
18
19static const u8 nan_network_id[ETH_ALEN] =
20{ 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 };
21static const u8 wildcard_bssid[ETH_ALEN] =
22{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
23
24enum nan_de_service_type {
25 NAN_DE_PUBLISH,
26 NAN_DE_SUBSCRIBE,
27};
28
29struct nan_de_service {
30 int id;
31 enum nan_de_service_type type;
32 char *service_name;
33 u8 service_id[NAN_SERVICE_ID_LEN];
34 struct nan_publish_params publish;
35 struct nan_subscribe_params subscribe;
36 enum nan_service_protocol_type srv_proto_type;
37 struct wpabuf *ssi;
38 struct wpabuf *elems;
39 struct os_reltime time_started;
40 struct os_reltime end_time;
41 struct os_reltime last_multicast;
42 struct os_reltime first_discovered;
43 struct os_reltime last_followup;
44 bool needs_fsd;
45 unsigned int freq;
46 unsigned int default_freq;
47 int *freq_list;
48
49 /* pauseState information for Publish function */
50 struct os_reltime pause_state_end;
51 u8 sel_peer_id;
52 u8 sel_peer_addr[ETH_ALEN];
53
54 /* Publish state - channel iteration */
55 bool in_multi_chan;
56 bool first_multi_chan;
57 int multi_chan_idx; /* index to freq_list[] */
58 struct os_reltime next_publish_state;
59 struct os_reltime next_publish_chan;
60 unsigned int next_publish_duration;
Sunil Ravic0f5d412024-09-11 22:12:49 +000061 bool is_p2p;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000062};
63
64struct nan_de {
65 u8 nmi[ETH_ALEN];
Sunil Ravic0f5d412024-09-11 22:12:49 +000066 bool offload;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000067 bool ap;
68 struct nan_callbacks cb;
69
70 struct nan_de_service *service[NAN_DE_MAX_SERVICE];
71 unsigned int num_service;
72
73 int next_handle;
74
75 unsigned int ext_listen_freq;
76 unsigned int listen_freq;
77 unsigned int tx_wait_status_freq;
78 unsigned int tx_wait_end_freq;
79};
80
81
Sunil Ravic0f5d412024-09-11 22:12:49 +000082struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
Sunil Ravib0ac25f2024-07-12 01:42:03 +000083 const struct nan_callbacks *cb)
84{
85 struct nan_de *de;
86
87 de = os_zalloc(sizeof(*de));
88 if (!de)
89 return NULL;
90
91 os_memcpy(de->nmi, nmi, ETH_ALEN);
Sunil Ravic0f5d412024-09-11 22:12:49 +000092 de->offload = offload;
Sunil Ravib0ac25f2024-07-12 01:42:03 +000093 de->ap = ap;
94 os_memcpy(&de->cb, cb, sizeof(*cb));
95
96 return de;
97}
98
99
100static void nan_de_service_free(struct nan_de_service *srv)
101{
102 os_free(srv->service_name);
103 wpabuf_free(srv->ssi);
104 wpabuf_free(srv->elems);
105 os_free(srv->freq_list);
106 os_free(srv);
107}
108
109
110static void nan_de_service_deinit(struct nan_de *de, struct nan_de_service *srv,
111 enum nan_de_reason reason)
112{
113 if (!srv)
114 return;
115 if (srv->type == NAN_DE_PUBLISH && de->cb.publish_terminated)
116 de->cb.publish_terminated(de->cb.ctx, srv->id, reason);
117 if (srv->type == NAN_DE_SUBSCRIBE && de->cb.subscribe_terminated)
118 de->cb.subscribe_terminated(de->cb.ctx, srv->id, reason);
119 nan_de_service_free(srv);
120}
121
122
123static void nan_de_clear_pending(struct nan_de *de)
124{
125 de->listen_freq = 0;
126 de->tx_wait_status_freq = 0;
127 de->tx_wait_end_freq = 0;
128}
129
130
131void nan_de_flush(struct nan_de *de)
132{
133 unsigned int i;
134
135 if (!de)
136 return;
137
138 for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
139 nan_de_service_deinit(de, de->service[i],
140 NAN_DE_REASON_USER_REQUEST);
141 de->service[i] = NULL;
142 }
143
144 de->num_service = 0;
145 nan_de_clear_pending(de);
146}
147
148
149static void nan_de_pause_state(struct nan_de_service *srv, const u8 *peer_addr,
150 u8 peer_id)
151{
152 wpa_printf(MSG_DEBUG, "NAN: Start pauseState");
153 os_get_reltime(&srv->pause_state_end);
154 srv->pause_state_end.sec += 60;
155 os_memcpy(srv->sel_peer_addr, peer_addr, ETH_ALEN);
156 srv->sel_peer_id = peer_id;
157}
158
159
160static void nan_de_unpause_state(struct nan_de_service *srv)
161{
162 wpa_printf(MSG_DEBUG, "NAN: Stop pauseState");
163 srv->pause_state_end.sec = 0;
164 srv->pause_state_end.usec = 0;
165 os_memset(srv->sel_peer_addr, 0, ETH_ALEN);
166 srv->sel_peer_id = 0;
167}
168
169
170static struct wpabuf * nan_de_alloc_sdf(size_t len)
171{
172 struct wpabuf *buf;
173
174 buf = wpabuf_alloc(2 + 4 + len);
175 if (buf) {
176 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
177 wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
178 wpabuf_put_be32(buf, NAN_SDF_VENDOR_TYPE);
179 }
180
181 return buf;
182}
183
184
185static int nan_de_tx(struct nan_de *de, unsigned int freq,
186 unsigned int wait_time,
187 const u8 *dst, const u8 *src, const u8 *bssid,
188 const struct wpabuf *buf)
189{
190 int res;
191
192 if (!de->cb.tx)
193 return -1;
194
195 res = de->cb.tx(de->cb.ctx, freq, wait_time, dst, src, bssid, buf);
196 if (res < 0)
197 return res;
198
199 de->tx_wait_status_freq = freq;
200 de->tx_wait_end_freq = wait_time ? freq : 0;
201
202 return res;
203}
204
205
206static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
207 unsigned int wait_time,
208 enum nan_service_control_type type,
209 const u8 *dst, u8 req_instance_id,
210 const struct wpabuf *ssi)
211{
212 struct wpabuf *buf;
213 size_t len = 0, sda_len, sdea_len;
214 u8 ctrl = type;
215 u16 sdea_ctrl = 0;
216
217 /* Service Descriptor attribute */
218 sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
219 len += NAN_ATTR_HDR_LEN + sda_len;
220
221 /* Service Descriptor Extension attribute */
222 sdea_len = 1 + 2;
223 if (ssi)
224 sdea_len += 2 + 4 + wpabuf_len(ssi);
225 len += NAN_ATTR_HDR_LEN + sdea_len;
226
227 /* Element Container attribute */
228 if (srv->elems)
229 len += NAN_ATTR_HDR_LEN + 1 + wpabuf_len(srv->elems);
230
231 buf = nan_de_alloc_sdf(len);
232 if (!buf)
233 return;
234
235 /* Service Descriptor attribute */
236 wpabuf_put_u8(buf, NAN_ATTR_SDA);
237 wpabuf_put_le16(buf, sda_len);
238 wpabuf_put_data(buf, srv->service_id, NAN_SERVICE_ID_LEN);
239 wpabuf_put_u8(buf, srv->id); /* Instance ID */
240 wpabuf_put_u8(buf, req_instance_id); /* Requestor Instance ID */
241 wpabuf_put_u8(buf, ctrl);
242
243 /* Service Descriptor Extension attribute */
244 if (srv->type == NAN_DE_PUBLISH || ssi) {
245 wpabuf_put_u8(buf, NAN_ATTR_SDEA);
246 wpabuf_put_le16(buf, sdea_len);
247 wpabuf_put_u8(buf, srv->id); /* Instance ID */
248 if (srv->type == NAN_DE_PUBLISH) {
249 if (srv->publish.fsd)
250 sdea_ctrl |= NAN_SDEA_CTRL_FSD_REQ;
251 if (srv->publish.fsd_gas)
252 sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
253 }
254 wpabuf_put_le16(buf, sdea_ctrl);
255 if (ssi) {
256 wpabuf_put_le16(buf, 4 + wpabuf_len(ssi));
257 wpabuf_put_be24(buf, OUI_WFA);
258 wpabuf_put_u8(buf, srv->srv_proto_type);
259 wpabuf_put_buf(buf, ssi);
260 }
261 }
262
263 /* Element Container attribute */
264 if (srv->elems) {
265 wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
266 wpabuf_put_le16(buf, 1 + wpabuf_len(srv->elems));
267 wpabuf_put_u8(buf, 0); /* Map ID */
268 wpabuf_put_buf(buf, srv->elems);
269 }
270
271 /* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
272 * but there is no synchronization in USD as as such, no NAN Cluster
273 * either. Use Wildcard BSSID instead. */
274 nan_de_tx(de, srv->freq, wait_time, dst, de->nmi, wildcard_bssid, buf);
275 wpabuf_free(buf);
276}
277
278
279static int nan_de_time_to_next_chan_change(struct nan_de_service *srv)
280{
281 struct os_reltime tmp, diff, now;
282
283 if (os_reltime_before(&srv->next_publish_state,
284 &srv->next_publish_chan))
285 tmp = srv->next_publish_state;
286 else if (srv->in_multi_chan)
287 tmp = srv->next_publish_chan;
288 else
289 tmp = srv->next_publish_state;
290
291 os_get_reltime(&now);
292 os_reltime_sub(&tmp, &now, &diff);
293 return os_reltime_in_ms(&diff);
294}
295
296
297static void nan_de_set_publish_times(struct nan_de_service *srv)
298{
299 os_get_reltime(&srv->next_publish_state);
300 srv->next_publish_chan = srv->next_publish_state;
301 /* Swap single/multi channel state in N * 100 TU */
302 os_reltime_add_ms(&srv->next_publish_state,
303 srv->next_publish_duration * 1024 / 1000);
304
305 /* Swap channel in multi channel state after 150 ms */
306 os_reltime_add_ms(&srv->next_publish_chan, 150);
307}
308
309
310static void nan_de_check_chan_change(struct nan_de_service *srv)
311{
312 if (srv->next_publish_duration) {
313 /* Update end times for the first operation of the publish
314 * iteration */
315 nan_de_set_publish_times(srv);
316 srv->next_publish_duration = 0;
317 } else if (srv->in_multi_chan) {
318 if (!os_reltime_initialized(&srv->pause_state_end)) {
319 srv->multi_chan_idx++;
320 if (srv->freq_list[srv->multi_chan_idx] == 0)
321 srv->multi_chan_idx = 0;
322 srv->freq = srv->freq_list[srv->multi_chan_idx];
323 wpa_printf(MSG_DEBUG,
324 "NAN: Publish multi-channel change to %u MHz",
325 srv->freq);
326 }
327 os_get_reltime(&srv->next_publish_chan);
328 os_reltime_add_ms(&srv->next_publish_chan, 150);
329 }
330}
331
332
333static void nan_de_tx_multicast(struct nan_de *de, struct nan_de_service *srv,
334 u8 req_instance_id)
335{
336 enum nan_service_control_type type;
337 unsigned int wait_time = 100;
338
339 if (srv->type == NAN_DE_PUBLISH) {
340 int ms;
341
342 type = NAN_SRV_CTRL_PUBLISH;
343
344 nan_de_check_chan_change(srv);
345 ms = nan_de_time_to_next_chan_change(srv);
346 if (ms < 100)
347 ms = 100;
348 wait_time = ms;
349 } else if (srv->type == NAN_DE_SUBSCRIBE) {
350 type = NAN_SRV_CTRL_SUBSCRIBE;
351 } else {
352 return;
353 }
354
355 nan_de_tx_sdf(de, srv, wait_time, type, nan_network_id,
356 req_instance_id, srv->ssi);
357 os_get_reltime(&srv->last_multicast);
358}
359
360
361static void nan_de_add_srv(struct nan_de *de, struct nan_de_service *srv)
362{
363 int ttl;
364
365 os_get_reltime(&srv->time_started);
366 ttl = srv->type == NAN_DE_PUBLISH ? srv->publish.ttl :
367 srv->subscribe.ttl;
368 if (ttl) {
369 srv->end_time = srv->time_started;
370 srv->end_time.sec += ttl;
371 }
372
373 de->service[srv->id - 1] = srv;
374 de->num_service++;
375}
376
377
378static void nan_de_del_srv(struct nan_de *de, struct nan_de_service *srv,
379 enum nan_de_reason reason)
380{
381 de->service[srv->id - 1] = NULL;
382 nan_de_service_deinit(de, srv, reason);
383 de->num_service--;
384 if (de->num_service == 0)
385 nan_de_clear_pending(de);
386}
387
388
389static bool nan_de_srv_expired(struct nan_de_service *srv,
390 struct os_reltime *now)
391{
392 if (os_reltime_initialized(&srv->end_time))
393 return os_reltime_before(&srv->end_time, now);
394
395 if (srv->type == NAN_DE_PUBLISH) {
396 /* Time out after one transmission (and wait for FSD) */
397 if (!os_reltime_initialized(&srv->last_multicast))
398 return false;
399 if (!srv->publish.fsd)
400 return true;
401 if (os_reltime_initialized(&srv->last_followup) &&
402 !os_reltime_expired(now, &srv->last_followup, 1))
403 return false;
404 if (os_reltime_expired(now, &srv->last_multicast, 1))
405 return true;
406 }
407
408 if (srv->type == NAN_DE_SUBSCRIBE) {
409 /* Time out after first DiscoveryResult event (and wait for
410 * FSD) */
411 if (!os_reltime_initialized(&srv->first_discovered))
412 return false;
413 if (!srv->needs_fsd)
414 return true;
415 if (os_reltime_initialized(&srv->last_followup) &&
416 !os_reltime_expired(now, &srv->last_followup, 1))
417 return false;
418 if (os_reltime_expired(now, &srv->first_discovered, 1))
419 return true;
420 }
421
422 return false;
423}
424
425
426static int nan_de_next_multicast(struct nan_de *de, struct nan_de_service *srv,
427 struct os_reltime *now)
428{
429 unsigned int period;
430 struct os_reltime next, diff;
431
432 if (srv->type == NAN_DE_PUBLISH && !srv->publish.unsolicited)
433 return -1;
434 if (srv->type == NAN_DE_SUBSCRIBE && !srv->subscribe.active)
435 return -1;
436
437 if (!os_reltime_initialized(&srv->last_multicast))
438 return 0;
439
440 if (srv->type == NAN_DE_PUBLISH && srv->publish.ttl == 0)
441 return -1;
442
443 if (srv->type == NAN_DE_PUBLISH &&
444 os_reltime_initialized(&srv->pause_state_end))
445 return -1;
446
447 period = srv->type == NAN_DE_PUBLISH ?
448 srv->publish.announcement_period :
449 srv->subscribe.query_period;
450 if (period == 0)
451 period = 100;
452 next = srv->last_multicast;
453 os_reltime_add_ms(&next, period);
454
455 if (srv->type == NAN_DE_PUBLISH) {
456 if (!de->tx_wait_end_freq && srv->publish.unsolicited &&
457 os_reltime_before(&next, now))
458 return 0;
459 next = srv->next_publish_state;
460 }
461
462 if (os_reltime_before(&next, now))
463 return 0;
464
465 os_reltime_sub(&next, now, &diff);
466 return os_reltime_in_ms(&diff);
467}
468
469
470static int nan_de_srv_time_to_next(struct nan_de *de,
471 struct nan_de_service *srv,
472 struct os_reltime *now)
473{
474 struct os_reltime diff;
475 int next = -1, tmp;
476
477 if (os_reltime_initialized(&srv->end_time)) {
478 os_reltime_sub(&srv->end_time, now, &diff);
479 tmp = os_reltime_in_ms(&diff);
480 if (next == -1 || tmp < next)
481 next = tmp;
482 }
483
484 tmp = nan_de_next_multicast(de, srv, now);
485 if (tmp >= 0 && (next == -1 || tmp < next))
486 next = tmp;
487
488 if (srv->type == NAN_DE_PUBLISH &&
489 os_reltime_initialized(&srv->last_multicast)) {
490 /* Time out after one transmission (and wait for FSD) */
491 tmp = srv->publish.fsd ? 1000 : 100;
492 if (next == -1 || tmp < next)
493 next = tmp;
494 }
495
496 if (srv->type == NAN_DE_SUBSCRIBE &&
497 os_reltime_initialized(&srv->first_discovered)) {
498 /* Time out after first DiscoveryResult event (and wait for
499 * FSD) */
500 tmp = srv->needs_fsd ? 1000 : 100;
501 if (next == -1 || tmp < next)
502 next = tmp;
503 }
504
505 if (os_reltime_initialized(&srv->next_publish_state)) {
506 os_reltime_sub(&srv->next_publish_state, now, &diff);
507 if (diff.sec < 0 || (diff.sec == 0 && diff.usec < 0))
508 tmp = 0;
509 else
510 tmp = os_reltime_in_ms(&diff);
511 if (next == -1 || tmp < next)
512 next = tmp;
513 }
514
515 return next;
516}
517
518
519static void nan_de_start_new_publish_state(struct nan_de_service *srv,
520 bool force_single)
521{
522 unsigned int n;
523
524 if (force_single || !srv->freq_list || srv->freq_list[0] == 0)
525 srv->in_multi_chan = false;
526 else
527 srv->in_multi_chan = !srv->in_multi_chan;
528
529 /* Use hardcoded Nmin=5 and Nmax=10 and pick a random N from that range.
530 * Use same values for M. */
531 n = 5 + os_random() % 5;
532 srv->next_publish_duration = n * 100;
533
534 nan_de_set_publish_times(srv);
535
536 if (os_reltime_initialized(&srv->pause_state_end))
537 return;
538
539 if (srv->in_multi_chan && srv->freq_list && srv->freq_list[0]) {
540 if (!srv->first_multi_chan)
541 srv->multi_chan_idx++;
542 if (srv->freq_list[srv->multi_chan_idx] == 0)
543 srv->multi_chan_idx = 0;
544 srv->first_multi_chan = false;
545 srv->freq = srv->freq_list[srv->multi_chan_idx];
546 } else {
547 srv->freq = srv->default_freq;
548 }
549
550 wpa_printf(MSG_DEBUG,
551 "NAN: Publish in %s channel state for %u TU; starting with %u MHz",
552 srv->in_multi_chan ? "multi" : "single", n * 100, srv->freq);
553}
554
555
556static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
557{
558 struct nan_de *de = eloop_ctx;
559 unsigned int i;
560 int next = -1;
561 bool started = false;
562 struct os_reltime now;
563
564 os_get_reltime(&now);
565
566 for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
567 struct nan_de_service *srv = de->service[i];
568 int srv_next;
569
570 if (!srv)
571 continue;
572
573 if (nan_de_srv_expired(srv, &now)) {
574 wpa_printf(MSG_DEBUG, "NAN: Service id %d expired",
575 srv->id);
576 nan_de_del_srv(de, srv, NAN_DE_REASON_TIMEOUT);
577 continue;
578 }
579
580 if (os_reltime_initialized(&srv->next_publish_state) &&
581 os_reltime_before(&srv->next_publish_state, &now))
582 nan_de_start_new_publish_state(srv, false);
583
584 if (srv->type == NAN_DE_PUBLISH &&
585 os_reltime_initialized(&srv->pause_state_end) &&
586 (os_reltime_before(&srv->pause_state_end, &now) ||
587 (srv->publish.fsd &&
588 os_reltime_initialized(&srv->last_followup) &&
589 os_reltime_expired(&now, &srv->last_followup, 1))))
590 nan_de_unpause_state(srv);
591
592 srv_next = nan_de_srv_time_to_next(de, srv, &now);
593 if (srv_next >= 0 && (next == -1 || srv_next < next))
594 next = srv_next;
595
Sunil Ravic0f5d412024-09-11 22:12:49 +0000596 if (srv_next == 0 && !started && !de->offload &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000597 de->listen_freq == 0 && de->ext_listen_freq == 0 &&
598 de->tx_wait_end_freq == 0 &&
599 nan_de_next_multicast(de, srv, &now) == 0) {
600 started = true;
601 nan_de_tx_multicast(de, srv, 0);
602 }
603
Sunil Ravic0f5d412024-09-11 22:12:49 +0000604 if (!started && !de->offload && de->cb.listen &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000605 de->listen_freq == 0 && de->ext_listen_freq == 0 &&
606 de->tx_wait_end_freq == 0 &&
607 ((srv->type == NAN_DE_PUBLISH &&
608 !srv->publish.unsolicited && srv->publish.solicited) ||
609 (srv->type == NAN_DE_SUBSCRIBE &&
610 !srv->subscribe.active))) {
611 int duration = 1000;
612
613 if (srv->type == NAN_DE_PUBLISH) {
614 nan_de_check_chan_change(srv);
615 duration = nan_de_time_to_next_chan_change(srv);
616 if (duration < 150)
617 duration = 150;
618 }
619
620 started = true;
621 if (de->cb.listen(de->cb.ctx, srv->freq, duration) == 0)
622 de->listen_freq = srv->freq;
623 }
624
625 }
626
627 if (next < 0)
628 return;
629
630 if (next == 0)
631 next = 1;
632 wpa_printf(MSG_DEBUG, "NAN: Next timer in %u ms", next);
633 eloop_register_timeout(next / 1000, (next % 1000) * 1000, nan_de_timer,
634 de, NULL);
635}
636
637
638static void nan_de_run_timer(struct nan_de *de)
639{
640 eloop_cancel_timeout(nan_de_timer, de, NULL);
641 eloop_register_timeout(0, 0, nan_de_timer, de, NULL);
642}
643
644
645void nan_de_deinit(struct nan_de *de)
646{
647 eloop_cancel_timeout(nan_de_timer, de, NULL);
648 nan_de_flush(de);
649 os_free(de);
650}
651
652
653void nan_de_listen_started(struct nan_de *de, unsigned int freq,
654 unsigned int duration)
655{
656 if (freq != de->listen_freq)
657 de->ext_listen_freq = freq;
658}
659
660
661void nan_de_listen_ended(struct nan_de *de, unsigned int freq)
662{
663 if (freq == de->ext_listen_freq)
664 de->ext_listen_freq = 0;
665
666 if (freq == de->listen_freq) {
667 de->listen_freq = 0;
668 nan_de_run_timer(de);
669 }
670}
671
672
673void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst)
674{
675 if (freq == de->tx_wait_status_freq)
676 de->tx_wait_status_freq = 0;
677}
678
679
680void nan_de_tx_wait_ended(struct nan_de *de)
681{
682 de->tx_wait_end_freq = 0;
683 nan_de_run_timer(de);
684}
685
686
687static const u8 *
688nan_de_get_attr(const u8 *buf, size_t len, enum nan_attr_id id,
689 unsigned int skip)
690{
691 const u8 *pos = buf, *end = buf + len;
692
693 while (end - pos >= NAN_ATTR_HDR_LEN) {
694 const u8 *attr = pos;
695 u8 attr_id;
696 u16 attr_len;
697
698 attr_id = *pos++;
699 attr_len = WPA_GET_LE16(pos);
700 pos += 2;
701 if (attr_len > end - pos) {
702 wpa_printf(MSG_DEBUG,
703 "NAN: Truncated attribute %u (len %u; left %zu)",
704 attr_id, attr_len, end - pos);
705 break;
706 }
707
708 if (attr_id == id) {
709 if (skip == 0)
710 return attr;
711 skip--;
712 }
713
714 pos += attr_len;
715 }
716
717 return NULL;
718}
719
720
721static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
722 u16 *sdea_control,
723 enum nan_service_protocol_type *srv_proto_type,
724 const u8 **ssi, size_t *ssi_len)
725{
726 unsigned int skip;
727 const u8 *sdea, *end;
728 u16 sdea_len;
729
730 for (skip = 0; ; skip++) {
731 sdea = nan_de_get_attr(buf, len, NAN_ATTR_SDEA, skip);
732 if (!sdea)
733 break;
734
735 sdea++;
736 sdea_len = WPA_GET_LE16(sdea);
737 sdea += 2;
738 if (sdea_len < 1 + 2)
739 continue;
740 end = sdea + sdea_len;
741
742 if (instance_id != *sdea++)
743 continue; /* Mismatching Instance ID */
744
745 *sdea_control = WPA_GET_LE16(sdea);
746 sdea += 2;
747
748 if (*sdea_control & NAN_SDEA_CTRL_RANGE_LIMIT) {
749 if (end - sdea < 4)
750 continue;
751 sdea += 4;
752 }
753
754 if (*sdea_control & NAN_SDEA_CTRL_SRV_UPD_INDIC) {
755 if (end - sdea < 1)
756 continue;
757 sdea++;
758 }
759
760 if (end - sdea >= 2) {
761 u16 srv_info_len;
762
763 srv_info_len = WPA_GET_LE16(sdea);
764 sdea += 2;
765
766 if (srv_info_len > end - sdea)
767 continue;
768
769 if (srv_info_len >= 4 &&
770 WPA_GET_BE24(sdea) == OUI_WFA) {
771 *srv_proto_type = sdea[3];
772 *ssi = sdea + 4;
773 *ssi_len = srv_info_len - 4;
774 }
775 }
776 }
777}
778
779
Sunil Ravic0f5d412024-09-11 22:12:49 +0000780static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
781 size_t len, const u8 *peer_addr,
782 unsigned int freq, bool p2p)
783{
784 const u8 *elem;
785 u16 elem_len;
786
787 elem = nan_de_get_attr(buf, len, NAN_ATTR_ELEM_CONTAINER, 0);
788 if (!elem)
789 return;
790
791 elem++;
792 elem_len = WPA_GET_LE16(elem);
793 elem += 2;
794 /* Skip the attribute if there is not enough froom for an element. */
795 if (elem_len < 1 + 2)
796 return;
797
798 /* Skip Map ID */
799 elem++;
800 elem_len--;
801
802 if (p2p && de->cb.process_p2p_usd_elems)
803 de->cb.process_p2p_usd_elems(de->cb.ctx, elem, elem_len,
804 peer_addr, freq);
805}
806
807
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000808static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
809 const u8 *peer_addr, u8 instance_id,
810 u8 req_instance_id, u16 sdea_control,
811 enum nan_service_protocol_type srv_proto_type,
812 const u8 *ssi, size_t ssi_len)
813{
814 /* Subscribe function processing of a receive Publish message */
815 if (!os_reltime_initialized(&srv->first_discovered)) {
816 os_get_reltime(&srv->first_discovered);
817 srv->needs_fsd = sdea_control & NAN_SDEA_CTRL_FSD_REQ;
818 nan_de_run_timer(de);
819 }
820
Sunil Ravic0f5d412024-09-11 22:12:49 +0000821 if (!de->offload && srv->subscribe.active && req_instance_id == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000822 /* Active subscriber replies with a Subscribe message if it
823 * received a matching unsolicited Publish message. */
824 nan_de_tx_multicast(de, srv, instance_id);
825 }
826
Sunil Ravic0f5d412024-09-11 22:12:49 +0000827 if (!de->offload && !srv->subscribe.active && req_instance_id == 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000828 /* Passive subscriber replies with a Follow-up message without
829 * Service Specific Info field if it received a matching
830 * unsolicited Publish message. */
831 nan_de_transmit(de, srv->id, NULL, NULL, peer_addr,
832 instance_id);
833 }
834
835 if (de->cb.discovery_result)
836 de->cb.discovery_result(
837 de->cb.ctx, srv->id, srv_proto_type,
838 ssi, ssi_len, instance_id,
839 peer_addr,
840 sdea_control & NAN_SDEA_CTRL_FSD_REQ,
841 sdea_control & NAN_SDEA_CTRL_FSD_GAS);
842}
843
844
845static bool nan_de_filter_match(struct nan_de_service *srv,
846 const u8 *matching_filter,
847 size_t matching_filter_len)
848{
849 const u8 *pos, *end;
850
851 /* Since we do not currently support matching_filter_rx values for the
852 * local Publish function, any matching filter with at least one
853 * <length,value> pair with length larger than zero implies a mismatch.
854 */
855
856 if (!matching_filter)
857 return true;
858
859 pos = matching_filter;
860 end = matching_filter + matching_filter_len;
861
862 while (pos < end) {
863 u8 len;
864
865 len = *pos++;
866 if (len > end - pos)
867 break;
868 if (len) {
869 /* A non-empty Matching Filter entry: no match since
870 * there is no local matching_filter_rx. */
871 return false;
872 }
873 }
874
875 return true;
876}
877
878
879static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
880 const u8 *peer_addr, u8 instance_id,
881 const u8 *matching_filter,
882 size_t matching_filter_len,
883 enum nan_service_protocol_type srv_proto_type,
884 const u8 *ssi, size_t ssi_len)
885{
886 struct wpabuf *buf;
887 size_t len = 0, sda_len, sdea_len;
888 u8 ctrl = 0;
889 u16 sdea_ctrl = 0;
890
891 /* Publish function processing of a receive Subscribe message */
892
893 if (!nan_de_filter_match(srv, matching_filter, matching_filter_len))
894 return;
895
896 if (!srv->publish.solicited)
897 return;
898
899 if (os_reltime_initialized(&srv->pause_state_end) &&
900 (!ether_addr_equal(peer_addr, srv->sel_peer_addr) ||
901 instance_id != srv->sel_peer_id)) {
902 wpa_printf(MSG_DEBUG,
903 "NAN: In pauseState - ignore Subscribe message from another subscriber");
904 return;
905 }
906
Sunil Ravic0f5d412024-09-11 22:12:49 +0000907 if (de->offload)
908 goto offload;
909
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000910 /* Reply with a solicited Publish message */
911 /* Service Descriptor attribute */
912 sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
913 len += NAN_ATTR_HDR_LEN + sda_len;
914
915 /* Service Descriptor Extension attribute */
916 sdea_len = 1 + 2;
917 if (srv->ssi)
918 sdea_len += 2 + 4 + wpabuf_len(srv->ssi);
919 len += NAN_ATTR_HDR_LEN + sdea_len;
920
921 /* Element Container attribute */
922 if (srv->elems)
923 len += NAN_ATTR_HDR_LEN + 1 + wpabuf_len(srv->elems);
924
925 buf = nan_de_alloc_sdf(len);
926 if (!buf)
927 return;
928
929 /* Service Descriptor attribute */
930 wpabuf_put_u8(buf, NAN_ATTR_SDA);
931 wpabuf_put_le16(buf, sda_len);
932 wpabuf_put_data(buf, srv->service_id, NAN_SERVICE_ID_LEN);
933 wpabuf_put_u8(buf, srv->id); /* Instance ID */
934 wpabuf_put_u8(buf, instance_id); /* Requestor Instance ID */
935 ctrl |= NAN_SRV_CTRL_PUBLISH;
936 wpabuf_put_u8(buf, ctrl);
937
938 /* Service Descriptor Extension attribute */
939 if (srv->type == NAN_DE_PUBLISH || srv->ssi) {
940 wpabuf_put_u8(buf, NAN_ATTR_SDEA);
941 wpabuf_put_le16(buf, sdea_len);
942 wpabuf_put_u8(buf, srv->id); /* Instance ID */
943 if (srv->type == NAN_DE_PUBLISH) {
944 if (srv->publish.fsd)
945 sdea_ctrl |= NAN_SDEA_CTRL_FSD_REQ;
946 if (srv->publish.fsd_gas)
947 sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
948 }
949 wpabuf_put_le16(buf, sdea_ctrl);
950 if (srv->ssi) {
951 wpabuf_put_le16(buf, 4 + wpabuf_len(srv->ssi));
952 wpabuf_put_be24(buf, OUI_WFA);
953 wpabuf_put_u8(buf, srv->srv_proto_type);
954 wpabuf_put_buf(buf, srv->ssi);
955 }
956 }
957
958 /* Element Container attribute */
959 if (srv->elems) {
960 wpabuf_put_u8(buf, NAN_ATTR_ELEM_CONTAINER);
961 wpabuf_put_le16(buf, 1 + wpabuf_len(srv->elems));
962 wpabuf_put_u8(buf, 0); /* Map ID */
963 wpabuf_put_buf(buf, srv->elems);
964 }
965
966 /* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
967 * but there is no synchronization in USD as as such, no NAN Cluster
968 * either. Use Wildcard BSSID instead. */
969 nan_de_tx(de, srv->freq, 100,
970 srv->publish.solicited_multicast ? nan_network_id : peer_addr,
971 de->nmi, wildcard_bssid, buf);
972 wpabuf_free(buf);
973
974 nan_de_pause_state(srv, peer_addr, instance_id);
975
Sunil Ravic0f5d412024-09-11 22:12:49 +0000976offload:
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000977 if (!srv->publish.disable_events && de->cb.replied)
978 de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
979 srv_proto_type, ssi, ssi_len);
980}
981
982
983static void nan_de_rx_follow_up(struct nan_de *de, struct nan_de_service *srv,
984 const u8 *peer_addr, u8 instance_id,
985 const u8 *ssi, size_t ssi_len)
986{
987 /* Follow-up function processing of a receive Follow-up message for a
988 * Subscribe or Publish instance */
989
990 if (srv->type == NAN_DE_PUBLISH &&
991 os_reltime_initialized(&srv->pause_state_end) &&
992 (!ether_addr_equal(peer_addr, srv->sel_peer_addr) ||
993 instance_id != srv->sel_peer_id ||
994 !ssi)) {
995 wpa_printf(MSG_DEBUG,
996 "NAN: In pauseState - ignore Follow-up message from another subscriber or without ssi");
997 return;
998 }
999
1000 os_get_reltime(&srv->last_followup);
1001
1002 if (srv->type == NAN_DE_PUBLISH && !ssi)
1003 nan_de_pause_state(srv, peer_addr, instance_id);
1004
1005 if (de->cb.receive)
1006 de->cb.receive(de->cb.ctx, srv->id, instance_id, ssi, ssi_len,
1007 peer_addr);
1008}
1009
1010
1011static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
1012 unsigned int freq, const u8 *buf, size_t len,
1013 const u8 *sda, size_t sda_len)
1014{
1015 const u8 *service_id;
1016 u8 instance_id, req_instance_id, ctrl;
1017 u16 sdea_control = 0;
1018 unsigned int i;
1019 enum nan_service_control_type type = 0;
1020 enum nan_service_protocol_type srv_proto_type = 0;
1021 const u8 *ssi = NULL;
1022 size_t ssi_len = 0;
1023 bool first = true;
1024 const u8 *end;
1025 const u8 *matching_filter = NULL;
1026 size_t matching_filter_len = 0;
1027
1028 if (sda_len < NAN_SERVICE_ID_LEN + 1 + 1 + 1)
1029 return;
1030 end = sda + sda_len;
1031
1032 service_id = sda;
1033 sda += NAN_SERVICE_ID_LEN;
1034 instance_id = *sda++;
1035 req_instance_id = *sda++;
1036 ctrl = *sda;
1037 type = ctrl & NAN_SRV_CTRL_TYPE_MASK;
1038 wpa_printf(MSG_DEBUG,
1039 "NAN: SDA - Service ID %02x%02x%02x%02x%02x%02x Instance ID %u Requestor Instance ID %u Service Control 0x%x (Service Control Type %u)",
1040 MAC2STR(service_id), instance_id, req_instance_id,
1041 ctrl, type);
1042 if (type != NAN_SRV_CTRL_PUBLISH &&
1043 type != NAN_SRV_CTRL_SUBSCRIBE &&
1044 type != NAN_SRV_CTRL_FOLLOW_UP) {
1045 wpa_printf(MSG_DEBUG,
1046 "NAN: Discard SDF with unknown Service Control Type %u",
1047 type);
1048 return;
1049 }
1050
1051 if (ctrl & NAN_SRV_CTRL_BINDING_BITMAP) {
1052 if (end - sda < 2)
1053 return;
1054 sda += 2;
1055 }
1056
1057 if (ctrl & NAN_SRV_CTRL_MATCHING_FILTER) {
1058 u8 flen;
1059
1060 if (end - sda < 1)
1061 return;
1062 flen = *sda++;
1063 if (end - sda < flen)
1064 return;
1065 matching_filter = sda;
1066 matching_filter_len = flen;
1067 sda += flen;
1068 }
1069
1070 if (ctrl & NAN_SRV_CTRL_RESP_FILTER) {
1071 u8 flen;
1072
1073 if (end - sda < 1)
1074 return;
1075 flen = *sda++;
1076 if (end - sda < flen)
1077 return;
1078 sda += flen;
1079 }
1080
1081 if (ctrl & NAN_SRV_CTRL_SRV_INFO) {
1082 u8 flen;
1083
1084 if (end - sda < 1)
1085 return;
1086 flen = *sda++;
1087 if (end - sda < flen)
1088 return;
1089 if (flen >= 4 && WPA_GET_BE24(sda) == OUI_WFA) {
1090 srv_proto_type = sda[3];
1091 ssi = sda + 4;
1092 ssi_len = flen - 4;
1093 wpa_printf(MSG_DEBUG, "NAN: Service Protocol Type %d",
1094 srv_proto_type);
1095 wpa_hexdump(MSG_MSGDUMP, "NAN: ssi", ssi, ssi_len);
1096 }
1097 sda += flen;
1098 }
1099
1100 for (i = 0; i < NAN_DE_MAX_SERVICE; i++) {
1101 struct nan_de_service *srv = de->service[i];
1102
1103 if (!srv)
1104 continue;
1105 if (os_memcmp(srv->service_id, service_id,
1106 NAN_SERVICE_ID_LEN) != 0)
1107 continue;
1108 if (type == NAN_SRV_CTRL_PUBLISH) {
1109 if (srv->type == NAN_DE_PUBLISH)
1110 continue;
1111 if (req_instance_id && srv->id != req_instance_id)
1112 continue;
1113 }
1114 if (type == NAN_SRV_CTRL_SUBSCRIBE &&
1115 srv->type == NAN_DE_SUBSCRIBE)
1116 continue;
1117 wpa_printf(MSG_DEBUG, "NAN: Received SDF matches service ID %u",
1118 i + 1);
1119
1120 if (first) {
1121 first = false;
1122 nan_de_get_sdea(buf, len, instance_id, &sdea_control,
1123 &srv_proto_type, &ssi, &ssi_len);
1124
1125 if (ssi) {
1126 wpa_printf(MSG_DEBUG,
1127 "NAN: Service Protocol Type %d",
1128 srv_proto_type);
1129 wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
1130 ssi, ssi_len);
1131 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00001132 nan_de_process_elem_container(de, buf, len, peer_addr,
1133 freq, srv->is_p2p);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001134 }
1135
1136 switch (type) {
1137 case NAN_SRV_CTRL_PUBLISH:
1138 nan_de_rx_publish(de, srv, peer_addr, instance_id,
1139 req_instance_id,
1140 sdea_control, srv_proto_type,
1141 ssi, ssi_len);
1142 break;
1143 case NAN_SRV_CTRL_SUBSCRIBE:
1144 nan_de_rx_subscribe(de, srv, peer_addr, instance_id,
1145 matching_filter,
1146 matching_filter_len,
1147 srv_proto_type,
1148 ssi, ssi_len);
1149 break;
1150 case NAN_SRV_CTRL_FOLLOW_UP:
1151 nan_de_rx_follow_up(de, srv, peer_addr, instance_id,
1152 ssi, ssi_len);
1153 break;
1154 }
1155 }
1156}
1157
1158
1159void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
1160 const u8 *buf, size_t len)
1161{
1162 const u8 *sda;
1163 u16 sda_len;
1164 unsigned int skip;
1165
1166 if (!de->num_service)
1167 return;
1168
1169 wpa_printf(MSG_DEBUG, "NAN: RX SDF from " MACSTR " freq=%u len=%zu",
1170 MAC2STR(peer_addr), freq, len);
1171
1172 wpa_hexdump(MSG_MSGDUMP, "NAN: SDF payload", buf, len);
1173
1174 for (skip = 0; ; skip++) {
1175 sda = nan_de_get_attr(buf, len, NAN_ATTR_SDA, skip);
1176 if (!sda)
1177 break;
1178
1179 sda++;
1180 sda_len = WPA_GET_LE16(sda);
1181 sda += 2;
1182 nan_de_rx_sda(de, peer_addr, freq, buf, len, sda, sda_len);
1183 }
1184}
1185
1186
1187static int nan_de_get_handle(struct nan_de *de)
1188{
1189 int i = de->next_handle;
1190
1191 if (de->num_service >= NAN_DE_MAX_SERVICE)
1192 goto fail;
1193
1194 do {
1195 if (!de->service[i]) {
1196 de->next_handle = (i + 1) % NAN_DE_MAX_SERVICE;
1197 return i + 1;
1198 }
1199 i = (i + 1) % NAN_DE_MAX_SERVICE;
1200 } while (i != de->next_handle);
1201
1202fail:
1203 wpa_printf(MSG_DEBUG, "NAN: No more room for a new service");
1204 return -1;
1205}
1206
1207
1208static int nan_de_derive_service_id(struct nan_de_service *srv)
1209{
1210 u8 hash[SHA256_MAC_LEN];
1211 char *name, *pos;
1212 int ret;
1213 const u8 *addr[1];
1214 size_t len[1];
1215
1216 name = os_strdup(srv->service_name);
1217 if (!name)
1218 return -1;
1219 pos = name;
1220 while (*pos) {
1221 *pos = tolower(*pos);
1222 pos++;
1223 }
1224
1225 addr[0] = (u8 *) name;
1226 len[0] = os_strlen(name);
1227 ret = sha256_vector(1, addr, len, hash);
1228 os_free(name);
1229 if (ret == 0)
1230 os_memcpy(srv->service_id, hash, NAN_SERVICE_ID_LEN);
1231
1232 return ret;
1233}
1234
1235
Sunil Ravic0f5d412024-09-11 22:12:49 +00001236const u8 * nan_de_get_service_id(struct nan_de *de, int id)
1237{
1238 struct nan_de_service *srv;
1239
1240 if (id < 1 || id > NAN_DE_MAX_SERVICE)
1241 return NULL;
1242 srv = de->service[id - 1];
1243 if (!srv)
1244 return NULL;
1245 return srv->service_id;
1246}
1247
1248
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001249int nan_de_publish(struct nan_de *de, const char *service_name,
1250 enum nan_service_protocol_type srv_proto_type,
1251 const struct wpabuf *ssi, const struct wpabuf *elems,
Sunil Ravic0f5d412024-09-11 22:12:49 +00001252 struct nan_publish_params *params, bool p2p)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001253{
1254 int publish_id;
1255 struct nan_de_service *srv;
1256
1257 if (!service_name) {
1258 wpa_printf(MSG_DEBUG, "NAN: Publish() - no service_name");
1259 return -1;
1260 }
1261
Sunil Ravi7f769292024-07-23 22:21:32 +00001262 if (!params->unsolicited && !params->solicited) {
1263 wpa_printf(MSG_INFO,
1264 "NAN: Publish() - both unsolicited and solicited disabled is invalid");
1265 return -1;
1266 }
1267
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001268 publish_id = nan_de_get_handle(de);
1269 if (publish_id < 1)
1270 return -1;
1271
1272 srv = os_zalloc(sizeof(*srv));
1273 if (!srv)
1274 return -1;
1275 srv->type = NAN_DE_PUBLISH;
1276 srv->freq = srv->default_freq = params->freq;
1277 srv->service_name = os_strdup(service_name);
1278 if (!srv->service_name)
1279 goto fail;
1280 if (nan_de_derive_service_id(srv) < 0)
1281 goto fail;
1282 os_memcpy(&srv->publish, params, sizeof(*params));
1283
1284 if (params->freq_list) {
1285 size_t len;
1286
1287 len = (int_array_len(params->freq_list) + 1) * sizeof(int);
1288 srv->freq_list = os_memdup(params->freq_list, len);
1289 if (!srv->freq_list)
1290 goto fail;
1291 }
1292 srv->publish.freq_list = NULL;
1293
1294 srv->srv_proto_type = srv_proto_type;
1295 if (ssi) {
1296 srv->ssi = wpabuf_dup(ssi);
1297 if (!srv->ssi)
1298 goto fail;
1299 }
1300 if (elems) {
1301 srv->elems = wpabuf_dup(elems);
1302 if (!srv->elems)
1303 goto fail;
1304 }
1305
1306 /* Prepare for single and multi-channel states; starting with
1307 * single channel */
1308 srv->first_multi_chan = true;
1309 nan_de_start_new_publish_state(srv, true);
1310
1311 wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
1312 publish_id, service_name);
1313 srv->id = publish_id;
Sunil Ravic0f5d412024-09-11 22:12:49 +00001314 srv->is_p2p = p2p;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001315 nan_de_add_srv(de, srv);
1316 nan_de_run_timer(de);
1317 return publish_id;
1318fail:
1319 nan_de_service_free(srv);
1320 return -1;
1321}
1322
1323
1324void nan_de_cancel_publish(struct nan_de *de, int publish_id)
1325{
1326 struct nan_de_service *srv;
1327
1328 wpa_printf(MSG_DEBUG, "NAN: CancelPublish(publish_id=%d)", publish_id);
1329
1330 if (publish_id < 1 || publish_id > NAN_DE_MAX_SERVICE)
1331 return;
1332 srv = de->service[publish_id - 1];
1333 if (!srv || srv->type != NAN_DE_PUBLISH)
1334 return;
1335 nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
1336}
1337
1338
1339int nan_de_update_publish(struct nan_de *de, int publish_id,
1340 const struct wpabuf *ssi)
1341{
1342 struct nan_de_service *srv;
1343
1344 wpa_printf(MSG_DEBUG, "NAN: UpdatePublish(publish_id=%d)", publish_id);
1345
1346 if (publish_id < 1 || publish_id > NAN_DE_MAX_SERVICE)
1347 return -1;
1348 srv = de->service[publish_id - 1];
1349 if (!srv || srv->type != NAN_DE_PUBLISH)
1350 return -1;
1351
1352 wpabuf_free(srv->ssi);
1353 srv->ssi = NULL;
1354 if (!ssi)
1355 return 0;
1356 srv->ssi = wpabuf_dup(ssi);
1357 if (!srv->ssi)
1358 return -1;
1359 return 0;
1360}
1361
1362
1363int nan_de_subscribe(struct nan_de *de, const char *service_name,
1364 enum nan_service_protocol_type srv_proto_type,
1365 const struct wpabuf *ssi, const struct wpabuf *elems,
Sunil Ravic0f5d412024-09-11 22:12:49 +00001366 struct nan_subscribe_params *params, bool p2p)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001367{
1368 int subscribe_id;
1369 struct nan_de_service *srv;
1370
1371 if (!service_name) {
1372 wpa_printf(MSG_DEBUG, "NAN: Subscribe() - no service_name");
1373 return -1;
1374 }
1375
1376 subscribe_id = nan_de_get_handle(de);
1377 if (subscribe_id < 1)
1378 return -1;
1379
1380 srv = os_zalloc(sizeof(*srv));
1381 if (!srv)
1382 return -1;
1383 srv->type = NAN_DE_SUBSCRIBE;
1384 srv->freq = params->freq;
1385 srv->service_name = os_strdup(service_name);
1386 if (!srv->service_name)
1387 goto fail;
1388 if (nan_de_derive_service_id(srv) < 0)
1389 goto fail;
1390 os_memcpy(&srv->subscribe, params, sizeof(*params));
Sunil Ravic0f5d412024-09-11 22:12:49 +00001391
1392 if (params->freq_list) {
1393 size_t len;
1394
1395 len = (int_array_len(params->freq_list) + 1) * sizeof(int);
1396 srv->freq_list = os_memdup(params->freq_list, len);
1397 if (!srv->freq_list)
1398 goto fail;
1399 }
1400 srv->subscribe.freq_list = NULL;
1401
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001402 srv->srv_proto_type = srv_proto_type;
1403 if (ssi) {
1404 srv->ssi = wpabuf_dup(ssi);
1405 if (!srv->ssi)
1406 goto fail;
1407 }
1408 if (elems) {
1409 srv->elems = wpabuf_dup(elems);
1410 if (!srv->elems)
1411 goto fail;
1412 }
1413
1414 wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
1415 subscribe_id, service_name);
1416 srv->id = subscribe_id;
Sunil Ravic0f5d412024-09-11 22:12:49 +00001417 srv->is_p2p = p2p;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001418 nan_de_add_srv(de, srv);
1419 nan_de_run_timer(de);
1420 return subscribe_id;
1421fail:
1422 nan_de_service_free(srv);
1423 return -1;
1424}
1425
1426
1427void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id)
1428{
1429 struct nan_de_service *srv;
1430
1431 if (subscribe_id < 1 || subscribe_id > NAN_DE_MAX_SERVICE)
1432 return;
1433 srv = de->service[subscribe_id - 1];
1434 if (!srv || srv->type != NAN_DE_SUBSCRIBE)
1435 return;
1436 nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
1437}
1438
1439
1440int nan_de_transmit(struct nan_de *de, int handle,
1441 const struct wpabuf *ssi, const struct wpabuf *elems,
1442 const u8 *peer_addr, u8 req_instance_id)
1443{
1444 struct nan_de_service *srv;
1445
1446 if (handle < 1 || handle > NAN_DE_MAX_SERVICE)
1447 return -1;
1448
1449 srv = de->service[handle - 1];
1450 if (!srv)
1451 return -1;
1452
1453 nan_de_tx_sdf(de, srv, 100, NAN_SRV_CTRL_FOLLOW_UP,
1454 peer_addr, req_instance_id, ssi);
1455
1456 os_get_reltime(&srv->last_followup);
1457 return 0;
1458}