[PATCH 18/97] NAN: Add support for communicating the IPv6 local address

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Apr 28 13:05:19 PDT 2026


From: Ilan Peer <ilan.peer at intel.com>

When both peers support the NAN Data Path Extension (NDPE)
attribute and IPv6 interface identifier is configured,
communicate the information as part of the NDP setup.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/nan/nan.c     |  7 +++++++
 src/nan/nan.h     |  6 ++++++
 src/nan/nan_i.h   | 13 +++++++++++++
 src/nan/nan_ndp.c | 41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index a91fb8c713..5614a7bd89 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -1508,6 +1508,13 @@ static int nan_ndp_connected(struct nan_data *nan, struct nan_peer *peer)
 	params.ssi = peer->ndp_setup.ssi;
 	params.ssi_len = peer->ndp_setup.ssi_len;
 
+	if (peer->ndp_setup.peer_interface_id_valid) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP connected with peer interface id");
+
+		params.interface_id = peer->ndp_setup.peer_interface_id;
+	}
+
 	if (peer->ndp_setup.ndp->initiator) {
 		params.local_ndi = peer->ndp_setup.ndp->init_ndi;
 		params.peer_ndi = peer->ndp_setup.ndp->resp_ndi;
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 2d9372f014..a999a6582c 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -223,6 +223,9 @@ struct nan_ndp_sec_params {
  * @reason_code: In case of rejected response, the rejection reason.
  * @sched_valid: Indicates whether the schedule field is valid
  * @sched: The NAN schedule associated with the NDP parameters
+ * @interface_id: The interface identifier to be used for the NDP. The interface
+ *    identifier is used to derive the IPv6 link-local address as specified in
+ *    Table 90 in WiFi Aware specification v4.0
  */
 struct nan_ndp_params {
 	enum nan_ndp_action type;
@@ -253,6 +256,7 @@ struct nan_ndp_params {
 
 	bool sched_valid;
 	struct nan_schedule sched;
+	u8 *interface_id;
 };
 
 /**
@@ -289,6 +293,7 @@ struct nan_channels {
  * @first_ndp: Whether this is the first NDP with the peer
  * @new_ndi_sta: Whether a new NDI station needs to be added (peer_ndi not
  * 	already used by another NDP with this peer)
+ * @interface_id: The interface identifier to be used by the peer for the NDP
  */
 struct nan_ndp_connection_params {
 	struct nan_ndp_id ndp_id;
@@ -299,6 +304,7 @@ struct nan_ndp_connection_params {
 	bool install_keys;
 	bool first_ndp;
 	bool new_ndi_sta;
+	const u8 *interface_id;
 };
 
 /**
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index 3bd01debc0..d01f720be6 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -163,6 +163,14 @@ struct nan_ndp {
  * @ssi_len: Service specific information length
  * @service_id: Service ID of the service used for NDP setup
  * @sec: NDP security data
+ * @local_interface_id_valid: Indicates whether the &local_interface_id
+ *      field is valid.
+ * @local_interface_id: The local interface identifier to be used for
+ *      the NDP
+ * @peer_interface_id_valid: Indicates whether the &peer_interface_id
+ *      field is valid.
+ * @peer_interface_id: The peer interface identifier to be used for
+ *      the NDP
  */
 struct nan_ndp_setup {
 	struct nan_ndp *ndp;
@@ -177,6 +185,11 @@ struct nan_ndp_setup {
 
 	u8 service_id[NAN_SERVICE_ID_LEN];
 	struct nan_ndp_sec sec;
+
+	bool local_interface_id_valid;
+	u8 local_interface_id[NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN];
+	bool peer_interface_id_valid;
+	u8 peer_interface_id[NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN];
 };
 
 /**
diff --git a/src/nan/nan_ndp.c b/src/nan/nan_ndp.c
index 91e517115a..5a95005d21 100644
--- a/src/nan/nan_ndp.c
+++ b/src/nan/nan_ndp.c
@@ -147,6 +147,17 @@ int nan_ndp_setup_req(struct nan_data *nan, struct nan_peer *peer,
 			peer->ndp_setup.publish_inst_id;
 	}
 
+	if (params->interface_id) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP setup request with local interface id");
+
+		os_memcpy(peer->ndp_setup.local_interface_id,
+			  params->interface_id,
+			  NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
+
+		peer->ndp_setup.local_interface_id_valid = true;
+	}
+
 	nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_START);
 	peer->ndp_setup.status = NAN_NDP_STATUS_CONTINUED;
 	return 0;
@@ -240,6 +251,17 @@ int nan_ndp_setup_resp(struct nan_data *nan, struct nan_peer *peer,
 	if (ret)
 		return ret;
 
+	if (params->interface_id) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP setup response with local interface id");
+
+		os_memcpy(peer->ndp_setup.local_interface_id,
+			  params->interface_id,
+			  NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
+
+		peer->ndp_setup.local_interface_id_valid = true;
+	}
+
 	return 0;
 }
 
@@ -264,6 +286,18 @@ static int nan_ndp_attr_handle_tlvs(struct nan_data *nan,
 		}
 
 		switch (tlv_type) {
+		case NAN_NDPE_TLV_IPV6_LINK_LOCAL:
+			if (tlv_len != NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN) {
+				wpa_printf(MSG_DEBUG,
+					   "NAN: NDP: req: Invalid interface ID tlv len=%u",
+					   tlv_len);
+				break;
+			}
+
+			peer->ndp_setup.peer_interface_id_valid = true;
+			os_memcpy(peer->ndp_setup.peer_interface_id, tlv_data,
+				  NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
+			break;
 		case NAN_NDPE_TLV_SRV_INFO:
 			wpa_printf(MSG_DEBUG,
 				   "NAN: NDP: Handle NDP service specific information");
@@ -950,6 +984,13 @@ int nan_ndp_add_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
 		}
 	}
 
+	if (ndpe_supported && ndp_setup->local_interface_id_valid) {
+		wpabuf_put_u8(buf, NAN_NDPE_TLV_IPV6_LINK_LOCAL);
+		wpabuf_put_le16(buf, NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
+		wpabuf_put_data(buf, ndp_setup->local_interface_id,
+				NAN_NDPE_TLV_IPV6_LINK_LOCAL_LEN);
+	}
+
 	WPA_PUT_LE16(len_ptr, (u8 *) wpabuf_put(buf, 0) - len_ptr - 2);
 	return 0;
 }
-- 
2.53.0




More information about the Hostap mailing list