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