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