1 /*
2 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "esp_wifi.h"
8 #include "esp_private/wifi.h"
9 #include "esp_wifi_netif.h"
10 #include "freertos/event_groups.h"
11 #include "lwip/netdb.h"
12 #include "lwip/sockets.h"
13 #include "esp_event.h"
14 #include "esp_log.h"
15 #include "esp_check.h"
16 #include "esp_mac.h"
17 #include "os.h"
18 #include "esp_nan.h"
19
20 /* NAN States */
21 #define NAN_STARTED_BIT BIT0
22 #define NAN_STOPPED_BIT BIT1
23
24 /* NAN Events */
25 #define NDP_INDICATION BIT2
26 #define NDP_ACCEPTED BIT3
27 #define NDP_TERMINATED BIT4
28 #define NDP_REJECTED BIT5
29
30 /* Macros */
31 #define MACADDR_LEN 6
32 #define MACADDR_EQUAL(a1, a2) (memcmp(a1, a2, MACADDR_LEN))
33 #define MACADDR_COPY(dst, src) (memcpy(dst, src, MACADDR_LEN))
34 #define NAN_DW_INTVL_MS 524 /* NAN DW interval (512 TU's ~= 524 mSec) */
35 #define NAN_NDP_RESP_TIMEOUT_DW 4
36 #define NAN_NDP_RESP_TIMEOUT NAN_NDP_RESP_TIMEOUT_DW*NAN_DW_INTVL_MS
37
38 /* Global Variables */
39 static const char *TAG = "nan_app";
40 static EventGroupHandle_t nan_event_group;
41 static bool s_app_default_handlers_set = false;
42 static uint8_t null_mac[MACADDR_LEN] = {0};
43
44 struct peer_svc_info {
45 SLIST_ENTRY(peer_svc_info) next;
46 uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< Information for followup message */
47 uint8_t svc_id; /**< Identifier of peer's service */
48 uint8_t own_svc_id; /**< Identifier for own service */
49 uint8_t type; /**< Service type (Publish/Subscribe) */
50 uint8_t peer_nmi[MACADDR_LEN]; /**< Peer's NAN Management Interface address */
51 };
52
53 struct own_svc_info {
54 char svc_name[ESP_WIFI_MAX_SVC_NAME_LEN]; /**< Name identifying a service */
55 uint8_t svc_id; /**< Identifier for a service */
56 uint8_t type; /**< Service type (Publish/Subscribe) */
57 bool ndp_resp_needed; /**< If enabled, NDP response is required */
58 uint8_t num_peer_records; /**< Count of peer records associated with svc_id */
59 SLIST_HEAD(peer_list_t, peer_svc_info) peer_list; /**< List of peers matched for specific service */
60 };
61
62 struct ndl_info {
63 uint8_t ndp_id; /**< Identifier for instance of NDP */
64 uint8_t peer_ndi[MACADDR_LEN]; /**< Peer's NAN Data Interface address */
65 uint8_t peer_nmi[MACADDR_LEN]; /**< Peer's NAN Management Interface address */
66 uint8_t publisher_id; /**< Publisher's service identifier */
67 uint8_t own_role; /**< Own role (Publisher/Subscriber) */
68 };
69
70 typedef struct {
71 uint8_t state;
72 uint8_t event;
73 struct ndl_info ndl[ESP_WIFI_NAN_DATAPATH_MAX_PEERS]; /**< Record of NDL of all peers */
74 struct own_svc_info own_svc[ESP_WIFI_NAN_MAX_SVC_SUPPORTED]; /**< Record of own service(s) */
75 esp_netif_t *nan_netif;
76 } nan_ctx_t;
77
78 static nan_ctx_t s_nan_ctx;
79
esp_wifi_nan_get_ipv6_linklocal_from_mac(ip6_addr_t * ip6,uint8_t * mac_addr)80 void esp_wifi_nan_get_ipv6_linklocal_from_mac(ip6_addr_t *ip6, uint8_t *mac_addr)
81 {
82 if (ip6 == NULL || mac_addr == NULL)
83 return;
84 /* Link-local prefix. */
85 ip6->addr[0] = htonl(0xfe800000ul);
86 ip6->addr[1] = 0;
87
88 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
89 ip6->addr[2] = htonl((((uint32_t)(mac_addr[0] ^ 0x02)) << 24) |
90 ((uint32_t)(mac_addr[1]) << 16) |
91 ((uint32_t)(mac_addr[2]) << 8) |
92 (0xff));
93 ip6->addr[3] = htonl((uint32_t)(0xfeul << 24) |
94 ((uint32_t)(mac_addr[3]) << 16) |
95 ((uint32_t)(mac_addr[4]) << 8) |
96 (mac_addr[5]));
97
98 ip6->zone = IP6_NO_ZONE;
99 }
100
nan_find_own_svc(uint8_t svc_id)101 static struct own_svc_info *nan_find_own_svc(uint8_t svc_id)
102 {
103 struct own_svc_info *p_svc = NULL;
104
105 if (svc_id == 0) {
106 ESP_LOGE(TAG, "Service id cannot be 0!");
107 return NULL;
108 }
109
110 for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
111 if (s_nan_ctx.own_svc[i].svc_id == svc_id) {
112 p_svc = &s_nan_ctx.own_svc[i];
113 break;
114 }
115 }
116
117 return p_svc;
118 }
119
nan_find_own_svc_by_name(const char * svc_name)120 static struct own_svc_info *nan_find_own_svc_by_name(const char *svc_name)
121 {
122 struct own_svc_info *p_svc = NULL;
123
124 if (!svc_name) {
125 ESP_LOGE(TAG, "Service name not given!");
126 return NULL;
127 }
128
129 for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
130 if (s_nan_ctx.own_svc[i].svc_id && !strcmp(s_nan_ctx.own_svc[i].svc_name, svc_name)) {
131 p_svc = &s_nan_ctx.own_svc[i];
132 break;
133 }
134 }
135
136 return p_svc;
137 }
138
nan_find_peer_svc(uint8_t own_svc_id,uint8_t peer_svc_id,uint8_t peer_nmi[])139 static struct peer_svc_info *nan_find_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[])
140 {
141 struct peer_svc_info *p_peer_svc = NULL, *temp;
142 struct own_svc_info *p_own_svc = NULL;
143 uint8_t *peer_nmi_valid = NULL;
144 int idx = 0;
145
146 if (MACADDR_EQUAL(peer_nmi, null_mac)) {
147 /* non-zero Peer NMI given, use it */
148 peer_nmi_valid = peer_nmi;
149 }
150 while (idx < ESP_WIFI_NAN_MAX_SVC_SUPPORTED) {
151 if (own_svc_id) {
152 p_own_svc = nan_find_own_svc(own_svc_id);
153 if (!p_own_svc) {
154 ESP_LOGE(TAG, "Cannot find own service with id %d!", own_svc_id);
155 return NULL;
156 }
157 } else {
158 p_own_svc = &s_nan_ctx.own_svc[idx++];
159 }
160 SLIST_FOREACH(temp, &(p_own_svc->peer_list), next) {
161 if (peer_svc_id != 0 && peer_nmi_valid) {
162 if (temp->svc_id == peer_svc_id && !MACADDR_EQUAL(temp->peer_nmi, peer_nmi_valid)) {
163 p_peer_svc = temp;
164 break;
165 }
166 } else if (peer_svc_id != 0) {
167 if (temp->svc_id == peer_svc_id) {
168 p_peer_svc = temp;
169 break;
170 }
171 } else {
172 if (peer_nmi_valid && !MACADDR_EQUAL(temp->peer_nmi, peer_nmi_valid)) {
173 p_peer_svc = temp;
174 break;
175 }
176 }
177 }
178 if (p_peer_svc || own_svc_id) { /* If no peer found with given own_svc_id, don't search in other services */
179 break;
180 }
181 }
182 return p_peer_svc;
183 }
184
nan_update_peer_svc(uint8_t own_svc_id,uint8_t peer_svc_id,uint8_t peer_nmi[])185 static bool nan_update_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[])
186 {
187 struct peer_svc_info *peer_info = nan_find_peer_svc(own_svc_id, 0, peer_nmi);
188 if (peer_info) {
189 peer_info->svc_id = peer_svc_id;
190 return true;
191 }
192 return false;
193 }
194
nan_record_peer_svc(uint8_t own_svc_id,uint8_t peer_svc_id,uint8_t peer_nmi[])195 static bool nan_record_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[])
196 {
197 struct own_svc_info *p_own_svc;
198 struct peer_svc_info *p_peer_svc;
199
200 p_own_svc = nan_find_own_svc(own_svc_id);
201 if (!p_own_svc) {
202 ESP_LOGE(TAG, "Unable to find own service with id %d", own_svc_id);
203 return false;
204 }
205 p_peer_svc = (struct peer_svc_info *)os_zalloc(sizeof(struct peer_svc_info));
206 if (!p_peer_svc) {
207 ESP_LOGE(TAG, "Unable to allocate for Peer Service");
208 return false;
209 }
210 p_peer_svc->svc_id = peer_svc_id;
211 p_peer_svc->own_svc_id = own_svc_id;
212 p_peer_svc->type = (p_own_svc->type == ESP_NAN_SUBSCRIBE) ? ESP_NAN_PUBLISH : ESP_NAN_SUBSCRIBE;
213 MACADDR_COPY(p_peer_svc->peer_nmi, peer_nmi);
214
215 if (p_own_svc->num_peer_records < NAN_MAX_PEERS_RECORD) {
216 SLIST_INSERT_HEAD(&(p_own_svc->peer_list), p_peer_svc, next);
217 p_own_svc->num_peer_records++;
218 } else {
219 struct peer_svc_info *temp;
220 temp = SLIST_FIRST(&(p_own_svc->peer_list));
221 SLIST_REMOVE_HEAD(&(p_own_svc->peer_list), next);
222 os_free(temp);
223 }
224
225 return true;
226 }
227
nan_reset_service(uint8_t svc_id,bool reset_all)228 static void nan_reset_service(uint8_t svc_id, bool reset_all)
229 {
230 struct own_svc_info *p_own_svc = NULL;
231 struct peer_svc_info *p_peer_svc = NULL, *temp;
232 int idx = 0;
233
234 if (svc_id == 0 && !reset_all) {
235 return;
236 }
237
238 while (idx < ESP_WIFI_NAN_MAX_SVC_SUPPORTED) {
239 p_own_svc = &s_nan_ctx.own_svc[idx++];
240 if (reset_all || (svc_id && p_own_svc->svc_id == svc_id)) {
241 SLIST_FOREACH_SAFE(p_peer_svc, &(p_own_svc->peer_list), next, temp) {
242 SLIST_REMOVE(&(p_own_svc->peer_list), p_peer_svc, peer_svc_info, next);
243 os_free(p_peer_svc);
244 }
245 memset(p_own_svc, 0, sizeof(struct own_svc_info));
246 }
247 }
248 }
249
nan_reset_ndl(uint8_t ndp_id,bool reset_all)250 static void nan_reset_ndl(uint8_t ndp_id, bool reset_all)
251 {
252 struct ndl_info *ndl = NULL;
253
254 if (reset_all) {
255 memset(s_nan_ctx.ndl, 0, sizeof(struct ndl_info) * ESP_WIFI_NAN_DATAPATH_MAX_PEERS);
256 return;
257 }
258 for (int i = 0; i < ESP_WIFI_NAN_DATAPATH_MAX_PEERS; i++) {
259 ndl = &s_nan_ctx.ndl[i];
260 if (ndl->ndp_id == ndp_id) {
261 memset(ndl, 0, sizeof(struct ndl_info));
262 break;
263 }
264 }
265 }
266
nan_services_limit_reached(void)267 static bool nan_services_limit_reached(void)
268 {
269 for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
270 if (s_nan_ctx.own_svc[i].svc_id == 0) {
271 return false;
272 }
273 }
274 return true;
275 }
276
nan_record_own_svc(uint8_t id,uint8_t type,const char svc_name[],bool ndp_resp_needed)277 static void nan_record_own_svc(uint8_t id, uint8_t type, const char svc_name[], bool ndp_resp_needed)
278 {
279 struct own_svc_info *p_svc = NULL;
280
281 for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
282 if (s_nan_ctx.own_svc[i].svc_id == 0) {
283 p_svc = &s_nan_ctx.own_svc[i];
284 break;
285 }
286 }
287
288 if (!p_svc) {
289 return;
290 }
291
292 p_svc->svc_id = id;
293 p_svc->type = type;
294 strlcpy(p_svc->svc_name, svc_name, ESP_WIFI_MAX_SVC_NAME_LEN);
295 SLIST_INIT(&(p_svc->peer_list));
296 if (type == ESP_NAN_PUBLISH) {
297 p_svc->ndp_resp_needed = ndp_resp_needed;
298 }
299 }
300
ndl_limit_reached(void)301 static bool ndl_limit_reached(void)
302 {
303 for (int i = 0; i < ESP_WIFI_NAN_DATAPATH_MAX_PEERS; i++) {
304 if (s_nan_ctx.ndl[i].ndp_id == 0) {
305 return false;
306 }
307 }
308 return true;
309 }
310
nan_record_new_ndl(uint8_t ndp_id,uint8_t publish_id,uint8_t peer_nmi[],uint8_t own_role)311 static void nan_record_new_ndl(uint8_t ndp_id, uint8_t publish_id, uint8_t peer_nmi[], uint8_t own_role)
312 {
313 struct ndl_info *ndl = NULL;
314
315 for (int i = 0; i < ESP_WIFI_NAN_DATAPATH_MAX_PEERS; i++) {
316 if (s_nan_ctx.ndl[i].ndp_id == 0) {
317 ndl = &s_nan_ctx.ndl[i];
318 break;
319 }
320 }
321 if (!ndl) {
322 return;
323 }
324 ndl->ndp_id = ndp_id;
325 if (peer_nmi) {
326 MACADDR_COPY(ndl->peer_nmi, peer_nmi);
327 }
328 ndl->publisher_id = publish_id;
329 ndl->own_role = own_role;
330 }
331
nan_find_ndl(uint8_t ndp_id,uint8_t peer_nmi[])332 static struct ndl_info *nan_find_ndl(uint8_t ndp_id, uint8_t peer_nmi[])
333 {
334 struct ndl_info *ndl = NULL;
335
336 for (int i = 0; i < ESP_WIFI_NAN_DATAPATH_MAX_PEERS; i++) {
337 ndl = &s_nan_ctx.ndl[i];
338 if (ndp_id != 0 && peer_nmi) {
339 if (ndl->ndp_id == ndp_id && !MACADDR_EQUAL(ndl->peer_nmi, peer_nmi)) {
340 return ndl;
341 }
342 } else if (ndp_id != 0) {
343 if (ndl->ndp_id == ndp_id) {
344 return ndl;
345 }
346 } else if (peer_nmi) {
347 if (!MACADDR_EQUAL(ndl->peer_nmi, peer_nmi)) {
348 return ndl;
349 }
350 }
351 }
352 return NULL;
353 }
354
nan_is_datapath_active(void)355 static bool nan_is_datapath_active(void)
356 {
357 for (int i = 0; i < ESP_WIFI_NAN_DATAPATH_MAX_PEERS; i++) {
358 if (s_nan_ctx.ndl[i].ndp_id != 0) {
359 return true;
360 }
361 }
362 return false;
363 }
364
nan_fill_params_from_event(void * evt_data,uint8_t event)365 static void nan_fill_params_from_event(void *evt_data, uint8_t event)
366 {
367 switch (event) {
368 case WIFI_EVENT_NDP_INDICATION: {
369 wifi_event_ndp_indication_t *evt = (wifi_event_ndp_indication_t *)evt_data;
370 nan_record_new_ndl(evt->ndp_id, evt->publish_id, evt->peer_nmi, ESP_WIFI_NDP_ROLE_RESPONDER);
371 break;
372 }
373 case WIFI_EVENT_NDP_CONFIRM: {
374 wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)evt_data;
375 struct ndl_info *ndl = NULL;
376
377 if ((ndl = nan_find_ndl(evt->ndp_id, evt->peer_nmi)) == NULL) {
378 ESP_LOGE(TAG, "No NDL with ndp id %d", evt->ndp_id);
379 return;
380 }
381 MACADDR_COPY(ndl->peer_ndi, evt->peer_ndi);
382 break;
383 }
384 case WIFI_EVENT_NAN_REPLIED: {
385 wifi_event_nan_replied_t *evt = (wifi_event_nan_replied_t *)evt_data;
386
387 if (!nan_find_peer_svc(evt->publish_id, evt->subscribe_id, evt->sub_if_mac)) {
388 nan_record_peer_svc(evt->publish_id, evt->subscribe_id, evt->sub_if_mac);
389 }
390 break;
391 }
392 case WIFI_EVENT_NAN_RECEIVE: {
393 wifi_event_nan_receive_t *evt = (wifi_event_nan_receive_t *)evt_data;
394
395 if (!nan_find_peer_svc(evt->inst_id, evt->peer_inst_id, evt->peer_if_mac)) {
396 nan_record_peer_svc(evt->inst_id, evt->peer_inst_id, evt->peer_if_mac);
397 }
398 break;
399 }
400 case WIFI_EVENT_NAN_SVC_MATCH: {
401 wifi_event_nan_svc_match_t *evt = (wifi_event_nan_svc_match_t *)evt_data;
402
403 if (evt->update_pub_id) {
404 if (nan_update_peer_svc(evt->subscribe_id, evt->publish_id, evt->pub_if_mac)) {
405 break;
406 }
407 }
408 if (!nan_find_peer_svc(evt->subscribe_id, evt->publish_id, evt->pub_if_mac)) {
409 nan_record_peer_svc(evt->subscribe_id, evt->publish_id, evt->pub_if_mac);
410 }
411 break;
412 }
413 default:
414 break;
415 }
416 }
417
nan_app_action_service_match(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)418 static void nan_app_action_service_match(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
419 {
420 if (data == NULL) {
421 return;
422 }
423 wifi_event_nan_svc_match_t *evt = (wifi_event_nan_svc_match_t *)data;
424
425 ESP_LOGI(TAG, "Service matched with "MACSTR" [Peer Publish id - %d]",
426 MAC2STR(evt->pub_if_mac), evt->publish_id);
427 nan_fill_params_from_event(evt, WIFI_EVENT_NAN_SVC_MATCH);
428 }
429
nan_app_action_replied(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)430 static void nan_app_action_replied(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
431 {
432 if (data == NULL) {
433 return;
434 }
435 wifi_event_nan_replied_t *evt = (wifi_event_nan_replied_t *)data;
436
437 ESP_LOGD(TAG, "Sent Publish to Peer "MACSTR" [Peer Subscribe id - %d]",
438 MAC2STR(evt->sub_if_mac), evt->subscribe_id);
439 nan_fill_params_from_event(evt, WIFI_EVENT_NAN_REPLIED);
440 }
441
nan_app_action_receive(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)442 static void nan_app_action_receive(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
443 {
444 if (data == NULL) {
445 return;
446 }
447 wifi_event_nan_receive_t *evt = (wifi_event_nan_receive_t *)data;
448
449 ESP_LOGI(TAG, "Received message '%s' from Peer "MACSTR" [Peer Service id - %d]",
450 evt->peer_svc_info, MAC2STR(evt->peer_if_mac), evt->peer_inst_id);
451 nan_fill_params_from_event(evt, WIFI_EVENT_NAN_RECEIVE);
452 }
453
nan_app_action_ndp_indication(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)454 static void nan_app_action_ndp_indication(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
455 {
456 if (data == NULL) {
457 return;
458 }
459 wifi_event_ndp_indication_t *evt = (wifi_event_ndp_indication_t *)data;
460 struct own_svc_info *p_own_svc = nan_find_own_svc(evt->publish_id);
461
462 if (!p_own_svc) {
463 ESP_LOGE(TAG, "No Publish found with id %d", evt->publish_id);
464 return;
465 }
466 if (ndl_limit_reached()) {
467 ESP_LOGE(TAG, "NDP limit reached");
468 return;
469 }
470
471 nan_fill_params_from_event(evt, WIFI_EVENT_NDP_INDICATION);
472 if (p_own_svc->ndp_resp_needed) {
473 ESP_LOGI(TAG, "NDP Req from "MACSTR" [NDP Id: %d], Accept OR Deny using NDP command",
474 MAC2STR(evt->peer_nmi), evt->ndp_id);
475 s_nan_ctx.event |= NDP_INDICATION;
476 } else {
477 wifi_nan_datapath_resp_t ndp_resp = {0};
478 ndp_resp.accept = true;
479 ndp_resp.ndp_id = evt->ndp_id;
480 MACADDR_COPY(ndp_resp.peer_mac, evt->peer_nmi);
481
482 esp_nan_internal_datapath_resp(&ndp_resp);
483 }
484 }
485
nan_app_action_ndp_confirm(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)486 static void nan_app_action_ndp_confirm(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
487 {
488 if (data == NULL) {
489 return;
490 }
491 wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)data;
492 wifi_netif_driver_t driver = esp_netif_get_io_driver(s_nan_ctx.nan_netif);
493 ip_addr_t target_addr = {0};
494
495 if (!s_nan_ctx.nan_netif) {
496 ESP_LOGE(TAG, "%s: NAN netif is NULL", __func__);
497 return;
498 }
499
500 if (nan_find_ndl(evt->ndp_id, NULL) == NULL) {
501 /* As ndl isn't found, timeout has occured for NDP response and datapath request is rejected */
502 return;
503 }
504 if (evt->status == NDP_STATUS_REJECTED) {
505 ESP_LOGE(TAG, "NDP request to Peer "MACSTR" rejected [NDP ID - %d]", MAC2STR(evt->peer_nmi), evt->ndp_id);
506 nan_reset_ndl(evt->ndp_id, false);
507 os_event_group_set_bits(nan_event_group, NDP_REJECTED);
508 return;
509 }
510
511 /* If interface not ready when started, rxcb to be registered on connection */
512 if (esp_wifi_register_if_rxcb(driver, esp_netif_receive, s_nan_ctx.nan_netif) != ESP_OK) {
513 ESP_LOGE(TAG, "%s: esp_wifi_register_if_rxcb failed", __func__);
514 return;
515 }
516
517 nan_fill_params_from_event(evt, WIFI_EVENT_NDP_CONFIRM);
518
519 esp_netif_action_connected(s_nan_ctx.nan_netif, event_base, event_id, data);
520
521 esp_netif_create_ip6_linklocal(s_nan_ctx.nan_netif);
522 esp_wifi_nan_get_ipv6_linklocal_from_mac(&target_addr.u_addr.ip6, evt->peer_ndi);
523 target_addr.type = IPADDR_TYPE_V6;
524 ESP_LOGI(TAG, "NDP confirmed with Peer "MACSTR" [NDP ID - %d, Peer IPv6 - %s]",
525 MAC2STR(evt->peer_nmi), evt->ndp_id, inet6_ntoa(*ip_2_ip6(&target_addr)));
526 os_event_group_set_bits(nan_event_group, NDP_ACCEPTED);
527 }
528
nan_app_action_ndp_terminated(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)529 static void nan_app_action_ndp_terminated(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
530 {
531 if (data == NULL) {
532 return;
533 }
534 wifi_event_ndp_terminated_t *evt = (wifi_event_ndp_terminated_t *)data;
535
536 if (s_nan_ctx.nan_netif && !nan_is_datapath_active()) {
537 esp_netif_action_disconnected(s_nan_ctx.nan_netif, event_base, event_id, data);
538 }
539 ESP_LOGI(TAG, "NDP terminated with Peer "MACSTR" [NDP ID - %d]", MAC2STR(evt->init_ndi), evt->ndp_id);
540 nan_reset_ndl(evt->ndp_id, false);
541
542 s_nan_ctx.event &= ~(NDP_INDICATION);
543 os_event_group_set_bits(nan_event_group, NDP_TERMINATED);
544 }
545
546 /* types of ipv6 addresses to be displayed on ipv6 events */
547 static const char *s_ipv6_addr_types[] = {
548 "UNKNOWN",
549 "GLOBAL",
550 "LINK_LOCAL",
551 "SITE_LOCAL",
552 "UNIQUE_LOCAL",
553 "IPV4_MAPPED_IPV6"
554 };
555
nan_app_action_got_ipv6(void * arg,esp_event_base_t event_base,int32_t event_id,void * data)556 static void nan_app_action_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
557 {
558 if (data == NULL) {
559 return;
560 }
561 ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)data;
562
563 if (event->esp_netif == s_nan_ctx.nan_netif) {
564 esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
565 ESP_LOGD(TAG, "NAN Data Interface ready [IPv6 - "IPV6STR", type - %s]",
566 IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]);
567 }
568 }
569
nan_clear_app_default_handlers(void)570 static esp_err_t nan_clear_app_default_handlers(void)
571 {
572 esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_SVC_MATCH, nan_app_action_service_match);
573 esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_REPLIED, nan_app_action_replied);
574 esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_RECEIVE, nan_app_action_receive);
575 esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NDP_INDICATION, nan_app_action_ndp_indication);
576 esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NDP_CONFIRM, nan_app_action_ndp_confirm);
577 esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NDP_TERMINATED, nan_app_action_ndp_terminated);
578 esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, nan_app_action_got_ipv6);
579 s_app_default_handlers_set = false;
580
581 return ESP_OK;
582 }
583
nan_set_app_default_handlers(void)584 static esp_err_t nan_set_app_default_handlers(void)
585 {
586 if (s_app_default_handlers_set) {
587 return ESP_OK;
588 }
589
590 int ret;
591 (void) ret;
592 ESP_GOTO_ON_ERROR(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_SVC_MATCH,
593 nan_app_action_service_match, NULL), fail, TAG, "Registering event handler failed");
594
595 ESP_GOTO_ON_ERROR(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_REPLIED,
596 nan_app_action_replied, NULL), fail, TAG, "Registering event handler failed");
597
598 ESP_GOTO_ON_ERROR(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_RECEIVE,
599 nan_app_action_receive, NULL), fail, TAG, "Registering event handler failed");
600
601 ESP_GOTO_ON_ERROR(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NDP_INDICATION,
602 nan_app_action_ndp_indication, NULL), fail, TAG, "Registering event handler failed");
603
604 ESP_GOTO_ON_ERROR(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NDP_CONFIRM,
605 nan_app_action_ndp_confirm, NULL), fail, TAG, "Registering event handler failed");
606
607 ESP_GOTO_ON_ERROR(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NDP_TERMINATED,
608 nan_app_action_ndp_terminated, NULL), fail, TAG, "Registering event handler failed");
609
610 ESP_GOTO_ON_ERROR(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6,
611 nan_app_action_got_ipv6, NULL), fail, TAG, "Registering event handler failed");
612
613 s_app_default_handlers_set = true;
614 return ESP_OK;
615
616 fail:
617 nan_clear_app_default_handlers();
618 return ESP_FAIL;
619 }
620
esp_nan_app_init(void)621 void esp_nan_app_init(void)
622 {
623 if (nan_event_group) {
624 os_event_group_delete(nan_event_group);
625 nan_event_group = NULL;
626 }
627 nan_event_group = os_event_group_create();
628 }
629
esp_nan_app_deinit(void)630 void esp_nan_app_deinit(void)
631 {
632 if (nan_event_group) {
633 os_event_group_delete(nan_event_group);
634 nan_event_group = NULL;
635 }
636 }
637
esp_nan_action_start(esp_netif_t * nan_netif)638 void esp_nan_action_start(esp_netif_t *nan_netif)
639 {
640 if (nan_set_app_default_handlers() != ESP_OK) {
641 ESP_LOGE(TAG, "Registering NAN handlers failed");
642 return;
643 }
644
645 s_nan_ctx.nan_netif = nan_netif;
646
647 s_nan_ctx.state = NAN_STARTED_BIT;
648 ESP_LOGI(TAG, "NAN Discovery started.");
649 os_event_group_set_bits(nan_event_group, NAN_STARTED_BIT);
650 }
651
esp_nan_action_stop(void)652 void esp_nan_action_stop(void)
653 {
654 nan_clear_app_default_handlers();
655
656 if (nan_is_datapath_active()) {
657 nan_reset_ndl(0, true);
658 esp_wifi_internal_reg_rxcb(WIFI_IF_NAN, NULL);
659 }
660
661 nan_reset_service(0, true);
662 s_nan_ctx.state &= ~NAN_STARTED_BIT;
663 s_nan_ctx.state |= NAN_STOPPED_BIT;
664 os_event_group_set_bits(nan_event_group, NAN_STOPPED_BIT);
665 }
666
esp_wifi_nan_start(const wifi_nan_config_t * nan_cfg)667 esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
668 {
669 wifi_mode_t mode;
670 esp_err_t ret;
671 wifi_config_t config = {0};
672
673 ret = esp_wifi_get_mode(&mode);
674 if (ret == ESP_ERR_WIFI_NOT_INIT) {
675 ESP_LOGE(TAG, "WiFi not initialised!");
676 return ret;
677 } else if (ret != ESP_OK) {
678 ESP_LOGE(TAG, "Unable to get mode");
679 return ret;
680 }
681 if (s_nan_ctx.state & NAN_STARTED_BIT) {
682 ESP_LOGI(TAG, "NAN already started");
683 return ESP_OK;
684 }
685
686 ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_NAN), TAG, "Set mode NAN failed");
687
688 memcpy(&config.nan, nan_cfg, sizeof(wifi_nan_config_t));
689 ESP_RETURN_ON_ERROR(esp_wifi_set_config(WIFI_IF_NAN, &config), TAG, "Setting NAN config failed");
690
691 if (esp_wifi_start() != ESP_OK) {
692 ESP_LOGE(TAG, "Starting wifi failed");
693 s_nan_ctx.nan_netif = NULL;
694 return ESP_FAIL;
695 }
696
697 EventBits_t bits = os_event_group_wait_bits(nan_event_group, NAN_STARTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
698 if (!(bits & NAN_STARTED_BIT)) {
699 s_nan_ctx.nan_netif = NULL;
700 return ESP_FAIL;
701 }
702 return ESP_OK;
703 }
704
esp_wifi_nan_stop(void)705 esp_err_t esp_wifi_nan_stop(void)
706 {
707 if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
708 ESP_LOGE(TAG, "NAN isn't started");
709 return ESP_FAIL;
710 }
711
712 if (nan_is_datapath_active()) {
713 /* Terminate all NDP's */
714 wifi_nan_datapath_end_req_t ndp_end = {0};
715 for (int i=0; i < ESP_WIFI_NAN_DATAPATH_MAX_PEERS; i++) {
716 if (s_nan_ctx.ndl[i].ndp_id) {
717 MACADDR_COPY(ndp_end.peer_mac, s_nan_ctx.ndl[i].peer_nmi);
718 ndp_end.ndp_id = s_nan_ctx.ndl[i].ndp_id;
719 esp_nan_internal_datapath_end(&ndp_end);
720 }
721 }
722 nan_reset_ndl(0, true);
723
724 os_event_group_clear_bits(nan_event_group, NDP_TERMINATED);
725 os_event_group_wait_bits(nan_event_group, NDP_TERMINATED, pdFALSE, pdFALSE, portMAX_DELAY);
726 os_event_group_clear_bits(nan_event_group, NDP_TERMINATED);
727 /* Wait for 1 NAN DW interval (512 TU's ~= 524 mSec) for successful termination */
728 g_wifi_osi_funcs._task_delay(NAN_DW_INTVL_MS/portTICK_PERIOD_MS);
729 }
730
731 ESP_RETURN_ON_ERROR(esp_wifi_stop(), TAG, "Stopping NAN failed");
732
733 EventBits_t bits = os_event_group_wait_bits(nan_event_group, NAN_STOPPED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
734 if (!(bits & NAN_STOPPED_BIT)) {
735 return ESP_FAIL;
736 }
737
738 memset(&s_nan_ctx, 0, sizeof(nan_ctx_t));
739 return ESP_OK;
740 }
741
esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t * publish_cfg,bool ndp_resp_needed)742 uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg, bool ndp_resp_needed)
743 {
744 uint8_t pub_id;
745
746 if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
747 ESP_LOGE(TAG, "NAN not started!");
748 return 0;
749 }
750 if (nan_services_limit_reached()) {
751 ESP_LOGE(TAG, "Maximum services limit reached");
752 return 0;
753 }
754
755 if (nan_find_own_svc_by_name(publish_cfg->service_name)) {
756 ESP_LOGE(TAG, "Service name already used!");
757 return 0;
758 }
759
760 if (esp_nan_internal_publish_service(publish_cfg, &pub_id, false) != ESP_OK) {
761 ESP_LOGE(TAG, "Failed to publish service '%s'", publish_cfg->service_name);
762 return 0;
763 }
764
765 ESP_LOGI(TAG, "Started Publishing %s [Service ID - %u]", publish_cfg->service_name, pub_id);
766 nan_record_own_svc(pub_id, ESP_NAN_PUBLISH, publish_cfg->service_name, ndp_resp_needed);
767
768 return pub_id;
769 }
770
esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t * subscribe_cfg)771 uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg)
772 {
773 uint8_t sub_id;
774
775 if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
776 ESP_LOGE(TAG, "NAN not started!");
777 return 0;
778 }
779 if (nan_services_limit_reached()) {
780 ESP_LOGE(TAG, "Maximum services limit reached");
781 return 0;
782 }
783
784 if (nan_find_own_svc_by_name(subscribe_cfg->service_name)) {
785 ESP_LOGE(TAG, "Service name already used!");
786 return 0;
787 }
788
789 if (esp_nan_internal_subscribe_service(subscribe_cfg, &sub_id, false) != ESP_OK) {
790 ESP_LOGE(TAG, "Failed to subscribe to service '%s'", subscribe_cfg->service_name);
791 return 0;
792 }
793
794 ESP_LOGI(TAG, "Started Subscribing to %s [Service ID - %u]", subscribe_cfg->service_name, sub_id);
795 nan_record_own_svc(sub_id, ESP_NAN_SUBSCRIBE, subscribe_cfg->service_name, false);
796
797 return sub_id;
798 }
799
esp_wifi_nan_send_message(wifi_nan_followup_params_t * fup_params)800 esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params)
801 {
802 struct peer_svc_info *p_peer_svc;
803
804 p_peer_svc = nan_find_peer_svc(fup_params->inst_id, fup_params->peer_inst_id,
805 fup_params->peer_mac);
806 if (!p_peer_svc) {
807 ESP_LOGE(TAG, "Cannot send Follow-up, peer not found!");
808 return ESP_FAIL;
809 }
810
811 if (!fup_params->inst_id) {
812 fup_params->inst_id = p_peer_svc->own_svc_id;
813 }
814 if (!MACADDR_EQUAL(fup_params->peer_mac, null_mac)) {
815 MACADDR_COPY(fup_params->peer_mac, p_peer_svc->peer_nmi);
816 }
817
818 if (esp_nan_internal_send_followup(fup_params) != ESP_OK) {
819 ESP_LOGE(TAG, "Failed to send Follow-up message!");
820 return ESP_FAIL;
821 }
822 ESP_LOGI(TAG, "Sent message '%s' to Peer "MACSTR" with Service ID %d", fup_params->svc_info,
823 MAC2STR(fup_params->peer_mac), fup_params->peer_inst_id);
824 return ESP_OK;
825 }
826
esp_wifi_nan_cancel_service(uint8_t service_id)827 esp_err_t esp_wifi_nan_cancel_service(uint8_t service_id)
828 {
829 struct own_svc_info *p_own_svc = nan_find_own_svc(service_id);
830
831 if (!p_own_svc) {
832 ESP_LOGE(TAG, "Cannot find own service with id %d!", service_id);
833 return ESP_FAIL;
834 }
835
836 if (p_own_svc->type == ESP_NAN_PUBLISH) {
837 if (esp_nan_internal_publish_service(NULL, &service_id, true) == ESP_OK) {
838 nan_reset_service(service_id, false);
839 ESP_LOGI(TAG, "Cancelled Publish with Service ID %d", service_id);
840 return ESP_OK;
841 }
842 }
843
844 if (p_own_svc->type == ESP_NAN_SUBSCRIBE) {
845 if (esp_nan_internal_subscribe_service(NULL, &service_id, true) == ESP_OK) {
846 nan_reset_service(service_id, false);
847 ESP_LOGI(TAG, "Cancelled Subscribe with Service ID %d", service_id);
848 return ESP_OK;
849 }
850 }
851
852 return ESP_FAIL;
853 }
854
esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t * req)855 uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req)
856 {
857 uint8_t ndp_id = 0;
858 struct peer_svc_info *p_peer_svc = nan_find_peer_svc(0, req->pub_id, req->peer_mac);
859
860 if (!p_peer_svc) {
861 ESP_LOGE(TAG, "Cannot send NDP Req, peer not found!");
862 return 0;
863 }
864 if (req->pub_id == 0)
865 req->pub_id = p_peer_svc->svc_id;
866
867 if (p_peer_svc->type != ESP_NAN_PUBLISH) {
868 ESP_LOGE(TAG, "Only subscriber can send an NDP Req to a Publisher");
869 return 0;
870 }
871 if (ndl_limit_reached()) {
872 ESP_LOGE(TAG, "Cannot establish new datapath, limit reached!");
873 return 0;
874 }
875
876 if (!MACADDR_EQUAL(req->peer_mac, null_mac)) {
877 MACADDR_COPY(req->peer_mac, p_peer_svc->peer_nmi);
878 }
879
880 if (esp_nan_internal_datapath_req(req, &ndp_id) != ESP_OK) {
881 ESP_LOGE(TAG, "Failed to initiate NDP req");
882 return 0;
883 }
884 nan_record_new_ndl(ndp_id, req->pub_id, req->peer_mac, ESP_WIFI_NDP_ROLE_INITIATOR);
885 ESP_LOGD(TAG, "Requested NDP with "MACSTR" [NDP ID - %d]", MAC2STR(req->peer_mac), ndp_id);
886
887 EventBits_t bits = os_event_group_wait_bits(nan_event_group, NDP_ACCEPTED | NDP_REJECTED, pdFALSE, pdFALSE, pdMS_TO_TICKS(NAN_NDP_RESP_TIMEOUT));
888 if (bits & NDP_ACCEPTED) {
889 os_event_group_clear_bits(nan_event_group, NDP_ACCEPTED);
890 return ndp_id;
891 } else if (bits & NDP_REJECTED) {
892 os_event_group_clear_bits(nan_event_group, NDP_REJECTED);
893 return 0;
894 } else {
895 nan_reset_ndl(ndp_id, false);
896 return 0;
897 }
898 }
899
esp_wifi_nan_datapath_resp(wifi_nan_datapath_resp_t * resp)900 esp_err_t esp_wifi_nan_datapath_resp(wifi_nan_datapath_resp_t *resp)
901 {
902 struct ndl_info *ndl = nan_find_ndl(resp->ndp_id, NULL);
903
904 if (!ndl) {
905 ESP_LOGE(TAG, "No NDL with ndp id %d", resp->ndp_id);
906 return ESP_FAIL;
907 }
908 if (!(s_nan_ctx.event & NDP_INDICATION)) { //INDICATION of specific peer
909 ESP_LOGE(TAG, "Need NDP Indication before NDP Response can be sent");
910 return ESP_FAIL;
911 }
912
913 if (!MACADDR_EQUAL(resp->peer_mac, null_mac)) {
914 MACADDR_COPY(resp->peer_mac, ndl->peer_nmi);
915 }
916
917 if (esp_nan_internal_datapath_resp(resp) == ESP_OK) {
918 s_nan_ctx.event &= ~NDP_INDICATION;
919 return ESP_OK;
920 }
921
922 return ESP_FAIL;
923 }
924
esp_wifi_nan_datapath_end(wifi_nan_datapath_end_req_t * req)925 esp_err_t esp_wifi_nan_datapath_end(wifi_nan_datapath_end_req_t *req)
926 {
927 struct ndl_info *ndl = NULL;
928
929 if (!nan_is_datapath_active()) {
930 ESP_LOGE(TAG, "No Datapath active");
931 return ESP_FAIL;
932 }
933
934 ndl = nan_find_ndl(req->ndp_id, NULL);
935 if (!ndl) {
936 ESP_LOGE(TAG, "No NDL with ndp id %d", req->ndp_id);
937 return ESP_FAIL;
938 }
939 if (!MACADDR_EQUAL(req->peer_mac, null_mac)) {
940 MACADDR_COPY(req->peer_mac, ndl->peer_nmi);
941 }
942
943 if (esp_nan_internal_datapath_end(req) == ESP_OK) {
944 return ESP_OK;
945 }
946
947 return ESP_FAIL;
948 }
949
esp_wifi_nan_get_own_svc_info(uint8_t * own_svc_id,char * svc_name,int * num_peer_records)950 esp_err_t esp_wifi_nan_get_own_svc_info(uint8_t *own_svc_id, char *svc_name, int *num_peer_records)
951 {
952 struct own_svc_info *own_svc = NULL;
953
954 if (!own_svc_id || !num_peer_records || !svc_name) {
955 ESP_LOGE(TAG, "NULL memory address for input parameters");
956 return ESP_FAIL;
957 }
958
959 if (*own_svc_id == 0) {
960 own_svc = nan_find_own_svc_by_name(svc_name);
961 if (!own_svc) {
962 ESP_LOGE(TAG, "No record found for given service name %s", svc_name);
963 return ESP_FAIL;
964 }
965 *own_svc_id = own_svc->svc_id;
966 } else {
967 own_svc = nan_find_own_svc(*own_svc_id);
968 if (!own_svc) {
969 ESP_LOGE(TAG, "No record found for given service ID %d", *own_svc_id);
970 return ESP_FAIL;
971 }
972 strlcpy(svc_name, own_svc->svc_name, ESP_WIFI_MAX_SVC_NAME_LEN);
973 }
974
975 *num_peer_records = own_svc->num_peer_records;
976
977 return ESP_OK;
978 }
979
esp_wifi_nan_get_peer_records(int * num_peer_records,uint8_t own_svc_id,struct nan_peer_record * peer_record)980 esp_err_t esp_wifi_nan_get_peer_records(int *num_peer_records, uint8_t own_svc_id, struct nan_peer_record *peer_record)
981 {
982 struct own_svc_info *own_record = NULL;
983 struct peer_svc_info *temp = NULL;
984 int peer_num = 0;
985
986 if (!peer_record || !num_peer_records) {
987 ESP_LOGE(TAG, "NULL memory address for input parameters");
988 return ESP_FAIL;
989 }
990 if (own_svc_id == 0) {
991 ESP_LOGE(TAG, "Invalid service ID");
992 return ESP_FAIL;
993 }
994 if (*num_peer_records == 0) {
995 ESP_LOGE(TAG, "Number of peer records provided is 0");
996 return ESP_FAIL;
997 }
998
999 own_record = nan_find_own_svc(own_svc_id);
1000 if (own_record) {
1001 SLIST_FOREACH(temp, &(own_record->peer_list), next) {
1002 struct ndl_info *p_ndl;
1003 peer_record[peer_num].peer_svc_id = temp->svc_id;
1004 peer_record[peer_num].own_svc_id = own_svc_id;
1005 peer_record[peer_num].peer_svc_type = temp->type;
1006 MACADDR_COPY(peer_record[peer_num].peer_nmi, temp->peer_nmi);
1007 p_ndl = nan_find_ndl(0, temp->peer_nmi);
1008 if (p_ndl) {
1009 if (p_ndl->own_role == ESP_NAN_PUBLISH) {
1010 if (p_ndl->publisher_id == own_svc_id) {
1011 peer_record[peer_num].ndp_id = p_ndl->ndp_id;
1012 MACADDR_COPY(peer_record[peer_num].peer_ndi, p_ndl->peer_ndi);
1013 }
1014 } else if (p_ndl->own_role == ESP_NAN_SUBSCRIBE) {
1015 struct peer_svc_info *peer_info = NULL;
1016 peer_info = nan_find_peer_svc(own_svc_id, temp->svc_id, temp->peer_nmi);
1017 if (peer_info && peer_info->svc_id == p_ndl->publisher_id) {
1018 peer_record[peer_num].ndp_id = p_ndl->ndp_id;
1019 MACADDR_COPY(peer_record[peer_num].peer_ndi, p_ndl->peer_ndi);
1020 }
1021 }
1022 } else {
1023 peer_record[peer_num].ndp_id = 0;
1024 MACADDR_COPY(peer_record[peer_num].peer_ndi, null_mac);
1025 }
1026 peer_num ++;
1027 if (peer_num == *num_peer_records) {
1028 break;
1029 }
1030 }
1031 if (*num_peer_records > peer_num) {
1032 *num_peer_records = peer_num;
1033 }
1034 return ESP_OK;
1035 } else {
1036 *num_peer_records = 0;
1037 ESP_LOGD(TAG, "No record found for own service id %d", own_svc_id);
1038 return ESP_FAIL;
1039 }
1040 }
1041
esp_wifi_nan_get_peer_info(char * svc_name,uint8_t * peer_mac,struct nan_peer_record * peer_info)1042 esp_err_t esp_wifi_nan_get_peer_info(char *svc_name, uint8_t *peer_mac, struct nan_peer_record *peer_info)
1043 {
1044 struct peer_svc_info *peer_svc = NULL;
1045 uint8_t own_svc_id = 0;
1046
1047 if (!peer_mac || !peer_info) {
1048 ESP_LOGE(TAG, "Invalid memory address for input parameters");
1049 return ESP_FAIL;
1050 }
1051
1052 if (svc_name) {
1053 struct own_svc_info *own_svc = nan_find_own_svc_by_name(svc_name);
1054 if (!own_svc) {
1055 ESP_LOGE(TAG, "No record found for given service name %s", svc_name);
1056 return ESP_FAIL;
1057 }
1058 own_svc_id = own_svc->svc_id;
1059 }
1060
1061 peer_svc = nan_find_peer_svc(own_svc_id, 0, peer_mac);
1062 if (peer_svc) {
1063 struct ndl_info *p_ndl;
1064 peer_info->peer_svc_id = peer_svc->svc_id;
1065 peer_info->own_svc_id = peer_svc->own_svc_id;
1066 peer_info->peer_svc_type = peer_svc->type;
1067 MACADDR_COPY(peer_info->peer_nmi, peer_mac);
1068 p_ndl = nan_find_ndl(0, peer_mac);
1069 if (p_ndl) {
1070 peer_info->ndp_id = p_ndl->ndp_id;
1071 MACADDR_COPY(peer_info->peer_ndi, p_ndl->peer_ndi);
1072 } else {
1073 peer_info->ndp_id = 0;
1074 MACADDR_COPY(peer_info->peer_ndi, null_mac);
1075 }
1076 return ESP_OK;
1077 } else {
1078 ESP_LOGD(TAG, "No record found for Peer "MACSTR, MAC2STR(peer_mac));
1079 return ESP_FAIL;
1080 }
1081 }
1082