1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <lwip/ip_addr.h>
9 #include <lwip/sockets.h>
10 
11 #include "esp_check.h"
12 #include "esp_netif_lwip_internal.h"
13 
14 #include "esp_netif.h"
15 #include "esp_netif_private.h"
16 
17 #if CONFIG_ESP_NETIF_TCPIP_LWIP
18 
19 #include "lwip/tcpip.h"
20 #include "lwip/dhcp.h"
21 #include "lwip/ip_addr.h"
22 #include "lwip/ip6_addr.h"
23 #include "lwip/mld6.h"
24 #include "lwip/nd6.h"
25 #include "lwip/priv/tcpip_priv.h"
26 #include "lwip/netif.h"
27 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
28 #include "lwip/dns.h"
29 #endif
30 
31 #if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
32 #include "lwip_default_hooks.h"
33 #endif
34 
35 #include "esp_netif_lwip_ppp.h"
36 #include "esp_netif_lwip_slip.h"
37 #include "dhcpserver/dhcpserver.h"
38 #include "dhcpserver/dhcpserver_options.h"
39 
40 #include "esp_event.h"
41 #include "esp_log.h"
42 
43 //
44 // This is the main module implementing lwip interaction with esp-netif
45 //
46 
47 #define ESP_NETIF_HOSTNAME_MAX_SIZE    32
48 
49 /**
50  * @brief lwip thread safe tcpip function utility macros
51  */
52 #define _RUN_IN_LWIP_TASK(function, netif, param) { return esp_netif_lwip_ipc_call(function, netif, (void *)(param)); }
53 
54 /**
55  * @brief macros to check netif related data to evaluate interface type
56  */
57 #if CONFIG_PPP_SUPPORT || CONFIG_LWIP_SLIP_SUPPORT
58 #define _IS_NETIF_ANY_POINT2POINT_TYPE(netif) (netif->related_data && netif->related_data->is_point2point)
59 #else
60 #define _IS_NETIF_ANY_POINT2POINT_TYPE(netif) false
61 #endif
62 #define _RUN_IN_LWIP_TASK_IF_SUPPORTED(function, netif, param) \
63 {                                                              \
64     if (_IS_NETIF_ANY_POINT2POINT_TYPE(netif)) {               \
65         return ESP_ERR_NOT_SUPPORTED;                          \
66     }                                                          \
67     return esp_netif_lwip_ipc_call(function, netif, (void *)(param)); \
68 }
69 
70 /**
71  * @brief If netif protocol not enabled in menuconfig, log the error and return appropriate code indicating failure
72 */
73 
74 #define LOG_NETIF_DISABLED_AND_DO(proto, action)                                                \
75 do {                                                                                            \
76     ESP_LOGE(TAG, "%s not supported, please enable it in lwIP component configuration", proto); \
77     action;                                                                                     \
78 } while(0)
79 
80 //
81 //  Internal types
82 //
83 typedef enum esp_netif_action {
84     ESP_NETIF_UNDEF,
85     ESP_NETIF_STARTED,
86     ESP_NETIF_STOPPED,
87 } esp_netif_action_t;
88 
89 //
90 //  Internal variables for this module
91 //
92 extern sys_thread_t g_lwip_task;
93 
94 static const char *TAG = "esp_netif_lwip";
95 
96 static bool tcpip_initialized = false;
97 static esp_netif_t *s_last_default_esp_netif = NULL;
98 
99 #if !LWIP_TCPIP_CORE_LOCKING
100 static sys_sem_t api_sync_sem = NULL;
101 static sys_sem_t api_lock_sem = NULL;
102 
103 /**
104  * @brief Api callback from tcpip thread used to call esp-netif
105  * function in lwip task context
106  */
esp_netif_api_cb(void * api_msg)107 static void esp_netif_api_cb(void *api_msg)
108 {
109     esp_netif_api_msg_t *msg = (esp_netif_api_msg_t *)api_msg;
110 
111     if (!msg || !msg->api_fn) {
112         ESP_LOGD(TAG, "null msg/api_fn");
113         return;
114     }
115 
116     msg->ret = msg->api_fn(msg);
117     ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
118     sys_sem_signal(&api_sync_sem);
119 
120 }
121 #endif
122 
123 /**
124  * @brief Initiates a tcpip remote call if called from another task
125  * or calls the function directly if executed from lwip task
126  */
esp_netif_lwip_ipc_call(esp_netif_api_fn fn,esp_netif_t * netif,void * data)127 static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t *netif, void *data)
128 {
129     esp_netif_api_msg_t msg = {
130             .esp_netif = netif,
131             .data = data,
132             .api_fn = fn
133     };
134 #if !LWIP_TCPIP_CORE_LOCKING
135     if (g_lwip_task != xTaskGetCurrentTaskHandle()) {
136         ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", netif, fn);
137         sys_arch_sem_wait(&api_lock_sem, 0);
138         tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, &msg, &api_sync_sem);
139         sys_sem_signal(&api_lock_sem);
140         return msg.ret;
141     }
142 #endif /* !LWIP_TCPIP_CORE_LOCKING */
143     ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", netif, fn);
144     return fn(&msg);
145 }
146 
147 /**
148  * @brief Check if supplied esp_netif handle is active, i.e. available within registered interfaces
149  * as it might have already been destroyed. Returns the supplied handle if active, nullptr otherwise
150  *
151  * @param esp_netif handle to check if available in the list of registered interfaces
152  * @return esp_netif handle if available, or NULL if it wasn't found
153  */
esp_netif_is_active(esp_netif_t * arg)154 static esp_netif_t* esp_netif_is_active(esp_netif_t *arg)
155 {
156     // looking for the netif in the list of registered interfaces
157     //  as it might have already been destroyed
158     if (esp_netif_is_netif_listed(arg)) {
159         return arg;
160     }
161     return NULL;
162 }
163 
164 /**
165  * @brief This function sets default netif no matter which implementation used
166  *
167  * @param esp_netif handle to network interface
168  *
169  * @note: This function must be called from lwip thread
170  */
esp_netif_set_default_netif(esp_netif_t * esp_netif)171 static void esp_netif_set_default_netif(esp_netif_t *esp_netif)
172 {
173     if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
174 #if CONFIG_PPP_SUPPORT
175         esp_netif_ppp_set_default_netif(esp_netif->netif_handle);
176 #endif
177     } else {
178         netif_set_default(esp_netif->lwip_netif);
179     }
180 }
181 
182 /**
183  * @brief tcpip thread version of esp_netif_update_default_netif
184  *
185  * @note This function and all functions called from this must be called from lwip task context
186  */
esp_netif_update_default_netif_lwip(esp_netif_api_msg_t * msg)187 static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg)
188 {
189     esp_netif_t *esp_netif = msg->esp_netif;
190     esp_netif_action_t action = (esp_netif_action_t)msg->data;
191 
192     ESP_LOGD(TAG, "%s %p", __func__, esp_netif);
193 
194     switch (action) {
195         case ESP_NETIF_STARTED:
196         {
197             // check if previously default interface hasn't been destroyed in the meantime
198             s_last_default_esp_netif = esp_netif_is_active(s_last_default_esp_netif);
199             if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)
200                 && (s_last_default_esp_netif->route_prio > esp_netif->route_prio)) {
201                 esp_netif_set_default_netif(s_last_default_esp_netif);
202             } else if (esp_netif_is_netif_up(esp_netif)) {
203                 s_last_default_esp_netif = esp_netif;
204                 esp_netif_set_default_netif(s_last_default_esp_netif);
205             }
206         }
207         break;
208 
209         default:
210         case ESP_NETIF_STOPPED:
211         {
212             s_last_default_esp_netif = NULL;
213             esp_netif_list_lock();
214             esp_netif_t *netif = esp_netif_next_unsafe(NULL);
215             while (netif) {
216                 if (esp_netif_is_netif_up(netif)) {
217                     if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)) {
218                         if (netif->route_prio > s_last_default_esp_netif->route_prio) {
219                             s_last_default_esp_netif = netif;
220                         } // else not needed, as the s_last_default_esp_netif is correct
221                     } else {
222                         // s_last_default is either not set or down, current netif is up
223                         s_last_default_esp_netif = netif;
224                     }
225                 }
226                 netif = esp_netif_next_unsafe(netif);
227             }
228             esp_netif_list_unlock();
229             if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)) {
230                 esp_netif_set_default_netif(s_last_default_esp_netif);
231             }
232         }
233         break;
234     }
235     return ESP_OK;
236 }
237 
238 /**
239  * @brief This function sets default routing netif based on priorities of all interfaces which are up
240  *
241  * @param esp_netif current interface which just updated state
242  * @param action updating action (on-off)
243  */
esp_netif_update_default_netif(esp_netif_t * esp_netif,esp_netif_action_t action)244 static esp_err_t esp_netif_update_default_netif(esp_netif_t *esp_netif, esp_netif_action_t action)
245 {
246     return esp_netif_lwip_ipc_call(esp_netif_update_default_netif_lwip, esp_netif, (void*)action);
247 }
248 
esp_netif_set_ip4_addr(esp_ip4_addr_t * addr,uint8_t a,uint8_t b,uint8_t c,uint8_t d)249 void esp_netif_set_ip4_addr(esp_ip4_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
250 {
251     ip4_addr_t *address = (ip4_addr_t*)addr;
252     IP4_ADDR(address, a, b, c, d);
253 }
254 
esp_ip4addr_ntoa(const esp_ip4_addr_t * addr,char * buf,int buflen)255 char * esp_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen)
256 {
257     return ip4addr_ntoa_r((ip4_addr_t *)addr, buf, buflen);
258 }
259 
esp_ip4addr_aton(const char * addr)260 uint32_t esp_ip4addr_aton(const char *addr)
261 {
262     return ipaddr_addr(addr);
263 }
264 
esp_netif_str_to_ip4(const char * src,esp_ip4_addr_t * dst)265 esp_err_t esp_netif_str_to_ip4(const char *src, esp_ip4_addr_t *dst)
266 {
267     if (src == NULL || dst == NULL) {
268         return ESP_ERR_INVALID_ARG;
269     }
270     int err = inet_pton(AF_INET, src, dst);
271     return err == 1 ? ESP_OK : ESP_FAIL;
272 }
273 
esp_netif_str_to_ip6(const char * src,esp_ip6_addr_t * dst)274 esp_err_t esp_netif_str_to_ip6(const char *src, esp_ip6_addr_t *dst)
275 {
276     if (src == NULL || dst == NULL) {
277         return ESP_ERR_INVALID_ARG;
278     }
279     int err = inet_pton(AF_INET6, src, dst);
280     return err == 1 ? ESP_OK : ESP_FAIL;
281 }
282 
esp_netif_get_io_driver(esp_netif_t * esp_netif)283 esp_netif_iodriver_handle esp_netif_get_io_driver(esp_netif_t *esp_netif)
284 {
285     return esp_netif->driver_handle;
286 }
287 
esp_netif_get_handle_from_netif_impl(void * dev)288 esp_netif_t* esp_netif_get_handle_from_netif_impl(void *dev)
289 {
290     // ppp_pcb ptr would never get to app code, so this function only works with vanilla lwip impl
291     struct netif *lwip_netif = dev;
292     return lwip_netif->state;
293 }
294 
esp_netif_get_netif_impl(esp_netif_t * esp_netif)295 void* esp_netif_get_netif_impl(esp_netif_t *esp_netif)
296 {
297     // get impl ptr only for vanilla lwip impl (ppp_pcb not supported)
298     if (esp_netif && !_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
299         return esp_netif->lwip_netif;
300     }
301     return NULL;
302 }
303 
esp_netif_init(void)304 esp_err_t esp_netif_init(void)
305 {
306     if (tcpip_initialized == false) {
307         tcpip_initialized = true;
308 #if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
309         uint8_t rand_buf[16];
310         /*
311          * This is early startup code where WiFi/BT is yet to be enabled and hence
312          * relevant entropy source is not available. However, bootloader enables
313          * SAR ADC based entropy source at its initialization, and our requirement
314          * of random bytes is pretty small (16), so we can assume that following
315          * API will provide sufficiently random data.
316          */
317         esp_fill_random(rand_buf, sizeof(rand_buf));
318         lwip_init_tcp_isn(esp_log_timestamp(), rand_buf);
319 #endif
320         tcpip_init(NULL, NULL);
321         ESP_LOGD(TAG, "LwIP stack has been initialized");
322     }
323 
324 #if !LWIP_TCPIP_CORE_LOCKING
325     if (!api_sync_sem) {
326         if (ERR_OK != sys_sem_new(&api_sync_sem, 0)) {
327             ESP_LOGE(TAG, "esp netif api sync sem init fail");
328             return ESP_FAIL;
329         }
330     }
331 
332     if (!api_lock_sem) {
333         if (ERR_OK != sys_sem_new(&api_lock_sem, 1)) {
334             ESP_LOGE(TAG, "esp netif api lock sem init fail");
335             return ESP_FAIL;
336         }
337     }
338 #endif
339 
340     ESP_LOGD(TAG, "esp-netif has been successfully initialized");
341     return ESP_OK;
342 }
343 
esp_netif_deinit(void)344 esp_err_t esp_netif_deinit(void)
345 {
346     if (tcpip_initialized == true) {
347         /* deinit of LwIP not supported:
348          * do not deinit semaphores and states,
349          * so init could be called multiple times
350          *
351         tcpip_initialized = false;
352         sys_sem_free(&api_sync_sem);
353         sys_sem_free(&api_lock_sem);
354          */
355         return ESP_ERR_NOT_SUPPORTED;
356 
357     }
358     return ESP_ERR_INVALID_STATE;
359 }
360 
esp_netif_init_configuration(esp_netif_t * esp_netif,const esp_netif_config_t * cfg)361 static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_netif_config_t *cfg)
362 {
363     // Basic esp_netif and lwip is a mandatory configuration and cannot be updated after esp_netif_new()
364     if (cfg == NULL || cfg->base == NULL || cfg->stack == NULL) {
365         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
366     }
367 
368     // Configure general esp-netif properties
369     memcpy(esp_netif->mac, cfg->base->mac, NETIF_MAX_HWADDR_LEN);
370     if (cfg->base->ip_info == NULL) {
371         ip4_addr_set_zero(&esp_netif->ip_info->ip);
372         ip4_addr_set_zero(&esp_netif->ip_info->gw);
373         ip4_addr_set_zero(&esp_netif->ip_info->netmask);
374     } else {
375         memcpy(esp_netif->ip_info, cfg->base->ip_info, sizeof(esp_netif_ip_info_t));
376     }
377     memcpy(esp_netif->ip_info_old, esp_netif->ip_info, sizeof(esp_netif_ip_info_t));
378 
379     // Setup main config parameters
380     esp_netif->lost_ip_event = cfg->base->lost_ip_event;
381     esp_netif->get_ip_event = cfg->base->get_ip_event;
382     esp_netif->flags = cfg->base->flags;
383 
384     if (cfg->base->if_key) {
385         esp_netif->if_key = strdup(cfg->base->if_key);
386     }
387     if (cfg->base->if_desc) {
388         esp_netif->if_desc = strdup(cfg->base->if_desc);
389     }
390     if (cfg->base->route_prio) {
391         esp_netif->route_prio = cfg->base->route_prio;
392     }
393 
394     // Install network stack functions -- connects netif and L3 stack
395     const esp_netif_netstack_config_t *esp_netif_stack_config = cfg->stack;
396     if (cfg->base->flags & ESP_NETIF_FLAG_IS_PPP) {
397 #if CONFIG_PPP_SUPPORT
398         esp_netif->related_data = esp_netif_new_ppp(esp_netif, esp_netif_stack_config);
399         if (esp_netif->related_data == NULL) {
400             return ESP_ERR_ESP_NETIF_INIT_FAILED;
401         }
402         esp_netif->lwip_input_fn = esp_netif_stack_config->lwip_ppp.input_fn;
403         // Make the netif handle (used for tcpip input function) the ppp_netif
404         esp_netif->netif_handle = esp_netif->related_data;
405 #else
406         LOG_NETIF_DISABLED_AND_DO("PPP", return ESP_ERR_NOT_SUPPORTED);
407 #endif
408     } else if (cfg->base->flags & ESP_NETIF_FLAG_IS_SLIP) {
409 #if CONFIG_LWIP_SLIP_SUPPORT
410         esp_netif->related_data = esp_netif_new_slip(esp_netif, esp_netif_stack_config);
411         if (esp_netif->related_data == NULL) {
412             return ESP_ERR_ESP_NETIF_INIT_FAILED;
413         }
414         if (esp_netif_stack_config->lwip.init_fn) {
415             esp_netif->lwip_init_fn = esp_netif_stack_config->lwip.init_fn;
416         }
417         if (esp_netif_stack_config->lwip.input_fn) {
418             esp_netif->lwip_input_fn = esp_netif_stack_config->lwip.input_fn;
419         }
420         // Make the netif handle (used for tcpip input function) the esp_netif itself
421         esp_netif->netif_handle = esp_netif;
422 #else
423         LOG_NETIF_DISABLED_AND_DO("SLIP", return ESP_ERR_NOT_SUPPORTED);
424 #endif
425     } else {
426         if (esp_netif_stack_config-> lwip.init_fn) {
427             esp_netif->lwip_init_fn = esp_netif_stack_config->lwip.init_fn;
428         }
429         if (esp_netif_stack_config->lwip.input_fn) {
430             esp_netif->lwip_input_fn = esp_netif_stack_config->lwip.input_fn;
431         }
432         // Make the netif handle (used for tcpip input function) the lwip_netif itself
433         esp_netif->netif_handle = esp_netif->lwip_netif;
434 
435     }
436 
437     // Install IO functions only if provided -- connects driver and netif
438     // this configuration could be updated after esp_netif_new(), typically in post_attach callback
439     if (cfg->driver) {
440         const esp_netif_driver_ifconfig_t *esp_netif_driver_config = cfg->driver;
441         if (esp_netif_driver_config->handle) {
442             esp_netif->driver_handle = esp_netif_driver_config->handle;
443         }
444         if (esp_netif_driver_config->transmit) {
445             esp_netif->driver_transmit = esp_netif_driver_config->transmit;
446         }
447         if (esp_netif_driver_config->transmit_wrap) {
448             esp_netif->driver_transmit_wrap = esp_netif_driver_config->transmit_wrap;
449         }
450         if (esp_netif_driver_config->driver_free_rx_buffer) {
451             esp_netif->driver_free_rx_buffer = esp_netif_driver_config->driver_free_rx_buffer;
452         }
453     }
454     return ESP_OK;
455 }
456 
esp_netif_new(const esp_netif_config_t * esp_netif_config)457 esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
458 {
459     // mandatory configuration must be provided when creating esp_netif object
460     if (esp_netif_config == NULL ||
461         esp_netif_config->base->if_key == NULL ||
462         NULL != esp_netif_get_handle_from_ifkey(esp_netif_config->base->if_key)) {
463         ESP_LOGE(TAG, "%s: Failed to configure netif with config=%p (config or if_key is NULL or duplicate key)",
464         __func__,  esp_netif_config);
465         return NULL;
466     }
467 
468     // Create parent esp-netif object
469     esp_netif_t *esp_netif = calloc(1, sizeof(struct esp_netif_obj));
470     if (!esp_netif) {
471         ESP_LOGE(TAG, "Failed to allocate %d bytes (fee heap size %d)", sizeof(struct esp_netif_obj),
472                  esp_get_free_heap_size());
473         return NULL;
474     }
475 
476     // Create ip info
477     esp_netif_ip_info_t *ip_info = calloc(1, sizeof(esp_netif_ip_info_t));
478     if (!ip_info) {
479         ESP_LOGE(TAG, "Failed to allocate %d bytes (fee heap size %d)", sizeof(esp_netif_ip_info_t),
480                  esp_get_free_heap_size());
481         free(esp_netif);
482         return NULL;
483     }
484     esp_netif->ip_info = ip_info;
485 
486     // creating another ip info (to store old ip)
487     ip_info = calloc(1, sizeof(esp_netif_ip_info_t));
488     if (!ip_info) {
489         ESP_LOGE(TAG, "Failed to allocate %d bytes (fee heap size %d)", sizeof(esp_netif_ip_info_t),
490                  esp_get_free_heap_size());
491         free(esp_netif->ip_info);
492         free(esp_netif);
493         return NULL;
494     }
495     esp_netif->ip_info_old = ip_info;
496 
497     // Create underlying lwip netif
498     struct netif * lwip_netif = calloc(1, sizeof(struct netif));
499     if (!lwip_netif) {
500         ESP_LOGE(TAG, "Failed to allocate %d bytes (fee heap size %d)", sizeof(struct netif),
501                  esp_get_free_heap_size());
502         free(esp_netif->ip_info_old);
503         free(esp_netif->ip_info);
504         free(esp_netif);
505         return NULL;
506     }
507 
508     lwip_netif->state = esp_netif;
509     esp_netif->lwip_netif = lwip_netif;
510 
511     esp_netif_add_to_list(esp_netif);
512 
513     // Configure the created object with provided configuration
514     esp_err_t ret =  esp_netif_init_configuration(esp_netif, esp_netif_config);
515     if (ret != ESP_OK) {
516         ESP_LOGE(TAG, "Initial configuration of esp_netif failed with %d", ret);
517         esp_netif_destroy(esp_netif);
518         return NULL;
519     }
520 
521     return esp_netif;
522 }
523 
esp_netif_lwip_remove(esp_netif_t * esp_netif)524 static void esp_netif_lwip_remove(esp_netif_t *esp_netif)
525 {
526     if (esp_netif->lwip_netif) {
527         if (netif_is_up(esp_netif->lwip_netif)) {
528             netif_set_down(esp_netif->lwip_netif);
529         }
530         netif_remove(esp_netif->lwip_netif);
531     }
532 }
533 
esp_netif_lwip_add(esp_netif_t * esp_netif)534 static esp_err_t esp_netif_lwip_add(esp_netif_t *esp_netif)
535 {
536     if (esp_netif->lwip_netif == NULL) {
537         esp_netif->lwip_netif = calloc(1, sizeof(struct netif));
538         if (esp_netif->lwip_netif == NULL) {
539             return ESP_ERR_NO_MEM;
540         }
541     }
542     if (esp_netif->flags & ESP_NETIF_FLAG_IS_PPP) {
543 #if CONFIG_PPP_SUPPORT
544         err_t err = esp_netif->lwip_init_fn(NULL);
545         if (err != ERR_OK) {
546             ESP_LOGE(TAG, "Init netif failed with  %d", err);
547             return ESP_ERR_ESP_NETIF_INIT_FAILED;
548         }
549 #else
550         LOG_NETIF_DISABLED_AND_DO("PPP", return ESP_ERR_NOT_SUPPORTED);
551 #endif
552     }
553 
554     if (NULL == netif_add(esp_netif->lwip_netif, (struct ip4_addr*)&esp_netif->ip_info->ip,
555                          (struct ip4_addr*)&esp_netif->ip_info->netmask, (struct ip4_addr*)&esp_netif->ip_info->gw,
556                          esp_netif, esp_netif->lwip_init_fn, tcpip_input)) {
557         esp_netif_lwip_remove(esp_netif);
558         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
559     }
560     return ESP_OK;
561 }
562 
esp_netif_destroy_related(esp_netif_t * esp_netif)563 static void esp_netif_destroy_related(esp_netif_t *esp_netif)
564 {
565     if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
566 #if CONFIG_PPP_SUPPORT
567         esp_netif_destroy_ppp(esp_netif->related_data);
568 #endif
569     } else if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, SLIP_LWIP_NETIF)) {
570 #if CONFIG_LWIP_SLIP_SUPPORT
571         esp_netif_destroy_slip(esp_netif->related_data);
572 #endif
573     }
574 }
575 
esp_netif_destroy(esp_netif_t * esp_netif)576 void esp_netif_destroy(esp_netif_t *esp_netif)
577 {
578     if (esp_netif) {
579         esp_netif_remove_from_list(esp_netif);
580         free(esp_netif->ip_info);
581         free(esp_netif->ip_info_old);
582         free(esp_netif->if_key);
583         free(esp_netif->if_desc);
584         esp_netif_lwip_remove(esp_netif);
585         esp_netif_destroy_related(esp_netif);
586         free(esp_netif->lwip_netif);
587         free(esp_netif->hostname);
588         if (s_last_default_esp_netif == esp_netif) {
589             // clear last default netif if it happens to be this just destroyed interface
590             s_last_default_esp_netif = NULL;
591         }
592         free(esp_netif);
593     }
594 }
595 
esp_netif_attach(esp_netif_t * esp_netif,esp_netif_iodriver_handle driver_handle)596 esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle)
597 {
598     esp_netif_driver_base_t *base_driver = driver_handle;
599 
600     esp_netif->driver_handle = driver_handle;
601     if (base_driver->post_attach) {
602         esp_err_t ret = base_driver->post_attach(esp_netif, driver_handle);
603         if (ret != ESP_OK) {
604             ESP_LOGE(TAG, "Post-attach callback of driver(%p) failed with %d", driver_handle, ret);
605             return ESP_ERR_ESP_NETIF_DRIVER_ATTACH_FAILED;
606         }
607     }
608     return ESP_OK;
609 }
610 
esp_netif_set_driver_config(esp_netif_t * esp_netif,const esp_netif_driver_ifconfig_t * driver_config)611 esp_err_t esp_netif_set_driver_config(esp_netif_t *esp_netif,
612                                       const esp_netif_driver_ifconfig_t *driver_config)
613 {
614     if (esp_netif == NULL || driver_config == NULL) {
615         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
616     }
617     esp_netif->driver_handle = driver_config->handle;
618     esp_netif->driver_transmit = driver_config->transmit;
619     esp_netif->driver_transmit_wrap = driver_config->transmit_wrap;
620     esp_netif->driver_free_rx_buffer = driver_config->driver_free_rx_buffer;
621     return ESP_OK;
622 }
623 
esp_netif_reset_ip_info(esp_netif_t * esp_netif)624 static esp_err_t esp_netif_reset_ip_info(esp_netif_t *esp_netif)
625 {
626     ip4_addr_set_zero(&(esp_netif->ip_info->ip));
627     ip4_addr_set_zero(&(esp_netif->ip_info->gw));
628     ip4_addr_set_zero(&(esp_netif->ip_info->netmask));
629     return ESP_OK;
630 }
631 
esp_netif_set_mac(esp_netif_t * esp_netif,uint8_t mac[])632 esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
633 {
634     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
635         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
636     }
637     if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
638         return ESP_ERR_NOT_SUPPORTED;
639     }
640     memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN);
641     memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN);
642     return ESP_OK;
643 }
644 
esp_netif_get_mac(esp_netif_t * esp_netif,uint8_t mac[])645 esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[])
646 {
647     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
648         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
649     }
650     if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
651         return ESP_ERR_NOT_SUPPORTED;
652     }
653     if (esp_netif_is_netif_up(esp_netif)) {
654         memcpy(mac, esp_netif->lwip_netif->hwaddr, NETIF_MAX_HWADDR_LEN);
655         return ESP_OK;
656     }
657     memcpy(mac, esp_netif->mac, NETIF_MAX_HWADDR_LEN);
658     return ESP_OK;
659 }
660 
661 #if ESP_DHCPS
esp_netif_dhcps_cb(u8_t client_ip[4])662 static void esp_netif_dhcps_cb(u8_t client_ip[4])
663 {
664     ESP_LOGI(TAG, "DHCP server assigned IP to a station, IP is: %d.%d.%d.%d",
665              client_ip[0], client_ip[1], client_ip[2], client_ip[3]);
666     ip_event_ap_staipassigned_t evt;
667 
668     memset(&evt, 0, sizeof(ip_event_ap_staipassigned_t));
669     memcpy((char *)&evt.ip.addr, (char *)client_ip, sizeof(evt.ip.addr));
670     int ret = esp_event_send_internal(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &evt, sizeof(evt), 0);
671     if (ESP_OK != ret) {
672         ESP_LOGE(TAG, "dhcps cb: failed to post IP_EVENT_AP_STAIPASSIGNED (%x)", ret);
673     }
674 }
675 #endif
676 
esp_netif_config_sanity_check(const esp_netif_t * esp_netif)677 static esp_err_t esp_netif_config_sanity_check(const esp_netif_t * esp_netif)
678 {
679     if (esp_netif == NULL) {
680         ESP_LOGE(TAG,  "Cannot start esp_netif: esp_netif must not be null");
681         return ESP_ERR_INVALID_STATE;
682     }
683 
684     if (esp_netif->driver_transmit == NULL ||
685         esp_netif->driver_handle == NULL ||
686         esp_netif->lwip_input_fn == NULL ||
687         esp_netif->lwip_init_fn == NULL) {
688         ESP_LOGE(TAG,  "Cannot start esp_netif: Missing mandatory configuration:\n"
689                        "esp_netif->driver_transmit: %p, esp_netif->driver_handle:%p, "
690                        "esp_netif->lwip_input_fn: %p, esp_netif->lwip_init_fn:%p",
691                        esp_netif->driver_transmit,  esp_netif->driver_handle,
692                        esp_netif->lwip_input_fn,  esp_netif->lwip_init_fn);
693 
694          return ESP_ERR_INVALID_STATE;
695     }
696     return ESP_OK;
697 }
698 
esp_netif_start_api(esp_netif_api_msg_t * msg)699 static esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg)
700 {
701     esp_netif_t * esp_netif = msg->esp_netif;
702 
703     ESP_LOGD(TAG, "%s %p", __func__, esp_netif);
704 
705     ESP_ERROR_CHECK(esp_netif_config_sanity_check(esp_netif));
706 
707     ESP_ERROR_CHECK(esp_netif_lwip_add(esp_netif));
708 
709     if (esp_netif->flags&ESP_NETIF_FLAG_GARP) {
710 #if ESP_GRATUITOUS_ARP
711         netif_set_garp_flag(esp_netif->lwip_netif);
712 #else
713         ESP_LOGW(TAG,"CONFIG_LWIP_ESP_GRATUITOUS_ARP not enabled, but esp-netif configured with ESP_NETIF_FLAG_GARP");
714 #endif
715     }
716     struct netif *p_netif = esp_netif->lwip_netif;
717     if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, SLIP_LWIP_NETIF)) {
718 #if CONFIG_LWIP_SLIP_SUPPORT
719         esp_netif_start_slip(esp_netif);
720 #endif
721     }
722     if (esp_netif->flags&ESP_NETIF_FLAG_AUTOUP) {
723         ESP_LOGD(TAG, "%s Setting the lwip netif%p UP", __func__, p_netif);
724         netif_set_up(p_netif);
725     }
726     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
727 #if ESP_DHCPS
728         if (esp_netif->dhcps_status == ESP_NETIF_DHCP_INIT) {
729             if (p_netif != NULL && netif_is_up(p_netif)) {
730                 esp_netif_ip_info_t *default_ip = esp_netif->ip_info;
731                 ip4_addr_t lwip_ip;
732                 ip4_addr_t lwip_netmask;
733                 memcpy(&lwip_ip, &default_ip->ip, sizeof(struct ip4_addr));
734                 memcpy(&lwip_netmask, &default_ip->netmask, sizeof(struct ip4_addr));
735                 dhcps_set_new_lease_cb(esp_netif_dhcps_cb);
736                 dhcps_set_option_info(SUBNET_MASK, (void*)&lwip_netmask, sizeof(lwip_netmask));
737                 dhcps_start(p_netif, lwip_ip);
738                 esp_netif->dhcps_status = ESP_NETIF_DHCP_STARTED;
739                 ESP_LOGD(TAG, "DHCP server started successfully");
740                 esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
741                 return ESP_OK;
742             } else {
743                 ESP_LOGD(TAG, "DHCP server re init");
744                 esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
745                 return ESP_OK;
746             }
747         } else if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) {
748             ESP_LOGD(TAG, "DHCP server already started");
749             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
750         }
751         return ESP_OK;
752 #else
753         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
754 #endif
755     } else if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
756         if (esp_netif->dhcpc_status != ESP_NETIF_DHCP_STARTED) {
757             if (p_netif != NULL) {
758                 struct dhcp *dhcp_data = NULL;
759                 dhcp_data = netif_dhcp_data(p_netif);
760                 if (dhcp_data == NULL) {
761                     dhcp_data = (struct dhcp *)malloc(sizeof(struct dhcp));
762                     if (dhcp_data == NULL) {
763                         return ESP_ERR_NO_MEM;
764                     }
765                     dhcp_set_struct(p_netif, dhcp_data);
766                 }
767             }
768         }
769     }
770 
771     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
772 
773     return ESP_OK;
774 }
775 
esp_netif_start(esp_netif_t * esp_netif)776 esp_err_t esp_netif_start(esp_netif_t *esp_netif)
777 {
778     if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
779 #if CONFIG_PPP_SUPPORT
780         // No need to start PPP interface in lwip thread
781         esp_err_t ret = esp_netif_start_ppp(esp_netif);
782         if (ret == ESP_OK) {
783             esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
784         }
785         return ret;
786 #endif
787     }
788     return esp_netif_lwip_ipc_call(esp_netif_start_api, esp_netif, NULL);
789 }
790 
esp_netif_stop_api(esp_netif_api_msg_t * msg)791 static esp_err_t esp_netif_stop_api(esp_netif_api_msg_t *msg)
792 {
793     esp_netif_t *esp_netif = msg->esp_netif;
794 
795     struct netif *lwip_netif = esp_netif->lwip_netif;
796     if (lwip_netif == NULL) {
797         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
798     }
799 
800     if (!netif_is_up(lwip_netif)) {
801         esp_netif_lwip_remove(esp_netif);
802         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
803     }
804 
805     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
806 #if ESP_DHCPS
807         dhcps_stop(lwip_netif);    // TODO(IDF-1099): dhcps checks status by its self
808         if (ESP_NETIF_DHCP_STOPPED != esp_netif->dhcps_status) {
809             esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
810         }
811 #else
812         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
813 #endif
814     } else if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
815         dhcp_release(lwip_netif);
816         dhcp_stop(lwip_netif);
817         dhcp_cleanup(lwip_netif);
818 
819         esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
820 
821         esp_netif_reset_ip_info(esp_netif);
822     }
823 
824     netif_set_down(lwip_netif);
825     esp_netif_lwip_remove(esp_netif);
826     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);;
827 
828     return ESP_OK;
829 }
830 
esp_netif_stop(esp_netif_t * esp_netif)831 esp_err_t esp_netif_stop(esp_netif_t *esp_netif)
832 {
833     if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
834 #if CONFIG_PPP_SUPPORT
835         // No need to stop PPP interface in lwip thread
836         esp_err_t ret = esp_netif_stop_ppp(esp_netif->related_data);
837         if (ret == ESP_OK) {
838             esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);;
839         }
840         return ret;
841 #endif
842     } else if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, SLIP_LWIP_NETIF)) {
843 #if CONFIG_LWIP_SLIP_SUPPORT
844         // No need to stop SLIP interface in lwip thread
845         esp_err_t ret = esp_netif_stop_slip(esp_netif);
846         if (ret == ESP_OK) {
847             esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);;
848         }
849         return ret;
850 #endif
851     }
852     return esp_netif_lwip_ipc_call(esp_netif_stop_api, esp_netif, NULL);
853 }
854 
esp_netif_netstack_buf_ref(void * pbuf)855 void esp_netif_netstack_buf_ref(void *pbuf)
856 {
857     pbuf_ref(pbuf);
858 }
859 
esp_netif_netstack_buf_free(void * pbuf)860 void esp_netif_netstack_buf_free(void *pbuf)
861 {
862     pbuf_free(pbuf);
863 }
864 
865 //
866 // IO translate functions
867 //
esp_netif_free_rx_buffer(void * h,void * buffer)868 void esp_netif_free_rx_buffer(void *h, void* buffer)
869 {
870     esp_netif_t *esp_netif = h;
871     esp_netif->driver_free_rx_buffer(esp_netif->driver_handle, buffer);
872 }
873 
esp_netif_transmit(esp_netif_t * esp_netif,void * data,size_t len)874 esp_err_t esp_netif_transmit(esp_netif_t *esp_netif, void* data, size_t len)
875 {
876     return (esp_netif->driver_transmit)(esp_netif->driver_handle, data, len);
877 }
878 
esp_netif_transmit_wrap(esp_netif_t * esp_netif,void * data,size_t len,void * pbuf)879 esp_err_t esp_netif_transmit_wrap(esp_netif_t *esp_netif, void *data, size_t len, void *pbuf)
880 {
881     return (esp_netif->driver_transmit_wrap)(esp_netif->driver_handle, data, len, pbuf);
882 }
883 
esp_netif_receive(esp_netif_t * esp_netif,void * buffer,size_t len,void * eb)884 esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb)
885 {
886     esp_netif->lwip_input_fn(esp_netif->netif_handle, buffer, len, eb);
887     return ESP_OK;
888 }
889 
890 //
891 // DHCP:
892 //
893 static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif);
894 
esp_netif_dhcpc_cb(struct netif * netif)895 static void esp_netif_dhcpc_cb(struct netif *netif)
896 {
897     if (!netif) {
898         ESP_LOGD(TAG, "null netif=%p", netif);
899         return;
900     }
901     ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, netif);
902 
903     esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
904 
905     esp_netif_ip_info_t *ip_info = esp_netif->ip_info;
906     esp_netif_ip_info_t *ip_info_old = esp_netif->ip_info_old;
907 
908 
909     if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4) ) {
910 
911         //check whether IP is changed
912         if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), (&ip_info->ip)) ||
913              !ip4_addr_cmp(ip_2_ip4(&netif->netmask), (&ip_info->netmask)) ||
914              !ip4_addr_cmp(ip_2_ip4(&netif->gw), (&ip_info->gw)) ) {
915             ip_event_got_ip_t evt = {
916                     .esp_netif = esp_netif,
917                     .if_index = -1, // invalid index, handle used
918                     .ip_changed = false,
919             };
920             ip_event_t evt_id = esp_netif_get_event_id(esp_netif, ESP_NETIF_IP_EVENT_GOT_IP);
921             int ret;
922 
923             ip4_addr_set(&ip_info->ip, ip_2_ip4(&netif->ip_addr));
924             ip4_addr_set(&ip_info->netmask, ip_2_ip4(&netif->netmask));
925             ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw));
926 
927             //notify event
928             if (memcmp(ip_info, ip_info_old, sizeof(esp_netif_ip_info_t))) {
929                 evt.ip_changed = true;
930             }
931 
932             memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t));
933             memcpy(ip_info_old, ip_info, sizeof(esp_netif_ip_info_t));
934             ESP_LOGD(TAG, "if%p ip changed=%d", esp_netif, evt.ip_changed);
935             ret = esp_event_send_internal(IP_EVENT, evt_id, &evt, sizeof(evt), 0);
936             if (ESP_OK != ret) {
937                 ESP_LOGE(TAG, "dhcpc cb: failed to post got ip event (%x)", ret);
938             }
939         } else {
940             ESP_LOGD(TAG, "if%p ip unchanged", esp_netif);
941         }
942     } else {
943         if (!ip4_addr_cmp(&ip_info->ip, IP4_ADDR_ANY4)) {
944             esp_netif_start_ip_lost_timer(esp_netif);
945         }
946     }
947 }
948 
esp_netif_ip_lost_timer(void * arg)949 static void esp_netif_ip_lost_timer(void *arg)
950 {
951     esp_netif_t *esp_netif = esp_netif_is_active(arg);
952 
953     if (esp_netif == NULL) {
954         ESP_LOGD(TAG, "%s esp_netif=%p not active any more", __func__, arg);
955         return;
956     }
957 
958     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
959 
960     esp_netif->timer_running = false;
961 
962     struct netif *netif = esp_netif->lwip_netif;
963 
964     if ( (!netif) || (netif && ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4))) {
965         ip_event_got_ip_t evt = {
966                 .esp_netif = esp_netif,
967                 .if_index = -1,
968         };
969         int ret;
970 
971         ESP_LOGD(TAG, "if%p ip lost tmr: raise ip lost event", esp_netif);
972         memset(esp_netif->ip_info_old, 0, sizeof(esp_netif_ip_info_t));
973         if (esp_netif->lost_ip_event) {
974             ret = esp_event_send_internal(IP_EVENT, esp_netif->lost_ip_event,
975                                           &evt, sizeof(evt), 0);
976             if (ESP_OK != ret) {
977                 ESP_LOGE(TAG, "ip lost timer: failed to post lost ip event (%x)", ret);
978             }
979         }
980     } else {
981         ESP_LOGD(TAG, "if%p ip lost tmr: no need raise ip lost event", esp_netif);
982     }
983 }
984 
985 
esp_netif_start_ip_lost_timer(esp_netif_t * esp_netif)986 static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif)
987 {
988     esp_netif_ip_info_t *ip_info_old = esp_netif->ip_info;
989     struct netif *netif = esp_netif->lwip_netif;
990 
991     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
992 
993     if (esp_netif->timer_running) {
994         ESP_LOGD(TAG, "if%p start ip lost tmr: already started", esp_netif);
995         return ESP_OK;
996     }
997 
998     if ( netif && (CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL > 0) && !ip4_addr_isany_val(ip_info_old->ip)) {
999         esp_netif->timer_running = true;
1000         sys_timeout(CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL * 1000, esp_netif_ip_lost_timer, (void *)esp_netif);
1001         ESP_LOGD(TAG, "if%p start ip lost tmr: interval=%d", esp_netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL);
1002         return ESP_OK;
1003     }
1004 
1005     ESP_LOGD(TAG, "if%p start ip lost tmr: no need start because netif=%p interval=%d ip=%x",
1006              esp_netif, netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL, ip_info_old->ip.addr);
1007 
1008     return ESP_OK;
1009 }
1010 
esp_netif_dhcpc_stop_api(esp_netif_api_msg_t * msg)1011 static esp_err_t esp_netif_dhcpc_stop_api(esp_netif_api_msg_t *msg)
1012 {
1013     esp_netif_t *esp_netif = msg->esp_netif;
1014 
1015     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1016 
1017     if (esp_netif == NULL) {
1018         ESP_LOGE(TAG, "dhcp client stop called with NULL api");
1019         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1020     }
1021 
1022     if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1023         struct netif *p_netif = esp_netif->lwip_netif;
1024 
1025         if (p_netif != NULL) {
1026             dhcp_stop(p_netif);
1027             esp_netif_reset_ip_info(esp_netif);
1028             esp_netif_start_ip_lost_timer(esp_netif);
1029         } else {
1030             ESP_LOGD(TAG, "dhcp client if not ready");
1031             return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1032         }
1033     } else if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
1034         ESP_LOGD(TAG, "dhcp client already stoped");
1035         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
1036     }
1037 
1038     ESP_LOGD(TAG, "dhcp client stop successfully");
1039     esp_netif->dhcpc_status = ESP_NETIF_DHCP_STOPPED;
1040 
1041     LWIP_DHCP_IP_ADDR_ERASE(esp_netif);
1042 
1043     return ESP_OK;
1044 }
1045 
esp_netif_dhcpc_stop(esp_netif_t * esp_netif)1046 esp_err_t esp_netif_dhcpc_stop(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_dhcpc_stop_api, esp_netif, NULL)
1047 
1048 static esp_err_t esp_netif_dhcpc_start_api(esp_netif_api_msg_t *msg)
1049 {
1050     esp_netif_t *esp_netif = msg->esp_netif;
1051 
1052     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1053 
1054     if (!esp_netif) {
1055         return ESP_ERR_INVALID_ARG;
1056     }
1057 
1058     if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1059         ESP_LOGD(TAG, "dhcp client already started");
1060         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1061     }
1062 
1063     struct netif *p_netif = esp_netif->lwip_netif;
1064 
1065     esp_netif_reset_ip_info(esp_netif);
1066 
1067 #if LWIP_DNS
1068     dns_clear_servers(true);
1069 #endif
1070 
1071     if (p_netif != NULL) {
1072         if (netif_is_up(p_netif)) {
1073             ip_addr_set_zero(&p_netif->ip_addr);
1074             ip_addr_set_zero(&p_netif->netmask);
1075             ip_addr_set_zero(&p_netif->gw);
1076             esp_netif_start_ip_lost_timer(esp_netif);
1077         } else {
1078             ESP_LOGD(TAG, "dhcp client re init");
1079             esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1080             return ESP_OK;
1081         }
1082         ESP_LOGD(TAG, "starting dhcp client");
1083 
1084         if (dhcp_start(p_netif) != ERR_OK) {
1085             ESP_LOGE(TAG, "dhcp client start failed");
1086             return ESP_ERR_ESP_NETIF_DHCPC_START_FAILED;
1087         }
1088 
1089         dhcp_set_cb(p_netif, esp_netif_dhcpc_cb);
1090 
1091         esp_netif->dhcpc_status = ESP_NETIF_DHCP_STARTED;
1092         return ESP_OK;
1093     } else {
1094         ESP_LOGD(TAG, "dhcp client re init");
1095         esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1096         return ESP_OK;
1097     }
1098 }
1099 
esp_netif_dhcpc_start(esp_netif_t * esp_netif)1100 esp_err_t esp_netif_dhcpc_start(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_dhcpc_start_api, esp_netif, NULL)
1101 
1102 #if ESP_DHCPS
1103 esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
1104 {
1105     if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1106         return ESP_ERR_INVALID_ARG;
1107     }
1108 
1109     *status = esp_netif->dhcps_status;
1110     return ESP_OK;
1111 }
1112 #endif
1113 
esp_netif_dhcpc_get_status(esp_netif_t * esp_netif,esp_netif_dhcp_status_t * status)1114 esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
1115 {
1116     if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_SERVER) || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1117         return ESP_ERR_INVALID_ARG;
1118     }
1119 
1120     *status = esp_netif->dhcpc_status;
1121     return ESP_OK;
1122 }
1123 
1124 #if ESP_DHCPS
esp_netif_dhcps_start_api(esp_netif_api_msg_t * msg)1125 static esp_err_t esp_netif_dhcps_start_api(esp_netif_api_msg_t *msg)
1126 {
1127     esp_netif_t *esp_netif = msg->esp_netif;
1128 
1129     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1130 
1131     if (!esp_netif) {
1132         return ESP_ERR_INVALID_ARG;
1133     }
1134 
1135     if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) {
1136         ESP_LOGD(TAG, "dhcp server already started");
1137         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1138     }
1139 
1140     struct netif *p_netif = esp_netif->lwip_netif;
1141     if (p_netif != NULL && netif_is_up(p_netif)) {
1142         esp_netif_ip_info_t *default_ip = esp_netif->ip_info;
1143         ip4_addr_t lwip_ip;
1144         ip4_addr_t lwip_netmask;
1145         memcpy(&lwip_ip, &default_ip->ip, sizeof(struct ip4_addr));
1146         memcpy(&lwip_netmask, &default_ip->netmask, sizeof(struct ip4_addr));
1147         dhcps_set_new_lease_cb(esp_netif_dhcps_cb);
1148         dhcps_set_option_info(SUBNET_MASK, (void*)&lwip_netmask, sizeof(lwip_netmask));
1149         dhcps_start(p_netif, lwip_ip);
1150         esp_netif->dhcps_status = ESP_NETIF_DHCP_STARTED;
1151         ESP_LOGD(TAG, "DHCP server started successfully");
1152         return ESP_OK;
1153     } else {
1154         ESP_LOGD(TAG, "dhcp server re init");
1155         esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
1156         return ESP_OK;
1157     }
1158 }
1159 
esp_netif_dhcps_start(esp_netif_t * esp_netif)1160 esp_err_t esp_netif_dhcps_start(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_dhcps_start_api, esp_netif, NULL)
1161 
1162 static esp_err_t esp_netif_dhcps_stop_api(esp_netif_api_msg_t *msg)
1163 {
1164     esp_netif_t *esp_netif = msg->esp_netif;
1165 
1166     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1167 
1168     if (!esp_netif) {
1169         return ESP_ERR_INVALID_ARG;
1170     }
1171 
1172     struct netif *p_netif = esp_netif->lwip_netif;
1173     if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) {
1174         if (p_netif != NULL) {
1175             dhcps_stop(p_netif);
1176         } else {
1177             ESP_LOGD(TAG, "dhcp server if not ready");
1178             return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1179         }
1180     } else if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STOPPED) {
1181         ESP_LOGD(TAG, "dhcp server already stoped");
1182         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
1183     }
1184 
1185     ESP_LOGD(TAG, "dhcp server stop successfully");
1186     esp_netif->dhcps_status = ESP_NETIF_DHCP_STOPPED;
1187     return ESP_OK;
1188 }
1189 
esp_netif_dhcps_stop(esp_netif_t * esp_netif)1190 esp_err_t esp_netif_dhcps_stop(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_dhcps_stop_api, esp_netif, NULL)
1191 #endif
1192 
1193 static esp_err_t esp_netif_set_hostname_api(esp_netif_api_msg_t *msg)
1194 {
1195     esp_netif_t *esp_netif = msg->esp_netif;
1196     const char *hostname = msg->data;
1197 
1198     ESP_LOGD(TAG, "%s esp_netif:%p hostname %s", __func__, esp_netif, hostname);
1199 
1200     if (!esp_netif) {
1201         return ESP_ERR_INVALID_ARG;
1202     }
1203 
1204 #if LWIP_NETIF_HOSTNAME
1205 
1206     struct netif *p_netif = esp_netif->lwip_netif;
1207 
1208     if (strlen(hostname) > ESP_NETIF_HOSTNAME_MAX_SIZE) {
1209         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1210     }
1211 
1212     if (p_netif != NULL) {
1213         if (esp_netif->hostname) {
1214             free(esp_netif->hostname);
1215         }
1216         esp_netif->hostname = strdup(hostname);
1217         if (esp_netif->hostname == NULL) {
1218             p_netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME;
1219             return ESP_ERR_NO_MEM;
1220         }
1221         p_netif->hostname = esp_netif->hostname;
1222         return ESP_OK;
1223     } else {
1224         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1225     }
1226 #else
1227     return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1228 #endif
1229 }
1230 
esp_netif_set_hostname(esp_netif_t * esp_netif,const char * hostname)1231 esp_err_t esp_netif_set_hostname(esp_netif_t *esp_netif, const char *hostname) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_set_hostname_api, esp_netif, hostname)
1232 
1233 esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname)
1234 {
1235     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1236 
1237     if (!esp_netif || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1238         return ESP_ERR_INVALID_ARG;
1239     }
1240 
1241 #if LWIP_NETIF_HOSTNAME
1242     struct netif *p_netif = esp_netif->lwip_netif;
1243 
1244     if (p_netif != NULL && p_netif->hostname != NULL) {
1245         *hostname = p_netif->hostname;
1246         return ESP_OK;
1247     } else {
1248         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1249     }
1250 #else
1251     return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1252 #endif
1253 }
1254 
esp_netif_up_api(esp_netif_api_msg_t * msg)1255 static esp_err_t esp_netif_up_api(esp_netif_api_msg_t *msg)
1256 {
1257     esp_netif_t *esp_netif = msg->esp_netif;
1258 
1259     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1260 
1261     if (!esp_netif) {
1262         return ESP_ERR_INVALID_STATE;
1263     }
1264 
1265     struct netif *lwip_netif = esp_netif->lwip_netif;
1266 
1267     /* use last obtained ip, or static ip */
1268     netif_set_addr(lwip_netif, (ip4_addr_t*)&esp_netif->ip_info->ip, (ip4_addr_t*)&esp_netif->ip_info->netmask, (ip4_addr_t*)&esp_netif->ip_info->gw);
1269     netif_set_up(lwip_netif);
1270 
1271     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
1272 
1273     return ESP_OK;
1274 }
1275 
esp_netif_up(esp_netif_t * esp_netif)1276 esp_err_t esp_netif_up(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK(esp_netif_up_api, esp_netif, NULL)
1277 
1278 static esp_err_t esp_netif_down_api(esp_netif_api_msg_t *msg)
1279 {
1280     esp_netif_t *esp_netif = msg->esp_netif;
1281 
1282     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1283 
1284     if (!esp_netif) {
1285         return ESP_ERR_INVALID_STATE;
1286     }
1287 
1288     struct netif *lwip_netif = esp_netif->lwip_netif;
1289 
1290     if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT && esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1291         dhcp_stop(esp_netif->lwip_netif);
1292 
1293         esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1294 
1295         esp_netif_reset_ip_info(esp_netif);
1296     }
1297 #if CONFIG_LWIP_IPV6
1298     for(int8_t i = 0 ;i < LWIP_IPV6_NUM_ADDRESSES ;i++) {
1299         netif_ip6_addr_set(lwip_netif, i, IP6_ADDR_ANY6);
1300         netif_ip6_addr_set_valid_life(lwip_netif, i, 0);
1301         netif_ip6_addr_set_pref_life(lwip_netif, i, 0);
1302         netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
1303     }
1304 #endif
1305     netif_set_addr(lwip_netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
1306     netif_set_down(lwip_netif);
1307 
1308     if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
1309         esp_netif_start_ip_lost_timer(esp_netif);
1310     }
1311 
1312     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);
1313 
1314     return ESP_OK;
1315 }
1316 
esp_netif_down(esp_netif_t * esp_netif)1317 esp_err_t esp_netif_down(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK(esp_netif_down_api, esp_netif, NULL)
1318 
1319 bool esp_netif_is_netif_up(esp_netif_t *esp_netif)
1320 {
1321     ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
1322 
1323     if (esp_netif != NULL && esp_netif->lwip_netif != NULL) {
1324         if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1325             // ppp implementation uses netif_set_link_up/down to update link state
1326             return netif_is_link_up(esp_netif->lwip_netif);
1327         }
1328         // esp-netif handlers and drivers take care to set_netif_up/down on link state update
1329         return netif_is_up(esp_netif->lwip_netif);
1330     } else {
1331         return false;
1332     }
1333 }
1334 
esp_netif_get_old_ip_info(esp_netif_t * esp_netif,esp_netif_ip_info_t * ip_info)1335 esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
1336 {
1337     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1338 
1339     if (esp_netif == NULL || ip_info == NULL) {
1340         return ESP_ERR_INVALID_ARG;
1341     }
1342     memcpy(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t));
1343     return ESP_OK;
1344 }
1345 
esp_netif_get_ip_info(esp_netif_t * esp_netif,esp_netif_ip_info_t * ip_info)1346 esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
1347 {
1348     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1349 
1350     if (esp_netif == NULL || ip_info == NULL) {
1351         return ESP_ERR_INVALID_ARG;
1352     }
1353 
1354     struct netif *p_netif = esp_netif->lwip_netif;
1355 
1356     if (p_netif != NULL && netif_is_up(p_netif)) {
1357         ip4_addr_set(&ip_info->ip, ip_2_ip4(&p_netif->ip_addr));
1358         ip4_addr_set(&ip_info->netmask, ip_2_ip4(&p_netif->netmask));
1359         ip4_addr_set(&ip_info->gw, ip_2_ip4(&p_netif->gw));
1360 
1361         return ESP_OK;
1362     }
1363 
1364     memcpy(ip_info, esp_netif->ip_info, sizeof(esp_netif_ip_info_t));
1365 
1366     return ESP_OK;
1367 }
1368 
1369 
esp_netif_is_valid_static_ip(esp_netif_ip_info_t * ip_info)1370 bool esp_netif_is_valid_static_ip(esp_netif_ip_info_t *ip_info)
1371 {
1372     if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask))) {
1373         // let's assume valid ip_info is when none of ip and netmask is 'any' address (zeros)
1374         return true;
1375     }
1376     return false;
1377 }
1378 
esp_netif_set_ip_old_info_api(esp_netif_api_msg_t * msg)1379 static esp_err_t esp_netif_set_ip_old_info_api(esp_netif_api_msg_t *msg)
1380 {
1381     esp_netif_t *esp_netif = msg->esp_netif;
1382     const esp_netif_ip_info_t *ip_info = msg->data;
1383 
1384     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1385 
1386     if (esp_netif == NULL || ip_info == NULL) {
1387         return ESP_ERR_INVALID_STATE;
1388     }
1389 
1390     memcpy(msg->esp_netif->ip_info_old, msg->data, sizeof(esp_netif_ip_info_t));
1391     return ESP_OK;
1392 }
1393 
esp_netif_set_old_ip_info(esp_netif_t * esp_netif,const esp_netif_ip_info_t * ip_info)1394 esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_set_ip_old_info_api, esp_netif, ip_info)
1395 
1396 static esp_err_t esp_netif_set_ip_info_api(esp_netif_api_msg_t *msg)
1397 {
1398     esp_netif_t *esp_netif = msg->esp_netif;
1399     const esp_netif_ip_info_t *ip_info = msg->data;
1400 
1401     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1402 
1403     if (esp_netif == NULL || ip_info == NULL) {
1404         return ESP_ERR_INVALID_STATE;
1405     }
1406 
1407     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1408         if (esp_netif->dhcps_status != ESP_NETIF_DHCP_STOPPED) {
1409             return ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED;
1410             }
1411     } else if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
1412         if (esp_netif->dhcpc_status != ESP_NETIF_DHCP_STOPPED) {
1413             return ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED;
1414         }
1415 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
1416         dns_clear_servers(true);
1417 #endif
1418     }
1419 
1420     ip4_addr_copy(esp_netif->ip_info->ip, ip_info->ip);
1421     ip4_addr_copy(esp_netif->ip_info->gw, ip_info->gw);
1422     ip4_addr_copy(esp_netif->ip_info->netmask, ip_info->netmask);
1423 
1424     struct netif *p_netif = esp_netif->lwip_netif;
1425 
1426     if (p_netif != NULL && netif_is_up(p_netif)) {
1427         netif_set_addr(p_netif, (ip4_addr_t*)&ip_info->ip, (ip4_addr_t*)&ip_info->netmask, (ip4_addr_t*)&ip_info->gw);
1428         if (ESP_NETIF_FLAG_EVENT_IP_MODIFIED & esp_netif->flags) {
1429             if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask) || ip4_addr_isany_val(ip_info->gw))) {
1430 
1431                 ip_event_t evt_id = esp_netif->get_ip_event;
1432                 ip_event_got_ip_t evt = { .esp_netif = esp_netif, .if_index = -1, .ip_changed = false};
1433                 int ret;
1434                 if (memcmp(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t))) {
1435                     evt.ip_changed = true;
1436                 }
1437 
1438                 memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t));
1439                 memcpy(esp_netif->ip_info_old, ip_info, sizeof(esp_netif_ip_info_t));
1440                 ret = esp_event_send_internal(IP_EVENT, evt_id, &evt, sizeof(evt), 0);
1441                 if (ESP_OK != ret) {
1442                     ESP_LOGE(TAG, "set ip info: failed to post got ip event (%x)", ret);
1443                 }
1444 
1445                 ESP_LOGD(TAG, "if%p netif set static ip: ip changed=%d", esp_netif, evt.ip_changed);
1446 
1447             }
1448         }
1449     }
1450 
1451     return ESP_OK;
1452 }
1453 
esp_netif_set_ip_info(esp_netif_t * esp_netif,const esp_netif_ip_info_t * ip_info)1454 esp_err_t esp_netif_set_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_set_ip_info_api, esp_netif, ip_info)
1455 
1456 static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg)
1457 {
1458     esp_netif_t *esp_netif = msg->esp_netif;
1459     esp_netif_dns_param_t *dns_param = msg->data;
1460     esp_netif_dns_type_t type = dns_param->dns_type;
1461     esp_netif_dns_info_t *dns = dns_param->dns_info;
1462 
1463     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1464 
1465     if (esp_netif == NULL) {
1466         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1467     }
1468 
1469     if (!dns) {
1470         ESP_LOGD(TAG, "set dns null dns");
1471         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1472     }
1473 
1474     if (ip4_addr_isany_val(dns->ip.u_addr.ip4)) {
1475         ESP_LOGD(TAG, "set dns invalid dns");
1476         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1477     }
1478 
1479     ESP_LOGD(TAG, "set dns if=%p type=%d dns=%x", esp_netif, type, dns->ip.u_addr.ip4.addr);
1480 
1481     ip_addr_t *lwip_ip = (ip_addr_t*)&dns->ip;
1482 #if CONFIG_LWIP_IPV6 && LWIP_IPV4
1483     lwip_ip->type = IPADDR_TYPE_V4;
1484 #endif
1485     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1486 #if ESP_DHCPS
1487         // if DHCP server configured to set DNS in dhcps API
1488         if (type != ESP_NETIF_DNS_MAIN) {
1489             ESP_LOGD(TAG, "set dns invalid type");
1490             return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1491         } else {
1492             dhcps_dns_setserver(lwip_ip);
1493         }
1494 #else
1495         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
1496 #endif
1497     } else {
1498         dns_setserver(type, lwip_ip);
1499     }
1500 
1501     return ESP_OK;
1502 }
1503 
esp_netif_set_dns_info(esp_netif_t * esp_netif,esp_netif_dns_type_t type,esp_netif_dns_info_t * dns)1504 esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns)
1505 {
1506     if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1507         return ESP_ERR_NOT_SUPPORTED;
1508     }
1509     esp_netif_dns_param_t dns_param = {
1510         .dns_type = type,
1511         .dns_info = dns
1512     };
1513     return esp_netif_lwip_ipc_call(esp_netif_set_dns_info_api, esp_netif, (void *)&dns_param);
1514 }
1515 
esp_netif_get_dns_info_api(esp_netif_api_msg_t * msg)1516 static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg)
1517 {
1518     esp_netif_t *esp_netif = msg->esp_netif;
1519     esp_netif_dns_param_t *dns_param = msg->data;
1520     esp_netif_dns_type_t type = dns_param->dns_type;
1521     esp_netif_dns_info_t *dns = dns_param->dns_info;
1522 
1523     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1524 
1525     if (!dns) {
1526         ESP_LOGE(TAG, "%s: dns_info cannot be NULL", __func__);
1527         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1528     }
1529 
1530     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1531 #if ESP_DHCPS
1532         ip4_addr_t dns_ip = dhcps_dns_getserver();
1533         memcpy(&dns->ip.u_addr.ip4, &dns_ip, sizeof(ip4_addr_t));
1534 #else
1535         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
1536 #endif
1537     } else {
1538         const ip_addr_t*  dns_ip = NULL;
1539         dns_ip = dns_getserver(type);
1540         if(dns_ip != NULL) {
1541             memcpy(&dns->ip, dns_ip, sizeof(ip_addr_t));
1542         }
1543     }
1544 
1545     return ESP_OK;
1546 }
1547 
esp_netif_get_dns_info(esp_netif_t * esp_netif,esp_netif_dns_type_t type,esp_netif_dns_info_t * dns)1548 esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns)
1549 {
1550     if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1551         const ip_addr_t *dns_ip = dns_getserver(type);
1552         if (dns_ip == IP_ADDR_ANY) {
1553             return ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED;
1554         }
1555 #if CONFIG_LWIP_IPV6
1556         memcpy(&dns->ip.u_addr.ip4, &dns_ip->u_addr.ip4, sizeof(ip4_addr_t));
1557 #else
1558         memcpy(&dns->ip.u_addr.ip4, &dns_ip->addr, sizeof(ip4_addr_t));
1559 #endif
1560         return ESP_OK;
1561     }
1562 
1563     esp_netif_dns_param_t dns_param = {
1564         .dns_type = type,
1565         .dns_info = dns
1566     };
1567     return esp_netif_lwip_ipc_call(esp_netif_get_dns_info_api, esp_netif, (void *)&dns_param);
1568 }
1569 
1570 #if CONFIG_LWIP_IPV6
esp_netif_ip6_get_addr_type(esp_ip6_addr_t * ip6_addr)1571 esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr)
1572 {
1573     ip6_addr_t* lwip_ip6_info = (ip6_addr_t*)ip6_addr;
1574 
1575     if (ip6_addr_isglobal(lwip_ip6_info)) {
1576         return ESP_IP6_ADDR_IS_GLOBAL;
1577     } else if (ip6_addr_islinklocal(lwip_ip6_info)) {
1578         return ESP_IP6_ADDR_IS_LINK_LOCAL;
1579     } else if (ip6_addr_issitelocal(lwip_ip6_info)) {
1580         return ESP_IP6_ADDR_IS_SITE_LOCAL;
1581     } else if (ip6_addr_isuniquelocal(lwip_ip6_info)) {
1582         return ESP_IP6_ADDR_IS_UNIQUE_LOCAL;
1583     } else if (ip6_addr_isipv4mappedipv6(lwip_ip6_info)) {
1584         return ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6;
1585     }
1586     return ESP_IP6_ADDR_IS_UNKNOWN;
1587 
1588 }
1589 
esp_netif_nd6_cb(struct netif * p_netif,uint8_t ip_index)1590 static void esp_netif_nd6_cb(struct netif *p_netif, uint8_t ip_index)
1591 {
1592     ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, p_netif);
1593     if (!p_netif) {
1594         ESP_LOGD(TAG, "esp_netif_nd6_cb called with null p_netif");
1595         return;
1596     }
1597 
1598     esp_netif_ip6_info_t ip6_info;
1599     ip6_addr_t lwip_ip6_info;
1600     //notify event
1601     ip_event_got_ip6_t evt = { .esp_netif = p_netif->state, .if_index = -1, .ip_index = ip_index };
1602 
1603     ip6_addr_set(&lwip_ip6_info, ip_2_ip6(&p_netif->ip6_addr[ip_index]));
1604 #if LWIP_IPV6_SCOPES
1605     memcpy(&ip6_info.ip, &lwip_ip6_info, sizeof(esp_ip6_addr_t));
1606 #else
1607     memcpy(&ip6_info.ip, &lwip_ip6_info, sizeof(ip6_addr_t));
1608     ip6_info.ip.zone = 0;   // zero out zone, as not used in lwip
1609 #endif /* LWIP_IPV6_SCOPES */
1610 
1611     memcpy(&evt.ip6_info, &ip6_info, sizeof(esp_netif_ip6_info_t));
1612     int ret = esp_event_send_internal(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0);
1613     if (ESP_OK != ret) {
1614         ESP_LOGE(TAG, "nd6 cb: failed to post IP_EVENT_GOT_IP6 (%x)", ret);
1615     }
1616 }
1617 
esp_netif_create_ip6_linklocal_api(esp_netif_api_msg_t * msg)1618 static esp_err_t esp_netif_create_ip6_linklocal_api(esp_netif_api_msg_t *msg)
1619 {
1620     esp_netif_t *esp_netif = msg->esp_netif;
1621 
1622     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
1623 
1624     struct netif *p_netif = esp_netif->lwip_netif;
1625     if (p_netif != NULL && netif_is_up(p_netif)) {
1626         netif_create_ip6_linklocal_address(p_netif, 1);
1627         nd6_set_cb(p_netif, esp_netif_nd6_cb);
1628         return ESP_OK;
1629     } else {
1630         return ESP_FAIL;
1631     }
1632 }
1633 
esp_netif_create_ip6_linklocal(esp_netif_t * esp_netif)1634 esp_err_t esp_netif_create_ip6_linklocal(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUPPORTED(esp_netif_create_ip6_linklocal_api, esp_netif, NULL)
1635 
1636 esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
1637 {
1638     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
1639 
1640     if (esp_netif == NULL || if_ip6 == NULL || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1641         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1642     }
1643     struct netif *p_netif = esp_netif->lwip_netif;
1644 
1645     if (p_netif != NULL && netif_is_up(p_netif) && ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, 0))) {
1646         memcpy(if_ip6, &p_netif->ip6_addr[0], sizeof(ip6_addr_t));
1647     } else {
1648         return ESP_FAIL;
1649     }
1650     return ESP_OK;
1651 }
1652 
esp_netif_get_ip6_global(esp_netif_t * esp_netif,esp_ip6_addr_t * if_ip6)1653 esp_err_t esp_netif_get_ip6_global(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
1654 {
1655     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
1656 
1657     if (esp_netif == NULL || if_ip6 == NULL) {
1658         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1659     }
1660 
1661     int i;
1662     struct netif *p_netif = esp_netif->lwip_netif;
1663 
1664     if (p_netif != NULL && netif_is_up(p_netif)) {
1665         for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1666             if (ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, i)) &&
1667                 ip6_addr_isglobal(netif_ip6_addr(p_netif, i))) {
1668                     memcpy(if_ip6, &p_netif->ip6_addr[i], sizeof(ip6_addr_t));
1669                     return ESP_OK;
1670             }
1671         }
1672     }
1673 
1674     return ESP_FAIL;
1675 }
1676 
esp_netif_get_all_ip6(esp_netif_t * esp_netif,esp_ip6_addr_t if_ip6[])1677 int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[])
1678 {
1679     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
1680 
1681     if (esp_netif == NULL || if_ip6 == NULL) {
1682         return 0;
1683     }
1684 
1685     int addr_count = 0;
1686     struct netif *p_netif = esp_netif->lwip_netif;
1687 
1688     if (p_netif != NULL && netif_is_up(p_netif)) {
1689         for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1690             if (!ip_addr_cmp(&p_netif->ip6_addr[i], IP6_ADDR_ANY)) {
1691                 memcpy(&if_ip6[addr_count++], &p_netif->ip6_addr[i], sizeof(ip6_addr_t));
1692             }
1693         }
1694     }
1695     return addr_count;
1696 }
1697 #endif
1698 
esp_netif_get_flags(esp_netif_t * esp_netif)1699 esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif)
1700 {
1701     return esp_netif->flags;
1702 }
1703 
esp_netif_get_ifkey(esp_netif_t * esp_netif)1704 const char *esp_netif_get_ifkey(esp_netif_t *esp_netif)
1705 {
1706     return esp_netif->if_key;
1707 }
1708 
esp_netif_get_desc(esp_netif_t * esp_netif)1709 const char *esp_netif_get_desc(esp_netif_t *esp_netif)
1710 {
1711     return esp_netif->if_desc;
1712 }
1713 
esp_netif_get_route_prio(esp_netif_t * esp_netif)1714 int esp_netif_get_route_prio(esp_netif_t *esp_netif)
1715 {
1716     if (esp_netif == NULL) {
1717         return -1;
1718     }
1719     return esp_netif->route_prio;
1720 }
1721 
esp_netif_get_event_id(esp_netif_t * esp_netif,esp_netif_ip_event_type_t event_type)1722 int32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t event_type)
1723 {
1724     switch(event_type) {
1725         case ESP_NETIF_IP_EVENT_GOT_IP:
1726             return esp_netif->get_ip_event;
1727         case ESP_NETIF_IP_EVENT_LOST_IP:
1728             return esp_netif->lost_ip_event;
1729         default:
1730             return -1;
1731     }
1732 }
1733 
1734 #if ESP_DHCPS
esp_netif_dhcps_option(esp_netif_t * esp_netif,esp_netif_dhcp_option_mode_t opt_op,esp_netif_dhcp_option_id_t opt_id,void * opt_val,uint32_t opt_len)1735 esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
1736                                  uint32_t opt_len)
1737 {
1738     void *opt_info = dhcps_option_info(opt_id, opt_len);
1739     if (esp_netif == NULL) {
1740         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1741     }
1742 
1743     esp_netif_dhcp_status_t dhcps_status = esp_netif->dhcps_status;
1744     if (opt_info == NULL || opt_val == NULL) {
1745         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1746     }
1747 
1748     if (opt_op == ESP_NETIF_OP_GET) {
1749         if (dhcps_status == ESP_NETIF_DHCP_STOPPED) {
1750             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
1751         }
1752 
1753         switch (opt_id) {
1754             case IP_ADDRESS_LEASE_TIME: {
1755                 *(uint32_t *)opt_val = *(uint32_t *)opt_info;
1756                 break;
1757             }
1758             case ESP_NETIF_SUBNET_MASK:
1759             case REQUESTED_IP_ADDRESS: {
1760                 memcpy(opt_val, opt_info, opt_len);
1761                 break;
1762             }
1763             case ROUTER_SOLICITATION_ADDRESS: {
1764                 if ((*(uint8_t *)opt_info) & OFFER_ROUTER) {
1765                     *(uint8_t *)opt_val = 1;
1766                 } else {
1767                     *(uint8_t *)opt_val = 0;
1768                 }
1769                 break;
1770             }
1771             case DOMAIN_NAME_SERVER: {
1772                 if ((*(uint8_t *)opt_info) & OFFER_DNS) {
1773                     *(uint8_t *)opt_val = 1;
1774                 } else {
1775                     *(uint8_t *)opt_val = 0;
1776                 }
1777                 break;
1778             }
1779             default:
1780                 break;
1781         }
1782     } else if (opt_op == ESP_NETIF_OP_SET) {
1783         if (dhcps_status == ESP_NETIF_DHCP_STARTED) {
1784             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1785         }
1786 
1787         switch (opt_id) {
1788             case IP_ADDRESS_LEASE_TIME: {
1789                 if (*(uint32_t *)opt_val != 0) {
1790                     *(uint32_t *)opt_info = *(uint32_t *)opt_val;
1791                 } else {
1792                     *(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF;
1793                 }
1794                 break;
1795             }
1796             case ESP_NETIF_SUBNET_MASK: {
1797                 memcpy(opt_info, opt_val, opt_len);
1798                 break;
1799             }
1800             case REQUESTED_IP_ADDRESS: {
1801                 esp_netif_ip_info_t info;
1802                 uint32_t softap_ip = 0;
1803                 uint32_t start_ip = 0;
1804                 uint32_t end_ip = 0;
1805                 dhcps_lease_t *poll = opt_val;
1806 
1807                 if (poll->enable) {
1808                     memset(&info, 0x00, sizeof(esp_netif_ip_info_t));
1809                     esp_netif_get_ip_info(esp_netif, &info);
1810 
1811                     softap_ip = htonl(info.ip.addr);
1812                     start_ip = htonl(poll->start_ip.addr);
1813                     end_ip = htonl(poll->end_ip.addr);
1814 
1815                     /*config ip information can't contain local ip*/
1816                     if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
1817                         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1818                     }
1819 
1820                     /*config ip information must be in the same segment as the local ip*/
1821                     softap_ip >>= 8;
1822                     if ((start_ip >> 8 != softap_ip)
1823                         || (end_ip >> 8 != softap_ip)) {
1824                         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1825                     }
1826 
1827                     if (end_ip - start_ip > DHCPS_MAX_LEASE) {
1828                         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1829                     }
1830                 }
1831 
1832                 memcpy(opt_info, opt_val, opt_len);
1833                 break;
1834             }
1835             case ROUTER_SOLICITATION_ADDRESS: {
1836                 if (*(uint8_t *)opt_val) {
1837                     *(uint8_t *)opt_info |= OFFER_ROUTER;
1838                 } else {
1839                     *(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF);
1840                 }
1841                 break;
1842             }
1843             case DOMAIN_NAME_SERVER: {
1844                 if (*(uint8_t *)opt_val) {
1845                     *(uint8_t *)opt_info |= OFFER_DNS;
1846                 } else {
1847                     *(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF);
1848                 }
1849                 break;
1850             }
1851 
1852             default:
1853                 break;
1854         }
1855         dhcps_set_option_info(opt_id, opt_info, opt_len);
1856     } else {
1857         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1858     }
1859 
1860     return ESP_OK;
1861 }
1862 #endif
1863 
esp_netif_dhcpc_option(esp_netif_t * esp_netif,esp_netif_dhcp_option_mode_t opt_op,esp_netif_dhcp_option_id_t opt_id,void * opt_val,uint32_t opt_len)1864 esp_err_t esp_netif_dhcpc_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
1865                                  uint32_t opt_len)
1866 {
1867     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
1868         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1869     }
1870     struct dhcp *dhcp = netif_dhcp_data(esp_netif->lwip_netif);
1871      if (dhcp == NULL || opt_val == NULL) {
1872         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1873     }
1874     if (opt_op == ESP_NETIF_OP_GET) {
1875         if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
1876             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
1877         }
1878         switch (opt_id) {
1879             case ESP_NETIF_IP_REQUEST_RETRY_TIME:
1880                 if (opt_len == sizeof(dhcp->tries)) {
1881                     *(uint8_t *)opt_val = dhcp->tries;
1882                 }
1883                 break;
1884 #if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
1885             case ESP_NETIF_VENDOR_SPECIFIC_INFO:
1886                 return dhcp_get_vendor_specific_information(opt_len, opt_val);
1887 #endif
1888             default:
1889                 return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1890         }
1891     } else if (opt_op == ESP_NETIF_OP_SET) {
1892         if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1893             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1894         }
1895         switch (opt_id) {
1896             case ESP_NETIF_IP_REQUEST_RETRY_TIME:
1897                 if (opt_len == sizeof(dhcp->tries)) {
1898                     dhcp->tries = *(uint8_t *)opt_val;
1899                 }
1900                 break;
1901 #if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
1902             case ESP_NETIF_VENDOR_CLASS_IDENTIFIER:
1903                 return dhcp_set_vendor_class_identifier(opt_len, opt_val);
1904 #endif
1905             default:
1906                 return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1907         }
1908     } else {
1909         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1910     }
1911     return ESP_OK;
1912 }
1913 
esp_netif_get_netif_impl_index(esp_netif_t * esp_netif)1914 int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
1915 {
1916     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
1917         return -1;
1918     }
1919     return netif_get_index(esp_netif->lwip_netif);
1920 }
1921 
esp_netif_get_netif_impl_name(esp_netif_t * esp_netif,char * name)1922 esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
1923 {
1924     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1925 
1926     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
1927         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1928     }
1929     netif_index_to_name(netif_get_index(esp_netif->lwip_netif), name);
1930     return ESP_OK;
1931 }
1932 
1933 #if CONFIG_LWIP_IPV6
1934 
esp_netif_join_ip6_multicast_group_api(esp_netif_api_msg_t * msg)1935 static esp_err_t esp_netif_join_ip6_multicast_group_api(esp_netif_api_msg_t *msg)
1936 {
1937     esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
1938     esp_err_t error = ESP_OK;
1939     ip6_addr_t ip6addr;
1940 
1941     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
1942     memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
1943 #if LWIP_IPV6_SCOPES
1944     ip6addr.zone = 0;
1945 #endif
1946     if (mld6_joingroup_netif(msg->esp_netif->lwip_netif, &ip6addr) != ERR_OK) {
1947         error = ESP_ERR_ESP_NETIF_MLD6_FAILED;
1948         ESP_LOGE(TAG, "failed to join ip6 multicast group");
1949     }
1950     return error;
1951 }
1952 
esp_netif_join_ip6_multicast_group(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)1953 esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
1954     _RUN_IN_LWIP_TASK(esp_netif_join_ip6_multicast_group_api, esp_netif, addr)
1955 
1956 static esp_err_t esp_netif_leave_ip6_multicast_group_api(esp_netif_api_msg_t *msg)
1957 {
1958     esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
1959     ip6_addr_t ip6addr;
1960 
1961     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
1962     memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
1963 #if LWIP_IPV6_SCOPES
1964     ip6addr.zone = 0;
1965 #endif
1966     ESP_RETURN_ON_FALSE(mld6_leavegroup_netif(msg->esp_netif->lwip_netif, &ip6addr) != ERR_OK,
1967                         ESP_ERR_ESP_NETIF_MLD6_FAILED, TAG, "Failed to leave ip6 multicast group");
1968     return ESP_OK;
1969 }
1970 
esp_netif_leave_ip6_multicast_group(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)1971 esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
1972     _RUN_IN_LWIP_TASK(esp_netif_leave_ip6_multicast_group_api, esp_netif, addr)
1973 
1974 static esp_err_t esp_netif_add_ip6_address_api(esp_netif_api_msg_t *msg)
1975 {
1976     ip_event_add_ip6_t *addr = (ip_event_add_ip6_t *)msg->data;
1977     ip6_addr_t ip6addr;
1978     esp_err_t error = ESP_OK;
1979     int8_t index = -1;
1980 
1981     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
1982     memcpy(ip6addr.addr, addr->addr.addr, sizeof(ip6addr.addr));
1983 #if LWIP_IPV6_SCOPES
1984     ip6addr.zone = 0;
1985 #endif
1986     err_t err = netif_add_ip6_address(msg->esp_netif->lwip_netif, &ip6addr, &index);
1987     ESP_RETURN_ON_FALSE(err == ERR_OK && index >= 0, ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED, TAG,
1988                         "Failed to add ip6 address");
1989 
1990     netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index,
1991                              addr->preferred ? IP6_ADDR_PREFERRED : IP6_ADDR_DEPRECATED);
1992     ip_event_got_ip6_t evt = {.esp_netif = msg->esp_netif, .if_index = -1, .ip_index = index};
1993     evt.ip6_info.ip = addr->addr;
1994     ESP_RETURN_ON_ERROR(esp_event_send_internal(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0), TAG,
1995                         "Failed to post IP_EVENT_GOT_IP6");
1996     return error;
1997 }
1998 
esp_netif_add_ip6_address(esp_netif_t * esp_netif,const ip_event_add_ip6_t * addr)1999 esp_err_t esp_netif_add_ip6_address(esp_netif_t *esp_netif, const ip_event_add_ip6_t *addr)
2000     _RUN_IN_LWIP_TASK(esp_netif_add_ip6_address_api, esp_netif, addr)
2001 
2002 static esp_err_t esp_netif_remove_ip6_address_api(esp_netif_api_msg_t *msg)
2003 {
2004     esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
2005     ip6_addr_t ip6addr;
2006 
2007     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
2008     memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
2009 #if LWIP_IPV6_SCOPES
2010     ip6addr.zone = 0;
2011 #endif
2012     int8_t index = netif_get_ip6_addr_match(msg->esp_netif->lwip_netif, &ip6addr);
2013     if (index != -1) {
2014         netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index, IP6_ADDR_INVALID);
2015     }
2016     return ESP_OK;
2017 }
2018 
2019 esp_err_t esp_netif_remove_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
2020     _RUN_IN_LWIP_TASK(esp_netif_remove_ip6_address_api, esp_netif, addr)
2021 
2022 #endif // CONFIG_LWIP_IPV6
2023 
2024 #endif /* CONFIG_ESP_NETIF_TCPIP_LWIP */
2025