diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 2f581be0b..d5a906691 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3976,10 +3976,12 @@ static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd) 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) @@ -3994,6 +3996,13 @@ static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd) 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; @@ -4022,7 +4031,7 @@ static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd) } 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; diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 4862c4f4f..ab76a5fc6 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1788,8 +1788,8 @@ static void hostapd_action_rx(struct hostapd_data *hapd, 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 */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 281d18dc6..10b59348f 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -6149,8 +6149,8 @@ static int handle_action(struct hostapd_data *hapd, 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 */ diff --git a/src/ap/nan_usd_ap.c b/src/ap/nan_usd_ap.c index 570abfce0..c908d6da8 100644 --- a/src/ap/nan_usd_ap.c +++ b/src/ap/nan_usd_ap.c @@ -29,8 +29,10 @@ static int hostapd_nan_de_tx(void *ctx, unsigned int freq, 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)); } @@ -127,7 +129,7 @@ static void hostapd_nan_de_subscribe_terminated(void *ctx, int subscribe_id, 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; @@ -138,8 +140,9 @@ static void hostapd_nan_de_receive(void *ctx, int id, int peer_instance_id, 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); } @@ -173,11 +176,12 @@ void hostapd_nan_usd_deinit(struct hostapd_data *hapd) 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); } @@ -258,10 +262,11 @@ void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd, 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); } diff --git a/src/ap/nan_usd_ap.h b/src/ap/nan_usd_ap.h index 0571643c6..59a164aa5 100644 --- a/src/ap/nan_usd_ap.h +++ b/src/ap/nan_usd_ap.h @@ -16,6 +16,7 @@ enum nan_service_protocol_type; 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, @@ -35,7 +36,8 @@ void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd, 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); diff --git a/src/common/nan_de.c b/src/common/nan_de.c index 6051cb858..7f2a79680 100644 --- a/src/common/nan_de.c +++ b/src/common/nan_de.c @@ -18,8 +18,6 @@ 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, @@ -212,7 +210,7 @@ static int nan_de_tx(struct nan_de *de, unsigned int freq, 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; @@ -274,10 +272,7 @@ static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv, 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); } @@ -358,7 +353,7 @@ static void nan_de_tx_multicast(struct nan_de *de, struct nan_de_service *srv, 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); } @@ -812,7 +807,7 @@ static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf, 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) @@ -834,7 +829,7 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv, /* 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); } @@ -883,7 +878,8 @@ static bool nan_de_filter_match(struct nan_de_service *srv, 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, @@ -969,12 +965,12 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv, 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); @@ -987,8 +983,8 @@ offload: 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 */ @@ -1010,11 +1006,11 @@ static void nan_de_rx_follow_up(struct nan_de *de, struct nan_de_service *srv, 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) { @@ -1141,20 +1137,20 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, 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; } @@ -1162,8 +1158,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, } -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; @@ -1185,7 +1181,7 @@ void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq, 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); } } @@ -1445,7 +1441,7 @@ void nan_de_cancel_subscribe(struct nan_de *de, int 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) { struct nan_de_service *srv; @@ -1456,8 +1452,10 @@ int nan_de_transmit(struct nan_de *de, int handle, 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; diff --git a/src/common/nan_de.h b/src/common/nan_de.h index 8e5282f98..5d803ef59 100644 --- a/src/common/nan_de.h +++ b/src/common/nan_de.h @@ -52,7 +52,7 @@ struct nan_callbacks { 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, @@ -71,8 +71,8 @@ void nan_de_listen_ended(struct nan_de *de, unsigned int freq); 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 { @@ -149,6 +149,6 @@ void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id); * 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 */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6dba46898..4b49b72cd 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -12514,10 +12514,12 @@ static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd) 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) @@ -12532,6 +12534,13 @@ static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd) 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; @@ -12560,7 +12569,7 @@ static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd) } 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; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 9e767e010..90e1c7b9f 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -5540,7 +5540,8 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, 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 */ diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c index 1125f950f..7faa2e508 100644 --- a/wpa_supplicant/nan_usd.c +++ b/wpa_supplicant/nan_usd.c @@ -282,11 +282,11 @@ static void wpas_nan_de_subscribe_terminated(void *ctx, int subscribe_id, 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); } @@ -336,11 +336,12 @@ 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) { 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); } @@ -466,11 +467,11 @@ void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s, 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); } diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h index ecb4973c4..7ff7eaa50 100644 --- a/wpa_supplicant/nan_usd.h +++ b/wpa_supplicant/nan_usd.h @@ -16,6 +16,7 @@ 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, + 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, @@ -34,7 +35,8 @@ 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); + 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); diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 8c1a817f9..cdde7fd6c 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -1121,6 +1121,7 @@ void wpas_notify_nan_replied(struct wpa_supplicant *wpa_s, 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; @@ -1131,8 +1132,9 @@ void wpas_notify_nan_receive(struct wpa_supplicant *wpa_s, int id, 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); } diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index 56fe7c58e..728952bfa 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -192,6 +192,7 @@ void wpas_notify_nan_replied(struct wpa_supplicant *wpa_s, 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,