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, &cb);
325 if (!wpa_s->nan_de)
326 return -1;
327 return 0;
328 }
329
330
wpas_nan_usd_deinit(struct wpa_supplicant * wpa_s)331 void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s)
332 {
333 nan_de_deinit(wpa_s->nan_de);
334 wpa_s->nan_de = NULL;
335 }
336
337
wpas_nan_usd_rx_sdf(struct wpa_supplicant * wpa_s,const u8 * src,unsigned int freq,const u8 * buf,size_t len)338 void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
339 unsigned int freq, const u8 *buf, size_t len)
340 {
341 if (!wpa_s->nan_de)
342 return;
343 nan_de_rx_sdf(wpa_s->nan_de, src, freq, buf, len);
344 }
345
346
wpas_nan_usd_flush(struct wpa_supplicant * wpa_s)347 void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
348 {
349 if (!wpa_s->nan_de)
350 return;
351 nan_de_flush(wpa_s->nan_de);
352 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
353 wpas_drv_nan_flush(wpa_s);
354 }
355
356
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)357 int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
358 enum nan_service_protocol_type srv_proto_type,
359 const struct wpabuf *ssi,
360 struct nan_publish_params *params, bool p2p)
361 {
362 int publish_id;
363 struct wpabuf *elems = NULL;
364 const u8 *addr;
365
366 if (!wpa_s->nan_de)
367 return -1;
368
369 if (p2p) {
370 elems = wpas_p2p_usd_elems(wpa_s);
371 addr = wpa_s->global->p2p_dev_addr;
372 } else {
373 addr = wpa_s->own_addr;
374 }
375
376 publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
377 ssi, elems, params, p2p);
378 if (publish_id >= 1 &&
379 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
380 wpas_drv_nan_publish(wpa_s, addr, publish_id, service_name,
381 nan_de_get_service_id(wpa_s->nan_de,
382 publish_id),
383 srv_proto_type, ssi, elems, params) < 0) {
384 nan_de_cancel_publish(wpa_s->nan_de, publish_id);
385 publish_id = -1;
386 }
387
388 wpabuf_free(elems);
389 return publish_id;
390 }
391
392
wpas_nan_usd_cancel_publish(struct wpa_supplicant * wpa_s,int publish_id)393 void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
394 {
395 if (!wpa_s->nan_de)
396 return;
397 nan_de_cancel_publish(wpa_s->nan_de, publish_id);
398 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
399 wpas_drv_nan_cancel_publish(wpa_s, publish_id);
400 }
401
402
wpas_nan_usd_update_publish(struct wpa_supplicant * wpa_s,int publish_id,const struct wpabuf * ssi)403 int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
404 const struct wpabuf *ssi)
405 {
406 int ret;
407
408 if (!wpa_s->nan_de)
409 return -1;
410 ret = nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
411 if (ret == 0 && (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
412 wpas_drv_nan_cancel_publish(wpa_s, publish_id) < 0)
413 return -1;
414 return ret;
415 }
416
417
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)418 int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
419 const char *service_name,
420 enum nan_service_protocol_type srv_proto_type,
421 const struct wpabuf *ssi,
422 struct nan_subscribe_params *params, bool p2p)
423 {
424 int subscribe_id;
425 struct wpabuf *elems = NULL;
426 const u8 *addr;
427
428 if (!wpa_s->nan_de)
429 return -1;
430
431 if (p2p) {
432 elems = wpas_p2p_usd_elems(wpa_s);
433 addr = wpa_s->global->p2p_dev_addr;
434 } else {
435 addr = wpa_s->own_addr;
436 }
437
438 subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
439 srv_proto_type, ssi, elems, params,
440 p2p);
441 if (subscribe_id >= 1 &&
442 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
443 wpas_drv_nan_subscribe(wpa_s, addr, subscribe_id, service_name,
444 nan_de_get_service_id(wpa_s->nan_de,
445 subscribe_id),
446 srv_proto_type, ssi, elems, params) < 0) {
447 nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
448 subscribe_id = -1;
449 }
450
451 wpabuf_free(elems);
452 return subscribe_id;
453 }
454
455
wpas_nan_usd_cancel_subscribe(struct wpa_supplicant * wpa_s,int subscribe_id)456 void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
457 int subscribe_id)
458 {
459 if (!wpa_s->nan_de)
460 return;
461 nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
462 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
463 wpas_drv_nan_cancel_subscribe(wpa_s, subscribe_id);
464 }
465
466
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)467 int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
468 const struct wpabuf *ssi, const struct wpabuf *elems,
469 const u8 *peer_addr, u8 req_instance_id)
470 {
471 if (!wpa_s->nan_de)
472 return -1;
473 return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
474 req_instance_id);
475 }
476
477
wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant * wpa_s,unsigned int freq,unsigned int duration)478 void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
479 unsigned int freq, unsigned int duration)
480 {
481 wpas_nan_usd_listen_work_done(wpa_s);
482
483 if (wpa_s->nan_de)
484 nan_de_listen_started(wpa_s->nan_de, freq, duration);
485 }
486
487
wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant * wpa_s,unsigned int freq)488 void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
489 unsigned int freq)
490 {
491 if (wpa_s->nan_de)
492 nan_de_listen_ended(wpa_s->nan_de, freq);
493 }
494
495
wpas_nan_usd_tx_wait_expire(struct wpa_supplicant * wpa_s)496 void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s)
497 {
498 wpas_nan_usd_tx_work_done(wpa_s);
499
500 if (wpa_s->nan_de)
501 nan_de_tx_wait_ended(wpa_s->nan_de);
502 }
503
504
wpas_nan_usd_all_freqs(struct wpa_supplicant * wpa_s)505 int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s)
506 {
507 int i, j;
508 int *freqs = NULL;
509
510 if (!wpa_s->hw.modes)
511 return NULL;
512
513 for (i = 0; i < wpa_s->hw.num_modes; i++) {
514 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
515
516 for (j = 0; j < mode->num_channels; j++) {
517 struct hostapd_channel_data *chan = &mode->channels[j];
518
519 /* All 20 MHz channels on 2.4 and 5 GHz band */
520 if (chan->freq < 2412 || chan->freq > 5900)
521 continue;
522
523 /* that allow frames to be transmitted */
524 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
525 HOSTAPD_CHAN_NO_IR |
526 HOSTAPD_CHAN_RADAR))
527 continue;
528
529 int_array_add_unique(&freqs, chan->freq);
530 }
531 }
532
533 return freqs;
534 }
535