[RFC PATCH 2/6] NAN: Discover Services and Peers from Proxy Meta Attributes
Benjamin Berg
benjamin at sipsolutions.net
Thu Feb 19 07:55:49 PST 2026
From: Benjamin Berg <benjamin.berg at intel.com>
Services may be published by another peer using a Proxy Meta attribute.
Find these attributes and handle them, also inserting the corresponding
peer as necessary.
Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
---
src/ap/nan_usd_ap.c | 15 +++++++++----
src/common/nan_de.c | 22 +++++++++++++-------
src/common/nan_de.h | 9 ++++++--
src/common/nan_defs.h | 1 +
wpa_supplicant/dbus/dbus_new.c | 11 +++++++++-
wpa_supplicant/dbus/dbus_new.h | 6 ++++--
wpa_supplicant/nan_supplicant.c | 37 ++++++++++++++++++++++++++++++---
wpa_supplicant/notify.c | 15 +++++++++----
wpa_supplicant/notify.h | 3 ++-
9 files changed, 95 insertions(+), 24 deletions(-)
diff --git a/src/ap/nan_usd_ap.c b/src/ap/nan_usd_ap.c
index 18c70be485..5579e7198a 100644
--- a/src/ap/nan_usd_ap.c
+++ b/src/ap/nan_usd_ap.c
@@ -48,9 +48,10 @@ hostapd_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)
+ bool fsd, bool fsd_gas, const u8 *origin_addr)
{
struct hostapd_data *hapd = ctx;
+ char proxied_by[32] = "";
char *ssi_hex;
ssi_hex = os_zalloc(2 * ssi_len + 1);
@@ -58,11 +59,17 @@ hostapd_nan_de_discovery_result(void *ctx, int subscribe_id,
return;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+
+ if (origin_addr)
+ os_snprintf(proxied_by, sizeof(proxied_by) - 1,
+ " proxied_by=" MACSTR, MAC2STR(origin_addr));
+
wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_DISCOVERY_RESULT
"subscribe_id=%d publish_id=%d address=" MACSTR
- " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
+ " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s%s",
subscribe_id, peer_publish_id, MAC2STR(peer_addr),
- fsd, fsd_gas, srv_proto_type, ssi_hex);
+ fsd, fsd_gas, srv_proto_type, ssi_hex,
+ proxied_by);
os_free(ssi_hex);
}
@@ -180,7 +187,7 @@ void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
{
if (!hapd->nan_de)
return;
- nan_de_rx_sdf(hapd->nan_de, src, a3, freq, buf, len, 0);
+ nan_de_rx_sdf(hapd->nan_de, src, a3, freq, buf, len, 0, NULL);
}
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
index 605968a2a3..95d6c5621b 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -942,7 +942,7 @@ void nan_de_tx_wait_ended(struct nan_de *de)
}
-static const u8 *
+const u8 *
nan_de_get_attr(const u8 *buf, size_t len, enum nan_attr_id id,
unsigned int skip)
{
@@ -1173,7 +1173,8 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
u8 req_instance_id, u16 sdea_control,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len,
- bool range_limit, int rssi)
+ bool range_limit, int rssi,
+ const u8 *origin_addr)
{
if (!nan_de_filter_match(srv, matching_filter, matching_filter_len))
return;
@@ -1220,7 +1221,8 @@ send_event:
ssi, ssi_len, instance_id,
peer_addr,
sdea_control & NAN_SDEA_CTRL_FSD_REQ,
- sdea_control & NAN_SDEA_CTRL_FSD_GAS);
+ sdea_control & NAN_SDEA_CTRL_FSD_GAS,
+ origin_addr);
}
@@ -1377,7 +1379,8 @@ static bool nan_srf_match(struct nan_de *de, const u8 *srf, size_t srf_len)
static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
unsigned int freq, const u8 *buf, size_t len,
- const u8 *sda, size_t sda_len, int rssi)
+ const u8 *sda, size_t sda_len, int rssi,
+ const u8 *origin_addr)
{
const u8 *service_id;
u8 instance_id, req_instance_id, ctrl;
@@ -1508,6 +1511,10 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
srv->is_pr);
}
+ /* Ignore everything other than publish for proxied SDAs */
+ if (origin_addr && type != NAN_SRV_CTRL_PUBLISH)
+ break;
+
switch (type) {
case NAN_SRV_CTRL_PUBLISH:
nan_de_rx_publish(de, srv, peer_addr, a3, instance_id,
@@ -1518,7 +1525,7 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
ssi, ssi_len,
ctrl &
NAN_SRV_CTRL_DISCOVERY_RANGE_LIMITED,
- rssi);
+ rssi, origin_addr);
break;
case NAN_SRV_CTRL_SUBSCRIBE:
nan_de_rx_subscribe(de, srv, peer_addr, a3, instance_id,
@@ -1540,7 +1547,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
- unsigned int freq, const u8 *buf, size_t len, int rssi)
+ unsigned int freq, const u8 *buf, size_t len, int rssi,
+ const u8 *origin_addr)
{
const u8 *sda;
u16 sda_len;
@@ -1564,7 +1572,7 @@ void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
sda_len = WPA_GET_LE16(sda);
sda += 2;
nan_de_rx_sda(de, peer_addr, a3, freq, buf, len, sda, sda_len,
- rssi);
+ rssi, origin_addr);
}
}
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index c842b90b3c..b14b22b4a0 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -37,7 +37,8 @@ struct nan_callbacks {
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);
+ const u8 *peer_addr, bool fsd, bool fsd_gas,
+ const u8 *origin_addr);
void (*replied)(void *ctx, int publish_id, const u8 *peer_addr,
int peer_subscribe_id,
@@ -66,6 +67,9 @@ struct nan_callbacks {
unsigned int freq);
};
+const u8 * nan_de_get_attr(const u8 *buf, size_t len, enum nan_attr_id id,
+ unsigned int skip);
+
bool nan_de_is_nan_network_id(const u8 *addr);
bool nan_de_is_p2p_network_id(const u8 *addr);
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
@@ -82,7 +86,8 @@ void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst);
void nan_de_tx_wait_ended(struct nan_de *de);
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
- unsigned int freq, const u8 *buf, size_t len, int rssi);
+ unsigned int freq, const u8 *buf, size_t len, int rssi,
+ const u8 *origin_addr);
const u8 * nan_de_get_service_id(struct nan_de *de, int id);
struct nan_publish_params {
diff --git a/src/common/nan_defs.h b/src/common/nan_defs.h
index e8428c2acf..472848a3c4 100644
--- a/src/common/nan_defs.h
+++ b/src/common/nan_defs.h
@@ -51,6 +51,7 @@ enum nan_attr_id {
NAN_ATTR_BPBA = 0x2C, /* NAN Pairing Bootstrapping attribute */
NAN_ATTR_S3 = 0x2D,
NAN_ATTR_TPEA = 0x2E, /* Transmit Power Envelope attribute */
+ NAN_ATTR_PROXY_META = 0x53,
NAN_ATTR_VENDOR_SPECIFIC = 0xDD,
};
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 2989002e4a..22e481126f 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -5482,6 +5482,7 @@ void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
* @peer_addr: MAC address of the peer device
* @ssi: Service specific information payload
* @ssi_len: Length of the SSI field
+ * @origin_addr: If proxied, the address of the reporter
*
* This is used to indicate the NAN DE DiscoveryResult event.
*/
@@ -5492,12 +5493,14 @@ void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
int peer_publish_id,
const u8 *peer_addr,
bool fsd, bool fsd_gas,
- const u8 *ssi, size_t ssi_len)
+ const u8 *ssi, size_t ssi_len,
+ const u8 *origin_addr)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
DBusMessageIter iter, dict_iter;
char addr_str[20];
+ char origin_addr_str[20];
iface = wpa_s->global->dbus;
/* Do nothing if the interface is not turned on */
@@ -5510,6 +5513,9 @@ void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
return;
snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
+ if (origin_addr)
+ snprintf(origin_addr_str, sizeof(origin_addr_str),
+ MACSTR, MAC2STR(origin_addr));
dbus_message_iter_init_append(msg, &iter);
@@ -5528,6 +5534,9 @@ void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
"ssi",
(const char *) ssi,
ssi_len)) ||
+ (origin_addr &&
+ !wpa_dbus_dict_append_string(&dict_iter, "proxied_by",
+ origin_addr_str)) ||
!wpa_dbus_dict_close_write(&iter, &dict_iter))
wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
else
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 92b0c70b4e..18efdf8fc4 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -299,7 +299,8 @@ void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
int peer_publish_id,
const u8 *peer_addr,
bool fsd, bool fsd_gas,
- const u8 *ssi, size_t ssi_len);
+ const u8 *ssi, size_t ssi_len,
+ const u8 *origin_addr);
void wpas_dbus_signal_nan_replied(struct wpa_supplicant *wpa_s,
enum nan_service_protocol_type srv_proto_type,
int publish_id, int peer_subscribe_id,
@@ -722,7 +723,8 @@ wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
int subscribe_id,
int peer_publish_id, const u8 *peer_addr,
bool fsd, bool fsd_gas,
- const u8 *ssi, size_t ssi_len)
+ const u8 *ssi, size_t ssi_len,
+ const u8 *origin_addr)
{
}
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index 70953eccc7..a42c158425 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -543,13 +543,14 @@ 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)
+ const u8 *peer_addr, bool fsd, bool fsd_gas,
+ const u8 *origin_addr)
{
struct wpa_supplicant *wpa_s = ctx;
wpas_notify_nan_discovery_result(wpa_s, srv_proto_type, subscribe_id,
peer_publish_id, peer_addr, fsd,
- fsd_gas, ssi, ssi_len);
+ fsd_gas, ssi, ssi_len, origin_addr);
}
@@ -681,9 +682,39 @@ void wpas_nan_de_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
const u8 *a3, unsigned int freq,
const u8 *buf, size_t len, int rssi)
{
+ unsigned int skip;
+
if (!wpa_s->nan_de)
return;
- nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len, rssi);
+
+ nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len, rssi, NULL);
+
+ for (skip = 0; ; skip++) {
+ const u8 *proxy_meta =
+ nan_de_get_attr(buf, len, NAN_ATTR_PROXY_META, skip);
+ const u8 *proxied_addr;
+ size_t proxy_meta_len;
+
+ if (!proxy_meta)
+ break;
+
+ proxy_meta++;
+ proxy_meta_len = WPA_GET_LE16(proxy_meta);
+ proxy_meta += 2;
+
+ /* Needs at least space for address plus SDA */
+ if (proxy_meta_len < 6 + 12)
+ continue;
+
+ proxied_addr = proxy_meta;
+ proxy_meta += 6;
+ proxy_meta_len -= 6;
+
+ nan_de_rx_sdf(wpa_s->nan_de, proxied_addr, a3, freq,
+ proxy_meta, proxy_meta_len, rssi, src);
+
+ /* Only one SDA inside each Proxy Meta Attribute */
+ }
}
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 36694b48c8..6171243136 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1105,8 +1105,10 @@ void wpas_notify_nan_discovery_result(struct wpa_supplicant *wpa_s,
int subscribe_id, int peer_publish_id,
const u8 *peer_addr,
bool fsd, bool fsd_gas,
- const u8 *ssi, size_t ssi_len)
+ const u8 *ssi, size_t ssi_len,
+ const u8 *origin_addr)
{
+ char proxied_by[32] = "";
char *ssi_hex;
ssi_hex = os_zalloc(2 * ssi_len + 1);
@@ -1114,17 +1116,22 @@ void wpas_notify_nan_discovery_result(struct wpa_supplicant *wpa_s,
return;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
+
+ if (origin_addr)
+ os_snprintf(proxied_by, sizeof(proxied_by) - 1,
+ " proxied_by=" MACSTR, MAC2STR(origin_addr));
+
wpa_msg_global(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",
+ " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s%s",
subscribe_id, peer_publish_id, MAC2STR(peer_addr),
- fsd, fsd_gas, srv_proto_type, ssi_hex);
+ fsd, fsd_gas, srv_proto_type, ssi_hex, proxied_by);
os_free(ssi_hex);
wpas_dbus_signal_nan_discovery_result(wpa_s, srv_proto_type,
subscribe_id, peer_publish_id,
peer_addr, fsd, fsd_gas,
- ssi, ssi_len);
+ ssi, ssi_len, origin_addr);
}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 79d7abd564..e7484f11a6 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -190,7 +190,8 @@ void wpas_notify_nan_discovery_result(struct wpa_supplicant *wpa_s,
int subscribe_id, int peer_publish_id,
const u8 *peer_addr,
bool fsd, bool fsd_gas,
- const u8 *ssi, size_t ssi_len);
+ const u8 *ssi, size_t ssi_len,
+ const u8 *origin_addr);
void wpas_notify_nan_replied(struct wpa_supplicant *wpa_s,
enum nan_service_protocol_type srv_proto_type,
int publish_id, int peer_subscribe_id,
--
2.53.0
More information about the Hostap
mailing list