int handle = 0;
int req_instance_id = 0;
struct wpabuf *ssi = NULL;
- u8 peer_addr[ETH_ALEN];
+ u8 peer_addr[ETH_ALEN], a3[ETH_ALEN];
int ret = -1;
+ bool a3_set = false;
os_memset(peer_addr, 0, ETH_ALEN);
+ os_memset(a3, 0, ETH_ALEN);
while ((token = str_token(cmd, " ", &context))) {
if (sscanf(token, "handle=%i", &handle) == 1)
continue;
}
+ if (os_strncmp(token, "a3=", 3) == 0) {
+ if (hwaddr_aton(token + 3, a3) < 0)
+ return -1;
+ a3_set = true;
+ continue;
+ }
+
if (os_strncmp(token, "ssi=", 4) == 0) {
if (ssi)
goto fail;
}
ret = hostapd_nan_usd_transmit(hapd, handle, ssi, NULL, peer_addr,
- req_instance_id);
+ a3_set ? a3 : NULL, req_instance_id);
fail:
wpabuf_free(ssi);
return ret;
pos = mgmt->u.action.u.vs_public_action.variable;
end = drv_mgmt->frame + drv_mgmt->frame_len;
pos++;
- hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, drv_mgmt->freq,
- pos, end - pos);
+ hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, mgmt->bssid,
+ drv_mgmt->freq, pos, end - pos);
return;
}
#endif /* CONFIG_NAN_USD */
pos = mgmt->u.action.u.vs_public_action.variable;
end = ((const u8 *) mgmt) + len;
pos++;
- hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, freq,
- pos, end - pos);
+ hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, mgmt->bssid,
+ freq, pos, end - pos);
return 1;
}
#endif /* CONFIG_NAN_USD */
wpabuf_len(buf));
/* TODO: Force use of OFDM */
- return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst,
- wpabuf_head(buf), wpabuf_len(buf));
+ return hostapd_drv_send_action_forced_addr3(hapd, hapd->iface->freq, 0,
+ dst, bssid,
+ wpabuf_head(buf),
+ wpabuf_len(buf));
}
static void hostapd_nan_de_receive(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
- const u8 *peer_addr)
+ const u8 *peer_addr, const u8 *a3)
{
struct hostapd_data *hapd = ctx;
char *ssi_hex;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_RECEIVE
- "id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
- id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
+ "id=%d peer_instance_id=%d address=" MACSTR " a3=" MACSTR
+ " ssi=%s",
+ id, peer_instance_id, MAC2STR(peer_addr), MAC2STR(a3), ssi_hex);
os_free(ssi_hex);
}
void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
- unsigned int freq, const u8 *buf, size_t len)
+ const u8 *a3, unsigned int freq,
+ const u8 *buf, size_t len)
{
if (!hapd->nan_de)
return;
- nan_de_rx_sdf(hapd->nan_de, src, freq, buf, len);
+ nan_de_rx_sdf(hapd->nan_de, src, a3, freq, buf, len);
}
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
const struct wpabuf *ssi,
const struct wpabuf *elems,
- const u8 *peer_addr, u8 req_instance_id)
+ const u8 *peer_addr, const u8 *a3,
+ u8 req_instance_id)
{
if (!hapd->nan_de)
return -1;
- return nan_de_transmit(hapd->nan_de, handle, ssi, elems, peer_addr,
+ return nan_de_transmit(hapd->nan_de, handle, ssi, elems, peer_addr, a3,
req_instance_id);
}
int hostapd_nan_usd_init(struct hostapd_data *hapd);
void hostapd_nan_usd_deinit(struct hostapd_data *hapd);
void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
+ const u8 *a3,
unsigned int freq, const u8 *buf, size_t len);
void hostapd_nan_usd_flush(struct hostapd_data *hapd);
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
const struct wpabuf *ssi,
const struct wpabuf *elems,
- const u8 *peer_addr, u8 req_instance_id);
+ const u8 *peer_addr, const u8 *a3,
+ u8 req_instance_id);
void hostapd_nan_usd_remain_on_channel_cb(struct hostapd_data *hapd,
unsigned int freq,
unsigned int duration);
static const u8 nan_network_id[ETH_ALEN] =
{ 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 };
-static const u8 wildcard_bssid[ETH_ALEN] =
-{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
enum nan_de_service_type {
NAN_DE_PUBLISH,
static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
unsigned int wait_time,
enum nan_service_control_type type,
- const u8 *dst, u8 req_instance_id,
+ const u8 *dst, const u8 *a3, u8 req_instance_id,
const struct wpabuf *ssi)
{
struct wpabuf *buf;
wpabuf_put_buf(buf, srv->elems);
}
- /* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
- * but there is no synchronization in USD as as such, no NAN Cluster
- * either. Use Wildcard BSSID instead. */
- nan_de_tx(de, srv->freq, wait_time, dst, de->nmi, wildcard_bssid, buf);
+ nan_de_tx(de, srv->freq, wait_time, dst, de->nmi, a3, buf);
wpabuf_free(buf);
}
return;
}
- nan_de_tx_sdf(de, srv, wait_time, type, nan_network_id,
+ nan_de_tx_sdf(de, srv, wait_time, type, nan_network_id, nan_network_id,
req_instance_id, srv->ssi);
os_get_reltime(&srv->last_multicast);
}
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
- const u8 *peer_addr, u8 instance_id,
+ const u8 *peer_addr, const u8 *a3, u8 instance_id,
u8 req_instance_id, u16 sdea_control,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len)
/* Passive subscriber replies with a Follow-up message without
* Service Specific Info field if it received a matching
* unsolicited Publish message. */
- nan_de_transmit(de, srv->id, NULL, NULL, peer_addr,
+ nan_de_transmit(de, srv->id, NULL, NULL, peer_addr, a3,
instance_id);
}
static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
- const u8 *peer_addr, u8 instance_id,
+ const u8 *peer_addr, const u8 *a3,
+ u8 instance_id,
const u8 *matching_filter,
size_t matching_filter_len,
enum nan_service_protocol_type srv_proto_type,
wpabuf_put_buf(buf, srv->elems);
}
- /* Wi-Fi Aware specification v4.0 uses NAN Cluster ID as A3 for USD,
- * but there is no synchronization in USD as as such, no NAN Cluster
- * either. Use Wildcard BSSID instead. */
+ if (srv->publish.solicited_multicast || !a3)
+ a3 = nan_network_id;
+
nan_de_tx(de, srv->freq, 100,
srv->publish.solicited_multicast ? nan_network_id : peer_addr,
- de->nmi, wildcard_bssid, buf);
+ de->nmi, a3, buf);
wpabuf_free(buf);
nan_de_pause_state(srv, peer_addr, instance_id);
static void nan_de_rx_follow_up(struct nan_de *de, struct nan_de_service *srv,
- const u8 *peer_addr, u8 instance_id,
- const u8 *ssi, size_t ssi_len)
+ const u8 *peer_addr, const u8 *a3,
+ u8 instance_id, const u8 *ssi, size_t ssi_len)
{
/* Follow-up function processing of a receive Follow-up message for a
* Subscribe or Publish instance */
if (de->cb.receive)
de->cb.receive(de->cb.ctx, srv->id, instance_id, ssi, ssi_len,
- peer_addr);
+ peer_addr, a3);
}
-static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
+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)
{
switch (type) {
case NAN_SRV_CTRL_PUBLISH:
- nan_de_rx_publish(de, srv, peer_addr, instance_id,
+ nan_de_rx_publish(de, srv, peer_addr, a3, instance_id,
req_instance_id,
sdea_control, srv_proto_type,
ssi, ssi_len);
break;
case NAN_SRV_CTRL_SUBSCRIBE:
- nan_de_rx_subscribe(de, srv, peer_addr, instance_id,
+ nan_de_rx_subscribe(de, srv, peer_addr, a3, instance_id,
matching_filter,
matching_filter_len,
srv_proto_type,
ssi, ssi_len);
break;
case NAN_SRV_CTRL_FOLLOW_UP:
- nan_de_rx_follow_up(de, srv, peer_addr, instance_id,
+ nan_de_rx_follow_up(de, srv, peer_addr, a3, instance_id,
ssi, ssi_len);
break;
}
}
-void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
- const u8 *buf, size_t len)
+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)
{
const u8 *sda;
u16 sda_len;
sda++;
sda_len = WPA_GET_LE16(sda);
sda += 2;
- nan_de_rx_sda(de, peer_addr, freq, buf, len, sda, sda_len);
+ nan_de_rx_sda(de, peer_addr, a3, freq, buf, len, sda, sda_len);
}
}
int nan_de_transmit(struct nan_de *de, int handle,
const struct wpabuf *ssi, const struct wpabuf *elems,
- const u8 *peer_addr, u8 req_instance_id)
+ const u8 *peer_addr, const u8 *a3, u8 req_instance_id)
{
struct nan_de_service *srv;
if (!srv)
return -1;
+ if (!a3)
+ a3 = nan_network_id;
nan_de_tx_sdf(de, srv, 100, NAN_SRV_CTRL_FOLLOW_UP,
- peer_addr, req_instance_id, ssi);
+ peer_addr, a3, req_instance_id, ssi);
os_get_reltime(&srv->last_followup);
return 0;
void (*receive)(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
- const u8 *peer_addr);
+ const u8 *peer_addr, const u8 *a3);
void (*process_p2p_usd_elems)(void *ctx, const u8 *buf,
u16 buf_len, const u8 *peer_addr,
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, unsigned int freq,
- const u8 *buf, size_t len);
+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);
const u8 * nan_de_get_service_id(struct nan_de *de, int id);
struct nan_publish_params {
* req_instance_id = peer publish_id or subscribe_id */
int nan_de_transmit(struct nan_de *de, int handle,
const struct wpabuf *ssi, const struct wpabuf *elems,
- const u8 *peer_addr, u8 req_instance_id);
+ const u8 *peer_addr, const u8 *a3, u8 req_instance_id);
#endif /* NAN_DE_H */
int handle = 0;
int req_instance_id = 0;
struct wpabuf *ssi = NULL;
- u8 peer_addr[ETH_ALEN];
+ u8 peer_addr[ETH_ALEN], a3[ETH_ALEN];
int ret = -1;
+ bool a3_set = false;
os_memset(peer_addr, 0, ETH_ALEN);
+ os_memset(a3, 0, ETH_ALEN);
while ((token = str_token(cmd, " ", &context))) {
if (sscanf(token, "handle=%i", &handle) == 1)
continue;
}
+ if (os_strncmp(token, "a3=", 3) == 0) {
+ if (hwaddr_aton(token + 3, a3) < 0)
+ return -1;
+ a3_set = true;
+ continue;
+ }
+
if (os_strncmp(token, "ssi=", 4) == 0) {
if (ssi)
goto fail;
}
ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
- req_instance_id);
+ a3_set ? a3 : NULL, req_instance_id);
fail:
wpabuf_free(ssi);
return ret;
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);
+ wpas_nan_usd_rx_sdf(wpa_s, mgmt->sa, mgmt->bssid, freq,
+ payload, plen);
return;
}
#endif /* CONFIG_NAN_USD */
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)
+ const u8 *peer_addr, const u8 *a3)
{
struct wpa_supplicant *wpa_s = ctx;
- wpas_notify_nan_receive(wpa_s, id, peer_instance_id, peer_addr,
+ wpas_notify_nan_receive(wpa_s, id, peer_instance_id, peer_addr, a3,
ssi, ssi_len);
}
void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *a3,
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);
+ nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len);
}
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)
+ const u8 *peer_addr, const u8 *a3, u8 req_instance_id)
{
if (!wpa_s->nan_de)
return -1;
- return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
+ return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr, a3,
req_instance_id);
}
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,
+ const u8 *a3,
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,
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);
+ const u8 *peer_addr, const u8 *a3,
+ 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_notify_nan_receive(struct wpa_supplicant *wpa_s, int id,
int peer_instance_id, const u8 *peer_addr,
+ const u8 *a3,
const u8 *ssi, size_t ssi_len)
{
char *ssi_hex;
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);
+ "id=%d peer_instance_id=%d address=" MACSTR " a3=" MACSTR
+ " ssi=%s",
+ id, peer_instance_id, MAC2STR(peer_addr), MAC2STR(a3), ssi_hex);
os_free(ssi_hex);
}
const u8 *ssi, size_t ssi_len);
void wpas_notify_nan_receive(struct wpa_supplicant *wpa_s, int id,
int peer_instance_id, const u8 *peer_addr,
+ const u8 *a3,
const u8 *ssi, size_t ssi_len);
void wpas_notify_nan_publish_terminated(struct wpa_supplicant *wpa_s,
int publish_id,