NAN: USD in wpa_supplicant
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>
This commit is contained in:
parent
9eb0bc1f0a
commit
e3f9ab3c3a
13 changed files with 1134 additions and 0 deletions
|
@ -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 "
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
147
wpa_supplicant/README-NAN-USD
Normal file
147
wpa_supplicant/README-NAN-USD
Normal file
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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(¶ms, 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, ¶ms);
|
||||
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(¶ms, 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,
|
||||
¶ms);
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
513
wpa_supplicant/nan_usd.c
Normal file
513
wpa_supplicant/nan_usd.c
Normal file
|
@ -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;
|
||||
}
|
46
wpa_supplicant/nan_usd.h
Normal file
46
wpa_supplicant/nan_usd.h
Normal file
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue