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