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