1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 
9 
10 #include "esp_netif.h"
11 #include "esp_netif_private.h"
12 
13 #if CONFIG_ESP_NETIF_LOOPBACK
14 
15 #include "esp_log.h"
16 
17 //
18 // Purpose of this module is to implement minimal loopback netif to facilitate
19 //   low level driver testing
20 //
21 
22 #define ESP_NETIF_HOSTNAME_MAX_SIZE    32
23 
24 static const char *TAG = "esp_netif_loopback";
25 
26 static bool s_netif_initialized = false;
27 static bool s_netif_started = false;
28 static bool s_netif_up = false;
29 
30 /**
31  * @brief Main esp-netif container with interface related information
32  *
33  *
34  */
35 
36 #ifndef NETIF_MAX_HWADDR_LEN
37 #define NETIF_MAX_HWADDR_LEN 6U
38 #endif
39 
40 struct esp_netif_obj {
41     // default interface addresses
42     uint8_t mac[NETIF_MAX_HWADDR_LEN];
43     esp_netif_ip_info_t* ip_info;
44     esp_netif_ip_info_t* ip_info_old;
45 
46     // io driver related
47     void* driver_handle;
48     esp_err_t (*driver_transmit)(void *h, void *buffer, size_t len);
49     void (*driver_free_rx_buffer)(void *h, void* buffer);
50 
51     // misc flags, types, keys, priority
52     esp_netif_flags_t flags;
53     char * hostname;
54     char * if_key;
55     char * if_desc;
56     int route_prio;
57 };
58 
esp_netif_set_ip4_addr(esp_ip4_addr_t * addr,uint8_t a,uint8_t b,uint8_t c,uint8_t d)59 void esp_netif_set_ip4_addr(esp_ip4_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
60 {
61     memset(addr, 0, sizeof(esp_ip4_addr_t));
62     addr->addr = esp_netif_htonl(esp_netif_ip4_makeu32(a,b,c,d));
63 }
64 
esp_ip4addr_ntoa(const esp_ip4_addr_t * addr,char * buf,int buflen)65 char * esp_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen)
66 {
67     return NULL;
68 }
69 
esp_netif_get_io_driver(esp_netif_t * esp_netif)70 esp_netif_iodriver_handle esp_netif_get_io_driver(esp_netif_t *esp_netif)
71 {
72     return esp_netif->driver_handle;
73 }
74 
esp_netif_get_handle_from_netif_impl(void * dev)75 esp_netif_t* esp_netif_get_handle_from_netif_impl(void *dev)
76 {
77     return NULL;
78 }
79 
esp_netif_get_netif_impl(esp_netif_t * esp_netif)80 void* esp_netif_get_netif_impl(esp_netif_t *esp_netif)
81 {
82     return NULL;
83 }
84 
esp_netif_init(void)85 esp_err_t esp_netif_init(void)
86 {
87     ESP_LOGI(TAG, "loopback initialization");
88     if (s_netif_initialized) {
89         ESP_LOGE(TAG, "esp-netif has already been initialized");
90         return ESP_ERR_INVALID_SIZE;
91     }
92 
93     s_netif_initialized = true;
94     ESP_LOGD(TAG, "esp-netif has been successfully initialized");
95     return ESP_OK;
96 }
97 
esp_netif_deinit(void)98 esp_err_t esp_netif_deinit(void)
99 {
100     ESP_LOGI(TAG, "loopback initialization");
101     if (!s_netif_initialized) {
102         ESP_LOGE(TAG, "esp-netif has not been initialized yet");
103         return ESP_ERR_INVALID_SIZE;
104     }
105     s_netif_initialized = false;
106     ESP_LOGD(TAG, "esp-netif has been successfully deinitialized");
107     return ESP_OK;
108 }
109 
esp_netif_init_configuration(esp_netif_t * esp_netif,const esp_netif_config_t * cfg)110 static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_netif_config_t *cfg)
111 {
112     // Basic esp_netif and lwip is a mandatory configuration and cannot be updated after esp_netif_new()
113     if (cfg == NULL || cfg->base == NULL || cfg->stack == NULL) {
114         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
115     }
116 
117     // Configure general esp-netif properties
118     memcpy(esp_netif->mac, cfg->base->mac, NETIF_MAX_HWADDR_LEN);
119     if (cfg->base->ip_info == NULL) {
120         esp_netif->ip_info->ip.addr = 0;
121         esp_netif->ip_info->gw.addr = 0;
122         esp_netif->ip_info->netmask.addr = 0;
123     } else {
124         memcpy(esp_netif->ip_info, cfg->base->ip_info, sizeof(esp_netif_ip_info_t));
125     }
126     memcpy(esp_netif->ip_info_old, esp_netif->ip_info, sizeof(esp_netif_ip_info_t));
127 
128     // Setup main config parameters
129     esp_netif->flags = cfg->base->flags;
130 
131     if (cfg->base->if_key) {
132         esp_netif->if_key = strdup(cfg->base->if_key);
133     }
134     if (cfg->base->if_desc) {
135         esp_netif->if_desc = strdup(cfg->base->if_desc);
136     }
137     if (cfg->base->route_prio) {
138         esp_netif->route_prio = cfg->base->route_prio;
139     }
140 
141     // Network stack is bypassed in loopback interface
142 
143     // Install IO functions only if provided -- connects driver and netif
144     // this configuration could be updated after esp_netif_new(), typically in post_attach callback
145     if (cfg->driver) {
146         const esp_netif_driver_ifconfig_t *esp_netif_driver_config = cfg->driver;
147         if (esp_netif_driver_config->handle) {
148             esp_netif->driver_handle = esp_netif_driver_config->handle;
149         }
150         if (esp_netif_driver_config->transmit) {
151             esp_netif->driver_transmit = esp_netif_driver_config->transmit;
152         }
153         if (esp_netif_driver_config->driver_free_rx_buffer) {
154             esp_netif->driver_free_rx_buffer = esp_netif_driver_config->driver_free_rx_buffer;
155         }
156     }
157     return ESP_OK;
158 }
159 
esp_netif_new(const esp_netif_config_t * esp_netif_config)160 esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
161 {
162     // mandatory configuration must be provided when creating esp_netif object
163     if (esp_netif_config == NULL) {
164         return NULL;
165     }
166 
167     // Create parent esp-netif object
168     esp_netif_t *esp_netif = calloc(1, sizeof(struct esp_netif_obj));
169     if (!esp_netif) {
170         return NULL;
171     }
172 
173     // Create ip info
174     esp_netif_ip_info_t *ip_info = calloc(1, sizeof(esp_netif_ip_info_t));
175     if (!ip_info) {
176         free(esp_netif);
177         return NULL;
178     }
179     esp_netif->ip_info = ip_info;
180 
181     // creating another ip info (to store old ip)
182     ip_info = calloc(1, sizeof(esp_netif_ip_info_t));
183     if (!ip_info) {
184         free(esp_netif->ip_info);
185         free(esp_netif);
186         return NULL;
187     }
188     esp_netif->ip_info_old = ip_info;
189 
190     esp_netif_add_to_list(esp_netif);
191 
192     // Configure the created object with provided configuration
193     esp_err_t ret =  esp_netif_init_configuration(esp_netif, esp_netif_config);
194     if (ret != ESP_OK) {
195         ESP_LOGE(TAG, "Initial configuration of esp_netif failed with %d", ret);
196         esp_netif_destroy(esp_netif);
197         return NULL;
198     }
199 
200     return esp_netif;
201 }
202 
esp_netif_destroy(esp_netif_t * esp_netif)203 void esp_netif_destroy(esp_netif_t *esp_netif)
204 {
205     if (esp_netif) {
206         esp_netif_remove_from_list(esp_netif);
207         free(esp_netif->ip_info);
208         free(esp_netif->ip_info_old);
209         free(esp_netif->if_key);
210         free(esp_netif->if_desc);
211         free(esp_netif);
212     }
213 }
214 
esp_netif_attach(esp_netif_t * esp_netif,esp_netif_iodriver_handle driver_handle)215 esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle)
216 {
217     esp_netif_driver_base_t *base_driver = driver_handle;
218 
219     esp_netif->driver_handle = driver_handle;
220     if (base_driver->post_attach) {
221         esp_err_t ret = base_driver->post_attach(esp_netif, driver_handle);
222         if (ret != ESP_OK) {
223             ESP_LOGE(TAG, "Post-attach callback of driver(%p) failed with %d", driver_handle, ret);
224             return ESP_ERR_ESP_NETIF_DRIVER_ATTACH_FAILED;
225         }
226     }
227     return ESP_OK;
228 }
229 
esp_netif_set_driver_config(esp_netif_t * esp_netif,const esp_netif_driver_ifconfig_t * driver_config)230 esp_err_t esp_netif_set_driver_config(esp_netif_t *esp_netif,
231                                       const esp_netif_driver_ifconfig_t *driver_config)
232 {
233     if (esp_netif == NULL || driver_config == NULL) {
234         return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
235     }
236     esp_netif->driver_handle = driver_config->handle;
237     esp_netif->driver_transmit = driver_config->transmit;
238     esp_netif->driver_free_rx_buffer = driver_config->driver_free_rx_buffer;
239     return ESP_OK;
240 }
241 
esp_netif_set_mac(esp_netif_t * esp_netif,uint8_t mac[])242 esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
243 {
244     return ESP_ERR_NOT_SUPPORTED;
245 }
246 
esp_netif_start(esp_netif_t * esp_netif)247 esp_err_t esp_netif_start(esp_netif_t *esp_netif)
248 {
249     ESP_LOGI(TAG, "Netif started");
250     s_netif_started = true;
251     return ESP_OK;
252 }
253 
254 
esp_netif_stop(esp_netif_t * esp_netif)255 esp_err_t esp_netif_stop(esp_netif_t *esp_netif)
256 {
257     ESP_LOGI(TAG, "Netif stopped");
258     s_netif_started = false;
259     return ESP_OK;
260 }
261 
262 //
263 // IO translate functions
264 //
esp_netif_free_rx_buffer(void * h,void * buffer)265 void esp_netif_free_rx_buffer(void *h, void* buffer)
266 {
267     esp_netif_t *esp_netif = h;
268     esp_netif->driver_free_rx_buffer(esp_netif->driver_handle, buffer);
269 }
270 
esp_netif_transmit(esp_netif_t * esp_netif,void * data,size_t len)271 esp_err_t esp_netif_transmit(esp_netif_t *esp_netif, void* data, size_t len)
272 {
273     ESP_LOGV(TAG, "Transmitting data: ptr:%p, size:%d", data, len);
274     return (esp_netif->driver_transmit)(esp_netif->driver_handle, data, len);
275 }
276 
esp_netif_receive(esp_netif_t * esp_netif,void * buffer,size_t len,void * eb)277 esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb)
278 {
279     ESP_LOGV(TAG, "Received data: ptr:%p, size:%d", buffer, len);
280     esp_netif_transmit(esp_netif, buffer, len);
281     if (eb) {
282         esp_netif_free_rx_buffer(esp_netif, eb);
283     }
284     return ESP_OK;
285 }
286 
esp_netif_dhcpc_stop(esp_netif_t * esp_netif)287 esp_err_t esp_netif_dhcpc_stop(esp_netif_t *esp_netif)
288 {
289     return ESP_ERR_NOT_SUPPORTED;
290 }
291 
esp_netif_dhcpc_start(esp_netif_t * esp_netif)292 esp_err_t esp_netif_dhcpc_start(esp_netif_t *esp_netif)
293 {
294     return ESP_ERR_NOT_SUPPORTED;
295 }
296 
esp_netif_dhcps_get_status(esp_netif_t * esp_netif,esp_netif_dhcp_status_t * status)297 esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
298 {
299     return ESP_ERR_NOT_SUPPORTED;
300 }
301 
esp_netif_dhcpc_get_status(esp_netif_t * esp_netif,esp_netif_dhcp_status_t * status)302 esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
303 {
304     return ESP_ERR_NOT_SUPPORTED;
305 }
306 
esp_netif_dhcps_start(esp_netif_t * esp_netif)307 esp_err_t esp_netif_dhcps_start(esp_netif_t *esp_netif)
308 {
309     return ESP_ERR_NOT_SUPPORTED;
310 }
311 
esp_netif_dhcps_stop(esp_netif_t * esp_netif)312 esp_err_t esp_netif_dhcps_stop(esp_netif_t *esp_netif)
313 {
314     return ESP_ERR_NOT_SUPPORTED;
315 }
316 
esp_netif_set_hostname(esp_netif_t * esp_netif,const char * hostname)317 esp_err_t esp_netif_set_hostname(esp_netif_t *esp_netif, const char *hostname)
318 {
319     return ESP_ERR_NOT_SUPPORTED;
320 }
321 
esp_netif_get_hostname(esp_netif_t * esp_netif,const char ** hostname)322 esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname)
323 {
324     return ESP_ERR_NOT_SUPPORTED;
325 }
326 
esp_netif_up(esp_netif_t * esp_netif)327 esp_err_t esp_netif_up(esp_netif_t *esp_netif)
328 {
329     ESP_LOGI(TAG, "Netif going up");
330     s_netif_up = true;
331     return ESP_OK;
332 }
333 
esp_netif_down(esp_netif_t * esp_netif)334 esp_err_t esp_netif_down(esp_netif_t *esp_netif)
335 {
336     ESP_LOGI(TAG, "Netif going down");
337     s_netif_up = false;
338     return ESP_OK;
339 }
340 
esp_netif_is_netif_up(esp_netif_t * esp_netif)341 bool esp_netif_is_netif_up(esp_netif_t *esp_netif)
342 {
343     return s_netif_up;
344 }
345 
esp_netif_get_old_ip_info(esp_netif_t * esp_netif,esp_netif_ip_info_t * ip_info)346 esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
347 {
348     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
349 
350     if (esp_netif == NULL || ip_info == NULL) {
351         return ESP_ERR_INVALID_ARG;
352     }
353     memcpy(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t));
354     return ESP_OK;
355 }
356 
esp_netif_get_ip_info(esp_netif_t * esp_netif,esp_netif_ip_info_t * ip_info)357 esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
358 {
359     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
360 
361     if (esp_netif == NULL || ip_info == NULL) {
362         return ESP_ERR_INVALID_ARG;
363     }
364 
365     memcpy(ip_info, esp_netif->ip_info, sizeof(esp_netif_ip_info_t));
366     return ESP_OK;
367 }
368 
369 
esp_netif_is_valid_static_ip(esp_netif_ip_info_t * ip_info)370 bool esp_netif_is_valid_static_ip(esp_netif_ip_info_t *ip_info)
371 {
372     return true;
373 }
374 
esp_netif_set_old_ip_info(esp_netif_t * esp_netif,const esp_netif_ip_info_t * ip_info)375 esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info)
376 {
377     ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
378 
379     if (esp_netif == NULL || ip_info == NULL) {
380         return ESP_ERR_INVALID_ARG;
381     }
382     memcpy(esp_netif->ip_info_old, ip_info, sizeof(esp_netif_ip_info_t));
383     return ESP_OK;
384 }
385 
esp_netif_set_dns_info(esp_netif_t * esp_netif,esp_netif_dns_type_t type,esp_netif_dns_info_t * dns)386 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)
387 {
388     return ESP_ERR_NOT_SUPPORTED;
389 }
390 
esp_netif_get_dns_info(esp_netif_t * esp_netif,esp_netif_dns_type_t type,esp_netif_dns_info_t * dns)391 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)
392 {
393     return ESP_ERR_NOT_SUPPORTED;
394 }
395 
esp_netif_create_ip6_linklocal(esp_netif_t * esp_netif)396 esp_err_t esp_netif_create_ip6_linklocal(esp_netif_t *esp_netif)
397 {
398     return ESP_ERR_NOT_SUPPORTED;
399 }
400 
esp_netif_get_ip6_linklocal(esp_netif_t * esp_netif,esp_ip6_addr_t * if_ip6)401 esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
402 {
403     return ESP_ERR_NOT_SUPPORTED;
404 }
405 
esp_netif_get_ip6_global(esp_netif_t * esp_netif,esp_ip6_addr_t * if_ip6)406 esp_err_t esp_netif_get_ip6_global(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
407 {
408     return ESP_ERR_NOT_SUPPORTED;
409 }
410 
esp_netif_get_flags(esp_netif_t * esp_netif)411 esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif)
412 {
413     return esp_netif->flags;
414 }
415 
esp_netif_get_ifkey(esp_netif_t * esp_netif)416 const char *esp_netif_get_ifkey(esp_netif_t *esp_netif)
417 {
418     return esp_netif->if_key;
419 }
420 
esp_netif_get_desc(esp_netif_t * esp_netif)421 const char *esp_netif_get_desc(esp_netif_t *esp_netif)
422 {
423     return esp_netif->if_desc;
424 }
425 
esp_netif_get_event_id(esp_netif_t * esp_netif,esp_netif_ip_event_type_t event_type)426 int32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t event_type)
427 {
428     return 0;
429 }
430 
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)431 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,
432                                  uint32_t opt_len)
433 {
434     return ESP_ERR_NOT_SUPPORTED;
435 }
436 
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)437 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,
438                                  uint32_t opt_len)
439 {
440     return ESP_ERR_NOT_SUPPORTED;
441 }
442 
esp_netif_get_netif_impl_index(esp_netif_t * esp_netif)443 int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
444 {
445     return 0;
446 }
447 
esp_netif_join_ip6_multicast_group(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)448 esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
449 {
450     return ESP_ERR_NOT_SUPPORTED;
451 }
452 
esp_netif_leave_ip6_multicast_group(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)453 esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
454 {
455     return ESP_ERR_NOT_SUPPORTED;
456 }
457 
esp_netif_add_ip6_address(esp_netif_t * esp_netif,const ip_event_add_ip6_t * addr)458 esp_err_t esp_netif_add_ip6_address(esp_netif_t *esp_netif, const ip_event_add_ip6_t *addr)
459 {
460     return ESP_ERR_NOT_SUPPORTED;
461 }
462 
esp_netif_remove_ip6_address(esp_netif_t * esp_netif,const esp_ip6_addr_t * addr)463 esp_err_t esp_netif_remove_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
464 {
465     return ESP_ERR_NOT_SUPPORTED;
466 }
467 
468 #endif /* CONFIG_ESP_NETIF_LOOPBACK */
469