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