1 /*
2 * NAN unsynchronized service discovery (USD)
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 "common/nan_de.h"
13 #include "wpa_supplicant_i.h"
14 #include "offchannel.h"
15 #include "driver_i.h"
16 #include "notify.h"
17 #include "p2p_supplicant.h"
18 #include "nan_usd.h"
19
20
21 static const char *
tx_status_result_txt(enum offchannel_send_action_result result)22 tx_status_result_txt(enum offchannel_send_action_result result)
23 {
24 switch (result) {
25 case OFFCHANNEL_SEND_ACTION_SUCCESS:
26 return "success";
27 case OFFCHANNEL_SEND_ACTION_NO_ACK:
28 return "no-ack";
29 case OFFCHANNEL_SEND_ACTION_FAILED:
30 return "failed";
31 }
32
33 return "?";
34 }
35
36
wpas_nan_de_tx_status(struct wpa_supplicant * wpa_s,unsigned int freq,const u8 * dst,const u8 * src,const u8 * bssid,const u8 * data,size_t data_len,enum offchannel_send_action_result result)37 static void wpas_nan_de_tx_status(struct wpa_supplicant *wpa_s,
38 unsigned int freq, const u8 *dst,
39 const u8 *src, const u8 *bssid,
40 const u8 *data, size_t data_len,
41 enum offchannel_send_action_result result)
42 {
43 if (!wpa_s->nan_de)
44 return;
45
46 wpa_printf(MSG_DEBUG, "NAN: TX status A1=" MACSTR " A2=" MACSTR
47 " A3=" MACSTR " freq=%d len=%zu result=%s",
48 MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
49 data_len, tx_status_result_txt(result));
50
51 nan_de_tx_status(wpa_s->nan_de, freq, dst);
52 }
53
54
55 struct wpas_nan_usd_tx_work {
56 unsigned int freq;
57 unsigned int wait_time;
58 u8 dst[ETH_ALEN];
59 u8 src[ETH_ALEN];
60 u8 bssid[ETH_ALEN];
61 struct wpabuf *buf;
62 };
63
64
wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work * twork)65 static void wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work *twork)
66 {
67 if (!twork)
68 return;
69 wpabuf_free(twork->buf);
70 os_free(twork);
71 }
72
73
wpas_nan_usd_tx_work_done(struct wpa_supplicant * wpa_s)74 static void wpas_nan_usd_tx_work_done(struct wpa_supplicant *wpa_s)
75 {
76 struct wpas_nan_usd_tx_work *twork;
77
78 if (!wpa_s->nan_usd_tx_work)
79 return;
80
81 twork = wpa_s->nan_usd_tx_work->ctx;
82 wpas_nan_usd_tx_work_free(twork);
83 radio_work_done(wpa_s->nan_usd_tx_work);
84 wpa_s->nan_usd_tx_work = NULL;
85 }
86
87
wpas_nan_de_tx_send(struct wpa_supplicant * wpa_s,unsigned int freq,unsigned int wait_time,const u8 * dst,const u8 * src,const u8 * bssid,const struct wpabuf * buf)88 static int wpas_nan_de_tx_send(struct wpa_supplicant *wpa_s, unsigned int freq,
89 unsigned int wait_time, const u8 *dst,
90 const u8 *src, const u8 *bssid,
91 const struct wpabuf *buf)
92 {
93 wpa_printf(MSG_DEBUG, "NAN: TX NAN SDF A1=" MACSTR " A2=" MACSTR
94 " A3=" MACSTR " freq=%d len=%zu",
95 MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
96 wpabuf_len(buf));
97
98 return offchannel_send_action(wpa_s, freq, dst, src, bssid,
99 wpabuf_head(buf), wpabuf_len(buf),
100 wait_time, wpas_nan_de_tx_status, 1);
101 }
102
103
wpas_nan_usd_start_tx_cb(struct wpa_radio_work * work,int deinit)104 static void wpas_nan_usd_start_tx_cb(struct wpa_radio_work *work, int deinit)
105 {
106 struct wpa_supplicant *wpa_s = work->wpa_s;
107 struct wpas_nan_usd_tx_work *twork = work->ctx;
108
109 if (deinit) {
110 if (work->started) {
111 wpa_s->nan_usd_tx_work = NULL;
112 offchannel_send_action_done(wpa_s);
113 }
114 wpas_nan_usd_tx_work_free(twork);
115 return;
116 }
117
118 wpa_s->nan_usd_tx_work = work;
119
120 if (wpas_nan_de_tx_send(wpa_s, twork->freq, twork->wait_time,
121 twork->dst, twork->src, twork->bssid,
122 twork->buf) < 0)
123 wpas_nan_usd_tx_work_done(wpa_s);
124 }
125
126
wpas_nan_de_tx(void * ctx,unsigned int freq,unsigned int wait_time,const u8 * dst,const u8 * src,const u8 * bssid,const struct wpabuf * buf)127 static int wpas_nan_de_tx(void *ctx, unsigned int freq, unsigned int wait_time,
128 const u8 *dst, const u8 *src, const u8 *bssid,
129 const struct wpabuf *buf)
130 {
131 struct wpa_supplicant *wpa_s = ctx;
132 struct wpas_nan_usd_tx_work *twork;
133
134 if (wpa_s->nan_usd_tx_work || wpa_s->nan_usd_listen_work) {
135 /* Reuse ongoing radio work */
136 return wpas_nan_de_tx_send(wpa_s, freq, wait_time, dst, src,
137 bssid, buf);
138 }
139
140 twork = os_zalloc(sizeof(*twork));
141 if (!twork)
142 return -1;
143 twork->freq = freq;
144 twork->wait_time = wait_time;
145 os_memcpy(twork->dst, dst, ETH_ALEN);
146 os_memcpy(twork->src, src, ETH_ALEN);
147 os_memcpy(twork->bssid, bssid, ETH_ALEN);
148 twork->buf = wpabuf_dup(buf);
149 if (!twork->buf) {
150 wpas_nan_usd_tx_work_free(twork);
151 return -1;
152 }
153
154 if (radio_add_work(wpa_s, freq, "nan-usd-tx", 0,
155 wpas_nan_usd_start_tx_cb, twork) < 0) {
156 wpas_nan_usd_tx_work_free(twork);
157 return -1;
158 }
159
160 return 0;
161 }
162
163
164 struct wpas_nan_usd_listen_work {
165 unsigned int freq;
166 unsigned int duration;
167 };
168
169
wpas_nan_usd_listen_work_done(struct wpa_supplicant * wpa_s)170 static void wpas_nan_usd_listen_work_done(struct wpa_supplicant *wpa_s)
171 {
172 struct wpas_nan_usd_listen_work *lwork;
173
174 if (!wpa_s->nan_usd_listen_work)
175 return;
176
177 lwork = wpa_s->nan_usd_listen_work->ctx;
178 os_free(lwork);
179 radio_work_done(wpa_s->nan_usd_listen_work);
180 wpa_s->nan_usd_listen_work = NULL;
181 }
182
183
wpas_nan_usd_start_listen_cb(struct wpa_radio_work * work,int deinit)184 static void wpas_nan_usd_start_listen_cb(struct wpa_radio_work *work,
185 int deinit)
186 {
187 struct wpa_supplicant *wpa_s = work->wpa_s;
188 struct wpas_nan_usd_listen_work *lwork = work->ctx;
189 unsigned int duration;
190
191 if (deinit) {
192 if (work->started) {
193 wpa_s->nan_usd_listen_work = NULL;
194 wpa_drv_cancel_remain_on_channel(wpa_s);
195 }
196 os_free(lwork);
197 return;
198 }
199
200 wpa_s->nan_usd_listen_work = work;
201
202 duration = lwork->duration;
203 if (duration > wpa_s->max_remain_on_chan)
204 duration = wpa_s->max_remain_on_chan;
205 wpa_printf(MSG_DEBUG, "NAN: Start listen on %u MHz for %u ms",
206 lwork->freq, duration);
207 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, duration) < 0) {
208 wpa_printf(MSG_DEBUG,
209 "NAN: Failed to request the driver to remain on channel (%u MHz) for listen",
210 lwork->freq);
211 wpas_nan_usd_listen_work_done(wpa_s);
212 return;
213 }
214 }
215
216
wpas_nan_de_listen(void * ctx,unsigned int freq,unsigned int duration)217 static int wpas_nan_de_listen(void *ctx, unsigned int freq,
218 unsigned int duration)
219 {
220 struct wpa_supplicant *wpa_s = ctx;
221 struct wpas_nan_usd_listen_work *lwork;
222
223 lwork = os_zalloc(sizeof(*lwork));
224 if (!lwork)
225 return -1;
226 lwork->freq = freq;
227 lwork->duration = duration;
228
229 if (radio_add_work(wpa_s, freq, "nan-usd-listen", 0,
230 wpas_nan_usd_start_listen_cb, lwork) < 0) {
231 os_free(lwork);
232 return -1;
233 }
234
235 return 0;
236 }
237
238
239 static void
wpas_nan_de_discovery_result(void * ctx,int subscribe_id,enum nan_service_protocol_type srv_proto_type,const u8 * ssi,size_t ssi_len,int peer_publish_id,const u8 * peer_addr,bool fsd,bool fsd_gas)240 wpas_nan_de_discovery_result(void *ctx, int subscribe_id,
241 enum nan_service_protocol_type srv_proto_type,
242 const u8 *ssi, size_t ssi_len, int peer_publish_id,
243 const u8 *peer_addr, bool fsd, bool fsd_gas)
244 {
245 struct wpa_supplicant *wpa_s = ctx;
246
247 wpas_notify_nan_discovery_result(wpa_s, srv_proto_type, subscribe_id,
248 peer_publish_id, peer_addr, fsd,
249 fsd_gas, ssi, ssi_len);
250 }
251
252
wpas_nan_de_replied(void * ctx,int publish_id,const u8 * peer_addr,int peer_subscribe_id,enum nan_service_protocol_type srv_proto_type,const u8 * ssi,size_t ssi_len)253 static void wpas_nan_de_replied(void *ctx, int publish_id, const u8 *peer_addr,
254 int peer_subscribe_id,
255 enum nan_service_protocol_type srv_proto_type,
256 const u8 *ssi, size_t ssi_len)
257 {
258 struct wpa_supplicant *wpa_s = ctx;
259
260 wpas_notify_nan_replied(wpa_s, srv_proto_type, publish_id,
261 peer_subscribe_id, peer_addr, ssi, ssi_len);
262 }
263
264
wpas_nan_de_publish_terminated(void * ctx,int publish_id,enum nan_de_reason reason)265 static void wpas_nan_de_publish_terminated(void *ctx, int publish_id,
266 enum nan_de_reason reason)
267 {
268 struct wpa_supplicant *wpa_s = ctx;
269
270 wpas_notify_nan_publish_terminated(wpa_s, publish_id, reason);
271 }
272
273
wpas_nan_de_subscribe_terminated(void * ctx,int subscribe_id,enum nan_de_reason reason)274 static void wpas_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
275 enum nan_de_reason reason)
276 {
277 struct wpa_supplicant *wpa_s = ctx;
278
279 wpas_notify_nan_subscribe_terminated(wpa_s, subscribe_id, reason);
280 }
281
282
wpas_nan_de_receive(void * ctx,int id,int peer_instance_id,const u8 * ssi,size_t ssi_len,const u8 * peer_addr)283 static void wpas_nan_de_receive(void *ctx, int id, int peer_instance_id,
284 const u8 *ssi, size_t ssi_len,
285 const u8 *peer_addr)
286 {
287 struct wpa_supplicant *wpa_s = ctx;
288
289 wpas_notify_nan_receive(wpa_s, id, peer_instance_id, peer_addr,
290 ssi, ssi_len);
291 }
292
293
294 #ifdef CONFIG_P2P
wpas_nan_process_p2p_usd_elems(void * ctx,const u8 * buf,u16 buf_len,const u8 * peer_addr,unsigned int freq)295 static void wpas_nan_process_p2p_usd_elems(void *ctx, const u8 *buf,
296 u16 buf_len, const u8 *peer_addr,
297 unsigned int freq)
298 {
299 struct wpa_supplicant *wpa_s = ctx;
300
301 wpas_p2p_process_usd_elems(wpa_s, buf, buf_len, peer_addr, freq);
302 }
303 #endif /* CONFIG_P2P */
304
305
wpas_nan_usd_init(struct wpa_supplicant * wpa_s)306 int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
307 {
308 struct nan_callbacks cb;
309 bool offload = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD;
310
311 os_memset(&cb, 0, sizeof(cb));
312 cb.ctx = wpa_s;
313 cb.tx = wpas_nan_de_tx;
314 cb.listen = wpas_nan_de_listen;
315 cb.discovery_result = wpas_nan_de_discovery_result;
316 cb.replied = wpas_nan_de_replied;
317 cb.publish_terminated = wpas_nan_de_publish_terminated;
318 cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
319 cb.receive = wpas_nan_de_receive;
320 #ifdef CONFIG_P2P
321 cb.process_p2p_usd_elems = wpas_nan_process_p2p_usd_elems;
322 #endif /* CONFIG_P2P */
323
324 wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false,
325 wpa_s->max_remain_on_chan, &cb);
326 if (!wpa_s->nan_de)
327 return -1;
328 return 0;
329 }
330
331
wpas_nan_usd_deinit(struct wpa_supplicant * wpa_s)332 void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s)
333 {
334 nan_de_deinit(wpa_s->nan_de);
335 wpa_s->nan_de = NULL;
336 }
337
338
wpas_nan_usd_rx_sdf(struct wpa_supplicant * wpa_s,const u8 * src,const u8 * a3,unsigned int freq,const u8 * buf,size_t len)339 void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
340 const u8 *a3,
341 unsigned int freq, const u8 *buf, size_t len)
342 {
343 if (!wpa_s->nan_de)
344 return;
345 nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len);
346 }
347
348
wpas_nan_usd_flush(struct wpa_supplicant * wpa_s)349 void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
350 {
351 if (!wpa_s->nan_de)
352 return;
353 nan_de_flush(wpa_s->nan_de);
354 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
355 wpas_drv_nan_flush(wpa_s);
356 }
357
358
wpas_nan_usd_publish(struct wpa_supplicant * wpa_s,const char * service_name,enum nan_service_protocol_type srv_proto_type,const struct wpabuf * ssi,struct nan_publish_params * params,bool p2p)359 int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
360 enum nan_service_protocol_type srv_proto_type,
361 const struct wpabuf *ssi,
362 struct nan_publish_params *params, bool p2p)
363 {
364 int publish_id;
365 struct wpabuf *elems = NULL;
366 const u8 *addr;
367
368 if (!wpa_s->nan_de)
369 return -1;
370
371 if (p2p) {
372 elems = wpas_p2p_usd_elems(wpa_s, service_name);
373 addr = wpa_s->global->p2p_dev_addr;
374 } else {
375 addr = wpa_s->own_addr;
376 }
377
378 publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
379 ssi, elems, params, p2p);
380 if (publish_id >= 1 &&
381 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
382 wpas_drv_nan_publish(wpa_s, addr, publish_id, service_name,
383 nan_de_get_service_id(wpa_s->nan_de,
384 publish_id),
385 srv_proto_type, ssi, elems, params) < 0) {
386 nan_de_cancel_publish(wpa_s->nan_de, publish_id);
387 publish_id = -1;
388 }
389
390 wpabuf_free(elems);
391 return publish_id;
392 }
393
394
wpas_nan_usd_cancel_publish(struct wpa_supplicant * wpa_s,int publish_id)395 void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
396 {
397 if (!wpa_s->nan_de)
398 return;
399 nan_de_cancel_publish(wpa_s->nan_de, publish_id);
400 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
401 wpas_drv_nan_cancel_publish(wpa_s, publish_id);
402 }
403
404
wpas_nan_usd_update_publish(struct wpa_supplicant * wpa_s,int publish_id,const struct wpabuf * ssi)405 int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
406 const struct wpabuf *ssi)
407 {
408 int ret;
409
410 if (!wpa_s->nan_de)
411 return -1;
412 ret = nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
413 if (ret == 0 && (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
414 wpas_drv_nan_update_publish(wpa_s, publish_id, ssi) < 0)
415 return -1;
416 return ret;
417 }
418
419
wpas_nan_usd_unpause_publish(struct wpa_supplicant * wpa_s,int publish_id,u8 peer_instance_id,const u8 * peer_addr)420 int wpas_nan_usd_unpause_publish(struct wpa_supplicant *wpa_s, int publish_id,
421 u8 peer_instance_id, const u8 *peer_addr)
422 {
423 if (!wpa_s->nan_de)
424 return -1;
425 return nan_de_unpause_publish(wpa_s->nan_de, publish_id,
426 peer_instance_id, peer_addr);
427 }
428
429
wpas_nan_usd_subscribe(struct wpa_supplicant * wpa_s,const char * service_name,enum nan_service_protocol_type srv_proto_type,const struct wpabuf * ssi,struct nan_subscribe_params * params,bool p2p)430 int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
431 const char *service_name,
432 enum nan_service_protocol_type srv_proto_type,
433 const struct wpabuf *ssi,
434 struct nan_subscribe_params *params, bool p2p)
435 {
436 int subscribe_id;
437 struct wpabuf *elems = NULL;
438 const u8 *addr;
439
440 if (!wpa_s->nan_de)
441 return -1;
442
443 if (p2p) {
444 elems = wpas_p2p_usd_elems(wpa_s, service_name);
445 addr = wpa_s->global->p2p_dev_addr;
446 } else {
447 addr = wpa_s->own_addr;
448 }
449
450 subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
451 srv_proto_type, ssi, elems, params,
452 p2p);
453 if (subscribe_id >= 1 &&
454 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
455 wpas_drv_nan_subscribe(wpa_s, addr, subscribe_id, service_name,
456 nan_de_get_service_id(wpa_s->nan_de,
457 subscribe_id),
458 srv_proto_type, ssi, elems, params) < 0) {
459 nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
460 subscribe_id = -1;
461 }
462
463 wpabuf_free(elems);
464 return subscribe_id;
465 }
466
467
wpas_nan_usd_cancel_subscribe(struct wpa_supplicant * wpa_s,int subscribe_id)468 void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
469 int subscribe_id)
470 {
471 if (!wpa_s->nan_de)
472 return;
473 nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
474 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
475 wpas_drv_nan_cancel_subscribe(wpa_s, subscribe_id);
476 }
477
478
wpas_nan_usd_transmit(struct wpa_supplicant * wpa_s,int handle,const struct wpabuf * ssi,const struct wpabuf * elems,const u8 * peer_addr,u8 req_instance_id)479 int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
480 const struct wpabuf *ssi, const struct wpabuf *elems,
481 const u8 *peer_addr, u8 req_instance_id)
482 {
483 if (!wpa_s->nan_de)
484 return -1;
485 return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
486 req_instance_id);
487 }
488
489
wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant * wpa_s,unsigned int freq,unsigned int duration)490 void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
491 unsigned int freq, unsigned int duration)
492 {
493 wpas_nan_usd_listen_work_done(wpa_s);
494
495 if (wpa_s->nan_de)
496 nan_de_listen_started(wpa_s->nan_de, freq, duration);
497 }
498
499
wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant * wpa_s,unsigned int freq)500 void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
501 unsigned int freq)
502 {
503 if (wpa_s->nan_de)
504 nan_de_listen_ended(wpa_s->nan_de, freq);
505 }
506
507
wpas_nan_usd_tx_wait_expire(struct wpa_supplicant * wpa_s)508 void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s)
509 {
510 wpas_nan_usd_tx_work_done(wpa_s);
511
512 if (wpa_s->nan_de)
513 nan_de_tx_wait_ended(wpa_s->nan_de);
514 }
515
516
wpas_nan_usd_all_freqs(struct wpa_supplicant * wpa_s)517 int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s)
518 {
519 int i, j;
520 int *freqs = NULL;
521
522 if (!wpa_s->hw.modes)
523 return NULL;
524
525 for (i = 0; i < wpa_s->hw.num_modes; i++) {
526 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
527
528 for (j = 0; j < mode->num_channels; j++) {
529 struct hostapd_channel_data *chan = &mode->channels[j];
530
531 /* All 20 MHz channels on 2.4 and 5 GHz band */
532 if (chan->freq < 2412 || chan->freq > 5900)
533 continue;
534
535 /* that allow frames to be transmitted */
536 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
537 HOSTAPD_CHAN_NO_IR |
538 HOSTAPD_CHAN_RADAR))
539 continue;
540
541 int_array_add_unique(&freqs, chan->freq);
542 }
543 }
544
545 return freqs;
546 }
547