1 /*
2  * SPDX-FileCopyrightText: 2019-2022 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 #include "lwip/esp_netif_net_stack.h"
14 
15 
16 #include "esp_netif.h"
17 #include "esp_netif_private.h"
18 #include "esp_random.h"
19 #include "esp_system.h"
20 
21 #include "lwip/tcpip.h"
22 #include "lwip/dhcp.h"
23 #include "lwip/ip_addr.h"
24 #include "lwip/ip6_addr.h"
25 #include "lwip/mld6.h"
26 #include "lwip/prot/mld6.h"
27 #include "lwip/nd6.h"
28 #include "lwip/snmp.h"
29 #include "lwip/priv/tcpip_priv.h"
30 #include "lwip/netif.h"
31 #include "lwip/etharp.h"
32 #if CONFIG_ESP_NETIF_BRIDGE_EN
33 #include "netif/bridgeif.h"
34 #endif // CONFIG_ESP_NETIF_BRIDGE_EN
35 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
36 #include "lwip/dns.h"
37 #endif // LWIP_DNS
38 
39 #if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
40 #include "lwip_default_hooks.h"
41 #endif // CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
42 
43 #include "esp_netif_lwip_ppp.h"
44 #if ESP_DHCPS
45 #include "dhcpserver/dhcpserver.h"
46 #include "dhcpserver/dhcpserver_options.h"
47 #endif
48 #include "netif/dhcp_state.h"
49 #include "esp_event.h"
50 #include "esp_log.h"
51 #if IP_NAPT
52 #include "lwip/lwip_napt.h"
53 #endif
54 
55 
56 //
57 // This is the main module implementing lwip interaction with esp-netif
58 //
59 
60 #define ESP_NETIF_HOSTNAME_MAX_SIZE    32
61 
62 #define DHCP_CB_CHANGE (LWIP_NSC_IPV4_SETTINGS_CHANGED | LWIP_NSC_IPV4_ADDRESS_CHANGED | LWIP_NSC_IPV4_GATEWAY_CHANGED | LWIP_NSC_IPV4_NETMASK_CHANGED)
63 
64 /**
65  * @brief lwip thread safe tcpip function utility macros
66  */
67 #define _RUN_IN_LWIP_TASK(function, netif, param) { return esp_netif_lwip_ipc_call(function, netif, (void *)(param)); }
68 
69 /**
70  * @brief macros to check netif related data to evaluate interface type
71  */
72 #if CONFIG_PPP_SUPPORT
73 #define _IS_NETIF_ANY_POINT2POINT_TYPE(netif) (netif->related_data && netif->related_data->is_point2point)
74 #else
75 #define _IS_NETIF_ANY_POINT2POINT_TYPE(netif) false
76 #endif
77 #define _RUN_IN_LWIP_TASK_IF_SUPPORTED(function, netif, param) \
78 {                                                              \
79     if (_IS_NETIF_ANY_POINT2POINT_TYPE(netif)) {               \
80         return ESP_ERR_NOT_SUPPORTED;                          \
81     }                                                          \
82     return esp_netif_lwip_ipc_call(function, netif, (void *)(param)); \
83 }
84 
85 /**
86  * @brief Utility macros to convert esp-ip addresses (both IPv6+IPv4 versions unconditionally)
87  * and lwip-ip addresses (contain only enabled portion of the address for each IP stack)
88 */
89 
90 #if LWIP_IPV4 && LWIP_IPV6
91 #define ESPIP_TO_IP(espip, ip) memcpy((ip), (espip), sizeof(ip_addr_t));
92 #define IP_TO_ESPIP(ip, espip) memcpy((espip), (ip), sizeof(ip_addr_t));
93 #elif LWIP_IPV4
94 #define ESPIP_TO_IP(espip, ip) memcpy((ip), &((espip)->u_addr.ip4), sizeof(ip_addr_t));
95 #define IP_TO_ESPIP(ip, espip) do { memcpy(&((espip)->u_addr.ip4), (ip), sizeof(ip4_addr_t)); \
96                                     (espip)->type = ESP_IPADDR_TYPE_V4;                       \
97                                } while(0)
98 #elif LWIP_IPV6
99 #define ESPIP_TO_IP(espip, ip) memcpy((ip), &((espip)->u_addr.ip6), sizeof(ip_addr_t));
100 #define IP_TO_ESPIP(ip, espip) do { memcpy(&((espip)->u_addr.ip6), (ip), sizeof(ip6_addr_t)); \
101                                     (espip)->type = ESP_IPADDR_TYPE_V6;                       \
102                               } while(0)
103 #endif
104 
105 /**
106  * @brief If netif protocol not enabled in menuconfig, log the error and return appropriate code indicating failure
107 */
108 
109 #define LOG_NETIF_DISABLED_AND_DO(proto, action)                                                \
110 do {                                                                                            \
111     ESP_LOGE(TAG, "%s not supported, please enable it in lwIP component configuration", proto); \
112     action;                                                                                     \
113 } while(0)
114 
115 //
116 //  Internal types
117 //
118 typedef enum esp_netif_action {
119     ESP_NETIF_UNDEF,
120     ESP_NETIF_STARTED,
121     ESP_NETIF_STOPPED,
122     ESP_NETIF_SET_DEFAULT,
123 } esp_netif_action_t;
124 
125 //
126 //  Internal variables for this module
127 //
128 static const char *TAG = "esp_netif_lwip";
129 
130 #if LWIP_ESP_NETIF_DATA
131 static u8_t lwip_netif_client_id = 0xff;
132 #endif
133 static esp_netif_t *s_last_default_esp_netif = NULL;
134 static bool s_is_last_default_esp_netif_overridden = false;
135 static netif_ext_callback_t netif_callback = { .callback_fn = NULL, .next = NULL };
136 
137 #if LWIP_IPV4
138 static void esp_netif_internal_dhcpc_cb(struct netif *netif);
139 #endif
140 #if LWIP_IPV6
141 static void esp_netif_internal_nd6_cb(struct netif *p_netif, uint8_t ip_index);
142 static void netif_set_mldv6_flag(struct netif *netif);
143 static void netif_unset_mldv6_flag(struct netif *netif);
144 #endif /* LWIP_IPV6 */
145 
netif_callback_fn(struct netif * netif,netif_nsc_reason_t reason,const netif_ext_callback_args_t * args)146 static void netif_callback_fn(struct netif* netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t* args)
147 {
148 #if LWIP_IPV4
149     if (reason & DHCP_CB_CHANGE) {
150         esp_netif_internal_dhcpc_cb(netif);
151     }
152 #endif /* LWIP_IPV4 */
153 #if LWIP_IPV6
154     if ((reason & LWIP_NSC_IPV6_ADDR_STATE_CHANGED) && (args != NULL)) {
155         s8_t addr_idx = args->ipv6_addr_state_changed.addr_index;
156         if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID)  {
157             /* address is valid -> call the callback function */
158             esp_netif_internal_nd6_cb(netif, addr_idx);
159         }
160     }
161 #endif /* #if LWIP_IPV6 */
162 }
163 
164 #if LWIP_ESP_NETIF_DATA
alloc_client_data_id(esp_netif_api_msg_t * msg)165 static esp_err_t alloc_client_data_id(esp_netif_api_msg_t *msg)
166 {
167     uint8_t *client_data_id = msg->data;
168     *client_data_id = netif_alloc_client_data_id();
169     return ESP_OK;
170 }
171 #endif // LWIP_ESP_NETIF_DATA
172 
set_lwip_netif_callback(struct esp_netif_api_msg_s * msg)173 static esp_err_t set_lwip_netif_callback(struct esp_netif_api_msg_s *msg)
174 {
175     (void)msg;
176     netif_add_ext_callback(&netif_callback, netif_callback_fn);
177     return ESP_OK;
178 }
179 
remove_lwip_netif_callback(struct esp_netif_api_msg_s * msg)180 static esp_err_t remove_lwip_netif_callback(struct esp_netif_api_msg_s *msg)
181 {
182     (void)msg;
183     netif_remove_ext_callback(&netif_callback);
184     memset(&netif_callback, 0, sizeof(netif_callback));
185     return ESP_OK;
186 }
187 
188 #ifdef CONFIG_LWIP_GARP_TMR_INTERVAL
189 
netif_send_garp(void * arg)190 static void netif_send_garp(void *arg)
191 {
192     struct netif *netif = arg;
193     if (!ip4_addr_cmp(netif_ip4_addr(netif), IP4_ADDR_ANY4)) {  // Send GARP requests only if we have a valid IP
194         etharp_gratuitous(netif);
195     }
196     sys_timeout(CONFIG_LWIP_GARP_TMR_INTERVAL*1000, netif_send_garp, netif);
197 }
198 
netif_set_garp_flag(struct netif * netif)199 static void netif_set_garp_flag(struct netif *netif)
200 {
201     sys_timeout(CONFIG_LWIP_GARP_TMR_INTERVAL*1000, netif_send_garp, netif);
202 }
203 
netif_unset_garp_flag(struct netif * netif)204 static void netif_unset_garp_flag(struct netif *netif)
205 {
206     sys_untimeout(netif_send_garp, netif);
207 }
208 
209 #endif  // CONFIG_LWIP_GARP_TMR_INTERVAL
210 
211 #if !LWIP_TCPIP_CORE_LOCKING
212 static sys_sem_t api_sync_sem = NULL;
213 static sys_sem_t api_lock_sem = NULL;
214 #endif
215 
216 /**
217  * @brief Api callback from tcpip thread used to call esp-netif
218  * function in lwip task context
219  */
esp_netif_api_cb(void * api_msg)220 static void esp_netif_api_cb(void *api_msg)
221 {
222     esp_netif_api_msg_t *msg = (esp_netif_api_msg_t *)api_msg;
223 
224     if (!msg || !msg->api_fn) {
225         ESP_LOGD(TAG, "null msg/api_fn");
226         return;
227     }
228 
229     msg->ret = msg->api_fn(msg);
230     ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
231 #if !LWIP_TCPIP_CORE_LOCKING
232     sys_sem_signal(&api_sync_sem);
233 #endif
234 }
235 
236 
237 /**
238  * @brief Initiates a tcpip remote call if called from another task
239  * or calls the function directly if executed from lwip task
240  */
esp_netif_lwip_ipc_call_msg(esp_netif_api_msg_t * msg)241 static inline esp_err_t esp_netif_lwip_ipc_call_msg(esp_netif_api_msg_t *msg)
242 {
243     if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) {
244         ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", msg->esp_netif, msg->api_fn);
245 #if LWIP_TCPIP_CORE_LOCKING
246         tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, NULL);
247 #else
248         sys_arch_sem_wait(&api_lock_sem, 0);
249         tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, &api_sync_sem);
250         sys_sem_signal(&api_lock_sem);
251 #endif /* LWIP_TCPIP_CORE_LOCKING */
252         return msg->ret;
253     }
254     ESP_LOGD(TAG, "check: local, if=%p fn=%p\n",  msg->esp_netif, msg->api_fn);
255     return msg->api_fn(msg);
256 }
257 
esp_netif_lwip_ipc_call(esp_netif_api_fn fn,esp_netif_t * netif,void * data)258 static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t* netif, void *data)
259 {
260     esp_netif_api_msg_t msg = {
261             .esp_netif = netif,
262             .data = data,
263             .api_fn = fn
264     };
265     return esp_netif_lwip_ipc_call_msg(&msg);
266 }
267 
esp_netif_lwip_ipc_call_fn(esp_netif_api_fn fn,esp_netif_callback_fn user_fn,void * ctx)268 static inline esp_err_t esp_netif_lwip_ipc_call_fn(esp_netif_api_fn fn, esp_netif_callback_fn user_fn, void *ctx)
269 {
270     esp_netif_api_msg_t msg = {
271             .user_fn = user_fn,
272             .data = ctx,
273             .api_fn = fn
274     };
275     return esp_netif_lwip_ipc_call_msg(&msg);
276 }
277 
esp_netif_lwip_ipc_no_args(esp_netif_api_fn fn)278 static inline esp_err_t esp_netif_lwip_ipc_no_args(esp_netif_api_fn fn)
279 {
280     esp_netif_api_msg_t msg = {
281             .api_fn = fn
282     };
283     return esp_netif_lwip_ipc_call_msg(&msg);
284 }
285 
286 /**
287  * @brief Check if supplied esp_netif handle is active, i.e. available within registered interfaces
288  * as it might have already been destroyed. Returns the supplied handle if active, nullptr otherwise
289  *
290  * @param esp_netif handle to check if available in the list of registered interfaces
291  * @return esp_netif handle if available, or NULL if it wasn't found
292  */
esp_netif_is_active(esp_netif_t * arg)293 static esp_netif_t* esp_netif_is_active(esp_netif_t *arg)
294 {
295     // looking for the netif in the list of registered interfaces
296     //  as it might have already been destroyed
297     if (esp_netif_is_netif_listed(arg)) {
298         return arg;
299     }
300     return NULL;
301 }
302 
303 /**
304  * @brief This function sets default netif no matter which implementation used
305  *
306  * @param esp_netif handle to network interface
307  *
308  * @note: This function must be called from lwip thread
309  */
esp_netif_set_default_netif_internal(esp_netif_t * esp_netif)310 static void esp_netif_set_default_netif_internal(esp_netif_t *esp_netif)
311 {
312     if (ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
313 #if CONFIG_PPP_SUPPORT
314         esp_netif_ppp_set_default_netif(esp_netif->netif_handle);
315 #endif
316     } else {
317         netif_set_default(esp_netif->lwip_netif);
318     }
319 }
320 
321 /**
322  * @brief tcpip thread version of esp_netif_update_default_netif
323  *
324  * @note This function and all functions called from this must be called from lwip task context
325  */
esp_netif_update_default_netif_lwip(esp_netif_api_msg_t * msg)326 static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg)
327 {
328     esp_netif_t *esp_netif = msg->esp_netif;
329     esp_netif_action_t action = (esp_netif_action_t)msg->data;
330 
331     ESP_LOGD(TAG, "%s %p", __func__, esp_netif);
332 
333     if (s_is_last_default_esp_netif_overridden && action != ESP_NETIF_SET_DEFAULT) {
334         // check if manually configured default interface hasn't been destroyed
335         s_last_default_esp_netif = esp_netif_is_active(s_last_default_esp_netif);
336         if (s_last_default_esp_netif != NULL) {
337             return ESP_OK; // still valid -> don't update default netif
338         }
339         // invalid -> reset the manual override and perform auto update
340         s_is_last_default_esp_netif_overridden = false;
341     }
342     switch (action) {
343         case ESP_NETIF_SET_DEFAULT:
344             s_last_default_esp_netif = esp_netif;
345             s_is_last_default_esp_netif_overridden = true;
346             esp_netif_set_default_netif_internal(s_last_default_esp_netif);
347         break;
348         case ESP_NETIF_STARTED:
349         {
350             // check if previously default interface hasn't been destroyed in the meantime
351             s_last_default_esp_netif = esp_netif_is_active(s_last_default_esp_netif);
352             if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)
353                 && (s_last_default_esp_netif->route_prio > esp_netif->route_prio)) {
354                 esp_netif_set_default_netif_internal(s_last_default_esp_netif);
355             } else if (esp_netif_is_netif_up(esp_netif)) {
356                 s_last_default_esp_netif = esp_netif;
357                 esp_netif_set_default_netif_internal(s_last_default_esp_netif);
358             }
359         }
360         break;
361 
362         default:
363         case ESP_NETIF_STOPPED:
364         {
365             s_last_default_esp_netif = NULL;
366             esp_netif_list_lock();
367             esp_netif_t *netif = esp_netif_next_unsafe(NULL);
368             while (netif) {
369                 if (esp_netif_is_netif_up(netif)) {
370                     if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)) {
371                         if (netif->route_prio > s_last_default_esp_netif->route_prio) {
372                             s_last_default_esp_netif = netif;
373                         } // else not needed, as the s_last_default_esp_netif is correct
374                     } else {
375                         // s_last_default is either not set or down, current netif is up
376                         s_last_default_esp_netif = netif;
377                     }
378                 }
379                 netif = esp_netif_next_unsafe(netif);
380             }
381             esp_netif_list_unlock();
382             if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)) {
383                 esp_netif_set_default_netif_internal(s_last_default_esp_netif);
384             }
385         }
386         break;
387     }
388     return ESP_OK;
389 }
390 
391 /**
392  * @brief This function sets default routing netif based on priorities of all interfaces which are up
393  *
394  * @param esp_netif current interface which just updated state
395  * @param action updating action (on-off)
396  */
esp_netif_update_default_netif(esp_netif_t * esp_netif,esp_netif_action_t action)397 static esp_err_t esp_netif_update_default_netif(esp_netif_t *esp_netif, esp_netif_action_t action)
398 {
399     return esp_netif_lwip_ipc_call(esp_netif_update_default_netif_lwip, esp_netif, (void*)action);
400 }
401 
esp_netif_set_default_netif(esp_netif_t * esp_netif)402 esp_err_t esp_netif_set_default_netif(esp_netif_t *esp_netif)
403 {
404     return esp_netif_update_default_netif(esp_netif, ESP_NETIF_SET_DEFAULT);
405 }
406 
esp_netif_get_default_netif(void)407 esp_netif_t *esp_netif_get_default_netif(void)
408 {
409     return s_last_default_esp_netif;
410 }
411 
lwip_get_esp_netif(struct netif * netif)412 static inline esp_netif_t* lwip_get_esp_netif(struct netif *netif)
413 {
414 #if LWIP_ESP_NETIF_DATA
415     return (esp_netif_t*)netif_get_client_data(netif, lwip_netif_client_id);
416 #else
417     return (esp_netif_t*)netif->state;
418 #endif
419 }
420 
lwip_set_esp_netif(struct netif * netif,esp_netif_t * esp_netif)421 static inline void lwip_set_esp_netif(struct netif *netif, esp_netif_t* esp_netif)
422 {
423 #if LWIP_ESP_NETIF_DATA
424     netif_set_client_data(netif, lwip_netif_client_id, esp_netif);
425 #else
426     netif->state = esp_netif;
427 #endif
428 }
429 
430 #if CONFIG_ESP_NETIF_BRIDGE_EN
esp_netif_bridge_add_port(esp_netif_t * esp_netif_br,esp_netif_t * esp_netif_port)431 esp_err_t esp_netif_bridge_add_port(esp_netif_t *esp_netif_br, esp_netif_t *esp_netif_port)
432 {
433     if (ERR_OK != bridgeif_add_port(esp_netif_br->lwip_netif, esp_netif_port->lwip_netif)) {
434         return ESP_FAIL;
435     }
436     return ESP_OK;
437 }
438 
esp_netif_bridge_fdb_add(esp_netif_t * esp_netif_br,uint8_t * addr,uint64_t ports_mask)439 esp_err_t esp_netif_bridge_fdb_add(esp_netif_t *esp_netif_br, uint8_t *addr, uint64_t ports_mask)
440 {
441     bridgeif_portmask_t ports = (bridgeif_portmask_t)ports_mask;
442     if (ports_mask & ESP_NETIF_BR_FDW_CPU) {
443         ports |= 1 << BRIDGEIF_MAX_PORTS;
444     }
445 
446     if (ERR_OK != bridgeif_fdb_add(esp_netif_br->lwip_netif, (const struct eth_addr *)addr, ports)) {
447         return ESP_FAIL;
448     }
449     return ESP_OK;
450 }
451 
esp_netif_bridge_fdb_remove(esp_netif_t * esp_netif_br,uint8_t * addr)452 esp_err_t esp_netif_bridge_fdb_remove(esp_netif_t *esp_netif_br, uint8_t *addr)
453 {
454     if (ERR_OK != bridgeif_fdb_remove(esp_netif_br->lwip_netif, (const struct eth_addr *)addr)) {
455         return ESP_FAIL;
456     }
457     return ESP_OK;
458 }
459 #endif // CONFIG_ESP_NETIF_BRIDGE_EN
460 
461 #if CONFIG_LWIP_IPV4
esp_netif_set_ip4_addr(esp_ip4_addr_t * addr,uint8_t a,uint8_t b,uint8_t c,uint8_t d)462 void esp_netif_set_ip4_addr(esp_ip4_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
463 {
464     ip4_addr_t *address = (ip4_addr_t*)addr;
465     IP4_ADDR(address, a, b, c, d);
466 }
467 
esp_ip4addr_ntoa(const esp_ip4_addr_t * addr,char * buf,int buflen)468 char * esp_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen)
469 {
470     return ip4addr_ntoa_r((ip4_addr_t *)addr, buf, buflen);
471 }
472 
esp_ip4addr_aton(const char * addr)473 uint32_t esp_ip4addr_aton(const char *addr)
474 {
475     return ipaddr_addr(addr);
476 }
477 #endif
478 
esp_netif_str_to_ip4(const char * src,esp_ip4_addr_t * dst)479 esp_err_t esp_netif_str_to_ip4(const char *src, esp_ip4_addr_t *dst)
480 {
481     if (src == NULL || dst == NULL) {
482         return ESP_ERR_INVALID_ARG;
483     }
484     int err = inet_pton(AF_INET, src, dst);
485     return err == 1 ? ESP_OK : ESP_FAIL;
486 }
487 
esp_netif_str_to_ip6(const char * src,esp_ip6_addr_t * dst)488 esp_err_t esp_netif_str_to_ip6(const char *src, esp_ip6_addr_t *dst)
489 {
490     if (src == NULL || dst == NULL) {
491         return ESP_ERR_INVALID_ARG;
492     }
493     int err = inet_pton(AF_INET6, src, dst);
494     return err == 1 ? ESP_OK : ESP_FAIL;
495 }
496 
esp_netif_get_io_driver(esp_netif_t * esp_netif)497 esp_netif_iodriver_handle esp_netif_get_io_driver(esp_netif_t *esp_netif)
498 {
499     return esp_netif->driver_handle;
500 }
501 
esp_netif_get_handle_from_netif_impl(void * dev)502 esp_netif_t* esp_netif_get_handle_from_netif_impl(void *dev)
503 {
504     // ppp_pcb ptr would never get to app code, so this function only works with vanilla lwip impl
505     struct netif *lwip_netif = dev;
506     return lwip_get_esp_netif(lwip_netif);
507 }
508 
esp_netif_get_netif_impl(esp_netif_t * esp_netif)509 void* esp_netif_get_netif_impl(esp_netif_t *esp_netif)
510 {
511     // get impl ptr only for vanilla lwip impl (ppp_pcb not supported)
512     if (esp_netif && !ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
513         return esp_netif->lwip_netif;
514     }
515     return NULL;
516 }
517 
tcpip_init_done(void * arg)518 static void tcpip_init_done(void *arg)
519 {
520     sys_sem_t *init_sem = arg;
521     sys_sem_signal(init_sem);
522 }
523 
esp_netif_init(void)524 esp_err_t esp_netif_init(void)
525 {
526     if (!sys_thread_tcpip(LWIP_CORE_IS_TCPIP_INITIALIZED)) {
527 #if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
528         uint8_t rand_buf[16];
529         /*
530          * This is early startup code where WiFi/BT is yet to be enabled and hence
531          * relevant entropy source is not available. However, bootloader enables
532          * SAR ADC based entropy source at its initialization, and our requirement
533          * of random bytes is pretty small (16), so we can assume that following
534          * API will provide sufficiently random data.
535          */
536         esp_fill_random(rand_buf, sizeof(rand_buf));
537         lwip_init_tcp_isn(esp_log_timestamp(), rand_buf);
538 #endif
539         sys_sem_t init_sem;
540         if (sys_sem_new(&init_sem, 0) != ERR_OK) {
541             ESP_LOGE(TAG, "esp netif cannot create tcpip_init semaphore");
542             return ESP_FAIL;
543         }
544 #if LWIP_TCPIP_CORE_LOCKING
545         /* TCPIP thread is not initialized yet,
546          * pretend that the calling thread is holder
547          * to correctly set up the TCPIP task */
548         sys_thread_tcpip(LWIP_CORE_LOCK_MARK_HOLDER);
549 #endif
550         tcpip_init(tcpip_init_done, &init_sem);
551         sys_sem_wait(&init_sem);
552         sys_sem_free(&init_sem);
553         ESP_LOGD(TAG, "LwIP stack has been initialized");
554     }
555 
556 #if !LWIP_TCPIP_CORE_LOCKING
557     if (!api_sync_sem) {
558         if (ERR_OK != sys_sem_new(&api_sync_sem, 0)) {
559             ESP_LOGE(TAG, "esp netif api sync sem init fail");
560             return ESP_FAIL;
561         }
562     }
563 
564     if (!api_lock_sem) {
565         if (ERR_OK != sys_sem_new(&api_lock_sem, 1)) {
566             ESP_LOGE(TAG, "esp netif api lock sem init fail");
567             return ESP_FAIL;
568         }
569     }
570 #endif
571 
572 #if LWIP_ESP_NETIF_DATA
573     if (lwip_netif_client_id == 0xFF) {
574         esp_netif_lwip_ipc_call(alloc_client_data_id, NULL, &lwip_netif_client_id);
575     }
576 #endif
577     ESP_LOGD(TAG, "esp-netif has been successfully initialized");
578     return ESP_OK;
579 }
580 
esp_netif_deinit(void)581 esp_err_t esp_netif_deinit(void)
582 {
583     if (sys_thread_tcpip(LWIP_CORE_IS_TCPIP_INITIALIZED)) {
584         /* deinit of LwIP not supported:
585          * do not deinit semaphores and states,
586          * so init could be called multiple times
587          *
588         sys_sem_free(&api_sync_sem);
589         sys_sem_free(&api_lock_sem);
590          */
591         return ESP_ERR_NOT_SUPPORTED;
592 
593     }
594     return ESP_ERR_INVALID_STATE;
595 }
596 
esp_netif_init_configuration(esp_netif_t * esp_netif,const esp_netif_config_t * cfg)597 static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_netif_config_t *cfg)
598 {
599     // Basic esp_netif and lwip is a mandatory configuration and cannot be updated after esp_netif_new()
600     if (cfg == NULL || cfg->base == NULL || cfg->stack == NULL) {
601         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
602     }
603 
604     // Configure general esp-netif properties
605     memcpy(esp_netif->mac, cfg->base->mac, NETIF_MAX_HWADDR_LEN);
606 #if CONFIG_LWIP_IPV4
607     if (cfg->base->ip_info == NULL) {
608         ip4_addr_set_zero(&esp_netif->ip_info->ip);
609         ip4_addr_set_zero(&esp_netif->ip_info->gw);
610         ip4_addr_set_zero(&esp_netif->ip_info->netmask);
611     } else {
612         memcpy(esp_netif->ip_info, cfg->base->ip_info, sizeof(esp_netif_ip_info_t));
613     }
614     memcpy(esp_netif->ip_info_old, esp_netif->ip_info, sizeof(esp_netif_ip_info_t));
615 #endif
616     // Setup main config parameters
617     esp_netif->lost_ip_event = cfg->base->lost_ip_event;
618     esp_netif->get_ip_event = cfg->base->get_ip_event;
619     esp_netif->flags = cfg->base->flags;
620 
621     if (cfg->base->if_key) {
622         esp_netif->if_key = strdup(cfg->base->if_key);
623     }
624     if (cfg->base->if_desc) {
625         esp_netif->if_desc = strdup(cfg->base->if_desc);
626     }
627     if (cfg->base->route_prio) {
628         esp_netif->route_prio = cfg->base->route_prio;
629     }
630 
631 #if CONFIG_ESP_NETIF_BRIDGE_EN
632     // Setup bridge configuration if the interface is to be bridge
633     if (cfg->base->flags & ESP_NETIF_FLAG_IS_BRIDGE) {
634         if (cfg->base->bridge_info != NULL) {
635             esp_netif->max_fdb_dyn_entries = cfg->base->bridge_info->max_fdb_dyn_entries;
636             esp_netif->max_fdb_sta_entries = cfg->base->bridge_info->max_fdb_sta_entries;
637             esp_netif->max_ports = cfg->base->bridge_info->max_ports;
638         } else {
639             return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
640         }
641     }
642 #endif // CONFIG_ESP_NETIF_BRIDGE_EN
643 
644     // Install network stack functions -- connects netif and L3 stack
645     const esp_netif_netstack_config_t *esp_netif_stack_config = cfg->stack;
646     if (cfg->base->flags & ESP_NETIF_FLAG_IS_PPP) {
647 #if CONFIG_PPP_SUPPORT
648         esp_netif->related_data = esp_netif_new_ppp(esp_netif, esp_netif_stack_config);
649         if (esp_netif->related_data == NULL) {
650             return ESP_ERR_ESP_NETIF_INIT_FAILED;
651         }
652         esp_netif->lwip_input_fn = esp_netif_stack_config->lwip_ppp.input_fn;
653         // Make the netif handle (used for tcpip input function) the ppp_netif
654         esp_netif->netif_handle = esp_netif->related_data;
655 #else
656         LOG_NETIF_DISABLED_AND_DO("PPP", return ESP_ERR_NOT_SUPPORTED);
657 #endif
658     } else {
659         if (esp_netif_stack_config-> lwip.init_fn) {
660             esp_netif->lwip_init_fn = esp_netif_stack_config->lwip.init_fn;
661         }
662         if (esp_netif_stack_config->lwip.input_fn) {
663             esp_netif->lwip_input_fn = esp_netif_stack_config->lwip.input_fn;
664         }
665         // Make the netif handle (used for tcpip input function) the lwip_netif itself
666         esp_netif->netif_handle = esp_netif->lwip_netif;
667 
668     }
669 
670     // Install IO functions only if provided -- connects driver and netif
671     // this configuration could be updated after esp_netif_new(), typically in post_attach callback
672     if (cfg->driver) {
673         const esp_netif_driver_ifconfig_t *esp_netif_driver_config = cfg->driver;
674         if (esp_netif_driver_config->handle) {
675             esp_netif->driver_handle = esp_netif_driver_config->handle;
676         }
677         if (esp_netif_driver_config->transmit) {
678             esp_netif->driver_transmit = esp_netif_driver_config->transmit;
679         }
680         if (esp_netif_driver_config->transmit_wrap) {
681             esp_netif->driver_transmit_wrap = esp_netif_driver_config->transmit_wrap;
682         }
683         if (esp_netif_driver_config->driver_free_rx_buffer) {
684             esp_netif->driver_free_rx_buffer = esp_netif_driver_config->driver_free_rx_buffer;
685         }
686     }
687     return ESP_OK;
688 }
689 
tcpip_exec_api(esp_netif_api_msg_t * msg)690 static esp_err_t tcpip_exec_api(esp_netif_api_msg_t *msg)
691 {
692     return msg->user_fn(msg->data);
693 }
694 
esp_netif_tcpip_exec(esp_netif_callback_fn fn,void * ctx)695 esp_err_t esp_netif_tcpip_exec(esp_netif_callback_fn fn, void*ctx)
696 {
697     return esp_netif_lwip_ipc_call_fn(tcpip_exec_api, fn, ctx);
698 }
699 
esp_netif_new(const esp_netif_config_t * esp_netif_config)700 esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
701 {
702     // mandatory configuration must be provided when creating esp_netif object
703     if (esp_netif_config == NULL ||
704         esp_netif_config->base->if_key == NULL ||
705         NULL != esp_netif_get_handle_from_ifkey(esp_netif_config->base->if_key)) {
706         ESP_LOGE(TAG, "%s: Failed to configure netif with config=%p (config or if_key is NULL or duplicate key)",
707         __func__,  esp_netif_config);
708         return NULL;
709     }
710 
711 #if ESP_DHCPS
712     // DHCP server and client cannot be configured together
713     if((esp_netif_config->base->flags & ESP_NETIF_DHCP_SERVER) &&
714        (esp_netif_config->base->flags & ESP_NETIF_DHCP_CLIENT)) {
715         ESP_LOGE(TAG, "%s: Failed to configure netif with config=%p (DHCP server and client cannot be configured together)",
716         __func__,  esp_netif_config);
717         return NULL;
718     }
719 #endif
720 
721     // Create parent esp-netif object
722     esp_netif_t *esp_netif = calloc(1, sizeof(struct esp_netif_obj));
723     if (!esp_netif) {
724         ESP_LOGE(TAG, "Failed to allocate %d bytes (free heap size %d)", sizeof(struct esp_netif_obj),
725                  esp_get_free_heap_size());
726         return NULL;
727     }
728 
729     // Create ip info
730     esp_netif_ip_info_t *ip_info = calloc(1, sizeof(esp_netif_ip_info_t));
731     if (!ip_info) {
732         ESP_LOGE(TAG, "Failed to allocate %d bytes (free heap size %d)", sizeof(esp_netif_ip_info_t),
733                  esp_get_free_heap_size());
734         free(esp_netif);
735         return NULL;
736     }
737     esp_netif->ip_info = ip_info;
738 
739     // creating another ip info (to store old ip)
740     ip_info = calloc(1, sizeof(esp_netif_ip_info_t));
741     if (!ip_info) {
742         ESP_LOGE(TAG, "Failed to allocate %d bytes (free heap size %d)", sizeof(esp_netif_ip_info_t),
743                  esp_get_free_heap_size());
744         free(esp_netif->ip_info);
745         free(esp_netif);
746         return NULL;
747     }
748     esp_netif->ip_info_old = ip_info;
749 
750     // Create underlying lwip netif
751 #if LWIP_ESP_NETIF_DATA
752     // Optionally allocate netif client data for esp-netif ptr
753     // to allow for running esp_netif_new() before esp_netif_init()
754     if (lwip_netif_client_id == 0xFF) {
755         esp_netif_lwip_ipc_call(alloc_client_data_id, NULL, &lwip_netif_client_id);
756     }
757 #endif
758 
759     struct netif * lwip_netif = calloc(1, sizeof(struct netif));
760     if (!lwip_netif) {
761         ESP_LOGE(TAG, "Failed to allocate %d bytes (free heap size %d)", sizeof(struct netif),
762                  esp_get_free_heap_size());
763         free(esp_netif->ip_info_old);
764         free(esp_netif->ip_info);
765         free(esp_netif);
766         return NULL;
767     }
768 
769     esp_netif->lwip_netif = lwip_netif;
770 
771     esp_netif_add_to_list(esp_netif);
772 
773 #if ESP_DHCPS
774     // Create DHCP server structure
775     if (esp_netif_config->base->flags & ESP_NETIF_DHCP_SERVER) {
776         esp_netif->dhcps = dhcps_new();
777         if (esp_netif->dhcps == NULL) {
778             ESP_LOGE(TAG, "Failed to create dhcp server handle");
779             esp_netif_destroy(esp_netif);
780             return NULL;
781         }
782     }
783 #endif
784 
785     // Configure the created object with provided configuration
786     esp_err_t ret =  esp_netif_init_configuration(esp_netif, esp_netif_config);
787     if (ret != ESP_OK) {
788         ESP_LOGE(TAG, "Initial configuration of esp_netif failed with %d", ret);
789         esp_netif_destroy(esp_netif);
790         return NULL;
791     }
792     lwip_set_esp_netif(lwip_netif, esp_netif);
793 
794     if (netif_callback.callback_fn == NULL ) {
795         esp_netif_lwip_ipc_no_args(set_lwip_netif_callback);
796     }
797 
798     return esp_netif;
799 }
800 
esp_netif_lwip_remove(esp_netif_t * esp_netif)801 static void esp_netif_lwip_remove(esp_netif_t *esp_netif)
802 {
803     if (esp_netif->lwip_netif) {
804         if (netif_is_up(esp_netif->lwip_netif)) {
805             netif_set_down(esp_netif->lwip_netif);
806         }
807         netif_remove(esp_netif->lwip_netif);
808 #if ESP_GRATUITOUS_ARP
809         if (esp_netif->flags & ESP_NETIF_FLAG_GARP) {
810             netif_unset_garp_flag(esp_netif->lwip_netif);
811         }
812 #endif
813 #if ESP_MLDV6_REPORT && LWIP_IPV6
814         if (esp_netif->flags & ESP_NETIF_FLAG_MLDV6_REPORT) {
815             netif_unset_mldv6_flag(esp_netif->lwip_netif);
816         }
817 #endif
818         if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
819 #if CONFIG_LWIP_IPV4
820             dhcp_cleanup(esp_netif->lwip_netif);
821 #endif
822         }
823 
824     }
825 }
826 
esp_netif_lwip_add(esp_netif_t * esp_netif)827 static esp_err_t esp_netif_lwip_add(esp_netif_t *esp_netif)
828 {
829     if (esp_netif->lwip_netif == NULL) {
830         esp_netif->lwip_netif = calloc(1, sizeof(struct netif));
831         if (esp_netif->lwip_netif == NULL) {
832             return ESP_ERR_NO_MEM;
833         }
834     }
835     if (esp_netif->flags & ESP_NETIF_FLAG_IS_PPP) {
836 #if CONFIG_PPP_SUPPORT
837         err_t err = esp_netif->lwip_init_fn(NULL);
838         if (err != ERR_OK) {
839             ESP_LOGE(TAG, "Init netif failed with  %d", err);
840             return ESP_ERR_ESP_NETIF_INIT_FAILED;
841         }
842 #else
843         LOG_NETIF_DISABLED_AND_DO("PPP", return ESP_ERR_NOT_SUPPORTED);
844 #endif
845     }
846 
847 #if CONFIG_ESP_NETIF_BRIDGE_EN
848     if (esp_netif->flags & ESP_NETIF_FLAG_IS_BRIDGE) {
849         bridgeif_initdata_t bridge_initdata = {
850             .max_fdb_dynamic_entries = esp_netif->max_fdb_dyn_entries,
851             .max_fdb_static_entries = esp_netif->max_fdb_sta_entries,
852             .max_ports = esp_netif->max_ports
853         };
854         memcpy(&bridge_initdata.ethaddr, esp_netif->mac, ETH_HWADDR_LEN);
855         if (NULL == netif_add(esp_netif->lwip_netif, (struct ip4_addr*)&esp_netif->ip_info->ip,
856                         (struct ip4_addr*)&esp_netif->ip_info->netmask, (struct ip4_addr*)&esp_netif->ip_info->gw,
857                         &bridge_initdata, esp_netif->lwip_init_fn, tcpip_input)) {
858             esp_netif_lwip_remove(esp_netif);
859             return ESP_ERR_ESP_NETIF_IF_NOT_READY;
860         }
861     } else {
862 #endif // CONFIG_ESP_NETIF_BRIDGE_EN
863         if (NULL == netif_add(esp_netif->lwip_netif,
864 #if CONFIG_LWIP_IPV4
865                             (struct ip4_addr*)&esp_netif->ip_info->ip,
866                             (struct ip4_addr*)&esp_netif->ip_info->netmask,
867                             (struct ip4_addr*)&esp_netif->ip_info->gw,
868 #endif
869                             esp_netif, esp_netif->lwip_init_fn, tcpip_input)) {
870             esp_netif_lwip_remove(esp_netif);
871             return ESP_ERR_ESP_NETIF_IF_NOT_READY;
872         }
873 #if CONFIG_ESP_NETIF_BRIDGE_EN
874     }
875 #endif // CONFIG_ESP_NETIF_BRIDGE_EN
876     lwip_set_esp_netif(esp_netif->lwip_netif, esp_netif);
877     return ESP_OK;
878 }
879 
esp_netif_destroy_related(esp_netif_t * esp_netif)880 static void esp_netif_destroy_related(esp_netif_t *esp_netif)
881 {
882     if (ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
883 #if CONFIG_PPP_SUPPORT
884         esp_netif_destroy_ppp(esp_netif->related_data);
885 #endif
886     }
887 }
888 
esp_netif_lwip_remove_api(esp_netif_api_msg_t * msg)889 static esp_err_t esp_netif_lwip_remove_api(esp_netif_api_msg_t *msg)
890 {
891     esp_netif_lwip_remove(msg->esp_netif);
892     return ESP_OK;
893 }
894 
esp_netif_destroy(esp_netif_t * esp_netif)895 void esp_netif_destroy(esp_netif_t *esp_netif)
896 {
897     if (esp_netif) {
898         esp_netif_remove_from_list(esp_netif);
899         if (esp_netif_get_nr_of_ifs() == 0) {
900             esp_netif_lwip_ipc_no_args(remove_lwip_netif_callback);
901         }
902         free(esp_netif->ip_info);
903         free(esp_netif->ip_info_old);
904         free(esp_netif->if_key);
905         free(esp_netif->if_desc);
906         esp_netif_lwip_ipc_call(esp_netif_lwip_remove_api, esp_netif, NULL);
907         esp_netif_destroy_related(esp_netif);
908         free(esp_netif->lwip_netif);
909         free(esp_netif->hostname);
910         esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);
911 #if ESP_DHCPS
912         dhcps_delete(esp_netif->dhcps);
913 #endif
914         free(esp_netif);
915     }
916 }
917 
esp_netif_attach(esp_netif_t * esp_netif,esp_netif_iodriver_handle driver_handle)918 esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle)
919 {
920     esp_netif_driver_base_t *base_driver = driver_handle;
921 
922     esp_netif->driver_handle = driver_handle;
923     if (base_driver->post_attach) {
924         esp_err_t ret = base_driver->post_attach(esp_netif, driver_handle);
925         if (ret != ESP_OK) {
926             ESP_LOGE(TAG, "Post-attach callback of driver(%p) failed with %d", driver_handle, ret);
927             return ESP_ERR_ESP_NETIF_DRIVER_ATTACH_FAILED;
928         }
929     }
930     return ESP_OK;
931 }
932 
esp_netif_set_driver_config(esp_netif_t * esp_netif,const esp_netif_driver_ifconfig_t * driver_config)933 esp_err_t esp_netif_set_driver_config(esp_netif_t *esp_netif,
934                                       const esp_netif_driver_ifconfig_t *driver_config)
935 {
936     if (esp_netif == NULL || driver_config == NULL) {
937         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
938     }
939     esp_netif->driver_handle = driver_config->handle;
940     esp_netif->driver_transmit = driver_config->transmit;
941     esp_netif->driver_transmit_wrap = driver_config->transmit_wrap;
942     esp_netif->driver_free_rx_buffer = driver_config->driver_free_rx_buffer;
943     return ESP_OK;
944 }
945 
946 #if CONFIG_LWIP_IPV4
esp_netif_reset_ip_info(esp_netif_t * esp_netif)947 static esp_err_t esp_netif_reset_ip_info(esp_netif_t *esp_netif)
948 {
949     ip4_addr_set_zero(&(esp_netif->ip_info->ip));
950     ip4_addr_set_zero(&(esp_netif->ip_info->gw));
951     ip4_addr_set_zero(&(esp_netif->ip_info->netmask));
952     return ESP_OK;
953 }
954 #endif
955 
esp_netif_set_mac_api(esp_netif_api_msg_t * msg)956 esp_err_t esp_netif_set_mac_api(esp_netif_api_msg_t *msg)
957 {
958     uint8_t *mac = msg->data;
959     esp_netif_t* esp_netif = msg->esp_netif;
960     memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN);
961     memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN);
962     return ESP_OK;
963 }
964 
esp_netif_set_mac(esp_netif_t * esp_netif,uint8_t mac[])965 esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
966 {
967     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
968         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
969     }
970     if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
971         return ESP_ERR_NOT_SUPPORTED;
972     }
973     return esp_netif_lwip_ipc_call(esp_netif_set_mac_api, esp_netif, mac);
974 }
975 
esp_netif_get_mac(esp_netif_t * esp_netif,uint8_t mac[])976 esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[])
977 {
978     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
979         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
980     }
981     if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
982         return ESP_ERR_NOT_SUPPORTED;
983     }
984     if (esp_netif_is_netif_up(esp_netif)) {
985         memcpy(mac, esp_netif->lwip_netif->hwaddr, NETIF_MAX_HWADDR_LEN);
986         return ESP_OK;
987     }
988     memcpy(mac, esp_netif->mac, NETIF_MAX_HWADDR_LEN);
989     return ESP_OK;
990 }
991 
992 #if ESP_DHCPS
esp_netif_dhcps_cb(void * arg,uint8_t ip[4],uint8_t mac[6])993 static void esp_netif_dhcps_cb(void* arg, uint8_t ip[4], uint8_t mac[6])
994 {
995     esp_netif_t *esp_netif = arg;
996     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
997     ip_event_ap_staipassigned_t evt = { .esp_netif = esp_netif };
998     memcpy((char *)&evt.ip.addr, (char *)ip, sizeof(evt.ip.addr));
999     memcpy((char *)&evt.mac, mac, sizeof(evt.mac));
1000     ESP_LOGI(TAG, "DHCP server assigned IP to a client, IP is: " IPSTR, IP2STR(&evt.ip));
1001     ESP_LOGD(TAG, "Client's MAC: %x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
1002 
1003     int ret = esp_event_post(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &evt, sizeof(evt), 0);
1004     if (ESP_OK != ret) {
1005         ESP_LOGE(TAG, "dhcps cb: failed to post IP_EVENT_AP_STAIPASSIGNED (%x)", ret);
1006     }
1007 }
1008 #endif
1009 
esp_netif_config_sanity_check(const esp_netif_t * esp_netif)1010 static esp_err_t esp_netif_config_sanity_check(const esp_netif_t * esp_netif)
1011 {
1012     if (esp_netif == NULL) {
1013         ESP_LOGE(TAG,  "Cannot start esp_netif: esp_netif must not be null");
1014         return ESP_ERR_INVALID_STATE;
1015     }
1016 
1017     if ((!(esp_netif->flags & ESP_NETIF_FLAG_IS_BRIDGE) && (esp_netif->driver_transmit == NULL ||
1018         esp_netif->driver_handle == NULL || esp_netif->lwip_input_fn == NULL)) ||
1019         esp_netif->lwip_init_fn == NULL) {
1020         ESP_LOGE(TAG,  "Cannot start esp_netif: Missing mandatory configuration:\n"
1021                        "esp_netif->driver_transmit: %p, esp_netif->driver_handle:%p, "
1022                        "esp_netif->lwip_input_fn: %p, esp_netif->lwip_init_fn:%p",
1023                        esp_netif->driver_transmit,  esp_netif->driver_handle,
1024                        esp_netif->lwip_input_fn,  esp_netif->lwip_init_fn);
1025 
1026          return ESP_ERR_INVALID_STATE;
1027     }
1028     return ESP_OK;
1029 }
1030 
esp_netif_start_api(esp_netif_api_msg_t * msg)1031 static esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg)
1032 {
1033     esp_netif_t * esp_netif = msg->esp_netif;
1034 
1035     ESP_LOGD(TAG, "%s %p", __func__, esp_netif);
1036 
1037     ESP_ERROR_CHECK(esp_netif_config_sanity_check(esp_netif));
1038 
1039     ESP_ERROR_CHECK(esp_netif_lwip_add(esp_netif));
1040 
1041 #if ESP_IPV6_AUTOCONFIG
1042     esp_netif->lwip_netif->ip6_autoconfig_enabled = 1;
1043 #endif
1044     if (esp_netif->flags&ESP_NETIF_FLAG_GARP) {
1045 #if ESP_GRATUITOUS_ARP
1046         netif_set_garp_flag(esp_netif->lwip_netif);
1047 #else
1048         ESP_LOGW(TAG,"CONFIG_LWIP_ESP_GRATUITOUS_ARP not enabled, but esp-netif configured with ESP_NETIF_FLAG_GARP");
1049 #endif
1050     }
1051     struct netif *p_netif = esp_netif->lwip_netif;
1052 
1053     if (esp_netif->flags&ESP_NETIF_FLAG_AUTOUP) {
1054         ESP_LOGD(TAG, "%s Setting the lwip netif%p UP", __func__, p_netif);
1055         netif_set_up(p_netif);
1056         netif_set_link_up(p_netif);
1057     }
1058     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1059 #if ESP_DHCPS
1060         if (esp_netif->dhcps_status == ESP_NETIF_DHCP_INIT) {
1061             if (p_netif != NULL && netif_is_up(p_netif)) {
1062                 esp_netif_ip_info_t *default_ip = esp_netif->ip_info;
1063                 ip4_addr_t lwip_ip;
1064                 ip4_addr_t lwip_netmask;
1065                 memcpy(&lwip_ip, &default_ip->ip, sizeof(struct ip4_addr));
1066                 memcpy(&lwip_netmask, &default_ip->netmask, sizeof(struct ip4_addr));
1067                 dhcps_set_new_lease_cb(esp_netif->dhcps, esp_netif_dhcps_cb, esp_netif);
1068                 dhcps_set_option_info(esp_netif->dhcps, SUBNET_MASK, (void*)&lwip_netmask, sizeof(lwip_netmask));
1069                 if (dhcps_start(esp_netif->dhcps, p_netif, lwip_ip) != ERR_OK) {
1070                     ESP_LOGE(TAG, "DHCP server cannot be started");
1071                     esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
1072                     return ESP_ERR_ESP_NETIF_DHCPS_START_FAILED;
1073                 }
1074                 esp_netif->dhcps_status = ESP_NETIF_DHCP_STARTED;
1075                 ESP_LOGI(TAG, "DHCP server started on interface %s with IP: " IPSTR, esp_netif->if_key, IP2STR(&lwip_ip));
1076                 esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
1077                 return ESP_OK;
1078             } else {
1079                 ESP_LOGD(TAG, "DHCP server re init");
1080                 esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
1081                 return ESP_OK;
1082             }
1083         } else if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) {
1084             ESP_LOGD(TAG, "DHCP server already started");
1085             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1086         }
1087         return ESP_OK;
1088 #else
1089         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
1090 #endif
1091     } else if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
1092 #if CONFIG_LWIP_IPV4
1093         if (esp_netif->dhcpc_status != ESP_NETIF_DHCP_STARTED) {
1094             if (p_netif != NULL) {
1095                 struct dhcp *dhcp_data = NULL;
1096                 dhcp_data = netif_dhcp_data(p_netif);
1097                 if (dhcp_data == NULL) {
1098                     dhcp_data = (struct dhcp *)malloc(sizeof(struct dhcp));
1099                     if (dhcp_data == NULL) {
1100                         return ESP_ERR_NO_MEM;
1101                     }
1102                     dhcp_set_struct(p_netif, dhcp_data);
1103                 }
1104             }
1105         }
1106 #else
1107         LOG_NETIF_DISABLED_AND_DO("IPv4's DHCP Client", return ESP_ERR_NOT_SUPPORTED);
1108 #endif
1109     }
1110 
1111     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
1112 
1113     return ESP_OK;
1114 }
1115 
esp_netif_start(esp_netif_t * esp_netif)1116 esp_err_t esp_netif_start(esp_netif_t *esp_netif)
1117 {
1118     if (ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
1119 #if CONFIG_PPP_SUPPORT
1120         // No need to start PPP interface in lwip thread
1121         esp_err_t ret = esp_netif_start_ppp(esp_netif);
1122         if (ret == ESP_OK) {
1123             esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
1124         }
1125         return ret;
1126 #endif
1127     }
1128     return esp_netif_lwip_ipc_call(esp_netif_start_api, esp_netif, NULL);
1129 }
1130 
esp_netif_stop_api(esp_netif_api_msg_t * msg)1131 static esp_err_t esp_netif_stop_api(esp_netif_api_msg_t *msg)
1132 {
1133     esp_netif_t *esp_netif = msg->esp_netif;
1134 
1135     struct netif *lwip_netif = esp_netif->lwip_netif;
1136     if (lwip_netif == NULL) {
1137         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1138     }
1139 
1140     if (!netif_is_up(lwip_netif)) {
1141         esp_netif_lwip_remove(esp_netif);
1142         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1143     }
1144 
1145     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1146 #if ESP_DHCPS
1147         if (dhcps_stop(esp_netif->dhcps, lwip_netif) != ERR_OK ||
1148             esp_netif->dhcps_status != ESP_NETIF_DHCP_STOPPED) {
1149             esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
1150         }
1151 #else
1152         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
1153 #endif
1154     } else if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
1155 #if CONFIG_LWIP_IPV4
1156         dhcp_release(lwip_netif);
1157         dhcp_stop(lwip_netif);
1158         dhcp_cleanup(lwip_netif);
1159 
1160         esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1161 
1162         esp_netif_reset_ip_info(esp_netif);
1163 #else
1164         LOG_NETIF_DISABLED_AND_DO("IPv4's DHCP Client", return ESP_ERR_NOT_SUPPORTED);
1165 #endif
1166     }
1167 
1168     netif_set_down(lwip_netif);
1169     esp_netif_lwip_remove(esp_netif);
1170     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);
1171 
1172     return ESP_OK;
1173 }
1174 
esp_netif_stop(esp_netif_t * esp_netif)1175 esp_err_t esp_netif_stop(esp_netif_t *esp_netif)
1176 {
1177     if (ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
1178 #if CONFIG_PPP_SUPPORT
1179         // No need to stop PPP interface in lwip thread
1180         esp_err_t ret = esp_netif_stop_ppp(esp_netif->related_data);
1181         if (ret == ESP_OK) {
1182             esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);
1183         }
1184         return ret;
1185 #endif
1186     }
1187     return esp_netif_lwip_ipc_call(esp_netif_stop_api, esp_netif, NULL);
1188 }
1189 
esp_netif_netstack_buf_ref(void * pbuf)1190 void esp_netif_netstack_buf_ref(void *pbuf)
1191 {
1192     pbuf_ref(pbuf);
1193 }
1194 
esp_netif_netstack_buf_free(void * pbuf)1195 void esp_netif_netstack_buf_free(void *pbuf)
1196 {
1197     pbuf_free(pbuf);
1198 }
1199 
1200 //
1201 // IO translate functions
1202 //
esp_netif_free_rx_buffer(void * h,void * buffer)1203 void esp_netif_free_rx_buffer(void *h, void* buffer)
1204 {
1205     esp_netif_t *esp_netif = h;
1206     esp_netif->driver_free_rx_buffer(esp_netif->driver_handle, buffer);
1207 }
1208 
esp_netif_transmit(esp_netif_t * esp_netif,void * data,size_t len)1209 esp_err_t esp_netif_transmit(esp_netif_t *esp_netif, void* data, size_t len)
1210 {
1211     return (esp_netif->driver_transmit)(esp_netif->driver_handle, data, len);
1212 }
1213 
esp_netif_transmit_wrap(esp_netif_t * esp_netif,void * data,size_t len,void * pbuf)1214 esp_err_t esp_netif_transmit_wrap(esp_netif_t *esp_netif, void *data, size_t len, void *pbuf)
1215 {
1216     return (esp_netif->driver_transmit_wrap)(esp_netif->driver_handle, data, len, pbuf);
1217 }
1218 
esp_netif_receive(esp_netif_t * esp_netif,void * buffer,size_t len,void * eb)1219 esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb)
1220 {
1221 #ifdef CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS
1222     return esp_netif->lwip_input_fn(esp_netif->netif_handle, buffer, len, eb);
1223 #else
1224     esp_netif->lwip_input_fn(esp_netif->netif_handle, buffer, len, eb);
1225     return ESP_OK;
1226 #endif
1227 }
1228 
1229 #if CONFIG_LWIP_IPV4
1230 static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif);
1231 
1232 //
1233 // DHCP:
1234 //
esp_netif_internal_dhcpc_cb(struct netif * netif)1235 static void esp_netif_internal_dhcpc_cb(struct netif *netif)
1236 {
1237     esp_netif_t *esp_netif;
1238     ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, netif);
1239     if (netif == NULL || (esp_netif = lwip_get_esp_netif(netif)) == NULL) {
1240         // internal pointer hasn't been configured yet (probably in the interface init_fn())
1241         return;
1242     }
1243 
1244     esp_netif_ip_info_t *ip_info = esp_netif->ip_info;
1245     esp_netif_ip_info_t *ip_info_old = esp_netif->ip_info_old;
1246 
1247     if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4) ) {
1248 
1249         //check whether IP is changed (or if we're an PPP interface)
1250         if ( (!ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), (&ip_info->ip)) ||
1251               !ip4_addr_cmp(ip_2_ip4(&netif->netmask), (&ip_info->netmask)) ||
1252               !ip4_addr_cmp(ip_2_ip4(&netif->gw), (&ip_info->gw)))
1253           // post IP event for PPP interfaces even if IP hasn't changed
1254              || (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif))) {
1255             ip_event_got_ip_t evt = {
1256                     .esp_netif = esp_netif,
1257                     .ip_changed = false,
1258             };
1259             ip_event_t evt_id = esp_netif_get_event_id(esp_netif, ESP_NETIF_IP_EVENT_GOT_IP);
1260             int ret;
1261 
1262             ip4_addr_set(&ip_info->ip, ip_2_ip4(&netif->ip_addr));
1263             ip4_addr_set(&ip_info->netmask, ip_2_ip4(&netif->netmask));
1264             ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw));
1265 
1266             //notify event
1267             if (memcmp(ip_info, ip_info_old, sizeof(esp_netif_ip_info_t))) {
1268                 evt.ip_changed = true;
1269             }
1270 
1271             memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t));
1272             memcpy(ip_info_old, ip_info, sizeof(esp_netif_ip_info_t));
1273             ESP_LOGD(TAG, "if%p ip changed=%d", esp_netif, evt.ip_changed);
1274             ret = esp_event_post(IP_EVENT, evt_id, &evt, sizeof(evt), 0);
1275             if (ESP_OK != ret) {
1276                 ESP_LOGE(TAG, "dhcpc cb: failed to post got ip event (%x)", ret);
1277             }
1278 #ifdef CONFIG_LWIP_DHCP_RESTORE_LAST_IP
1279             dhcp_ip_addr_store(netif);
1280 #endif /* CONFIG_LWIP_DHCP_RESTORE_LAST_IP */
1281         } else {
1282             ESP_LOGD(TAG, "if%p ip unchanged", esp_netif);
1283         }
1284     } else {
1285         if (!ip4_addr_cmp(&ip_info->ip, IP4_ADDR_ANY4)) {
1286             esp_netif_start_ip_lost_timer(esp_netif);
1287         }
1288     }
1289 }
1290 
esp_netif_ip_lost_timer(void * arg)1291 static void esp_netif_ip_lost_timer(void *arg)
1292 {
1293     esp_netif_t *esp_netif = esp_netif_is_active(arg);
1294 
1295     if (esp_netif == NULL) {
1296         ESP_LOGD(TAG, "%s esp_netif=%p not active any more", __func__, arg);
1297         return;
1298     }
1299 
1300     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1301 
1302     esp_netif->timer_running = false;
1303 
1304     struct netif *netif = esp_netif->lwip_netif;
1305 
1306     if ( (!netif) || (netif && ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4))) {
1307         ip_event_got_ip_t evt = {
1308                 .esp_netif = esp_netif,
1309         };
1310         int ret;
1311 
1312         ESP_LOGD(TAG, "if%p ip lost tmr: raise ip lost event", esp_netif);
1313         memset(esp_netif->ip_info_old, 0, sizeof(esp_netif_ip_info_t));
1314         if (esp_netif->lost_ip_event) {
1315             ret = esp_event_post(IP_EVENT, esp_netif->lost_ip_event,
1316                                           &evt, sizeof(evt), 0);
1317             if (ESP_OK != ret) {
1318                 ESP_LOGE(TAG, "ip lost timer: failed to post lost ip event (%x)", ret);
1319             }
1320         }
1321     } else {
1322         ESP_LOGD(TAG, "if%p ip lost tmr: no need raise ip lost event", esp_netif);
1323     }
1324 }
1325 
esp_netif_start_ip_lost_timer(esp_netif_t * esp_netif)1326 static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif)
1327 {
1328     esp_netif_ip_info_t *ip_info_old = esp_netif->ip_info;
1329     struct netif *netif = esp_netif->lwip_netif;
1330 
1331     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1332 
1333     if (esp_netif->timer_running) {
1334         ESP_LOGD(TAG, "if%p start ip lost tmr: already started", esp_netif);
1335         return ESP_OK;
1336     }
1337 
1338     if ( netif && (CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL > 0) && !ip4_addr_isany_val(ip_info_old->ip)) {
1339         esp_netif->timer_running = true;
1340         sys_timeout(CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL * 1000, esp_netif_ip_lost_timer, (void *)esp_netif);
1341         ESP_LOGD(TAG, "if%p start ip lost tmr: interval=%d", esp_netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL);
1342         return ESP_OK;
1343     }
1344 
1345     ESP_LOGD(TAG, "if%p start ip lost tmr: no need start because netif=%p interval=%d ip=%x",
1346              esp_netif, netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL, ip_info_old->ip.addr);
1347 
1348     return ESP_OK;
1349 }
1350 
esp_netif_dhcpc_stop_api(esp_netif_api_msg_t * msg)1351 static esp_err_t esp_netif_dhcpc_stop_api(esp_netif_api_msg_t *msg)
1352 {
1353     esp_netif_t *esp_netif = msg->esp_netif;
1354 
1355     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1356 
1357     if (esp_netif == NULL) {
1358         ESP_LOGE(TAG, "dhcp client stop called with NULL api");
1359         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1360     }
1361 
1362     if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1363         struct netif *p_netif = esp_netif->lwip_netif;
1364 
1365         if (p_netif != NULL) {
1366             dhcp_stop(p_netif);
1367             esp_netif_reset_ip_info(esp_netif);
1368             esp_netif_start_ip_lost_timer(esp_netif);
1369         } else {
1370             ESP_LOGD(TAG, "dhcp client if not ready");
1371             return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1372         }
1373     } else if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
1374         ESP_LOGD(TAG, "dhcp client already stoped");
1375         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
1376     }
1377 
1378     ESP_LOGD(TAG, "dhcp client stop successfully");
1379     esp_netif->dhcpc_status = ESP_NETIF_DHCP_STOPPED;
1380 
1381 #ifdef CONFIG_LWIP_DHCP_RESTORE_LAST_IP
1382     dhcp_ip_addr_erase(esp_netif->lwip_netif);
1383 #endif /* CONFIG_LWIP_DHCP_RESTORE_LAST_IP */
1384 
1385     return ESP_OK;
1386 }
1387 
esp_netif_dhcpc_stop(esp_netif_t * esp_netif)1388 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)
1389 
1390 static void dns_clear_servers(bool keep_fallback)
1391 {
1392     u8_t numdns = 0;
1393 
1394     for (numdns = 0; numdns < DNS_MAX_SERVERS; numdns ++) {
1395         if (keep_fallback && numdns == DNS_FALLBACK_SERVER_INDEX) {
1396             continue;
1397         }
1398 
1399         dns_setserver(numdns, NULL);
1400     }
1401 }
1402 
esp_netif_dhcpc_start_api(esp_netif_api_msg_t * msg)1403 static esp_err_t esp_netif_dhcpc_start_api(esp_netif_api_msg_t *msg)
1404 {
1405     esp_netif_t *esp_netif = msg->esp_netif;
1406 
1407     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1408 
1409     if (!esp_netif) {
1410         return ESP_ERR_INVALID_ARG;
1411     }
1412 
1413     if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1414         ESP_LOGD(TAG, "dhcp client already started");
1415         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1416     }
1417 
1418     struct netif *p_netif = esp_netif->lwip_netif;
1419 
1420     esp_netif_reset_ip_info(esp_netif);
1421 
1422 #if LWIP_DNS
1423     dns_clear_servers(true);
1424 #endif
1425 
1426     if (p_netif != NULL) {
1427         if (netif_is_up(p_netif)) {
1428             ip_addr_set_zero(&p_netif->ip_addr);
1429             ip_addr_set_zero(&p_netif->netmask);
1430             ip_addr_set_zero(&p_netif->gw);
1431             esp_netif_start_ip_lost_timer(esp_netif);
1432         } else {
1433             ESP_LOGD(TAG, "dhcp client re init");
1434             esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1435             return ESP_OK;
1436         }
1437         ESP_LOGD(TAG, "starting dhcp client");
1438 
1439         if (dhcp_start(p_netif) != ERR_OK) {
1440             ESP_LOGE(TAG, "dhcp client start failed");
1441             return ESP_ERR_ESP_NETIF_DHCPC_START_FAILED;
1442         }
1443 
1444         esp_netif->dhcpc_status = ESP_NETIF_DHCP_STARTED;
1445         return ESP_OK;
1446     } else {
1447         ESP_LOGD(TAG, "dhcp client re init");
1448         esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1449         return ESP_OK;
1450     }
1451 }
1452 
esp_netif_dhcpc_start(esp_netif_t * esp_netif)1453 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)
1454 #endif /* CONFIG_LWIP_IPV4 */
1455 
1456 #if ESP_DHCPS
1457 esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
1458 {
1459     if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1460         return ESP_ERR_INVALID_ARG;
1461     }
1462 
1463     *status = esp_netif->dhcps_status;
1464     return ESP_OK;
1465 }
1466 #endif
1467 
esp_netif_dhcpc_get_status(esp_netif_t * esp_netif,esp_netif_dhcp_status_t * status)1468 esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
1469 {
1470     if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_SERVER) || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1471         return ESP_ERR_INVALID_ARG;
1472     }
1473 
1474     *status = esp_netif->dhcpc_status;
1475     return ESP_OK;
1476 }
1477 
1478 #if ESP_DHCPS
esp_netif_dhcps_start_api(esp_netif_api_msg_t * msg)1479 static esp_err_t esp_netif_dhcps_start_api(esp_netif_api_msg_t *msg)
1480 {
1481     esp_netif_t *esp_netif = msg->esp_netif;
1482 
1483     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1484 
1485     if (!esp_netif) {
1486         return ESP_ERR_INVALID_ARG;
1487     }
1488 
1489     if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) {
1490         ESP_LOGD(TAG, "dhcp server already started");
1491         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
1492     }
1493 
1494     struct netif *p_netif = esp_netif->lwip_netif;
1495     if (p_netif != NULL && netif_is_up(p_netif)) {
1496         esp_netif_ip_info_t *default_ip = esp_netif->ip_info;
1497         ip4_addr_t lwip_ip;
1498         ip4_addr_t lwip_netmask;
1499         memcpy(&lwip_ip, &default_ip->ip, sizeof(struct ip4_addr));
1500         memcpy(&lwip_netmask, &default_ip->netmask, sizeof(struct ip4_addr));
1501         dhcps_set_new_lease_cb(esp_netif->dhcps, esp_netif_dhcps_cb, esp_netif);
1502         dhcps_set_option_info(esp_netif->dhcps, SUBNET_MASK, (void*)&lwip_netmask, sizeof(lwip_netmask));
1503         if (dhcps_start(esp_netif->dhcps, p_netif, lwip_ip) != ERR_OK) {
1504             ESP_LOGE(TAG, "DHCP server cannot be started");
1505             esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
1506             return ESP_ERR_ESP_NETIF_DHCPS_START_FAILED;
1507         }
1508         esp_netif->dhcps_status = ESP_NETIF_DHCP_STARTED;
1509         ESP_LOGD(TAG, "DHCP server started successfully");
1510         return ESP_OK;
1511     } else {
1512         ESP_LOGD(TAG, "dhcp server re init");
1513         esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT;
1514         return ESP_OK;
1515     }
1516 }
1517 
esp_netif_dhcps_start(esp_netif_t * esp_netif)1518 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)
1519 
1520 static esp_err_t esp_netif_dhcps_stop_api(esp_netif_api_msg_t *msg)
1521 {
1522     esp_netif_t *esp_netif = msg->esp_netif;
1523 
1524     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1525 
1526     if (!esp_netif) {
1527         return ESP_ERR_INVALID_ARG;
1528     }
1529 
1530     struct netif *p_netif = esp_netif->lwip_netif;
1531     if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) {
1532         if (dhcps_stop(esp_netif->dhcps, p_netif) != ERR_OK) {
1533             ESP_LOGD(TAG, "dhcp server if not ready");
1534             return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1535         }
1536     } else if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STOPPED) {
1537         ESP_LOGD(TAG, "dhcp server already stoped");
1538         return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
1539     }
1540 
1541     ESP_LOGD(TAG, "dhcp server stop successfully");
1542     esp_netif->dhcps_status = ESP_NETIF_DHCP_STOPPED;
1543     return ESP_OK;
1544 }
1545 
esp_netif_dhcps_stop(esp_netif_t * esp_netif)1546 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)
1547 #endif
1548 
1549 static esp_err_t esp_netif_set_hostname_api(esp_netif_api_msg_t *msg)
1550 {
1551     esp_netif_t *esp_netif = msg->esp_netif;
1552     const char *hostname = msg->data;
1553 
1554     ESP_LOGD(TAG, "%s esp_netif:%p hostname %s", __func__, esp_netif, hostname);
1555 
1556     if (!esp_netif) {
1557         return ESP_ERR_INVALID_ARG;
1558     }
1559 
1560 #if LWIP_NETIF_HOSTNAME
1561 
1562     struct netif *p_netif = esp_netif->lwip_netif;
1563 
1564     if (strlen(hostname) > ESP_NETIF_HOSTNAME_MAX_SIZE) {
1565         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1566     }
1567 
1568     if (p_netif != NULL) {
1569         if (esp_netif->hostname) {
1570             free(esp_netif->hostname);
1571         }
1572         esp_netif->hostname = strdup(hostname);
1573         if (esp_netif->hostname == NULL) {
1574             p_netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME;
1575             return ESP_ERR_NO_MEM;
1576         }
1577         p_netif->hostname = esp_netif->hostname;
1578         return ESP_OK;
1579     } else {
1580         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1581     }
1582 #else
1583     return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1584 #endif
1585 }
1586 
esp_netif_set_hostname(esp_netif_t * esp_netif,const char * hostname)1587 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)
1588 
1589 esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname)
1590 {
1591     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1592 
1593     if (!esp_netif || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1594         return ESP_ERR_INVALID_ARG;
1595     }
1596 
1597 #if LWIP_NETIF_HOSTNAME
1598     struct netif *p_netif = esp_netif->lwip_netif;
1599 
1600     if (p_netif != NULL && p_netif->hostname != NULL) {
1601         *hostname = p_netif->hostname;
1602         return ESP_OK;
1603     } else {
1604         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1605     }
1606 #else
1607     return ESP_ERR_ESP_NETIF_IF_NOT_READY;
1608 #endif
1609 }
1610 
esp_netif_up_api(esp_netif_api_msg_t * msg)1611 static esp_err_t esp_netif_up_api(esp_netif_api_msg_t *msg)
1612 {
1613     esp_netif_t *esp_netif = msg->esp_netif;
1614 
1615     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1616 
1617     if (!esp_netif) {
1618         return ESP_ERR_INVALID_STATE;
1619     }
1620 
1621     struct netif *lwip_netif = esp_netif->lwip_netif;
1622 
1623 #if CONFIG_LWIP_IPV4
1624     /* use last obtained ip, or static ip */
1625     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);
1626 #endif
1627     netif_set_up(lwip_netif);
1628     netif_set_link_up(lwip_netif);
1629 
1630     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED);
1631 
1632     return ESP_OK;
1633 }
1634 
esp_netif_up(esp_netif_t * esp_netif)1635 esp_err_t esp_netif_up(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK(esp_netif_up_api, esp_netif, NULL)
1636 
1637 static esp_err_t esp_netif_down_api(esp_netif_api_msg_t *msg)
1638 {
1639     esp_netif_t *esp_netif = msg->esp_netif;
1640 
1641     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1642 
1643     if (!esp_netif) {
1644         return ESP_ERR_INVALID_STATE;
1645     }
1646 
1647     struct netif *lwip_netif = esp_netif->lwip_netif;
1648 
1649     if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT && esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
1650 #if CONFIG_LWIP_IPV4
1651         dhcp_stop(esp_netif->lwip_netif);
1652 
1653         esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT;
1654 
1655         esp_netif_reset_ip_info(esp_netif);
1656 #endif
1657     }
1658 #if CONFIG_LWIP_IPV6
1659 #if ESP_MLDV6_REPORT
1660         if (esp_netif->flags & ESP_NETIF_FLAG_MLDV6_REPORT) {
1661             netif_unset_mldv6_flag(esp_netif->lwip_netif);
1662         }
1663 #endif
1664     for(int8_t i = 0 ;i < LWIP_IPV6_NUM_ADDRESSES ;i++) {
1665         netif_ip6_addr_set(lwip_netif, i, IP6_ADDR_ANY6);
1666         netif_ip6_addr_set_valid_life(lwip_netif, i, 0);
1667         netif_ip6_addr_set_pref_life(lwip_netif, i, 0);
1668         netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
1669     }
1670 #endif
1671 #if CONFIG_LWIP_IPV4
1672     netif_set_addr(lwip_netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
1673 #endif
1674     netif_set_down(lwip_netif);
1675     netif_set_link_down(lwip_netif);
1676 
1677     if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
1678 #if CONFIG_LWIP_IPV4
1679         esp_netif_start_ip_lost_timer(esp_netif);
1680 #endif
1681     }
1682 
1683     esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);
1684 
1685     return ESP_OK;
1686 }
1687 
esp_netif_down(esp_netif_t * esp_netif)1688 esp_err_t esp_netif_down(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK(esp_netif_down_api, esp_netif, NULL)
1689 
1690 bool esp_netif_is_netif_up(esp_netif_t *esp_netif)
1691 {
1692     ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
1693 
1694     if (esp_netif != NULL && esp_netif->lwip_netif != NULL) {
1695         if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
1696             // ppp implementation uses netif_set_link_up/down to update link state
1697             return netif_is_link_up(esp_netif->lwip_netif);
1698         }
1699         // esp-netif handlers and drivers take care to set_netif_up/down on link state update
1700         return netif_is_up(esp_netif->lwip_netif);
1701     } else {
1702         return false;
1703     }
1704 }
1705 
1706 #if CONFIG_LWIP_IPV4
esp_netif_get_old_ip_info(esp_netif_t * esp_netif,esp_netif_ip_info_t * ip_info)1707 esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
1708 {
1709     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1710 
1711     if (esp_netif == NULL || ip_info == NULL) {
1712         return ESP_ERR_INVALID_ARG;
1713     }
1714     memcpy(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t));
1715     return ESP_OK;
1716 }
1717 
esp_netif_get_ip_info(esp_netif_t * esp_netif,esp_netif_ip_info_t * ip_info)1718 esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
1719 {
1720     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1721 
1722     if (esp_netif == NULL || ip_info == NULL) {
1723         return ESP_ERR_INVALID_ARG;
1724     }
1725 
1726     struct netif *p_netif = esp_netif->lwip_netif;
1727 
1728     if (p_netif != NULL && netif_is_up(p_netif)) {
1729         ip4_addr_set(&ip_info->ip, ip_2_ip4(&p_netif->ip_addr));
1730         ip4_addr_set(&ip_info->netmask, ip_2_ip4(&p_netif->netmask));
1731         ip4_addr_set(&ip_info->gw, ip_2_ip4(&p_netif->gw));
1732 
1733         return ESP_OK;
1734     }
1735 
1736     memcpy(ip_info, esp_netif->ip_info, sizeof(esp_netif_ip_info_t));
1737 
1738     return ESP_OK;
1739 }
1740 
1741 
esp_netif_is_valid_static_ip(esp_netif_ip_info_t * ip_info)1742 bool esp_netif_is_valid_static_ip(esp_netif_ip_info_t *ip_info)
1743 {
1744     if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask))) {
1745         // let's assume valid ip_info is when none of ip and netmask is 'any' address (zeros)
1746         return true;
1747     }
1748     return false;
1749 }
1750 
esp_netif_set_ip_old_info_api(esp_netif_api_msg_t * msg)1751 static esp_err_t esp_netif_set_ip_old_info_api(esp_netif_api_msg_t *msg)
1752 {
1753     esp_netif_t *esp_netif = msg->esp_netif;
1754     const esp_netif_ip_info_t *ip_info = msg->data;
1755 
1756     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1757 
1758     if (esp_netif == NULL || ip_info == NULL) {
1759         return ESP_ERR_INVALID_STATE;
1760     }
1761 
1762     memcpy(msg->esp_netif->ip_info_old, msg->data, sizeof(esp_netif_ip_info_t));
1763     return ESP_OK;
1764 }
1765 
esp_netif_set_old_ip_info(esp_netif_t * esp_netif,const esp_netif_ip_info_t * ip_info)1766 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)
1767 
1768 static esp_err_t esp_netif_set_ip_info_api(esp_netif_api_msg_t *msg)
1769 {
1770     esp_netif_t *esp_netif = msg->esp_netif;
1771     const esp_netif_ip_info_t *ip_info = msg->data;
1772 
1773     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
1774 
1775     if (esp_netif == NULL || ip_info == NULL) {
1776         return ESP_ERR_INVALID_STATE;
1777     }
1778 
1779     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1780         if (esp_netif->dhcps_status != ESP_NETIF_DHCP_STOPPED) {
1781             return ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED;
1782             }
1783     } else if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
1784         if (esp_netif->dhcpc_status != ESP_NETIF_DHCP_STOPPED) {
1785             return ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED;
1786         }
1787 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
1788         dns_clear_servers(true);
1789 #endif
1790     }
1791 
1792     ip4_addr_copy(esp_netif->ip_info->ip, ip_info->ip);
1793     ip4_addr_copy(esp_netif->ip_info->gw, ip_info->gw);
1794     ip4_addr_copy(esp_netif->ip_info->netmask, ip_info->netmask);
1795 
1796     struct netif *p_netif = esp_netif->lwip_netif;
1797 
1798     if (p_netif != NULL && netif_is_up(p_netif)) {
1799         netif_set_addr(p_netif, (ip4_addr_t*)&ip_info->ip, (ip4_addr_t*)&ip_info->netmask, (ip4_addr_t*)&ip_info->gw);
1800         if (ESP_NETIF_FLAG_EVENT_IP_MODIFIED & esp_netif->flags) {
1801             if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask) || ip4_addr_isany_val(ip_info->gw))) {
1802 
1803                 ip_event_t evt_id = esp_netif->get_ip_event;
1804                 ip_event_got_ip_t evt = { .esp_netif = esp_netif, .ip_changed = false};
1805                 int ret;
1806                 if (memcmp(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t))) {
1807                     evt.ip_changed = true;
1808                 }
1809 
1810                 memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t));
1811                 memcpy(esp_netif->ip_info_old, ip_info, sizeof(esp_netif_ip_info_t));
1812                 ret = esp_event_post(IP_EVENT, evt_id, &evt, sizeof(evt), 0);
1813                 if (ESP_OK != ret) {
1814                     ESP_LOGE(TAG, "set ip info: failed to post got ip event (%x)", ret);
1815                 }
1816 
1817                 ESP_LOGD(TAG, "if%p netif set static ip: ip changed=%d", esp_netif, evt.ip_changed);
1818 
1819             }
1820         }
1821     }
1822 
1823     return ESP_OK;
1824 }
1825 
1826 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)
1827 #endif /* CONFIG_LWIP_IPV4 */
1828 
1829 struct array_mac_ip_t {
1830     int num;
1831     esp_netif_pair_mac_ip_t *mac_ip_pair;
1832 };
1833 
1834 #if CONFIG_LWIP_DHCPS
esp_netif_dhcps_get_clients_by_mac_api(esp_netif_api_msg_t * msg)1835 static esp_err_t esp_netif_dhcps_get_clients_by_mac_api(esp_netif_api_msg_t *msg)
1836 {
1837     esp_netif_t *netif = msg->esp_netif;
1838     struct array_mac_ip_t *mac_ip_list = msg->data;
1839     for (int i = 0; i < mac_ip_list->num; i++) {
1840         dhcp_search_ip_on_mac(netif->dhcps, mac_ip_list->mac_ip_pair[i].mac, (ip4_addr_t*)&mac_ip_list->mac_ip_pair[i].ip);
1841     }
1842     return ESP_OK;
1843 }
1844 #endif // CONFIG_LWIP_DHCPS
1845 
esp_netif_dhcps_get_clients_by_mac(esp_netif_t * esp_netif,int num,esp_netif_pair_mac_ip_t * mac_ip_pair)1846 esp_err_t esp_netif_dhcps_get_clients_by_mac(esp_netif_t *esp_netif, int num, esp_netif_pair_mac_ip_t *mac_ip_pair)
1847 {
1848 #if CONFIG_LWIP_DHCPS
1849     if (esp_netif == NULL || esp_netif->dhcps == NULL || num < 0 || mac_ip_pair == NULL) {
1850         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1851     }
1852     struct array_mac_ip_t array_mac_ip = { num, mac_ip_pair };
1853     return esp_netif_lwip_ipc_call(esp_netif_dhcps_get_clients_by_mac_api, esp_netif, (void *)&array_mac_ip);
1854 #else
1855     return ESP_ERR_NOT_SUPPORTED;
1856 #endif // CONFIG_LWIP_DHCPS
1857 }
1858 
esp_netif_set_dns_info_api(esp_netif_api_msg_t * msg)1859 static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg)
1860 {
1861     esp_netif_t *esp_netif = msg->esp_netif;
1862     esp_netif_dns_param_t *dns_param = msg->data;
1863     esp_netif_dns_type_t type = dns_param->dns_type;
1864     esp_netif_dns_info_t *dns = dns_param->dns_info;
1865 
1866     ESP_LOGD(TAG, "esp_netif_set_dns_info: if=%p type=%d dns=%x", esp_netif, type, dns->ip.u_addr.ip4.addr);
1867 
1868     ip_addr_t lwip_ip = {};
1869     ESPIP_TO_IP(&dns->ip, &lwip_ip);
1870     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1871 #if ESP_DHCPS
1872         // if DHCP server configured to set DNS in dhcps API
1873         if (type != ESP_NETIF_DNS_MAIN) {
1874             ESP_LOGD(TAG, "set dns invalid type");
1875             return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1876         } else {
1877             dhcps_dns_setserver(esp_netif->dhcps, &lwip_ip);
1878         }
1879 #else
1880         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
1881 #endif
1882     } else {
1883         dns_setserver(type, &lwip_ip);
1884     }
1885 
1886     return ESP_OK;
1887 }
1888 
esp_netif_set_dns_info(esp_netif_t * esp_netif,esp_netif_dns_type_t type,esp_netif_dns_info_t * dns)1889 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)
1890 {
1891     if (esp_netif == NULL) {
1892         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1893     }
1894 
1895     if (dns == NULL) {
1896         ESP_LOGD(TAG, "set dns null dns");
1897         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1898     }
1899 
1900     if (ESP_IP_IS_ANY(dns->ip)) {
1901         ESP_LOGD(TAG, "set dns invalid dns");
1902         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1903     }
1904 
1905     esp_netif_dns_param_t dns_param = {
1906         .dns_type = type,
1907         .dns_info = dns
1908     };
1909     return esp_netif_lwip_ipc_call(esp_netif_set_dns_info_api, esp_netif, (void *)&dns_param);
1910 }
1911 
esp_netif_get_dns_info_api(esp_netif_api_msg_t * msg)1912 static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg)
1913 {
1914     esp_netif_t *esp_netif = msg->esp_netif;
1915     esp_netif_dns_param_t *dns_param = msg->data;
1916     esp_netif_dns_type_t type = dns_param->dns_type;
1917     esp_netif_dns_info_t *dns = dns_param->dns_info;
1918 
1919     ESP_LOGD(TAG, "esp_netif_get_dns_info: esp_netif=%p type=%d", esp_netif, type);
1920 
1921     if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
1922 #if ESP_DHCPS
1923         ip4_addr_t dns_ip;
1924         dhcps_dns_getserver(esp_netif->dhcps, &dns_ip);
1925         memcpy(&dns->ip.u_addr.ip4, &dns_ip, sizeof(ip4_addr_t));
1926         dns->ip.type = ESP_IPADDR_TYPE_V4;
1927 #else
1928         LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED);
1929 #endif
1930     } else {
1931         const ip_addr_t*  dns_ip = NULL;
1932         dns_ip = dns_getserver(type);
1933         if(dns_ip != NULL) {
1934             IP_TO_ESPIP(dns_ip, &dns->ip);
1935         }
1936     }
1937 
1938     return ESP_OK;
1939 }
1940 
esp_netif_get_dns_info(esp_netif_t * esp_netif,esp_netif_dns_type_t type,esp_netif_dns_info_t * dns)1941 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)
1942 {
1943     if (esp_netif == NULL) {
1944         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1945     }
1946 
1947     if (dns == NULL) {
1948         ESP_LOGE(TAG, "%s: dns_info cannot be NULL", __func__);
1949         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
1950     }
1951 
1952     esp_netif_dns_param_t dns_param = {
1953         .dns_type = type,
1954         .dns_info = dns
1955     };
1956     return esp_netif_lwip_ipc_call(esp_netif_get_dns_info_api, esp_netif, (void *)&dns_param);
1957 }
1958 
1959 #if CONFIG_LWIP_IPV6
1960 
1961 #ifdef CONFIG_LWIP_MLDV6_TMR_INTERVAL
1962 
netif_send_mldv6(void * arg)1963 static void netif_send_mldv6(void *arg)
1964 {
1965     struct netif *netif = arg;
1966     if (!netif_is_up(netif)) {
1967         return;
1968     }
1969     mld6_report_groups(netif);
1970     sys_timeout(CONFIG_LWIP_MLDV6_TMR_INTERVAL*1000, netif_send_mldv6, netif);
1971 }
1972 
netif_set_mldv6_flag(struct netif * netif)1973 static void netif_set_mldv6_flag(struct netif *netif)
1974 {
1975     if (!netif_is_up(netif)) {
1976         return;
1977     }
1978     sys_timeout(CONFIG_LWIP_MLDV6_TMR_INTERVAL*1000, netif_send_mldv6, netif);
1979 }
1980 
netif_unset_mldv6_flag(struct netif * netif)1981 static void netif_unset_mldv6_flag(struct netif *netif)
1982 {
1983     sys_untimeout(netif_send_mldv6, netif);
1984 }
1985 
1986 #endif
1987 
esp_netif_ip6_get_addr_type(esp_ip6_addr_t * ip6_addr)1988 esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr)
1989 {
1990     ip6_addr_t* lwip_ip6_info = (ip6_addr_t*)ip6_addr;
1991 
1992     if (ip6_addr_isglobal(lwip_ip6_info)) {
1993         return ESP_IP6_ADDR_IS_GLOBAL;
1994     } else if (ip6_addr_islinklocal(lwip_ip6_info)) {
1995         return ESP_IP6_ADDR_IS_LINK_LOCAL;
1996     } else if (ip6_addr_issitelocal(lwip_ip6_info)) {
1997         return ESP_IP6_ADDR_IS_SITE_LOCAL;
1998     } else if (ip6_addr_isuniquelocal(lwip_ip6_info)) {
1999         return ESP_IP6_ADDR_IS_UNIQUE_LOCAL;
2000     } else if (ip6_addr_isipv4mappedipv6(lwip_ip6_info)) {
2001         return ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6;
2002     }
2003     return ESP_IP6_ADDR_IS_UNKNOWN;
2004 
2005 }
2006 
esp_netif_internal_nd6_cb(struct netif * netif,uint8_t ip_index)2007 static void esp_netif_internal_nd6_cb(struct netif *netif, uint8_t ip_index)
2008 {
2009     esp_netif_t *esp_netif;
2010     ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, netif);
2011     if (netif == NULL || (esp_netif = lwip_get_esp_netif(netif)) == NULL) {
2012         // internal pointer hasn't been configured yet (probably in the interface init_fn())
2013         return;
2014     }
2015 
2016     esp_netif_ip6_info_t ip6_info;
2017     ip6_addr_t lwip_ip6_info;
2018     ip_event_got_ip6_t evt = { .esp_netif = esp_netif, .ip_index = ip_index };
2019 
2020     ip6_addr_set(&lwip_ip6_info, ip_2_ip6(&netif->ip6_addr[ip_index]));
2021 #if LWIP_IPV6_SCOPES
2022     memcpy(&ip6_info.ip, &lwip_ip6_info, sizeof(esp_ip6_addr_t));
2023 #else
2024     memcpy(&ip6_info.ip, &lwip_ip6_info, sizeof(ip6_addr_t));
2025     ip6_info.ip.zone = 0;   // zero out zone, as not used in lwip
2026 #endif /* LWIP_IPV6_SCOPES */
2027 
2028     if (esp_netif->flags&ESP_NETIF_FLAG_MLDV6_REPORT) {
2029 #if ESP_MLDV6_REPORT
2030         netif_set_mldv6_flag(netif);
2031 #else
2032         ESP_LOGW(TAG,"CONFIG_LWIP_ESP_MLDV6_REPORT not enabled, but esp-netif configured with ESP_NETIF_FLAG_MLDV6_REPORT");
2033 #endif
2034     }
2035 
2036     memcpy(&evt.ip6_info, &ip6_info, sizeof(esp_netif_ip6_info_t));
2037     int ret = esp_event_post(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0);
2038     if (ESP_OK != ret) {
2039         ESP_LOGE(TAG, "nd6 cb: failed to post IP_EVENT_GOT_IP6 (%x)", ret);
2040     }
2041 }
2042 
esp_netif_create_ip6_linklocal_api(esp_netif_api_msg_t * msg)2043 static esp_err_t esp_netif_create_ip6_linklocal_api(esp_netif_api_msg_t *msg)
2044 {
2045     esp_netif_t *esp_netif = msg->esp_netif;
2046 
2047     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
2048 
2049     struct netif *p_netif = esp_netif->lwip_netif;
2050     if (p_netif != NULL && netif_is_up(p_netif)) {
2051         netif_create_ip6_linklocal_address(p_netif, 1);
2052         return ESP_OK;
2053     } else {
2054         return ESP_FAIL;
2055     }
2056 }
2057 
esp_netif_create_ip6_linklocal(esp_netif_t * esp_netif)2058 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)
2059 
2060 esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
2061 {
2062     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
2063 
2064     if (esp_netif == NULL || if_ip6 == NULL || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
2065         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2066     }
2067     struct netif *p_netif = esp_netif->lwip_netif;
2068 
2069     if (p_netif != NULL && netif_is_up(p_netif) && ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, 0))) {
2070         memcpy(if_ip6, &p_netif->ip6_addr[0], sizeof(ip6_addr_t));
2071     } else {
2072         return ESP_FAIL;
2073     }
2074     return ESP_OK;
2075 }
2076 
esp_netif_get_ip6_global(esp_netif_t * esp_netif,esp_ip6_addr_t * if_ip6)2077 esp_err_t esp_netif_get_ip6_global(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
2078 {
2079     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
2080 
2081     if (esp_netif == NULL || if_ip6 == NULL) {
2082         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2083     }
2084 
2085     int i;
2086     struct netif *p_netif = esp_netif->lwip_netif;
2087 
2088     if (p_netif != NULL && netif_is_up(p_netif)) {
2089         for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2090             if (ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, i)) &&
2091                 ip6_addr_isglobal(netif_ip6_addr(p_netif, i))) {
2092                     memcpy(if_ip6, &p_netif->ip6_addr[i], sizeof(ip6_addr_t));
2093                     return ESP_OK;
2094             }
2095         }
2096     }
2097 
2098     return ESP_FAIL;
2099 }
2100 
esp_netif_get_all_ip6(esp_netif_t * esp_netif,esp_ip6_addr_t if_ip6[])2101 int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[])
2102 {
2103     ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif);
2104 
2105     if (esp_netif == NULL || if_ip6 == NULL) {
2106         return 0;
2107     }
2108 
2109     int addr_count = 0;
2110     struct netif *p_netif = esp_netif->lwip_netif;
2111 
2112     if (p_netif != NULL && netif_is_up(p_netif)) {
2113         for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2114             if (!ip_addr_cmp(&p_netif->ip6_addr[i], IP6_ADDR_ANY)) {
2115                 memcpy(&if_ip6[addr_count++], &p_netif->ip6_addr[i], sizeof(ip6_addr_t));
2116             }
2117         }
2118     }
2119     return addr_count;
2120 }
2121 #endif
2122 
esp_netif_get_flags(esp_netif_t * esp_netif)2123 esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif)
2124 {
2125     return esp_netif->flags;
2126 }
2127 
esp_netif_get_ifkey(esp_netif_t * esp_netif)2128 const char *esp_netif_get_ifkey(esp_netif_t *esp_netif)
2129 {
2130     return esp_netif->if_key;
2131 }
2132 
esp_netif_get_desc(esp_netif_t * esp_netif)2133 const char *esp_netif_get_desc(esp_netif_t *esp_netif)
2134 {
2135     return esp_netif->if_desc;
2136 }
2137 
esp_netif_get_route_prio(esp_netif_t * esp_netif)2138 int esp_netif_get_route_prio(esp_netif_t *esp_netif)
2139 {
2140     if (esp_netif == NULL) {
2141         return -1;
2142     }
2143     return esp_netif->route_prio;
2144 }
2145 
esp_netif_get_event_id(esp_netif_t * esp_netif,esp_netif_ip_event_type_t event_type)2146 int32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t event_type)
2147 {
2148     switch(event_type) {
2149         case ESP_NETIF_IP_EVENT_GOT_IP:
2150             return esp_netif->get_ip_event;
2151         case ESP_NETIF_IP_EVENT_LOST_IP:
2152             return esp_netif->lost_ip_event;
2153         default:
2154             return -1;
2155     }
2156 }
2157 
2158 struct dhcp_params {
2159     esp_netif_dhcp_option_mode_t op;
2160     esp_netif_dhcp_option_id_t id;
2161     void *val;
2162     uint32_t len;
2163 };
2164 
2165 #if ESP_DHCPS
esp_netif_dhcps_option_api(esp_netif_api_msg_t * msg)2166 esp_err_t esp_netif_dhcps_option_api(esp_netif_api_msg_t *msg)
2167 {
2168     esp_netif_t *esp_netif = msg->esp_netif;
2169     struct dhcp_params *opt = msg->data;
2170     void *opt_info = dhcps_option_info(esp_netif->dhcps, opt->id, opt->len);
2171 
2172     esp_netif_dhcp_status_t dhcps_status = esp_netif->dhcps_status;
2173     if (opt_info == NULL || opt->val == NULL) {
2174         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2175     }
2176 
2177     if (opt->op == ESP_NETIF_OP_GET) {
2178         if (dhcps_status == ESP_NETIF_DHCP_STOPPED) {
2179             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
2180         }
2181 
2182         switch (opt->id) {
2183             case IP_ADDRESS_LEASE_TIME: {
2184                 *(uint32_t *)opt->val = *(uint32_t *)opt_info;
2185                 break;
2186             }
2187             case ESP_NETIF_SUBNET_MASK:
2188             case REQUESTED_IP_ADDRESS: {
2189                 memcpy(opt->val, opt_info, opt->len);
2190                 break;
2191             }
2192             case ROUTER_SOLICITATION_ADDRESS: {
2193                 if ((*(uint8_t *)opt_info) & OFFER_ROUTER) {
2194                     *(uint8_t *)opt->val = 1;
2195                 } else {
2196                     *(uint8_t *)opt->val = 0;
2197                 }
2198                 break;
2199             }
2200             case DOMAIN_NAME_SERVER: {
2201                 if ((*(uint8_t *)opt_info) & OFFER_DNS) {
2202                     *(uint8_t *)opt->val = 1;
2203                 } else {
2204                     *(uint8_t *)opt->val = 0;
2205                 }
2206                 break;
2207             }
2208             default:
2209                 break;
2210         }
2211     } else if (opt->op == ESP_NETIF_OP_SET) {
2212         if (dhcps_status == ESP_NETIF_DHCP_STARTED) {
2213             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
2214         }
2215 
2216         switch (opt->id) {
2217             case IP_ADDRESS_LEASE_TIME: {
2218                 if (*(uint32_t *)opt->val != 0) {
2219                     *(uint32_t *)opt_info = *(uint32_t *)opt->val;
2220                 } else {
2221                     *(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF;
2222                 }
2223                 break;
2224             }
2225             case ESP_NETIF_SUBNET_MASK: {
2226                 memcpy(opt_info, opt->val, opt->len);
2227                 break;
2228             }
2229             case REQUESTED_IP_ADDRESS: {
2230                 esp_netif_ip_info_t info;
2231                 uint32_t softap_ip = 0;
2232                 uint32_t start_ip = 0;
2233                 uint32_t end_ip = 0;
2234                 dhcps_lease_t *poll = opt->val;
2235 
2236                 if (poll->enable) {
2237                     memset(&info, 0x00, sizeof(esp_netif_ip_info_t));
2238                     esp_netif_get_ip_info(esp_netif, &info);
2239 
2240                     softap_ip = htonl(info.ip.addr);
2241                     start_ip = htonl(poll->start_ip.addr);
2242                     end_ip = htonl(poll->end_ip.addr);
2243 
2244                     /*config ip information can't contain local ip*/
2245                     if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
2246                         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2247                     }
2248 
2249                     /*config ip information must be in the same segment as the local ip*/
2250                     softap_ip >>= 8;
2251                     if ((start_ip >> 8 != softap_ip)
2252                         || (end_ip >> 8 != softap_ip)) {
2253                         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2254                     }
2255 
2256                     if (end_ip - start_ip > DHCPS_MAX_LEASE) {
2257                         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2258                     }
2259                 }
2260 
2261                 memcpy(opt_info, opt->val, opt->len);
2262                 break;
2263             }
2264             case ROUTER_SOLICITATION_ADDRESS: {
2265                 if (*(uint8_t *)opt->val) {
2266                     *(uint8_t *)opt_info |= OFFER_ROUTER;
2267                 } else {
2268                     *(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF);
2269                 }
2270                 break;
2271             }
2272             case DOMAIN_NAME_SERVER: {
2273                 if (*(uint8_t *)opt->val) {
2274                     *(uint8_t *)opt_info |= OFFER_DNS;
2275                 } else {
2276                     *(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF);
2277                 }
2278                 break;
2279             }
2280 
2281             default:
2282                 break;
2283         }
2284         dhcps_set_option_info(esp_netif->dhcps, opt->id, opt_info, opt->len);
2285     } else {
2286         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2287     }
2288 
2289     return ESP_OK;
2290 }
2291 
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)2292 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,
2293                                  uint32_t opt_len)
2294 {
2295     if (esp_netif == NULL || esp_netif->dhcps == NULL) {
2296         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
2297     }
2298     struct dhcp_params opts = { .op = opt_op, .id = opt_id, .len = opt_len, .val = opt_val };
2299     return esp_netif_lwip_ipc_call(esp_netif_dhcps_option_api, esp_netif, &opts);
2300 }
2301 #endif // ESP_DHCPS
2302 
2303 #if CONFIG_LWIP_IPV4
2304 
esp_netif_dhcpc_option_api(esp_netif_api_msg_t * msg)2305 esp_err_t esp_netif_dhcpc_option_api(esp_netif_api_msg_t *msg)
2306 {
2307     esp_netif_t *esp_netif = msg->esp_netif;
2308     struct dhcp_params *opt = msg->data;
2309 
2310     struct dhcp *dhcp = netif_dhcp_data(esp_netif->lwip_netif);
2311     if (dhcp == NULL || opt->val == NULL) {
2312         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2313     }
2314     if (opt->op == ESP_NETIF_OP_GET) {
2315         if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
2316             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
2317         }
2318         switch (opt->id) {
2319             case ESP_NETIF_IP_REQUEST_RETRY_TIME:
2320                 if (opt->len == sizeof(dhcp->tries)) {
2321                     *(uint8_t *)opt->val = dhcp->tries;
2322                 }
2323                 break;
2324 #if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
2325             case ESP_NETIF_VENDOR_SPECIFIC_INFO:
2326                 return dhcp_get_vendor_specific_information(opt->len, opt->val);
2327 #endif
2328             default:
2329                 return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2330         }
2331     } else if (opt->op == ESP_NETIF_OP_SET) {
2332         if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
2333             return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
2334         }
2335         switch (opt->id) {
2336             case ESP_NETIF_IP_REQUEST_RETRY_TIME:
2337                 if (opt->len == sizeof(dhcp->tries)) {
2338                     dhcp->tries = *(uint8_t *)opt->val;
2339                 }
2340                 break;
2341 #if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
2342                 case ESP_NETIF_VENDOR_CLASS_IDENTIFIER:
2343                 return dhcp_set_vendor_class_identifier(opt->len, opt->val);
2344 #endif
2345             default:
2346                 return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2347         }
2348     } else {
2349         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2350     }
2351     return ESP_OK;
2352 }
2353 
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)2354 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,
2355                                  uint32_t opt_len)
2356 {
2357     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
2358         return ESP_ERR_ESP_NETIF_IF_NOT_READY;
2359     }
2360     struct dhcp_params opts = { .op = opt_op, .id = opt_id, .len = opt_len, .val = opt_val };
2361     return esp_netif_lwip_ipc_call(esp_netif_dhcpc_option_api, esp_netif, &opts);
2362 }
2363 
2364 #endif /* CONFIG_LWIP_IPV4 */
2365 
esp_netif_get_netif_impl_index(esp_netif_t * esp_netif)2366 int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
2367 {
2368     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
2369         return -1;
2370     }
2371     return netif_get_index(esp_netif->lwip_netif);
2372 }
2373 
esp_netif_get_netif_impl_name_api(esp_netif_api_msg_t * msg)2374 esp_err_t esp_netif_get_netif_impl_name_api(esp_netif_api_msg_t *msg)
2375 {
2376     struct netif* netif = msg->esp_netif->lwip_netif;
2377     netif_index_to_name(netif_get_index(netif), msg->data);
2378     return ESP_OK;
2379 }
2380 
esp_netif_get_netif_impl_name(esp_netif_t * esp_netif,char * name)2381 esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
2382 {
2383     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
2384 
2385     if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
2386         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
2387     }
2388     return esp_netif_lwip_ipc_call(esp_netif_get_netif_impl_name_api, esp_netif, name);
2389 }
2390 
esp_netif_napt_enable(esp_netif_t * esp_netif)2391 esp_err_t esp_netif_napt_enable(esp_netif_t *esp_netif)
2392 {
2393 #if !IP_NAPT
2394     return ESP_ERR_NOT_SUPPORTED;
2395 #else
2396     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
2397 
2398     /* Check if the interface is up */
2399     if (!netif_is_up(esp_netif->lwip_netif)) {
2400         return ESP_FAIL;
2401     }
2402 
2403     esp_netif_list_lock();
2404     /* Disable napt on all other interface */
2405     esp_netif_t *netif = esp_netif_next_unsafe(NULL);
2406     while (netif) {
2407         if (netif != esp_netif) {
2408             ip_napt_enable_netif(netif->lwip_netif, 0); // Fails only if netif is down
2409             ESP_LOGW(TAG, "napt disabled on esp_netif:%p", esp_netif);
2410         }
2411         netif = esp_netif_next_unsafe(netif);
2412     }
2413 
2414     int ret = ip_napt_enable_netif(esp_netif->lwip_netif, 1);
2415     esp_netif_list_unlock();
2416 
2417     if (ret == 0) {
2418         return ESP_FAIL;
2419     }
2420 
2421     return ESP_OK;
2422 #endif /* IP_NAPT */
2423 }
2424 
esp_netif_napt_disable(esp_netif_t * esp_netif)2425 esp_err_t esp_netif_napt_disable(esp_netif_t *esp_netif)
2426 {
2427 #if !IP_NAPT
2428     return ESP_ERR_NOT_SUPPORTED;
2429 #else
2430     /* Check if the interface is up */
2431     if (!netif_is_up(esp_netif->lwip_netif)) {
2432         return ESP_FAIL;
2433     }
2434 
2435     esp_netif_list_lock();
2436     ip_napt_enable_netif(esp_netif->lwip_netif, 0); // Fails only if netif is down
2437     ESP_LOGD(TAG, "napt disabled on esp_netif:%p", esp_netif);
2438     esp_netif_list_unlock();
2439 
2440     return ESP_OK;
2441 #endif /* IP_NAPT */
2442 }
2443 
2444 #if MIB2_STATS
esp_netif_set_link_speed_api(esp_netif_api_msg_t * msg)2445 static esp_err_t esp_netif_set_link_speed_api(esp_netif_api_msg_t *msg)
2446 {
2447     uint32_t speed = *((uint32_t*)msg->data);
2448     esp_err_t error = ESP_OK;
2449     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
2450     NETIF_INIT_SNMP(msg->esp_netif->lwip_netif, snmp_ifType_ethernet_csmacd, speed);
2451     LWIP_UNUSED_ARG(speed);     // Maybe unused if SNMP disabled
2452     return error;
2453 }
2454 
esp_netif_set_link_speed(esp_netif_t * esp_netif,uint32_t speed)2455 esp_err_t esp_netif_set_link_speed(esp_netif_t *esp_netif, uint32_t speed)
2456 _RUN_IN_LWIP_TASK(esp_netif_set_link_speed_api, esp_netif, &speed)
2457 #else
2458 esp_err_t esp_netif_set_link_speed(esp_netif_t *esp_netif, uint32_t speed)
2459 {
2460     // link speed is used only to collect interface related statistics (if MIB2_STATS enabled)
2461     return ESP_OK;
2462 }
2463 #endif /* MIB2_STATS */
2464 
2465 #if CONFIG_LWIP_IPV6
2466 
2467 static esp_err_t esp_netif_join_ip6_multicast_group_api(esp_netif_api_msg_t *msg)
2468 {
2469     esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
2470     esp_err_t error = ESP_OK;
2471     ip6_addr_t ip6addr;
2472 
2473     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
2474     memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
2475 #if LWIP_IPV6_SCOPES
2476     ip6addr.zone = 0;
2477 #endif
2478     if (mld6_joingroup_netif(msg->esp_netif->lwip_netif, &ip6addr) != ERR_OK) {
2479         error = ESP_ERR_ESP_NETIF_MLD6_FAILED;
2480         ESP_LOGE(TAG, "failed to join ip6 multicast group");
2481     }
2482     return error;
2483 }
2484 
esp_netif_join_ip6_multicast_group(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)2485 esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
2486     _RUN_IN_LWIP_TASK(esp_netif_join_ip6_multicast_group_api, esp_netif, addr)
2487 
2488 static esp_err_t esp_netif_leave_ip6_multicast_group_api(esp_netif_api_msg_t *msg)
2489 {
2490     esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
2491     ip6_addr_t ip6addr;
2492 
2493     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
2494     memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
2495 #if LWIP_IPV6_SCOPES
2496     ip6addr.zone = 0;
2497 #endif
2498     ESP_RETURN_ON_FALSE(mld6_leavegroup_netif(msg->esp_netif->lwip_netif, &ip6addr) == ERR_OK,
2499                         ESP_ERR_ESP_NETIF_MLD6_FAILED, TAG, "Failed to leave ip6 multicast group");
2500     return ESP_OK;
2501 }
2502 
esp_netif_leave_ip6_multicast_group(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)2503 esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
2504     _RUN_IN_LWIP_TASK(esp_netif_leave_ip6_multicast_group_api, esp_netif, addr)
2505 
2506 static esp_err_t esp_netif_add_ip6_address_api(esp_netif_api_msg_t *msg)
2507 {
2508     ip_event_add_ip6_t *addr = (ip_event_add_ip6_t *)msg->data;
2509     ip6_addr_t ip6addr;
2510     esp_err_t error = ESP_OK;
2511     int8_t index = -1;
2512 
2513     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
2514     memcpy(ip6addr.addr, addr->addr.addr, sizeof(ip6addr.addr));
2515 #if LWIP_IPV6_SCOPES
2516     ip6addr.zone = 0;
2517 #endif
2518     err_t err = netif_add_ip6_address(msg->esp_netif->lwip_netif, &ip6addr, &index);
2519     ESP_RETURN_ON_FALSE(err == ERR_OK && index >= 0, ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED, TAG,
2520                         "Failed to add ip6 address");
2521 
2522     netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index,
2523                              addr->preferred ? IP6_ADDR_PREFERRED : IP6_ADDR_DEPRECATED);
2524     ip_event_got_ip6_t evt = {.esp_netif = msg->esp_netif, .ip_index = index};
2525     evt.ip6_info.ip = addr->addr;
2526     ESP_RETURN_ON_ERROR(esp_event_post(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0), TAG,
2527                         "Failed to post IP_EVENT_GOT_IP6");
2528     return error;
2529 }
2530 
esp_netif_add_ip6_address(esp_netif_t * esp_netif,const ip_event_add_ip6_t * addr)2531 esp_err_t esp_netif_add_ip6_address(esp_netif_t *esp_netif, const ip_event_add_ip6_t *addr)
2532     _RUN_IN_LWIP_TASK(esp_netif_add_ip6_address_api, esp_netif, addr)
2533 
2534 static esp_err_t esp_netif_remove_ip6_address_api(esp_netif_api_msg_t *msg)
2535 {
2536     esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
2537     ip6_addr_t ip6addr;
2538 
2539     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
2540     memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
2541 #if LWIP_IPV6_SCOPES
2542     ip6addr.zone = 0;
2543 #endif
2544     int8_t index = netif_get_ip6_addr_match(msg->esp_netif->lwip_netif, &ip6addr);
2545     if (index != -1) {
2546         netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index, IP6_ADDR_INVALID);
2547     }
2548     return ESP_OK;
2549 }
2550 
2551 esp_err_t esp_netif_remove_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
2552     _RUN_IN_LWIP_TASK(esp_netif_remove_ip6_address_api, esp_netif, addr)
2553 
2554 #endif // CONFIG_LWIP_IPV6
2555