]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
NAN: USD in wpa_supplicant
authorJouni Malinen <quic_jouni@quicinc.com>
Sat, 10 Feb 2024 09:57:23 +0000 (11:57 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 15 Feb 2024 17:54:17 +0000 (19:54 +0200)
Add wpa_supplicant support for interacting with the NAN discovery engine
to allow USD as Publisher or Subscriber.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
13 files changed:
src/common/wpa_ctrl.h
src/drivers/driver_nl80211.c
wpa_supplicant/Android.mk
wpa_supplicant/Makefile
wpa_supplicant/README-NAN-USD [new file with mode: 0644]
wpa_supplicant/android.config
wpa_supplicant/ctrl_iface.c
wpa_supplicant/defconfig
wpa_supplicant/events.c
wpa_supplicant/nan_usd.c [new file with mode: 0644]
wpa_supplicant/nan_usd.h [new file with mode: 0644]
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 154bac8fe74f427cd89e51c1218a0f1aa6819953..c5bb9abd7b641653fcc51037a90433a5abf4d9a6 100644 (file)
@@ -232,6 +232,13 @@ extern "C" {
 #define DPP_EVENT_PB_RESULT "DPP-PB-RESULT "
 #define DPP_EVENT_RELAY_NEEDS_CONTROLLER "DPP-RELAY-NEEDS-CONTROLLER "
 
+/* Wi-Fi Aware (NAN USD) events */
+#define NAN_DISCOVERY_RESULT "NAN-DISCOVERY-RESULT "
+#define NAN_REPLIED "NAN-REPLIED "
+#define NAN_PUBLISH_TERMINATED "NAN-PUBLISH-TERMINATED "
+#define NAN_SUBSCRIBE_TERMINATED "NAN-SUBSCRIBE-TERMINATED "
+#define NAN_RECEIVE "NAN-RECEIVE "
+
 /* MESH events */
 #define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
 #define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
index 01d8a5ab7140bcf97b6c86c43dadba2c6d2ab583..aa5ed58b2ca077e2fc9debce954ad780ec67c0c7 100644 (file)
@@ -2564,6 +2564,13 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
                                          5) < 0)
                ret = -1;
 #endif /* CONFIG_P2P */
+#ifdef CONFIG_NAN_USD
+       /* NAN SDF Public Action */
+       if (nl80211_register_action_frame(bss,
+                                         (u8 *) "\x04\x09\x50\x6f\x9a\x13",
+                                         6) < 0)
+               ret = -1;
+#endif /* CONFIG_NAN_USD */
 #ifdef CONFIG_DPP
        /* DPP Public Action */
        if (nl80211_register_action_frame(bss,
index c80c17a0b9a7f86e1fc46f26ea107680be4ca120..b6fcebd69581702541d3c4bce144f7795f08cf28 100644 (file)
@@ -281,6 +281,12 @@ L_CFLAGS += -DCONFIG_DPP3
 endif
 endif
 
+ifdef CONFIG_NAN_USD
+OBJS += src/common/nan_de.c
+OBJS += nan_usd.c
+L_CFLAGS += -DCONFIG_NAN_USD
+endif
+
 ifdef CONFIG_OWE
 L_CFLAGS += -DCONFIG_OWE
 NEED_ECC=y
index 60042bcc777e07d7fbcacebfc2b01e37dc25f060..288f8553601ae07348daa26d3a2fa32c93a2d3a7 100644 (file)
@@ -315,6 +315,12 @@ CFLAGS += -DCONFIG_DPP3
 endif
 endif
 
+ifdef CONFIG_NAN_USD
+OBJS += ../src/common/nan_de.o
+OBJS += nan_usd.o
+CFLAGS += -DCONFIG_NAN_USD
+endif
+
 ifdef CONFIG_OWE
 CFLAGS += -DCONFIG_OWE
 NEED_ECC=y
diff --git a/wpa_supplicant/README-NAN-USD b/wpa_supplicant/README-NAN-USD
new file mode 100644 (file)
index 0000000..5dfe6ee
--- /dev/null
@@ -0,0 +1,147 @@
+Wi-Fi Aware unsynchronized service discovery (NAN USD)
+======================================================
+
+This document descibes how the unsynchronized service discovery defined
+in the Wi-Fi Aware specification v4.0 can be used with wpa_spplicant.
+
+More information about Wi-Fi Aware is available from this Wi-Fi
+Alliance web page:
+https://www.wi-fi.org/discover-wi-fi/wi-fi-aware
+
+Build config setup
+------------------
+
+The following parameters must be included in the config file used to
+compile hostapd and wpa_supplicant.
+
+wpa_supplicant build config
+---------------------------
+
+Enable NAN USD in wpa_supplicant build config file
+
+CONFIG_NAN_USD=y
+
+Control interface commands and events
+-------------------------------------
+
+Following control interface commands can be used:
+
+NAN_PUBLISH service_name=<name> [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [freq_list=<comma separate list of MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>] [solicited=0] [unsolicited=0] [fsd=0]
+
+If ttl=0 or the parameter is not included, only one Publish message is
+transmitted.
+
+If freq is not included, the default frequency 2437 MHz (channel 6 on
+the 2.4 GHz band) is used.
+
+If freq_list is included, publisher iterates over all the listed
+channels. A special freq_list=all value can be used to generate the
+channel list automatically based on the list of allowed 2.4 and 5 GHz
+channels.
+
+srv_proto_type values are defined in the Service Protocol Types table in
+the Wi-Fi Aware specification.
+
+This command returns the assigned publish_id value or FAIL on failure.
+
+This command maps to the Publish() method in the NAN Discovery Engine.
+
+NAN_CANCEL_PUBLISH publish_id=<id from NAN_PUBLISH>
+
+This command maps to the CancelPublish() method in the NAN Discovery
+Engine.
+
+NAN_UPDATE_PUBLISH publish_id=<id from NAN_PUBLISH> [ssi=<service specific information (hexdump)>]
+
+This command maps to the UpdatePublish() method in the NAN Discovery
+Engine.
+
+NAN_SUBSCRIBE service_name=<name> [active=1] [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>]
+
+If ttl=0 or the parameter is not included, operation is terminated once
+the first matching publisher is found.
+
+If freq is not included, the default frequency 2437 MHz (channel 6 on
+the 2.4 GHz band) is used.
+
+srv_proto_type values are defined in the Service Protocol Types table in
+the Wi-Fi Aware specification.
+
+This command returns the assigned subscribe_id value or FAIL on failure.
+
+This command maps to the Subscribe() method in the NAN Discovery Engine.
+
+NAN_CANCEL_SUBSCRIBE subscribe_id=<id from NAN_SUBSCRIBE>
+
+This command maps to the CancelSubscribe() method in the NAN Discovery Engine.
+
+NAN_TRANSMIT handle=<id from NAN_PUBLISH or NAN_SUBSCRIBE> req_instance=<peer's id> address=<peer's MAC address> [ssi=<service specific information (hexdump)>]
+
+This command maps to the Transmit() method in the NAN Discovery Engine.
+
+Following control interface events are used:
+
+NAN-DISCOVERY-RESULT subscribe_id=<own id> publish_id=<peer's id> address=<peer MAC address> fsd=<0/1> fsd_gas=<0/1> srv_proto_type=<type> ssi=<service specific information (hexdump)>
+
+This event maps to the DiscoveryResult() event in the NAN Discovery
+Engine.
+
+NAN-REPLIED publish_id=<own id> address=<peer MAC address> subscribe_id=<peer id> srv_proto_type=<ype> ssi=<service specific information (hexdump)>
+
+This event maps to the Replied() event in the NAN Discovery Engine.
+
+NAN-PUBLISH-TERMINATED publish_id=<own id> reason=<timeout/user-request/failure>
+
+This event maps to the PublishTerminated() event in the NAN Discovery
+Engine.
+
+NAN-SUBSCRIBE-TERMINATED subscribe_id=<own id> reason=<timeout/user-request/failure>
+
+This event maps to the SubscribeTerminate() event in the NAN Discovery
+Engine.
+
+NAN-RECEIVE id=<own id> peer_instance_id=<peer id> address=<peer MAC adress> ssi=<service specific information (hexdump)>
+
+This event maps to the Receive() event in the NAN Discovery Engine.
+
+
+Example operation
+-----------------
+
+Start Subscribe and Publish functions:
+
+dev0: NAN_SUBSCRIBE service_name=_test srv_proto_type=3 ssi=1122334455
+--> returns 7
+
+dev1: NAN_PUBLISH service_name=_test srv_proto_type=3 ssi=6677
+--> returns 5
+
+Subscriber notification of a discovery:
+
+event on dev0: <3>NAN-DISCOVERY-RESULT subscribe_id=7 publish_id=5 address=02:00:00:00:01:00 fsd=1 fsd_gas=0 srv_proto_type=3 ssi=6677
+
+Publisher notification of a Follow-up message with no ssi (to enter
+paused state to continue exchange with the subscriber):
+
+event on dev1: <3>NAN-RECEIVE id=5 peer_instance_id=7 address=02:00:00:00:00:00 ssi=
+
+Subscriber sending a Follow-up message:
+
+dev0: NAN_TRANSMIT handle=7 req_instance_id=5 address=02:00:00:00:01:00 ssi=8899
+
+Publisher receiving the Follow-up message:
+
+event on dev1: <3>NAN-RECEIVE id=5 peer_instance_id=7 address=02:00:00:00:00:00 ssi=8899
+
+Publisher sending a Follow-up message:
+
+dev1: NAN_TRANSMIT handle=5 req_instance_id=7 address=02:00:00:00:00:00 ssi=aabbccdd
+
+Subscriber receiving the Follow-up message:
+
+event on dev0: <3>NAN-RECEIVE id=7 peer_instance_id=5 address=02:00:00:00:01:00 ssi=aabbccdd
+
+Stop Subscribe and Publish functions:
+
+dev0: NAN_CANCEL_SUBSCRIBE subscribe_id=7
+dev1: NAN_CANCEL_PUBLIST publish_id=5
index 9aff882e2538a6cfc9a6e1c8e275853915abb3e0..5ae3808fb6632f39b2b5b2ca96d41344157ef6e2 100644 (file)
@@ -554,4 +554,7 @@ CONFIG_WEP=y
 # Disable support for WMM admission control
 #CONFIG_NO_WMM_AC=y
 
+# Wi-Fi Aware unsynchronized service discovery (NAN USD)
+#CONFIG_NAN_USD=y
+
 include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
index f3a31160f8a49722700eb8597812415bf96544da..500f4d1b5ece54fa2b897deb82af8bc422e5f4ad 100644 (file)
@@ -22,6 +22,7 @@
 #ifdef CONFIG_DPP
 #include "common/dpp.h"
 #endif /* CONFIG_DPP */
+#include "common/nan_de.h"
 #include "common/ptksa_cache.h"
 #include "crypto/tls.h"
 #include "ap/hostapd.h"
@@ -58,6 +59,7 @@
 #include "mesh.h"
 #include "dpp_supplicant.h"
 #include "sme.h"
+#include "nan_usd.h"
 
 #ifdef __NetBSD__
 #include <net/if_ether.h>
@@ -4875,6 +4877,15 @@ static int wpa_supplicant_ctrl_iface_get_capability(
        }
 #endif /* CONFIG_DPP */
 
+#ifdef CONFIG_NAN_USD
+       if (os_strcmp(field, "nan") == 0) {
+               res = os_snprintf(buf, buflen, "USD");
+               if (os_snprintf_error(buflen, res))
+                       return -1;
+               return res;
+       }
+#endif /* CONFIG_NAN_USD */
+
 #ifdef CONFIG_SAE
        if (os_strcmp(field, "sae") == 0 &&
            (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
@@ -8952,6 +8963,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
                wpas_restore_permanent_mac_addr(wpa_s);
 
        wpa_s->conf->ignore_old_scan_res = 0;
+
+#ifdef CONFIG_NAN_USD
+       wpas_nan_usd_flush(wpa_s);
+#endif /* CONFIG_NAN_USD */
 }
 
 
@@ -12148,6 +12163,327 @@ static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd)
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
+#ifdef CONFIG_NAN_USD
+
+static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
+                                char *buf, size_t buflen)
+{
+       char *token, *context = NULL;
+       int publish_id;
+       struct nan_publish_params params;
+       const char *service_name = NULL;
+       struct wpabuf *ssi = NULL;
+       int ret = -1;
+       enum nan_service_protocol_type srv_proto_type = 0;
+       int *freq_list = NULL;
+
+       os_memset(&params, 0, sizeof(params));
+       /* USD shall use both solicited and unsolicited transmissions */
+       params.unsolicited = true;
+       params.solicited = true;
+       /* USD shall require FSD without GAS */
+       params.fsd = true;
+       params.freq = NAN_USD_DEFAULT_FREQ;
+
+       while ((token = str_token(cmd, " ", &context))) {
+               if (os_strncmp(token, "service_name=", 13) == 0) {
+                       service_name = token + 13;
+                       continue;
+               }
+
+               if (os_strncmp(token, "ttl=", 4) == 0) {
+                       params.ttl = atoi(token + 4);
+                       continue;
+               }
+
+               if (os_strncmp(token, "freq=", 5) == 0) {
+                       params.freq = atoi(token + 5);
+                       continue;
+               }
+
+               if (os_strncmp(token, "freq_list=", 10) == 0) {
+                       char *pos = token + 10;
+
+                       if (os_strcmp(pos, "all") == 0) {
+                               os_free(freq_list);
+                               freq_list = wpas_nan_usd_all_freqs(wpa_s);
+                               params.freq_list = freq_list;
+                               continue;
+                       }
+
+                       while (pos && pos[0]) {
+                               int_array_add_unique(&freq_list, atoi(pos));
+                               pos = os_strchr(pos, ',');
+                               if (pos)
+                                       pos++;
+                       }
+
+                       params.freq_list = freq_list;
+                       continue;
+               }
+
+               if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
+                       srv_proto_type = atoi(token + 15);
+                       continue;
+               }
+
+               if (os_strncmp(token, "ssi=", 4) == 0) {
+                       if (ssi)
+                               goto fail;
+                       ssi = wpabuf_parse_bin(token + 4);
+                       if (!ssi)
+                               goto fail;
+                       continue;
+               }
+
+               if (os_strcmp(token, "solicited=0") == 0) {
+                       params.solicited = false;
+                       continue;
+               }
+
+               if (os_strcmp(token, "unsolicited=0") == 0) {
+                       params.unsolicited = false;
+                       continue;
+               }
+
+               if (os_strcmp(token, "fsd=0") == 0) {
+                       params.fsd = false;
+                       continue;
+               }
+
+               wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
+                          token);
+               goto fail;
+       }
+
+       publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
+                                         ssi, &params);
+       if (publish_id > 0)
+               ret = os_snprintf(buf, buflen, "%d", publish_id);
+fail:
+       wpabuf_free(ssi);
+       os_free(freq_list);
+       return ret;
+}
+
+
+static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s,
+                                       char *cmd)
+{
+       char *token, *context = NULL;
+       int publish_id = 0;
+
+       while ((token = str_token(cmd, " ", &context))) {
+               if (sscanf(token, "publish_id=%i", &publish_id) == 1)
+                       continue;
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
+                          token);
+               return -1;
+       }
+
+       if (publish_id <= 0) {
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
+               return -1;
+       }
+
+       wpas_nan_usd_cancel_publish(wpa_s, publish_id);
+       return 0;
+}
+
+
+static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s,
+                                       char *cmd)
+{
+       char *token, *context = NULL;
+       int publish_id = 0;
+       struct wpabuf *ssi = NULL;
+       int ret = -1;
+
+       while ((token = str_token(cmd, " ", &context))) {
+               if (sscanf(token, "publish_id=%i", &publish_id) == 1)
+                       continue;
+               if (os_strncmp(token, "ssi=", 4) == 0) {
+                       if (ssi)
+                               goto fail;
+                       ssi = wpabuf_parse_bin(token + 4);
+                       if (!ssi)
+                               goto fail;
+                       continue;
+               }
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
+                          token);
+               goto fail;
+       }
+
+       if (publish_id <= 0) {
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
+               goto fail;
+       }
+
+       ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi);
+fail:
+       wpabuf_free(ssi);
+       return ret;
+}
+
+
+static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
+                                  char *buf, size_t buflen)
+{
+       char *token, *context = NULL;
+       int subscribe_id;
+       struct nan_subscribe_params params;
+       const char *service_name = NULL;
+       struct wpabuf *ssi = NULL;
+       int ret = -1;
+       enum nan_service_protocol_type srv_proto_type = 0;
+
+       os_memset(&params, 0, sizeof(params));
+       params.freq = NAN_USD_DEFAULT_FREQ;
+
+       while ((token = str_token(cmd, " ", &context))) {
+               if (os_strncmp(token, "service_name=", 13) == 0) {
+                       service_name = token + 13;
+                       continue;
+               }
+
+               if (os_strcmp(token, "active=1") == 0) {
+                       params.active = true;
+                       continue;
+               }
+
+               if (os_strncmp(token, "ttl=", 4) == 0) {
+                       params.ttl = atoi(token + 4);
+                       continue;
+               }
+
+               if (os_strncmp(token, "freq=", 5) == 0) {
+                       params.freq = atoi(token + 5);
+                       continue;
+               }
+
+               if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
+                       srv_proto_type = atoi(token + 15);
+                       continue;
+               }
+
+               if (os_strncmp(token, "ssi=", 4) == 0) {
+                       if (ssi)
+                               goto fail;
+                       ssi = wpabuf_parse_bin(token + 4);
+                       if (!ssi)
+                               goto fail;
+                       continue;
+               }
+
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
+                          token);
+               goto fail;
+       }
+
+       subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
+                                             srv_proto_type, ssi,
+                                             &params);
+       if (subscribe_id > 0)
+               ret = os_snprintf(buf, buflen, "%d", subscribe_id);
+fail:
+       wpabuf_free(ssi);
+       return ret;
+}
+
+
+static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s,
+                                         char *cmd)
+{
+       char *token, *context = NULL;
+       int subscribe_id = 0;
+
+       while ((token = str_token(cmd, " ", &context))) {
+               if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
+                       continue;
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
+                          token);
+               return -1;
+       }
+
+       if (subscribe_id <= 0) {
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
+               return -1;
+       }
+
+       wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id);
+       return 0;
+}
+
+
+static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       char *token, *context = NULL;
+       int handle = 0;
+       int req_instance_id = 0;
+       struct wpabuf *ssi = NULL;
+       u8 peer_addr[ETH_ALEN];
+       int ret = -1;
+
+       os_memset(peer_addr, 0, ETH_ALEN);
+
+       while ((token = str_token(cmd, " ", &context))) {
+               if (sscanf(token, "handle=%i", &handle) == 1)
+                       continue;
+
+               if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
+                       continue;
+
+               if (os_strncmp(token, "address=", 8) == 0) {
+                       if (hwaddr_aton(token + 8, peer_addr) < 0)
+                               return -1;
+                       continue;
+               }
+
+               if (os_strncmp(token, "ssi=", 4) == 0) {
+                       if (ssi)
+                               goto fail;
+                       ssi = wpabuf_parse_bin(token + 4);
+                       if (!ssi)
+                               goto fail;
+                       continue;
+               }
+
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid NAN_TRANSMIT parameter: %s",
+                          token);
+               goto fail;
+       }
+
+       if (handle <= 0) {
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid or missing NAN_TRANSMIT handle");
+               goto fail;
+       }
+
+       if (is_zero_ether_addr(peer_addr)) {
+               wpa_printf(MSG_INFO,
+                          "CTRL: Invalid or missing NAN_TRANSMIT address");
+               goto fail;
+       }
+
+       ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
+                                   req_instance_id);
+fail:
+       wpabuf_free(ssi);
+       return ret;
+}
+
+#endif /* CONFIG_NAN_USD */
+
+
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                                         char *buf, size_t *resp_len)
 {
@@ -13151,6 +13487,26 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        reply_len = -1;
 #endif /* CONFIG_DPP3 */
 #endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+       } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
+               reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply,
+                                                 reply_size);
+       } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
+               if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0)
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
+               if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0)
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
+               reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply,
+                                                   reply_size);
+       } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
+               if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0)
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
+               if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
+                       reply_len = -1;
+#endif /* CONFIG_NAN_USD */
 #ifdef CONFIG_PASN
        } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
                if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
index 60d1bfc5715e79c5ccbdca934b029c6f7e6cd272..52befd8f15fc1e01f2a9a3e90ede99b79b9677dd 100644 (file)
@@ -683,3 +683,6 @@ CONFIG_DPP2=y
 
 # Disable support for WMM admission control
 #CONFIG_NO_WMM_AC=y
+
+# Wi-Fi Aware unsynchronized service discovery (NAN USD)
+#CONFIG_NAN_USD=y
index e168cf38b02a645ba363ad58e2529030a92bc3dc..201e43f6727157815ffca41deb4c83e99df3b1ba 100644 (file)
@@ -50,6 +50,7 @@
 #include "mesh.h"
 #include "mesh_mpm.h"
 #include "wmm_ac.h"
+#include "nan_usd.h"
 #include "dpp_supplicant.h"
 
 
@@ -5363,6 +5364,17 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
        }
 #endif /* CONFIG_FST */
 
+#ifdef CONFIG_NAN_USD
+       if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
+           payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
+           WPA_GET_BE32(&payload[1]) == NAN_SDF_VENDOR_TYPE) {
+               payload += 5;
+               plen -= 5;
+               wpas_nan_usd_rx_sdf(wpa_s, mgmt->sa, freq, payload, plen);
+               return;
+       }
+#endif /* CONFIG_NAN_USD */
+
 #ifdef CONFIG_DPP
        if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
            payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
@@ -6495,6 +6507,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                        wpa_s, data->remain_on_channel.freq,
                        data->remain_on_channel.duration);
 #endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+               wpas_nan_usd_remain_on_channel_cb(
+                       wpa_s, data->remain_on_channel.freq,
+                       data->remain_on_channel.duration);
+#endif /* CONFIG_NAN_USD */
                break;
        case EVENT_CANCEL_REMAIN_ON_CHANNEL:
 #ifdef CONFIG_OFFCHANNEL
@@ -6507,6 +6524,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                wpas_dpp_cancel_remain_on_channel_cb(
                        wpa_s, data->remain_on_channel.freq);
 #endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+               wpas_nan_usd_cancel_remain_on_channel_cb(
+                       wpa_s, data->remain_on_channel.freq);
+#endif /* CONFIG_NAN_USD */
                break;
        case EVENT_EAPOL_RX:
                wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
@@ -6842,6 +6863,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 #ifdef CONFIG_DPP
                wpas_dpp_tx_wait_expire(wpa_s);
 #endif /* CONFIG_DPP */
+#ifdef CONFIG_NAN_USD
+               wpas_nan_usd_tx_wait_expire(wpa_s);
+#endif /* CONFIG_NAN_USD */
                break;
        case EVENT_TID_LINK_MAP:
                if (data)
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
new file mode 100644 (file)
index 0000000..657b302
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * NAN unsynchronized service discovery (USD)
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/nan_de.h"
+#include "wpa_supplicant_i.h"
+#include "offchannel.h"
+#include "driver_i.h"
+#include "nan_usd.h"
+
+
+static const char *
+tx_status_result_txt(enum offchannel_send_action_result result)
+{
+       switch (result) {
+       case OFFCHANNEL_SEND_ACTION_SUCCESS:
+               return "success";
+       case OFFCHANNEL_SEND_ACTION_NO_ACK:
+               return "no-ack";
+       case OFFCHANNEL_SEND_ACTION_FAILED:
+               return "failed";
+       }
+
+       return "?";
+}
+
+
+static void 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)
+{
+       if (!wpa_s->nan_de)
+               return;
+
+       wpa_printf(MSG_DEBUG, "NAN: TX status A1=" MACSTR " A2=" MACSTR
+                  " A3=" MACSTR " freq=%d len=%zu result=%s",
+                  MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
+                  data_len, tx_status_result_txt(result));
+
+       nan_de_tx_status(wpa_s->nan_de, freq, dst);
+}
+
+
+struct wpas_nan_usd_tx_work {
+       unsigned int freq;
+       unsigned int wait_time;
+       u8 dst[ETH_ALEN];
+       u8 src[ETH_ALEN];
+       u8 bssid[ETH_ALEN];
+       struct wpabuf *buf;
+};
+
+
+static void wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work *twork)
+{
+       if (!twork)
+               return;
+       wpabuf_free(twork->buf);
+       os_free(twork);
+}
+
+
+static void wpas_nan_usd_tx_work_done(struct wpa_supplicant *wpa_s)
+{
+       struct wpas_nan_usd_tx_work *twork;
+
+       if (!wpa_s->nan_usd_tx_work)
+               return;
+
+       twork = wpa_s->nan_usd_tx_work->ctx;
+       wpas_nan_usd_tx_work_free(twork);
+       radio_work_done(wpa_s->nan_usd_tx_work);
+       wpa_s->nan_usd_tx_work = NULL;
+}
+
+
+static int 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)
+{
+       wpa_printf(MSG_DEBUG, "NAN: TX NAN SDF A1=" MACSTR " A2=" MACSTR
+                  " A3=" MACSTR " freq=%d len=%zu",
+                  MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
+                  wpabuf_len(buf));
+
+       return offchannel_send_action(wpa_s, freq, dst, src, bssid,
+                                     wpabuf_head(buf), wpabuf_len(buf),
+                                     wait_time, wpas_nan_de_tx_status, 1);
+}
+
+
+static void wpas_nan_usd_start_tx_cb(struct wpa_radio_work *work, int deinit)
+{
+       struct wpa_supplicant *wpa_s = work->wpa_s;
+       struct wpas_nan_usd_tx_work *twork = work->ctx;
+
+       if (deinit) {
+               if (work->started) {
+                       wpa_s->nan_usd_tx_work = NULL;
+                       offchannel_send_action_done(wpa_s);
+               }
+               wpas_nan_usd_tx_work_free(twork);
+               return;
+       }
+
+       wpa_s->nan_usd_tx_work = work;
+
+       if (wpas_nan_de_tx_send(wpa_s, twork->freq, twork->wait_time,
+                               twork->dst, twork->src, twork->bssid,
+                               twork->buf) < 0)
+               wpas_nan_usd_tx_work_done(wpa_s);
+}
+
+
+static int 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)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       struct wpas_nan_usd_tx_work *twork;
+
+       if (wpa_s->nan_usd_tx_work || wpa_s->nan_usd_listen_work) {
+               /* Reuse ongoing radio work */
+               return wpas_nan_de_tx_send(wpa_s, freq, wait_time, dst, src,
+                                          bssid, buf);
+       }
+
+       twork = os_zalloc(sizeof(*twork));
+       if (!twork)
+               return -1;
+       twork->freq = freq;
+       twork->wait_time = wait_time;
+       os_memcpy(twork->dst, dst, ETH_ALEN);
+       os_memcpy(twork->src, src, ETH_ALEN);
+       os_memcpy(twork->bssid, bssid, ETH_ALEN);
+       twork->buf = wpabuf_dup(buf);
+       if (!twork->buf) {
+               wpas_nan_usd_tx_work_free(twork);
+               return -1;
+       }
+
+       if (radio_add_work(wpa_s, freq, "nan-usd-tx", 0,
+                          wpas_nan_usd_start_tx_cb, twork) < 0) {
+               wpas_nan_usd_tx_work_free(twork);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+struct wpas_nan_usd_listen_work {
+       unsigned int freq;
+       unsigned int duration;
+};
+
+
+static void wpas_nan_usd_listen_work_done(struct wpa_supplicant *wpa_s)
+{
+       struct wpas_nan_usd_listen_work *lwork;
+
+       if (!wpa_s->nan_usd_listen_work)
+               return;
+
+       lwork = wpa_s->nan_usd_listen_work->ctx;
+       os_free(lwork);
+       radio_work_done(wpa_s->nan_usd_listen_work);
+       wpa_s->nan_usd_listen_work = NULL;
+}
+
+
+static void wpas_nan_usd_start_listen_cb(struct wpa_radio_work *work,
+                                        int deinit)
+{
+       struct wpa_supplicant *wpa_s = work->wpa_s;
+       struct wpas_nan_usd_listen_work *lwork = work->ctx;
+       unsigned int duration;
+
+       if (deinit) {
+               if (work->started) {
+                       wpa_s->nan_usd_listen_work = NULL;
+                       wpa_drv_cancel_remain_on_channel(wpa_s);
+               }
+               os_free(lwork);
+               return;
+       }
+
+       wpa_s->nan_usd_listen_work = work;
+
+       duration = lwork->duration;
+       if (duration > wpa_s->max_remain_on_chan)
+               duration = wpa_s->max_remain_on_chan;
+       wpa_printf(MSG_DEBUG, "NAN: Start listen on %u MHz for %u ms",
+                  lwork->freq, duration);
+       if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, duration) < 0) {
+               wpa_printf(MSG_DEBUG,
+                          "NAN: Failed to request the driver to remain on channel (%u MHz) for listen",
+                          lwork->freq);
+               wpas_nan_usd_listen_work_done(wpa_s);
+               return;
+       }
+}
+
+
+static int wpas_nan_de_listen(void *ctx, unsigned int freq,
+                             unsigned int duration)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       struct wpas_nan_usd_listen_work *lwork;
+
+       lwork = os_zalloc(sizeof(*lwork));
+       if (!lwork)
+               return -1;
+       lwork->freq = freq;
+       lwork->duration = duration;
+
+       if (radio_add_work(wpa_s, freq, "nan-usd-listen", 0,
+                          wpas_nan_usd_start_listen_cb, lwork) < 0) {
+               os_free(lwork);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+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)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       char *ssi_hex;
+
+       ssi_hex = os_zalloc(2 * ssi_len + 1);
+       if (!ssi_hex)
+               return;
+       if (ssi)
+               wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+       wpa_msg(wpa_s, MSG_INFO, NAN_DISCOVERY_RESULT
+               "subscribe_id=%d publish_id=%d address=" MACSTR
+               " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
+               subscribe_id, peer_publish_id, MAC2STR(peer_addr),
+               fsd, fsd_gas, srv_proto_type, ssi_hex);
+       os_free(ssi_hex);
+}
+
+
+static void 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)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       char *ssi_hex;
+
+       ssi_hex = os_zalloc(2 * ssi_len + 1);
+       if (!ssi_hex)
+               return;
+       if (ssi)
+               wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+       wpa_msg(wpa_s, MSG_INFO, NAN_REPLIED
+               "publish_id=%d address=" MACSTR
+               " subscribe_id=%d srv_proto_type=%u ssi=%s",
+               publish_id, MAC2STR(peer_addr), peer_subscribe_id,
+               srv_proto_type, ssi_hex);
+       os_free(ssi_hex);
+}
+
+
+static const char * nan_reason_txt(enum nan_de_reason reason)
+{
+       switch (reason) {
+       case NAN_DE_REASON_TIMEOUT:
+               return "timeout";
+       case NAN_DE_REASON_USER_REQUEST:
+               return "user-request";
+       case NAN_DE_REASON_FAILURE:
+               return "failure";
+       }
+
+       return "unknown";
+}
+
+
+static void wpas_nan_de_publish_terminated(void *ctx, int publish_id,
+                                          enum nan_de_reason reason)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+
+       wpa_msg(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
+               "publish_id=%d reason=%s",
+               publish_id, nan_reason_txt(reason));
+}
+
+
+static void wpas_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
+                                            enum nan_de_reason reason)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+
+       wpa_msg(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
+               "subscribe_id=%d reason=%s",
+               subscribe_id, nan_reason_txt(reason));
+}
+
+
+static void wpas_nan_de_receive(void *ctx, int id, int peer_instance_id,
+                               const u8 *ssi, size_t ssi_len,
+                               const u8 *peer_addr)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       char *ssi_hex;
+
+       ssi_hex = os_zalloc(2 * ssi_len + 1);
+       if (!ssi_hex)
+               return;
+       if (ssi)
+               wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+       wpa_msg(wpa_s, MSG_INFO, NAN_RECEIVE
+               "id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
+               id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
+       os_free(ssi_hex);
+}
+
+
+int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
+{
+       struct nan_callbacks cb;
+
+       os_memset(&cb, 0, sizeof(cb));
+       cb.ctx = wpa_s;
+       cb.tx = wpas_nan_de_tx;
+       cb.listen = wpas_nan_de_listen;
+       cb.discovery_result = wpas_nan_de_discovery_result;
+       cb.replied = wpas_nan_de_replied;
+       cb.publish_terminated = wpas_nan_de_publish_terminated;
+       cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
+       cb.receive = wpas_nan_de_receive;
+
+       wpa_s->nan_de = nan_de_init(wpa_s->own_addr, false, &cb);
+       if (!wpa_s->nan_de)
+               return -1;
+       return 0;
+}
+
+
+void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s)
+{
+       nan_de_deinit(wpa_s->nan_de);
+       wpa_s->nan_de = NULL;
+}
+
+
+void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+                        unsigned int freq, const u8 *buf, size_t len)
+{
+       if (!wpa_s->nan_de)
+               return;
+       nan_de_rx_sdf(wpa_s->nan_de, src, freq, buf, len);
+}
+
+
+void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
+{
+       if (!wpa_s->nan_de)
+               return;
+       nan_de_flush(wpa_s->nan_de);
+}
+
+
+int 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)
+{
+       int publish_id;
+       struct wpabuf *elems = NULL;
+
+       if (!wpa_s->nan_de)
+               return -1;
+
+       publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
+                                   ssi, elems, params);
+       wpabuf_free(elems);
+       return publish_id;
+}
+
+
+void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
+{
+       if (!wpa_s->nan_de)
+               return;
+       nan_de_cancel_publish(wpa_s->nan_de, publish_id);
+}
+
+
+int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
+                               const struct wpabuf *ssi)
+{
+       if (!wpa_s->nan_de)
+               return -1;
+       return nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
+}
+
+
+int 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)
+{
+       int subscribe_id;
+       struct wpabuf *elems = NULL;
+
+       if (!wpa_s->nan_de)
+               return -1;
+
+       subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
+                                       srv_proto_type, ssi, elems, params);
+       wpabuf_free(elems);
+       return subscribe_id;
+}
+
+
+void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
+                                  int subscribe_id)
+{
+       if (!wpa_s->nan_de)
+               return;
+       nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
+}
+
+
+int 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)
+{
+       if (!wpa_s->nan_de)
+               return -1;
+       return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
+                              req_instance_id);
+}
+
+
+void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+                                      unsigned int freq, unsigned int duration)
+{
+       wpas_nan_usd_listen_work_done(wpa_s);
+
+       if (wpa_s->nan_de)
+               nan_de_listen_started(wpa_s->nan_de, freq, duration);
+}
+
+
+void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+                                             unsigned int freq)
+{
+       if (wpa_s->nan_de)
+               nan_de_listen_ended(wpa_s->nan_de, freq);
+}
+
+
+void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s)
+{
+       wpas_nan_usd_tx_work_done(wpa_s);
+
+       if (wpa_s->nan_de)
+               nan_de_tx_wait_ended(wpa_s->nan_de);
+}
+
+
+int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s)
+{
+       int i, j;
+       int *freqs = NULL;
+
+       if (!wpa_s->hw.modes)
+               return NULL;
+
+       for (i = 0; i < wpa_s->hw.num_modes; i++) {
+               struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+
+               for (j = 0; j < mode->num_channels; j++) {
+                       struct hostapd_channel_data *chan = &mode->channels[j];
+
+                       /* All 20 MHz channels on 2.4 and 5 GHz band */
+                       if (chan->freq < 2412 || chan->freq > 5900)
+                               continue;
+
+                       /* that allow frames to be transmitted */
+                       if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+                                         HOSTAPD_CHAN_NO_IR |
+                                         HOSTAPD_CHAN_RADAR))
+                               continue;
+
+                       int_array_add_unique(&freqs, chan->freq);
+               }
+       }
+
+       return freqs;
+}
diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h
new file mode 100644 (file)
index 0000000..149ac9e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * NAN unsynchronized service discovery (USD)
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef NAN_USD_H
+#define NAN_USD_H
+
+struct nan_subscribe_params;
+struct nan_publish_params;
+enum nan_service_protocol_type;
+
+int wpas_nan_usd_init(struct wpa_supplicant *wpa_s);
+void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s);
+void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+                        unsigned int freq, const u8 *buf, size_t len);
+void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s);
+int 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);
+void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id);
+int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
+                               const struct wpabuf *ssi);
+int 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);
+void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
+                                  int subscribe_id);
+int 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);
+void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+                                      unsigned int freq,
+                                      unsigned int duration);
+void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+                                             unsigned int freq);
+void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s);
+int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s);
+
+#endif /* NAN_USD_H */
index 172a863cbb1fcfb3b5c141bdd01a575c4fdd5117..91a213dacb387808874be53a620c52843c54174c 100644 (file)
@@ -65,6 +65,7 @@
 #include "wpas_kay.h"
 #include "mesh.h"
 #include "dpp_supplicant.h"
+#include "nan_usd.h"
 #ifdef CONFIG_MESH
 #include "ap/ap_config.h"
 #include "ap/hostapd.h"
@@ -750,6 +751,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        wpa_s->dpp = NULL;
 #endif /* CONFIG_DPP */
 
+#ifdef CONFIG_NAN_USD
+       wpas_nan_usd_deinit(wpa_s);
+#endif /* CONFIG_NAN_USD */
+
 #ifdef CONFIG_PASN
        wpas_pasn_auth_stop(wpa_s);
 #endif /* CONFIG_PASN */
@@ -7333,6 +7338,11 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
                return -1;
 #endif /* CONFIG_DPP */
 
+#ifdef CONFIG_NAN_USD
+       if (wpas_nan_usd_init(wpa_s) < 0)
+               return -1;
+#endif /* CONFIG_NAN_USD */
+
        if (wpa_supplicant_init_eapol(wpa_s) < 0)
                return -1;
        wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
index 933fc36268a00e553c509d1d0262eda3efd10b45..6cacfe4854f05f44dbe620a3edf0d648d8d0ae98 100644 (file)
@@ -1599,6 +1599,12 @@ struct wpa_supplicant {
         * owe_transition_search == 1 */
        int *owe_trans_scan_freq;
 #endif /* CONFIG_OWE */
+
+#ifdef CONFIG_NAN_USD
+       struct nan_de *nan_de;
+       struct wpa_radio_work *nan_usd_listen_work;
+       struct wpa_radio_work *nan_usd_tx_work;
+#endif /* CONFIG_NAN_USD */
 };