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