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