From dcee0ad023e5f889bad0799b9f933489fac03a67 Mon Sep 17 00:00:00 2001 From: Zhang Jun Hao Date: Tue, 26 Jun 2018 17:13:12 +0800 Subject: [PATCH 1/4] feat(esp8266): Add wifi event default handlers --- components/esp8266/include/esp_event.h | 1 + .../esp8266/source/event_default_handlers.c | 195 ++++++++++++++++++ components/esp8266/source/event_loop.c | 59 +++--- 3 files changed, 224 insertions(+), 31 deletions(-) diff --git a/components/esp8266/include/esp_event.h b/components/esp8266/include/esp_event.h index cc130bd8..e31da16a 100644 --- a/components/esp8266/include/esp_event.h +++ b/components/esp8266/include/esp_event.h @@ -45,6 +45,7 @@ typedef enum { SYSTEM_EVENT_AP_STOP, /**< ESP8266 soft-AP stop */ SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP8266 soft-AP */ SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP8266 soft-AP */ + SYSTEM_EVENT_AP_STAIPASSIGNED, /**< ESP8266 soft-AP assign an IP to a connected station */ SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ SYSTEM_EVENT_GOT_IP6, /**< ESP8266 station or ap or ethernet interface v6IP addr is preferred */ SYSTEM_EVENT_ETH_START, /**< ESP8266 ethernet start */ diff --git a/components/esp8266/source/event_default_handlers.c b/components/esp8266/source/event_default_handlers.c index 5fca64bd..aa22abaf 100644 --- a/components/esp8266/source/event_default_handlers.c +++ b/components/esp8266/source/event_default_handlers.c @@ -18,6 +18,7 @@ #include "esp_err.h" #include "esp_wifi.h" +#include "esp_misc.h" #include "esp_event.h" #include "esp_event_loop.h" #include "esp_system.h" @@ -32,6 +33,15 @@ static const char* TAG = "event"; +#define WIFI_API_CALL_CHECK(info, api_call, ret) \ +do{\ + esp_err_t __err = (api_call);\ + if ((ret) != __err) {\ + ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\ + return __err;\ + }\ +} while(0) + typedef esp_err_t (*system_event_handler_t)(system_event_t *e); static esp_err_t system_event_ap_start_handle_default(system_event_t *event); @@ -51,58 +61,241 @@ static system_event_handler_t default_event_handlers[SYSTEM_EVENT_MAX] = { 0 }; static esp_err_t system_event_sta_got_ip_default(system_event_t *event) { + ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, + IP2STR(&event->event_info.got_ip.ip_info.ip), + IP2STR(&event->event_info.got_ip.ip_info.netmask), + IP2STR(&event->event_info.got_ip.ip_info.gw)); + return ESP_OK; } static esp_err_t system_event_sta_lost_ip_default(system_event_t *event) { + ESP_LOGI(TAG, "station ip lost"); return ESP_OK; } esp_err_t system_event_ap_start_handle_default(system_event_t *event) { + tcpip_adapter_ip_info_t ap_ip; + uint8_t ap_mac[6]; + + WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK); + + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); + tcpip_adapter_start(TCPIP_ADAPTER_IF_AP, ap_mac, &ap_ip); + return ESP_OK; } esp_err_t system_event_ap_stop_handle_default(system_event_t *event) { + tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP); + return ESP_OK; } esp_err_t system_event_sta_start_handle_default(system_event_t *event) { + tcpip_adapter_ip_info_t sta_ip; + uint8_t sta_mac[6]; + + WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK); + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, sta_mac, &sta_ip); + return ESP_OK; } esp_err_t system_event_sta_stop_handle_default(system_event_t *event) { + tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA); return ESP_OK; } esp_err_t system_event_sta_connected_handle_default(system_event_t *event) { + tcpip_adapter_dhcp_status_t status; + + tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); + tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status); + + if (status == TCPIP_ADAPTER_DHCP_INIT) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) { + tcpip_adapter_ip_info_t sta_ip; + tcpip_adapter_ip_info_t sta_old_ip; + + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip); + + if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask) || ip4_addr_isany_val(sta_ip.gw))) { + system_event_t evt; + + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; + evt.event_info.got_ip.ip_changed = false; + + if (memcmp(&sta_ip, &sta_old_ip, sizeof(sta_ip))) { + evt.event_info.got_ip.ip_changed = true; + } + + memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); + tcpip_adapter_set_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + + esp_event_send(&evt); + ESP_LOGD(TAG, "static ip: ip changed=%d", evt.event_info.got_ip.ip_changed); + } else { + ESP_LOGE(TAG, "invalid static ip"); + } + } + return ESP_OK; } esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event) { + tcpip_adapter_down(TCPIP_ADAPTER_IF_STA); return ESP_OK; } +static esp_err_t esp_system_event_debug(system_event_t *event) +{ + if (event == NULL) { + ESP_LOGE(TAG, "event is null!"); + printf("event is null!"); + return ESP_FAIL; + } + switch (event->event_id) { + case SYSTEM_EVENT_WIFI_READY: { + ESP_LOGD(TAG, "SYSTEM_EVENT_WIFI_READY"); + break; + } + case SYSTEM_EVENT_SCAN_DONE: { + system_event_sta_scan_done_t *scan_done = &event->event_info.scan_done; + ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE, status:%d, number:%d", scan_done->status, scan_done->number); + break; + } + case SYSTEM_EVENT_STA_START: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START"); + break; + } + case SYSTEM_EVENT_STA_STOP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_STOP"); + break; + } + case SYSTEM_EVENT_STA_CONNECTED: { + system_event_sta_connected_t *connected = &event->event_info.connected; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_CONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", channel:%d, authmode:%d", \ + connected->ssid, connected->ssid_len, MAC2STR(connected->bssid), connected->channel, connected->authmode); + break; + } + case SYSTEM_EVENT_STA_DISCONNECTED: { + system_event_sta_disconnected_t *disconnected = &event->event_info.disconnected; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_DISCONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d", \ + disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason); + break; + } + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { + system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHNAGE, old_mode:%d, new_mode:%d", auth_change->old_mode, auth_change->new_mode); + break; + } + case SYSTEM_EVENT_STA_GOT_IP: { + system_event_sta_got_ip_t *got_ip = &event->event_info.got_ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP, ip:" IPSTR ", mask:" IPSTR ", gw:" IPSTR, + IP2STR(&got_ip->ip_info.ip), + IP2STR(&got_ip->ip_info.netmask), + IP2STR(&got_ip->ip_info.gw)); + break; + } + case SYSTEM_EVENT_STA_LOST_IP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_LOST_IP"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_FAILED: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_PIN: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN"); + break; + } + case SYSTEM_EVENT_AP_START: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START"); + break; + } + case SYSTEM_EVENT_AP_STOP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STOP"); + break; + } + case SYSTEM_EVENT_AP_STACONNECTED: { + system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STACONNECTED, mac:" MACSTR ", aid:%d", \ + MAC2STR(staconnected->mac), staconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STADISCONNECTED: { + system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED, mac:" MACSTR ", aid:%d", \ + MAC2STR(stadisconnected->mac), stadisconnected->aid); + break; + } + case SYSTEM_EVENT_AP_PROBEREQRECVED: { + system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \ + ap_probereqrecved->rssi, \ + MAC2STR(ap_probereqrecved->mac)); + break; + } + case SYSTEM_EVENT_GOT_IP6: { + ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + IP6_ADDR_BLOCK1(addr), + IP6_ADDR_BLOCK2(addr), + IP6_ADDR_BLOCK3(addr), + IP6_ADDR_BLOCK4(addr), + IP6_ADDR_BLOCK5(addr), + IP6_ADDR_BLOCK6(addr), + IP6_ADDR_BLOCK7(addr), + IP6_ADDR_BLOCK8(addr)); + break; + } + + default: { + ESP_LOGW(TAG, "unexpected system event %d!", event->event_id); + break; + } + } + + return ESP_OK; +} esp_err_t esp_event_process_default(system_event_t *event) { if (event == NULL) { + ESP_LOGE(TAG, "Error: event is null!"); return ESP_FAIL; } + esp_system_event_debug(event); if ((event->event_id < SYSTEM_EVENT_MAX)) { if (default_event_handlers[event->event_id] != NULL) { + ESP_LOGV(TAG, "enter default callback"); default_event_handlers[event->event_id](event); + ESP_LOGV(TAG, "exit default callback"); } } else { + ESP_LOGE(TAG, "mismatch or invalid event, id=%d", event->event_id); return ESP_FAIL; } return ESP_OK; @@ -118,4 +311,6 @@ void esp_event_set_default_wifi_handlers() default_event_handlers[SYSTEM_EVENT_STA_LOST_IP] = system_event_sta_lost_ip_default; default_event_handlers[SYSTEM_EVENT_AP_START] = system_event_ap_start_handle_default; default_event_handlers[SYSTEM_EVENT_AP_STOP] = system_event_ap_stop_handle_default; + + //esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop); } \ No newline at end of file diff --git a/components/esp8266/source/event_loop.c b/components/esp8266/source/event_loop.c index 3b8162d7..335e4685 100644 --- a/components/esp8266/source/event_loop.c +++ b/components/esp8266/source/event_loop.c @@ -27,10 +27,9 @@ static const char* TAG = "event"; static bool s_event_init_flag = false; +static void *s_event_queue = NULL; static system_event_cb_t s_event_handler_cb = NULL; static void *s_event_ctx = NULL; -static void *s_event_queue = NULL; - static esp_err_t esp_event_post_to_user(system_event_t *event) { @@ -40,33 +39,6 @@ static esp_err_t esp_event_post_to_user(system_event_t *event) return ESP_OK; } -system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx) -{ - system_event_cb_t old_cb = s_event_handler_cb; - s_event_handler_cb = cb; - s_event_ctx = ctx; - return old_cb; -} - -esp_err_t esp_event_send(system_event_t *event) -{ - if (s_event_queue == NULL) { - ESP_LOGE(TAG, "Event loop not initialized via esp_event_loop_init, but esp_event_send called"); - return ESP_ERR_INVALID_STATE; - } - - portBASE_TYPE ret = wifi_queue_send(s_event_queue, event, 0, 1); - if (ret != pdPASS) { - if (event) { - ESP_LOGE(TAG, "e=%d f", event->event_id); - } else { - ESP_LOGE(TAG, "e null"); - } - return ESP_FAIL; - } - return ESP_OK; -} - static void esp_event_loop_task(void *pvParameters) { while (1) { @@ -80,12 +52,37 @@ static void esp_event_loop_task(void *pvParameters) if (ret != ESP_OK) { ESP_LOGE(TAG, "post event to user fail!"); } - } else { - ESP_LOGE(TAG, "esp_event_loop_task end"); } } } +system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx) +{ + system_event_cb_t old_cb = s_event_handler_cb; + s_event_handler_cb = cb; + s_event_ctx = ctx; + return old_cb; +} + +esp_err_t esp_event_send(system_event_t *event) +{ + if (s_event_queue == NULL) { + ESP_LOGE(TAG, "Event loop not initialized via esp_event_loop_init, but esp_event_send called"); + return ESP_ERR_INVALID_STATE; + } + + int ret = wifi_queue_send(s_event_queue, event, 0, 1); + if (ret != true) { + if (event) { + ESP_LOGE(TAG, "e=%d f", event->event_id); + } else { + ESP_LOGE(TAG, "e null"); + } + return ESP_FAIL; + } + return ESP_OK; +} + QueueHandle_t esp_event_loop_get_queue(void) { return s_event_queue; From b041d65caa30b2ce6d86c364727575c78aa8f30f Mon Sep 17 00:00:00 2001 From: Zhang Jun Hao Date: Tue, 26 Jun 2018 17:15:50 +0800 Subject: [PATCH 2/4] feat(tcpip_adapter): Refactor tcpip_adapter APIs --- components/esp8266/include/esp_wifi_types.h | 1 - components/esp8266/source/esp_wifi.c | 2 + .../lwip/port/esp8266/netif/ethernetif.c | 21 +- components/tcpip_adapter/Kconfig | 15 +- .../tcpip_adapter/include/tcpip_adapter.h | 530 +++++++- components/tcpip_adapter/tcpip_adapter_lwip.c | 1100 +++++++++++++++++ components/tcpip_adapter/tcpip_adapter_wifi.c | 600 --------- 7 files changed, 1639 insertions(+), 630 deletions(-) create mode 100644 components/tcpip_adapter/tcpip_adapter_lwip.c delete mode 100644 components/tcpip_adapter/tcpip_adapter_wifi.c diff --git a/components/esp8266/include/esp_wifi_types.h b/components/esp8266/include/esp_wifi_types.h index 20e656f0..76fdf746 100755 --- a/components/esp8266/include/esp_wifi_types.h +++ b/components/esp8266/include/esp_wifi_types.h @@ -20,7 +20,6 @@ #include #include "esp_err.h" #include "esp_interface.h" -#include "queue.h" #ifdef __cplusplus extern "C" { diff --git a/components/esp8266/source/esp_wifi.c b/components/esp8266/source/esp_wifi.c index d2b39672..1cd489c9 100644 --- a/components/esp8266/source/esp_wifi.c +++ b/components/esp8266/source/esp_wifi.c @@ -18,6 +18,8 @@ #include "esp_socket.h" #include "net/sockio.h" +esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config); + /** * @brief Init WiFi * Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, diff --git a/components/lwip/port/esp8266/netif/ethernetif.c b/components/lwip/port/esp8266/netif/ethernetif.c index 37ecd0d4..21b18a49 100644 --- a/components/lwip/port/esp8266/netif/ethernetif.c +++ b/components/lwip/port/esp8266/netif/ethernetif.c @@ -26,6 +26,9 @@ int8_t ieee80211_output_pbuf(uint8_t fd, uint8_t* dataptr, uint16_t datalen); int8_t wifi_get_netif(uint8_t fd); void wifi_station_set_default_hostname(uint8_t* hwaddr); +#define IFNAME0 'e' +#define IFNAME1 'n' + /** * In this function, the hardware should be initialized. * Called from ethernetif_init(). @@ -36,7 +39,7 @@ void wifi_station_set_default_hostname(uint8_t* hwaddr); static void low_level_init(struct netif* netif) { if (netif == NULL) { - TCPIP_ATAPTER_LOG("ERROR netif is NULL\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_init: netif is NULL\n")); return; } @@ -48,7 +51,7 @@ static void low_level_init(struct netif* netif) /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; #if LWIP_IGMP netif->flags |= NETIF_FLAG_IGMP; @@ -131,7 +134,7 @@ static int8_t low_level_output(struct netif* netif, struct pbuf* p) int8_t err = ERR_OK; if (netif == NULL) { - TCPIP_ATAPTER_LOG("ERROR netif is NULL\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: netif is NULL\n")); return ERR_ARG; } @@ -186,23 +189,23 @@ void ethernetif_input(struct netif* netif, struct pbuf* p) struct eth_hdr* ethhdr; if (p == NULL) { - TCPIP_ATAPTER_LOG("ERROR pbuf is NULL\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: pbuf is NULL\n")); goto _exit; } if (p->payload == NULL) { - TCPIP_ATAPTER_LOG("ERROR payload is NULL\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: payload is NULL\n")); pbuf_free(p); goto _exit; } if (netif == NULL) { - TCPIP_ATAPTER_LOG("ERROR netif is NULL\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: netif is NULL\n")); goto _exit; } if (!(netif->flags & NETIF_FLAG_LINK_UP)) { - TCPIP_ATAPTER_LOG("ERROR netif is not up\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: netif is not up\n")); pbuf_free(p); p = NULL; goto _exit; @@ -225,7 +228,7 @@ void ethernetif_input(struct netif* netif, struct pbuf* p) /* full packet send to tcpip_thread to process */ if (netif->input(p, netif) != ERR_OK) { - TCPIP_ATAPTER_LOG("ERROR IP input error\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); pbuf_free(p); p = NULL; } @@ -259,7 +262,7 @@ int8_t ethernetif_init(struct netif* netif) uint8_t mac[NETIF_MAX_HWADDR_LEN]; if (netif == NULL) { - TCPIP_ATAPTER_LOG("ERROR netif is NULL\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: netif is NULL\n")); } /* set MAC hardware address */ diff --git a/components/tcpip_adapter/Kconfig b/components/tcpip_adapter/Kconfig index 86eb7a3c..eecf1205 100644 --- a/components/tcpip_adapter/Kconfig +++ b/components/tcpip_adapter/Kconfig @@ -1,7 +1,16 @@ menu "tcpip adapter" -config TCPIP_ADAPER_DEBUG - bool "Enable tcpip adaptor debug" - default 1 +config IP_LOST_TIMER_INTERVAL + int "IP Address lost timer interval (seconds)" + range 0 65535 + default 120 + help + The value of 0 indicates the IP lost timer is disabled, otherwise the timer is enabled. + + The IP address may be lost because of some reasons, e.g. when the station disconnects + from soft-AP, or when DHCP IP renew fails etc. If the IP lost timer is enabled, it will + be started everytime the IP is lost. Event SYSTEM_EVENT_STA_LOST_IP will be raised if + the timer expires. The IP lost timer is stopped if the station get the IP again before + the timer expires. endmenu diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h index 9270a1cf..1d48b322 100644 --- a/components/tcpip_adapter/include/tcpip_adapter.h +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -15,7 +15,6 @@ #ifndef _TCPIP_ADAPTER_H_ #define _TCPIP_ADAPTER_H_ -#include "sdkconfig.h" /** * @brief TCPIP adapter library * @@ -33,8 +32,41 @@ * get free station list APIs in application side. Other APIs are used in ESP8266_RTOS_SDK internal, * otherwise the state maybe wrong. * + * TODO: ipv6 support will be added, use menuconfig to disable CONFIG_TCPIP_LWIP */ +#include +#include "esp_wifi_types.h" + +#define CONFIG_TCPIP_LWIP 1 +#define CONFIG_DHCP_STA_LIST 1 + +#if CONFIG_TCPIP_LWIP +#include "lwip/ip_addr.h" +#include "dhcpserver/dhcpserver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ + ip4_addr2_16(ipaddr), \ + ip4_addr3_16(ipaddr), \ + ip4_addr4_16(ipaddr) + +#define IPSTR "%d.%d.%d.%d" + +#define IPV62STR(ipaddr) IP6_ADDR_BLOCK1(&(ipaddr)), \ + IP6_ADDR_BLOCK2(&(ipaddr)), \ + IP6_ADDR_BLOCK3(&(ipaddr)), \ + IP6_ADDR_BLOCK4(&(ipaddr)), \ + IP6_ADDR_BLOCK5(&(ipaddr)), \ + IP6_ADDR_BLOCK6(&(ipaddr)), \ + IP6_ADDR_BLOCK7(&(ipaddr)), \ + IP6_ADDR_BLOCK8(&(ipaddr)) + +#define IPV6STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" + typedef struct { ip4_addr_t ip; ip4_addr_t netmask; @@ -45,28 +77,101 @@ typedef struct { ip6_addr_t ip; } tcpip_adapter_ip6_info_t; +typedef dhcps_lease_t tcpip_adapter_dhcps_lease_t; + +#if CONFIG_DHCP_STA_LIST +typedef struct { + uint8_t mac[6]; + ip4_addr_t ip; +} tcpip_adapter_sta_info_t; + +typedef struct { + tcpip_adapter_sta_info_t sta[ESP_WIFI_MAX_CONN_NUM]; + int num; +} tcpip_adapter_sta_list_t; +#endif + +#endif + +#define ESP_ERR_TCPIP_ADAPTER_BASE 0x5000 // TODO: move base address to esp_err.h + +#define ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS ESP_ERR_TCPIP_ADAPTER_BASE + 0x01 +#define ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY ESP_ERR_TCPIP_ADAPTER_BASE + 0x02 +#define ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED ESP_ERR_TCPIP_ADAPTER_BASE + 0x03 +#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED ESP_ERR_TCPIP_ADAPTER_BASE + 0x04 +#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED ESP_ERR_TCPIP_ADAPTER_BASE + 0x05 +#define ESP_ERR_TCPIP_ADAPTER_NO_MEM ESP_ERR_TCPIP_ADAPTER_BASE + 0x06 +#define ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED ESP_ERR_TCPIP_ADAPTER_BASE + 0x07 + +/* TODO: add Ethernet interface */ typedef enum { - TCPIP_ADAPTER_IF_STA = 0, /**< ESP8266 station interface */ - TCPIP_ADAPTER_IF_AP, /**< ESP8266 soft-AP interface */ + TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ + TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ + TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ TCPIP_ADAPTER_IF_MAX } tcpip_adapter_if_t; -struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX]; -char* hostname; -bool default_hostname; +/*type of DNS server*/ +typedef enum { + TCPIP_ADAPTER_DNS_MAIN= 0, /**DNS main server address*/ + TCPIP_ADAPTER_DNS_BACKUP, /**DNS backup server address,for STA only,support soft-AP in future*/ + TCPIP_ADAPTER_DNS_FALLBACK, /**DNS fallback server address,for STA only*/ + TCPIP_ADAPTER_DNS_MAX /**Max DNS */ +} tcpip_adapter_dns_type_t; -#define TCPIP_ADAPTER_IF_VALID(fd) ((fd < TCPIP_ADAPTER_IF_MAX) ? 1 : 0) +/*info of DNS server*/ +typedef struct { + ip_addr_t ip; +} tcpip_adapter_dns_info_t; -/* Define those to better describe your network interface. */ -#define IFNAME0 'e' -#define IFNAME1 'n' +/* status of DHCP client or DHCP server */ +typedef enum { + TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */ + TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server already been started */ + TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server already been stopped */ + TCPIP_ADAPTER_DHCP_STATUS_MAX +} tcpip_adapter_dhcp_status_t; -#ifdef CONFIG_TCPIP_ADAPER_DEBUG -#define TAG "TCPIP_ADAPTER" -#define TCPIP_ATAPTER_LOG(str, ...) printf(TAG " line: %d " str, __LINE__, ##__VA_ARGS__) -#else -#define TCPIP_ATAPTER_LOG(str, ...) -#endif +/* set the option mode for DHCP client or DHCP server */ +typedef enum{ + TCPIP_ADAPTER_OP_START = 0, + TCPIP_ADAPTER_OP_SET, /**< set option mode */ + TCPIP_ADAPTER_OP_GET, /**< get option mode */ + TCPIP_ADAPTER_OP_MAX +} tcpip_adapter_option_mode_t; + +typedef enum{ + TCPIP_ADAPTER_DOMAIN_NAME_SERVER = 6, /**< domain name server */ + TCPIP_ADAPTER_ROUTER_SOLICITATION_ADDRESS = 32, /**< solicitation router address */ + TCPIP_ADAPTER_REQUESTED_IP_ADDRESS = 50, /**< request IP address pool */ + TCPIP_ADAPTER_IP_ADDRESS_LEASE_TIME = 51, /**< request IP address lease time */ + TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME = 52, /**< request IP address retry counter */ +} tcpip_adapter_option_id_t; + +struct tcpip_adapter_api_msg_s; +typedef int (*tcpip_adapter_api_fn)(struct tcpip_adapter_api_msg_s *msg); +typedef struct tcpip_adapter_api_msg_s { + int type; /**< The first field MUST be int */ + int ret; + tcpip_adapter_api_fn api_fn; + tcpip_adapter_if_t tcpip_if; + tcpip_adapter_ip_info_t *ip_info; + uint8_t *mac; + void *data; +} tcpip_adapter_api_msg_t; + +typedef struct tcpip_adapter_dns_param_s { + tcpip_adapter_dns_type_t dns_type; + tcpip_adapter_dns_info_t *dns_info; +} tcpip_adapter_dns_param_t; + +#define TCPIP_ADAPTER_TRHEAD_SAFE 1 +#define TCPIP_ADAPTER_IPC_LOCAL 0 +#define TCPIP_ADAPTER_IPC_REMOTE 1 + +typedef struct tcpip_adatper_ip_lost_timer_s { + bool timer_running; +} tcpip_adapter_ip_lost_timer_t; /** * @brief Initialize tcpip adapter @@ -75,4 +180,395 @@ bool default_hostname; */ void tcpip_adapter_init(void); -#endif /* _TCPIP_ADAPTER_H_ */ \ No newline at end of file +/** + * @brief Start the Wi-Fi station/AP interface with specific MAC and IP + * + * Station/AP interface will be initialized, connect WiFi stack with TCPIP stack. + * + * @param[in] tcpip_if: Station/AP interface + * @param[in] mac: set MAC address of this interface + * @param[in] ip_info: set IP address of this interface + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_NO_MEM + */ +esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_adapter_ip_info_t *ip_info); + +/** + * @brief Stop an interface + * + * The interface will be cleanup in this API, if DHCP server/client are started, will be stopped. + * + * @param[in] tcpip_if: the interface which will be started + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY + */ +esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Bring up an interface + * + * Only station interface need to be brought up, since station interface will be shut down when disconnect. + * + * @param[in] tcpip_if: the interface which will be up + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY + */ +esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Shut down an interface + * + * Only station interface need to be shut down, since station interface will be brought up when connect. + * + * @param[in] tcpip_if: the interface which will be down + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY + */ +esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Get interface's IP information + * + * There has an IP information copy in adapter library, if interface is up, get IP information from + * interface, otherwise get from copy. + * + * @param[in] tcpip_if: the interface which we want to get IP information + * @param[out] ip_info: If successful, IP information will be returned in this argument. + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info); + +/** + * @brief Set interface's IP information + * + * There has an IP information copy in adapter library, if interface is up, also set interface's IP. + * DHCP client/server should be stopped before set new IP information. + * + * This function is mainly used for setting static IP. + * + * @param[in] tcpip_if: the interface which we want to set IP information + * @param[in] ip_info: store the IP information which needs to be set to specified interface + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info); + +/** + * @brief Set DNS Server's information + * + * There has an DNS Server information copy in adapter library, set DNS Server for appointed interface and type. + * + * 1.In station mode, if dhcp client is enabled, then only the fallback DNS server can be set(TCPIP_ADAPTER_DNS_FALLBACK). + * Fallback DNS server is only used if no DNS servers are set via DHCP. + * If dhcp client is disabled, then need to set main/backup dns server(TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP). + * + * 2.In soft-AP mode, the DNS Server's main dns server offered to the station is the IP address of soft-AP, + * if the application don't want to use the IP address of soft-AP, they can set the main dns server. + * + * This function is mainly used for setting static or Fallback DNS Server. + * + * @param[in] tcpip_if: the interface which we want to set DNS Server information + * @param[in] type: the type of DNS Server,including TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK + * @param[in] dns: the DNS Server address to be set + * + * @return + * - ESP_OK on success + * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params + */ +esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns); + +/** + * @brief Get DNS Server's information + * + * When set the DNS Server information successfully, can get the DNS Server's information via the appointed tcpip_if and type + * + * This function is mainly used for getting DNS Server information. + * + * @param[in] tcpip_if: the interface which we want to get DNS Server information + * @param[in] type: the type of DNS Server,including TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK + * @param[in] dns: the DNS Server address to be get + * + * @return + * - ESP_OK on success + * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params + */ +esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns); + +/** + * @brief Get interface's old IP information + * + * When the interface successfully gets a valid IP from DHCP server or static configured, a copy of + * the IP information is set to the old IP information. When IP lost timer expires, the old IP + * information is reset to 0. + * + * @param[in] tcpip_if: the interface which we want to get old IP information + * @param[out] ip_info: If successful, IP information will be returned in this argument. + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_get_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info); + +/** + * @brief Set interface's old IP information + * + * When the interface successfully gets a valid IP from DHCP server or static configured, a copy of + * the IP information is set to the old IP information. When IP lost timer expires, the old IP + * information is reset to 0. + * + * @param[in] tcpip_if: the interface which we want to set old IP information + * @param[in] ip_info: store the IP information which needs to be set to specified interface + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_set_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info); + + +/** + * @brief create interface's linklocal IPv6 information + * + * @note this function will create a linklocal IPv6 address about input interface, + * if this address status changed to preferred, will call event call back , + * notify user linklocal IPv6 address has been verified + * + * @param[in] tcpip_if: the interface which we want to set IP information + * + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if); + +/** + * @brief get interface's linkloacl IPv6 information + * + * There has an IPv6 information copy in adapter library, if interface is up,and IPv6 info + * is preferred,it will get IPv6 linklocal IP successfully + * + * @param[in] tcpip_if: the interface which we want to set IP information + * @param[in] if_ip6: If successful, IPv6 information will be returned in this argument. + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6); + +#if 0 +esp_err_t tcpip_adapter_get_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac); + +esp_err_t tcpip_adapter_set_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac); +#endif + +/** + * @brief Get DHCP server's status + * + * @param[in] tcpip_if: the interface which we will get status of DHCP server + * @param[out] status: If successful, the status of DHCP server will be return in this argument. + * + * @return ESP_OK + */ +esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); + +/** + * @brief Set or Get DHCP server's option + * + * @param[in] opt_op: option operate type, 1 for SET, 2 for GET. + * @param[in] opt_id: option index, 32 for ROUTER, 50 for IP POLL, 51 for LEASE TIME, 52 for REQUEST TIME + * @param[in] opt_val: option parameter + * @param[in] opt_len: option length + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED + * ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED + */ +esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len); + +/** + * @brief Start DHCP server + * + * @note Currently DHCP server is bind to softAP interface. + * + * @param[in] tcpip_if: the interface which we will start DHCP server + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED + */ +esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Stop DHCP server + * + * @note Currently DHCP server is bind to softAP interface. + * + * @param[in] tcpip_if: the interface which we will stop DHCP server + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY + */ +esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Get DHCP client status + * + * @param[in] tcpip_if: the interface which we will get status of DHCP client + * @param[out] status: If successful, the status of DHCP client will be return in this argument. + * + * @return ESP_OK + */ +esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); + +/** + * @brief Set or Get DHCP client's option + * + * @note This function is not implement now. + * + * @param[in] opt_op: option operate type, 1 for SET, 2 for GET. + * @param[in] opt_id: option index, 32 for ROUTER, 50 for IP POLL, 51 for LEASE TIME, 52 for REQUEST TIME + * @param[in] opt_val: option parameter + * @param[in] opt_len: option length + * + * @return ESP_OK + */ +esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len); + +/** + * @brief Start DHCP client + * + * @note Currently DHCP client is bind to station interface. + * + * @param[in] tcpip_if: the interface which we will start DHCP client + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED + * ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED + */ +esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Stop DHCP client + * + * @note Currently DHCP client is bind to station interface. + * + * @param[in] tcpip_if: the interface which we will stop DHCP client + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY + */ +esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if); + + + +esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb); + +/** + * @brief Get data from station interface + * + * This function should be installed by esp_wifi_reg_rxcb, so WiFi packets will be forward to TCPIP stack. + * + * @param[in] void *buffer: the received data point + * @param[in] uint16_t len: the received data length + * @param[in] void *eb: parameter + * + * @return ESP_OK + */ +esp_err_t tcpip_adapter_sta_input(void *buffer, uint16_t len, void *eb); + +/** + * @brief Get data from softAP interface + * + * This function should be installed by esp_wifi_reg_rxcb, so WiFi packets will be forward to TCPIP stack. + * + * @param[in] void *buffer: the received data point + * @param[in] uint16_t len: the received data length + * @param[in] void *eb: parameter + * + * @return ESP_OK + */ +esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void *eb); + +/** + * @brief Get WiFi interface index + * + * Get WiFi interface from TCPIP interface struct pointer. + * + * @param[in] void *dev: adapter interface + * + * @return ESP_IF_WIFI_STA + * ESP_IF_WIFI_AP + ESP_IF_ETH + * ESP_IF_MAX + */ +esp_interface_t tcpip_adapter_get_esp_if(void *dev); + +/** + * @brief Get the station information list + * + * @param[in] wifi_sta_list_t *wifi_sta_list: station list info + * @param[out] tcpip_adapter_sta_list_t *tcpip_sta_list: station list info + * + * @return ESP_OK + * ESP_ERR_TCPIP_ADAPTER_NO_MEM + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + */ +esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list); + +#define TCPIP_HOSTNAME_MAX_SIZE 32 +/** + * @brief Set the hostname to the interface + * + * @param[in] tcpip_if: the interface which we will set the hostname + * @param[in] hostname: the host name for set the interface, the max length of hostname is 32 bytes + * + * @return ESP_OK:success + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error + */ +esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname); + +/** + * @brief Get the hostname from the interface + * + * @param[in] tcpip_if: the interface which we will get the hostname + * @param[in] hostname: the host name from the interface + * + * @return ESP_OK:success + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error + */ +esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname); + +/** + * @brief Get the LwIP netif* that is assigned to the interface + * + * @param[in] tcpip_if: the interface which we will get the hostname + * @param[out] void ** netif: pointer to fill the resulting interface + * + * @return ESP_OK:success + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error + */ +esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif); + +#ifdef __cplusplus +} +#endif + +#endif /* _TCPIP_ADAPTER_H_ */ + diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c new file mode 100644 index 00000000..634d3997 --- /dev/null +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -0,0 +1,1100 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "tcpip_adapter.h" + +#if CONFIG_TCPIP_LWIP + +#include "lwip/netif.h" +#include "lwip/tcpip.h" +#include "lwip/dhcp.h" +#include "lwip/dns.h" +#include "lwip/errno.h" +#include "lwip/prot/dhcp.h" +#include "netif/etharp.h" +#include "esp_wifi.h" +#include "esp_timer.h" +#include "esp_misc.h" +#include "dhcpserver/dhcpserver.h" +#include "dhcpserver/dhcpserver_options.h" +#include "net/sockio.h" +#include "esp_socket.h" +#include "esp_log.h" + +struct tcpip_adapter_pbuf { + struct pbuf_custom pbuf; + + void *base; + + struct netif *netif; +}; + +static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX]; +static tcpip_adapter_ip_info_t esp_ip[TCPIP_ADAPTER_IF_MAX]; +static tcpip_adapter_ip_info_t esp_ip_old[TCPIP_ADAPTER_IF_MAX]; +#if 0 +/*TODO need add ip6*/ +static tcpip_adapter_ip6_info_t esp_ip6[TCPIP_ADAPTER_IF_MAX]; +#endif +static netif_init_fn esp_netif_init_fn[TCPIP_ADAPTER_IF_MAX]; +static tcpip_adapter_ip_lost_timer_t esp_ip_lost_timer[TCPIP_ADAPTER_IF_MAX]; + +static tcpip_adapter_dhcp_status_t dhcps_status = TCPIP_ADAPTER_DHCP_INIT; +static tcpip_adapter_dhcp_status_t dhcpc_status[TCPIP_ADAPTER_IF_MAX] = {TCPIP_ADAPTER_DHCP_INIT}; +static esp_err_t tcpip_adapter_reset_ip_info(tcpip_adapter_if_t tcpip_if); +static esp_err_t tcpip_adapter_start_ip_lost_timer(tcpip_adapter_if_t tcpip_if); +static void tcpip_adapter_dhcpc_cb(struct netif *netif); +static void tcpip_adapter_ip_lost_timer(void *arg); +static int tcpip_adapter_bind_netcard(const char *name, struct netif *netif); +static bool tcpip_inited = false; + +static const char* TAG = "tcpip_adapter"; + +u32_t LwipTimOutLim = 0; // For light sleep. time out. limit is 3000ms + +/* Avoid warning. No header file has include these function */ +err_t ethernetif_init(struct netif* netif); +void system_station_got_ip_set(); + +static os_timer_t* get_ip_timer; +static int dhcp_fail_time; +static tcpip_adapter_ip_info_t esp_ip[TCPIP_ADAPTER_IF_MAX]; + +static void tcpip_adapter_dhcps_cb(u8_t client_ip[4]) +{ + ESP_LOGI(TAG,"softAP assign IP to station,IP is: %d.%d.%d.%d", + client_ip[0],client_ip[1],client_ip[2],client_ip[3]); + system_event_t evt; + evt.event_id = SYSTEM_EVENT_AP_STAIPASSIGNED; + esp_event_send(&evt); +} + +void tcpip_adapter_init(void) +{ + if (tcpip_inited == false) { + tcpip_inited = true; + tcpip_init(NULL, NULL); + + memset(esp_ip, 0, sizeof(tcpip_adapter_ip_info_t)*TCPIP_ADAPTER_IF_MAX); + memset(esp_ip_old, 0, sizeof(tcpip_adapter_ip_info_t)*TCPIP_ADAPTER_IF_MAX); + + IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].ip, 192, 168 , 4, 1); + IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].gw, 192, 168 , 4, 1); + IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); + } +} + +static void tcpip_adapter_dhcpc_done() +{ + struct dhcp *clientdhcp = netif_dhcp_data(esp_netif[TCPIP_ADAPTER_IF_STA]) ; + + os_timer_disarm(get_ip_timer); + + if (clientdhcp->state == DHCP_STATE_BOUND) { + /*send event here*/ + tcpip_adapter_dhcpc_cb(esp_netif[TCPIP_ADAPTER_IF_STA]); + printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", IP2STR(ip_2_ip4(&(esp_netif[0]->ip_addr))), + IP2STR(ip_2_ip4(&(esp_netif[0]->netmask))), IP2STR(ip_2_ip4(&(esp_netif[0]->gw)))); + } else if (dhcp_fail_time < (CONFIG_IP_LOST_TIMER_INTERVAL * 1000 / 100)) { + ESP_LOGD(TAG,"dhcpc time(ms): %d\n", dhcp_fail_time * 100); + dhcp_fail_time ++; + os_timer_setfn(get_ip_timer, tcpip_adapter_dhcpc_done, NULL); + os_timer_arm(get_ip_timer, 200, 1); + } else { + ESP_LOGD(TAG,"ERROR dhcp get ip error\n"); + free(get_ip_timer); + } +} + +static inline netif_init_fn tcpip_if_to_netif_init_fn(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if < TCPIP_ADAPTER_IF_MAX) + return esp_netif_init_fn[tcpip_if]; + else + return NULL; +} + +static esp_err_t tcpip_adapter_update_default_netif(void) +{ + if ((esp_netif[TCPIP_ADAPTER_IF_STA] != NULL) && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_STA])) { + netif_set_default(esp_netif[TCPIP_ADAPTER_IF_STA]); + } else if ((esp_netif[TCPIP_ADAPTER_IF_AP] != NULL) && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_AP])) { + netif_set_default(esp_netif[TCPIP_ADAPTER_IF_AP]); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_adapter_ip_info_t *ip_info) +{ + int s = -1; + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL || ip_info == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (esp_netif[tcpip_if] == NULL || !netif_is_up(esp_netif[tcpip_if])) { + if (esp_netif[tcpip_if] == NULL) { + esp_netif[tcpip_if] = (struct netif*)os_zalloc(sizeof(*esp_netif[tcpip_if])); + } + + if (esp_netif[tcpip_if] == NULL) { + ESP_LOGE(TAG, "TCPIP adapter has no menory\n"); + return ESP_ERR_NO_MEM; + } + memcpy(esp_netif[tcpip_if]->hwaddr, mac, NETIF_MAX_HWADDR_LEN); + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + const char *netcard_name = "sta0"; + s = tcpip_adapter_bind_netcard(netcard_name, esp_netif[tcpip_if]); + if (s < 0) { + ESP_LOGE(TAG, "TCPIP adapter bind net card %s error\n", netcard_name); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + } else if (tcpip_if == TCPIP_ADAPTER_IF_AP) { + const char *netcard_name = "ap0"; + + s = tcpip_adapter_bind_netcard(netcard_name, esp_netif[tcpip_if]); + if (s < 0) { + ESP_LOGE(TAG, "TCPIP adapter bind net card %s error\n", netcard_name); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + } + netif_add(esp_netif[tcpip_if], &ip_info->ip, &ip_info->netmask, &ip_info->gw, (void *)s, ethernetif_init, tcpip_input); + } + + if (tcpip_if == TCPIP_ADAPTER_IF_AP) { + netif_set_up(esp_netif[tcpip_if]); + + if (dhcps_status == TCPIP_ADAPTER_DHCP_INIT) { + dhcps_set_new_lease_cb(tcpip_adapter_dhcps_cb); + + dhcps_start(esp_netif[tcpip_if], ip_info->ip); + + ESP_LOGD(TAG, "dhcp server start:(ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR ")", + IP2STR(&ip_info->ip), IP2STR(&ip_info->netmask), IP2STR(&ip_info->gw)); + + dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; + } + } + + tcpip_adapter_update_default_netif(); + + return ESP_OK; +} + +esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (esp_netif[tcpip_if] == NULL) { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + if (!netif_is_up(esp_netif[tcpip_if])) { + netif_remove(esp_netif[tcpip_if]); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + if (tcpip_if == TCPIP_ADAPTER_IF_AP) { + dhcps_stop(esp_netif[tcpip_if]); // TODO: dhcps checks status by its self + if (TCPIP_ADAPTER_DHCP_STOPPED != dhcps_status) { + dhcps_status = TCPIP_ADAPTER_DHCP_INIT; + } + } else if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { + dhcp_release(esp_netif[tcpip_if]); + dhcp_stop(esp_netif[tcpip_if]); + dhcp_cleanup(esp_netif[tcpip_if]); + + dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; + + tcpip_adapter_reset_ip_info(tcpip_if); + } + + esp_close((int)esp_netif[tcpip_if]->state); + netif_set_down(esp_netif[tcpip_if]); + netif_remove(esp_netif[tcpip_if]); + tcpip_adapter_update_default_netif(); + //os_free(esp_netif[tcpip_if]); + //esp_netif[netif_index] = NULL; + return ESP_OK; +} + + +/* + * @brief LWIP custom pbuf callback function, it is to free custom pbuf + * + * @param p LWIP pbuf pointer + * + * @return none + */ +static void tcpip_adapter_free_pbuf(struct pbuf *p) +{ + struct tcpip_adapter_pbuf *pa = (struct tcpip_adapter_pbuf *)p; + int s = (int)pa->netif->state; + + esp_free_pbuf(s, pa->base); + os_free(pa); +} + +/* + * @brief TCPIP adapter AI/O recieve callback function, it is to recieve input data + * and pass it to LWIP core + * + * @param aio AI/O control block pointer + * + * @return 0 if success or others if failed + */ +static int tcpip_adapter_recv_cb(struct esp_aio *aio) +{ + struct pbuf *pbuf = NULL; + struct tcpip_adapter_pbuf *p; + struct netif *netif = (struct netif *)aio->arg; + + extern void ethernetif_input(struct netif *netif, struct pbuf *p); + + p = os_malloc(sizeof(struct tcpip_adapter_pbuf)); + if (!p) + return -ENOMEM; + p->pbuf.custom_free_function = tcpip_adapter_free_pbuf; + p->base = (void *)aio->pbuf; + p->netif = netif; + + // PBUF_RAW means payload = (char *)aio->pbuf + offset(=0) + pbuf = pbuf_alloced_custom(PBUF_RAW, aio->len, PBUF_REF, &p->pbuf, (void *)aio->pbuf, aio->len); + if (!pbuf) + return -ENOMEM; + + ethernetif_input(netif, pbuf); + + return 0; +} + +/* + * @brief create a "esp_socket" and bind it to target net card + * + * @param name net card name pointer + * @param netif LWIP net interface pointer + * + * @return 0 if success or others if failed + */ +static int tcpip_adapter_bind_netcard(const char *name, struct netif *netif) +{ + int s, ret; + s = esp_socket(AF_PACKET, SOCK_RAW, ETH_P_ALL); + if (s < 0) { + ESP_LOGE(TAG,"create socket of (AF_PACKET, SOCK_RAW, ETH_P_ALL) error\n"); + return -1; + } + + ret = esp_ioctl(s, SIOCGIFINDEX, name); + if (ret) { + ESP_LOGE(TAG,"bind socket %d to netcard %s error\n", s, name); + esp_close(s); + return -1; + } + + ret = esp_aio_event(s, ESP_SOCKET_RECV_EVENT, tcpip_adapter_recv_cb, netif); + if (ret) { + ESP_LOGE(TAG,"socket %d register receive callback function %p error\n", s, tcpip_adapter_recv_cb); + esp_close(s); + return -1; + } + return s; +} + +esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + if (esp_netif[tcpip_if] == NULL) { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + /* use last obtained ip, or static ip */ + netif_set_addr(esp_netif[tcpip_if], &esp_ip[tcpip_if].ip, &esp_ip[tcpip_if].netmask, &esp_ip[tcpip_if].gw); + netif_set_up(esp_netif[tcpip_if]); + } + + tcpip_adapter_update_default_netif(); + + return ESP_OK; +} + +static esp_err_t tcpip_adapter_reset_ip_info(tcpip_adapter_if_t tcpip_if) +{ + ip4_addr_set_zero(&esp_ip[tcpip_if].ip); + ip4_addr_set_zero(&esp_ip[tcpip_if].gw); + ip4_addr_set_zero(&esp_ip[tcpip_if].netmask); + return ESP_OK; +} + +esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + if (esp_netif[tcpip_if] == NULL) { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STARTED) { + dhcp_stop(esp_netif[tcpip_if]); + + dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; + + tcpip_adapter_reset_ip_info(tcpip_if); + } + + netif_set_addr(esp_netif[tcpip_if], IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + netif_set_down(esp_netif[tcpip_if]); + tcpip_adapter_start_ip_lost_timer(tcpip_if); + } + + tcpip_adapter_update_default_netif(); + + return ESP_OK; +} + +esp_err_t tcpip_adapter_set_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + memcpy(&esp_ip_old[tcpip_if], ip_info, sizeof(tcpip_adapter_ip_info_t)); + + return ESP_OK; +} + +esp_err_t tcpip_adapter_get_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + memcpy(ip_info, &esp_ip_old[tcpip_if], sizeof(tcpip_adapter_ip_info_t)); + + return ESP_OK; +} + +esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL && netif_is_up(p_netif)) { + ip4_addr_set(&ip_info->ip, ip_2_ip4(&p_netif->ip_addr)); + ip4_addr_set(&ip_info->netmask, ip_2_ip4(&p_netif->netmask)); + ip4_addr_set(&ip_info->gw, ip_2_ip4(&p_netif->gw)); + + return ESP_OK; + } + + ip4_addr_copy(ip_info->ip, esp_ip[tcpip_if].ip); + ip4_addr_copy(ip_info->gw, esp_ip[tcpip_if].gw); + ip4_addr_copy(ip_info->netmask, esp_ip[tcpip_if].netmask); + + return ESP_OK; +} + +esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) +{ + struct netif *p_netif; + tcpip_adapter_dhcp_status_t status; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (tcpip_if == TCPIP_ADAPTER_IF_AP) { + tcpip_adapter_dhcps_get_status(tcpip_if, &status); + + if (status != TCPIP_ADAPTER_DHCP_STOPPED) { + return ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED; + } + } else if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + tcpip_adapter_dhcpc_get_status(tcpip_if, &status); + + if (status != TCPIP_ADAPTER_DHCP_STOPPED) { + return ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED; + } +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + //dns_clear_servers(true); +#endif + } + + ip4_addr_copy(esp_ip[tcpip_if].ip, ip_info->ip); + ip4_addr_copy(esp_ip[tcpip_if].gw, ip_info->gw); + ip4_addr_copy(esp_ip[tcpip_if].netmask, ip_info->netmask); + + p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL && netif_is_up(p_netif)) { + netif_set_addr(p_netif, &ip_info->ip, &ip_info->netmask, &ip_info->gw); + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask) || ip4_addr_isany_val(ip_info->gw))) { + system_event_t evt; + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; + } else if (tcpip_if == TCPIP_ADAPTER_IF_ETH) { + evt.event_id = SYSTEM_EVENT_ETH_GOT_IP; + } + evt.event_info.got_ip.ip_changed = false; + + if (memcmp(ip_info, &esp_ip_old[tcpip_if], sizeof(tcpip_adapter_ip_info_t))) { + evt.event_info.got_ip.ip_changed = true; + } + + memcpy(&evt.event_info.got_ip.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); + memcpy(&esp_ip_old[tcpip_if], ip_info, sizeof(tcpip_adapter_ip_info_t)); + esp_event_send(&evt); + ESP_LOGD(TAG, "if%d tcpip adapter set static ip: ip changed=%d", tcpip_if, evt.event_info.got_ip.ip_changed); + } + } + } + + return ESP_OK; +} + +#if 0 +static void tcpip_adapter_nd6_cb(struct netif *p_netif, uint8_t ip_idex) +{ + tcpip_adapter_ip6_info_t *ip6_info; + + system_event_t evt; + //notify event + + evt.event_id = SYSTEM_EVENT_GOT_IP6; + + if (!p_netif) { + ESP_LOGD(TAG, "null p_netif=%p", p_netif); + return; + } + + if (p_netif == esp_netif[TCPIP_ADAPTER_IF_STA]) { + ip6_info = &esp_ip6[TCPIP_ADAPTER_IF_STA]; + evt.event_info.got_ip6.if_index = TCPIP_ADAPTER_IF_STA; + } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_AP]) { + ip6_info = &esp_ip6[TCPIP_ADAPTER_IF_AP]; + evt.event_info.got_ip6.if_index = TCPIP_ADAPTER_IF_AP; + } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_ETH]) { + ip6_info = &esp_ip6[TCPIP_ADAPTER_IF_ETH]; + evt.event_info.got_ip6.if_index = TCPIP_ADAPTER_IF_ETH; + } else { + return; + } + + ip6_addr_set(&ip6_info->ip, ip_2_ip6(&p_netif->ip6_addr[ip_idex])); + + memcpy(&evt.event_info.got_ip6.ip6_info, ip6_info, sizeof(tcpip_adapter_ip6_info_t)); + esp_event_send(&evt); +} +#endif + +esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + if (p_netif != NULL && netif_is_up(p_netif)) { + netif_create_ip6_linklocal_address(p_netif, 1); + /*TODO need add ipv6 address cb*/ + //nd6_set_cb(p_netif, tcpip_adapter_nd6_cb); + + return ESP_OK; + } else { + return ESP_FAIL; + } +} + +esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || if_ip6 == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + if (p_netif != NULL && netif_is_up(p_netif) && ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, 0))) { + memcpy(if_ip6, &p_netif->ip6_addr[0], sizeof(ip6_addr_t)); + } else { + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len) +{ + void *opt_info = dhcps_option_info(opt_id, opt_len); + + if (opt_info == NULL || opt_val == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (opt_op == TCPIP_ADAPTER_OP_GET) { + if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPPED) { + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; + } + + switch (opt_id) { + case IP_ADDRESS_LEASE_TIME: { + *(uint32_t *)opt_val = *(uint32_t *)opt_info; + break; + } + case REQUESTED_IP_ADDRESS: { + memcpy(opt_val, opt_info, opt_len); + break; + } + case ROUTER_SOLICITATION_ADDRESS: { + if ((*(uint8_t *)opt_info) & OFFER_ROUTER) { + *(uint8_t *)opt_val = 1; + } else { + *(uint8_t *)opt_val = 0; + } + break; + } + case DOMAIN_NAME_SERVER: { + if ((*(uint8_t *)opt_info) & OFFER_DNS) { + *(uint8_t *)opt_val = 1; + } else { + *(uint8_t *)opt_val = 0; + } + break; + } + default: + break; + } + } else if (opt_op == TCPIP_ADAPTER_OP_SET) { + if (dhcps_status == TCPIP_ADAPTER_DHCP_STARTED) { + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; + } + + switch (opt_id) { + case IP_ADDRESS_LEASE_TIME: { + if (*(uint32_t *)opt_val != 0) { + *(uint32_t *)opt_info = *(uint32_t *)opt_val; + } else { + *(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF; + } + break; + } + case REQUESTED_IP_ADDRESS: { + tcpip_adapter_ip_info_t info; + uint32_t softap_ip = 0; + uint32_t start_ip = 0; + uint32_t end_ip = 0; + dhcps_lease_t *poll = opt_val; + + if (poll->enable) { + memset(&info, 0x00, sizeof(tcpip_adapter_ip_info_t)); + tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &info); + softap_ip = htonl(info.ip.addr); + start_ip = htonl(poll->start_ip.addr); + end_ip = htonl(poll->end_ip.addr); + + /*config ip information can't contain local ip*/ + if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + /*config ip information must be in the same segment as the local ip*/ + softap_ip >>= 8; + if ((start_ip >> 8 != softap_ip) + || (end_ip >> 8 != softap_ip)) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (end_ip - start_ip > DHCPS_MAX_LEASE) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + } + + memcpy(opt_info, opt_val, opt_len); + break; + } + case ROUTER_SOLICITATION_ADDRESS: { + if (*(uint8_t *)opt_val) { + *(uint8_t *)opt_info |= OFFER_ROUTER; + } else { + *(uint8_t *)opt_info &= ((~OFFER_ROUTER)&0xFF); + } + break; + } + case DOMAIN_NAME_SERVER: { + if (*(uint8_t *)opt_val) { + *(uint8_t *)opt_info |= OFFER_DNS; + } else { + *(uint8_t *)opt_info &= ((~OFFER_DNS)&0xFF); + } + break; + } + + default: + break; + } + dhcps_set_option_info(opt_id, opt_info,opt_len); + } else { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + ESP_LOGD(TAG, "set dns invalid if=%d", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (!dns) { + ESP_LOGD(TAG, "set dns null dns"); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (type >= TCPIP_ADAPTER_DNS_MAX) { + ESP_LOGD(TAG, "set dns invalid type=%d", type); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (ip4_addr_isany_val(dns->ip.u_addr.ip4)) { + ESP_LOGD(TAG, "set dns invalid dns"); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + ESP_LOGD(TAG, "set dns if=%d type=%d dns=%x", tcpip_if, type, dns->ip.u_addr.ip4.addr); + dns->ip.type = IPADDR_TYPE_V4; + + if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { + dns_setserver(type, &(dns->ip)); + } else { + if (type != TCPIP_ADAPTER_DNS_MAIN) { + ESP_LOGD(TAG, "set dns invalid type"); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } else { + dhcps_dns_setserver(&(dns->ip)); + } + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns) +{ + const ip_addr_t *ns; + + if (!dns) { + ESP_LOGD(TAG, "get dns null dns"); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (type >= TCPIP_ADAPTER_DNS_MAX) { + ESP_LOGD(TAG, "get dns invalid type=%d", type); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + ESP_LOGD(TAG, "get dns invalid tcpip_if=%d",tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { + ns = dns_getserver(type); + dns->ip = *ns; + } else { + dns->ip.u_addr.ip4 = dhcps_dns_getserver(); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status) +{ + *status = dhcps_status; + + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if) +{ + /* only support ap now */ + if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + ESP_LOGD(TAG, "dhcp server invalid if=%d", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcps_status != TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL && netif_is_up(p_netif)) { + tcpip_adapter_ip_info_t default_ip; + tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &default_ip); + dhcps_start(p_netif, default_ip.ip); + dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; + ESP_LOGD(TAG, "dhcp server start successfully"); + return ESP_OK; + } else { + ESP_LOGD(TAG, "dhcp server re init"); + dhcps_status = TCPIP_ADAPTER_DHCP_INIT; + return ESP_OK; + } + } + + ESP_LOGD(TAG, "dhcp server already start"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; +} + +esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if) +{ + /* only support ap now */ + if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + ESP_LOGD(TAG, "dhcp server invalid if=%d", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcps_status == TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + dhcps_stop(p_netif); + } else { + ESP_LOGD(TAG, "dhcp server if not ready"); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + } else if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPPED) { + ESP_LOGD(TAG, "dhcp server already stoped"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; + } + + ESP_LOGD(TAG, "dhcp server stop successfully"); + dhcps_status = TCPIP_ADAPTER_DHCP_STOPPED; + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len) +{ + // TODO: when dhcp request timeout,change the retry count + return ESP_OK; +} + +static void tcpip_adapter_dhcpc_cb(struct netif *netif) +{ + tcpip_adapter_ip_info_t *ip_info_old = NULL; + tcpip_adapter_ip_info_t *ip_info = NULL; + tcpip_adapter_if_t tcpip_if; + + if (!netif) { + ESP_LOGD(TAG, "null netif=%p", netif); + return; + } + + if( netif == esp_netif[TCPIP_ADAPTER_IF_STA] ) { + tcpip_if = TCPIP_ADAPTER_IF_STA; + } else { + ESP_LOGD(TAG, "err netif=%p", netif); + return; + } + + ESP_LOGD(TAG, "if%d dhcpc cb", tcpip_if); + ip_info = &esp_ip[tcpip_if]; + ip_info_old = &esp_ip_old[tcpip_if]; + + if ( !ip_addr_isany_val(netif->ip_addr) ) { + + //check whether IP is changed + if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), &ip_info->ip) || + !ip4_addr_cmp(ip_2_ip4(&netif->netmask), &ip_info->netmask) || + !ip4_addr_cmp(ip_2_ip4(&netif->gw), &ip_info->gw) ) { + system_event_t evt; + + ip4_addr_set(&ip_info->ip, ip_2_ip4(&netif->ip_addr)); + ip4_addr_set(&ip_info->netmask, ip_2_ip4(&netif->netmask)); + ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw)); + + //notify event + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; + evt.event_info.got_ip.ip_changed = false; + + if (memcmp(ip_info, ip_info_old, sizeof(tcpip_adapter_ip_info_t))) { + evt.event_info.got_ip.ip_changed = true; + } + + memcpy(&evt.event_info.got_ip.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); + memcpy(ip_info_old, ip_info, sizeof(tcpip_adapter_ip_info_t)); + ESP_LOGD(TAG, "if%d ip changed=%d", tcpip_if, evt.event_info.got_ip.ip_changed); + esp_event_send(&evt); + } else { + ESP_LOGD(TAG, "if%d ip unchanged", CONFIG_IP_LOST_TIMER_INTERVAL); + } + } else { + if (!ip4_addr_isany_val(ip_info->ip)) { + tcpip_adapter_start_ip_lost_timer(tcpip_if); + } + } + + return; +} + +static esp_err_t tcpip_adapter_start_ip_lost_timer(tcpip_adapter_if_t tcpip_if) +{ + tcpip_adapter_ip_info_t *ip_info_old = &esp_ip_old[tcpip_if]; + struct netif *netif = esp_netif[tcpip_if]; + + ESP_LOGD(TAG, "if%d start ip lost tmr: enter", tcpip_if); + if (tcpip_if != TCPIP_ADAPTER_IF_STA) { + ESP_LOGD(TAG, "if%d start ip lost tmr: only sta support ip lost timer", tcpip_if); + return ESP_OK; + } + + if (esp_ip_lost_timer[tcpip_if].timer_running) { + ESP_LOGD(TAG, "if%d start ip lost tmr: already started", tcpip_if); + return ESP_OK; + } + + if ( netif && (CONFIG_IP_LOST_TIMER_INTERVAL > 0) && !ip4_addr_isany_val(ip_info_old->ip)) { + esp_ip_lost_timer[tcpip_if].timer_running = true; + sys_timeout(CONFIG_IP_LOST_TIMER_INTERVAL*1000, tcpip_adapter_ip_lost_timer, (void*)tcpip_if); + ESP_LOGD(TAG, "if%d start ip lost tmr: interval=%d", tcpip_if, CONFIG_IP_LOST_TIMER_INTERVAL); + return ESP_OK; + } + + ESP_LOGD(TAG, "if%d start ip lost tmr: no need start because netif=%p interval=%d ip=%x", + tcpip_if, netif, CONFIG_IP_LOST_TIMER_INTERVAL, ip_info_old->ip.addr); + + return ESP_OK; +} + +static void tcpip_adapter_ip_lost_timer(void *arg) +{ + tcpip_adapter_if_t tcpip_if = (tcpip_adapter_if_t)arg; + + ESP_LOGD(TAG, "if%d ip lost tmr: enter", tcpip_if); + esp_ip_lost_timer[tcpip_if].timer_running = false; + + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + struct netif *netif = esp_netif[tcpip_if]; + + if ( (!netif) || (netif && ip_addr_isany_val(netif->ip_addr))){ + system_event_t evt; + + ESP_LOGD(TAG, "if%d ip lost tmr: raise ip lost event", tcpip_if); + memset(&esp_ip_old[tcpip_if], 0, sizeof(tcpip_adapter_ip_info_t)); + evt.event_id = SYSTEM_EVENT_STA_LOST_IP; + esp_event_send(&evt); + } else { + ESP_LOGD(TAG, "if%d ip lost tmr: no need raise ip lost event", tcpip_if); + } + } else { + ESP_LOGD(TAG, "if%d ip lost tmr: not station", tcpip_if); + } +} + +esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status) +{ + *status = dhcpc_status[tcpip_if]; + + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if) +{ + if ((tcpip_if != TCPIP_ADAPTER_IF_STA) || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + ESP_LOGD(TAG, "dhcp client invalid if=%d", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + get_ip_timer = (os_timer_t*)malloc(sizeof(*get_ip_timer)); + + if (get_ip_timer == NULL) { + ESP_LOGE(TAG, "ERROR NO MEMORY\n"); + } + + if (dhcpc_status[tcpip_if] != TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + tcpip_adapter_reset_ip_info(tcpip_if); +#if LWIP_DNS + //dns_clear_servers(true); +#endif + + if (p_netif != NULL) { + if (netif_is_up(p_netif)) { + ESP_LOGD(TAG, "dhcp client init ip/mask/gw to all-0"); + ip_addr_set_zero(&p_netif->ip_addr); + ip_addr_set_zero(&p_netif->netmask); + ip_addr_set_zero(&p_netif->gw); + tcpip_adapter_start_ip_lost_timer(tcpip_if); + } else { + ESP_LOGD(TAG, "dhcp client re init"); + dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; + return ESP_OK; + } + + if (dhcp_start(p_netif) != ERR_OK) { + ESP_LOGD(TAG, "dhcp client start failed"); + return ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED; + } + + //dhcp_set_cb(p_netif, tcpip_adapter_dhcpc_cb); + os_timer_disarm(get_ip_timer); + os_timer_setfn(get_ip_timer, tcpip_adapter_dhcpc_done, NULL); + os_timer_arm(get_ip_timer, 100, 1); + + ESP_LOGD(TAG, "dhcp client start successfully"); + dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STARTED; + return ESP_OK; + } else { + ESP_LOGD(TAG, "dhcp client re init"); + dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; + return ESP_OK; + } + } + + ESP_LOGD(TAG, "dhcp client already started"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; +} + +esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if != TCPIP_ADAPTER_IF_STA || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + ESP_LOGD(TAG, "dhcp client invalid if=%d", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + dhcp_stop(p_netif); + tcpip_adapter_reset_ip_info(tcpip_if); + tcpip_adapter_start_ip_lost_timer(tcpip_if); + } else { + ESP_LOGD(TAG, "dhcp client if not ready"); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + } else if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STOPPED) { + ESP_LOGD(TAG, "dhcp client already stoped"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; + } + + ESP_LOGD(TAG, "dhcp client stop successfully"); + dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STOPPED; + return ESP_OK; +} + +esp_interface_t tcpip_adapter_get_esp_if(void *dev) +{ + struct netif *p_netif = (struct netif *)dev; + + if (p_netif == esp_netif[TCPIP_ADAPTER_IF_STA]) { + return ESP_IF_WIFI_STA; + } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_AP]) { + return ESP_IF_WIFI_AP; + } + + return ESP_IF_MAX; +} + +esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list) +{ + int i; + + if ((wifi_sta_list == NULL) || (tcpip_sta_list == NULL)) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + memset(tcpip_sta_list, 0, sizeof(tcpip_adapter_sta_list_t)); + tcpip_sta_list->num = wifi_sta_list->num; + for (i = 0; i < wifi_sta_list->num; i++) { + memcpy(tcpip_sta_list->sta[i].mac, wifi_sta_list->sta[i].mac, 6); + dhcp_search_ip_on_mac(tcpip_sta_list->sta[i].mac, &tcpip_sta_list->sta[i].ip); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname) +{ +#if LWIP_NETIF_HOSTNAME + struct netif *p_netif; + static char hostinfo[TCPIP_ADAPTER_IF_MAX][TCPIP_HOSTNAME_MAX_SIZE + 1]; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (strlen(hostname) > TCPIP_HOSTNAME_MAX_SIZE) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + if (p_netif != NULL) { + memset(hostinfo[tcpip_if], 0, sizeof(hostinfo[tcpip_if])); + strlcpy(hostinfo[tcpip_if], hostname, sizeof(hostinfo[tcpip_if])); + p_netif->hostname = hostinfo[tcpip_if]; + return ESP_OK; + } else { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } +#else + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; +#endif +} + +esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname) +{ +#if LWIP_NETIF_HOSTNAME + struct netif *p_netif = NULL; + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + if (p_netif != NULL) { + *hostname = p_netif->hostname; + return ESP_OK; + } else { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } +#else + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; +#endif +} + +esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + *netif = esp_netif[tcpip_if]; + + if (*netif == NULL) { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + return ESP_OK; +} + +#endif /* CONFIG_TCPIP_LWIP */ diff --git a/components/tcpip_adapter/tcpip_adapter_wifi.c b/components/tcpip_adapter/tcpip_adapter_wifi.c deleted file mode 100644 index fdaa0c36..00000000 --- a/components/tcpip_adapter/tcpip_adapter_wifi.c +++ /dev/null @@ -1,600 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "lwip/netif.h" -#include "lwip/tcpip.h" -#include "lwip/dhcp.h" -#include "lwip/errno.h" -#include "lwip/prot/dhcp.h" -#include "netif/etharp.h" -#include "esp_wifi.h" -#include "esp_timer.h" -#include "esp_misc.h" -#include "tcpip_adapter.h" -#include "dhcpserver/dhcpserver.h" -#include "net/sockio.h" -#include "esp_socket.h" - -struct tcpip_adapter_pbuf { - struct pbuf_custom pbuf; - - void *base; - - struct netif *netif; -}; - -u32_t LwipTimOutLim = 0; // For light sleep. time out. limit is 3000ms - -/* Avoid warning. No header file has include these function */ -err_t ethernetif_init(struct netif* netif); -void system_station_got_ip_set(); - -static os_timer_t* get_ip_timer; -static uint8_t dhcp_fail_time; -static bool dhcps_flag = true; -static bool dhcpc_flag = true; -static tcpip_adapter_ip_info_t esp_ip[TCPIP_ADAPTER_IF_MAX]; - -void tcpip_adapter_init(void) -{ - //TODO:add tcpip init function. -} - -void esp_wifi_station_dhcpc_event(uint8_t netif_index) -{ - if (TCPIP_ADAPTER_IF_VALID(netif_index)) { - TCPIP_ATAPTER_LOG("wifi station dhcpc start\n"); - dhcp_stop(esp_netif[netif_index]); - dhcp_cleanup(esp_netif[netif_index]); - dhcp_inform(esp_netif[netif_index]); - } else { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - } -} - -static void tcpip_adapter_dhcpc_done() -{ - struct dhcp *clientdhcp = netif_dhcp_data(esp_netif[TCPIP_ADAPTER_IF_STA]) ; - - os_timer_disarm(get_ip_timer); - - if (clientdhcp->state == DHCP_STATE_BOUND) { - /*send event here*/ - system_station_got_ip_set(); - printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", IP2STR(ip_2_ip4(&(esp_netif[0]->ip_addr))), - IP2STR(ip_2_ip4(&(esp_netif[0]->netmask))), IP2STR(ip_2_ip4(&(esp_netif[0]->gw)))); - } else if (dhcp_fail_time < 100) { - TCPIP_ATAPTER_LOG("dhcpc time(ms): %d\n", dhcp_fail_time * 200); - dhcp_fail_time ++; - os_timer_setfn(get_ip_timer, tcpip_adapter_dhcpc_done, NULL); - os_timer_arm(get_ip_timer, 200, 1); - } else { - TCPIP_ATAPTER_LOG("ERROR dhcp get ip error\n"); - free(get_ip_timer); - } -} - -static void tcpip_adapter_station_dhcp_start() -{ - err_t ret; - get_ip_timer = (os_timer_t*)malloc(sizeof(*get_ip_timer)); - - if (get_ip_timer == NULL) { - TCPIP_ATAPTER_LOG("ERROR NO MEMORY\n"); - } - - TCPIP_ATAPTER_LOG("dhcpc start\n"); - ret = dhcp_start(esp_netif[TCPIP_ADAPTER_IF_STA]); - dhcp_fail_time = 0; - - if (ret == 0) { - os_timer_disarm(get_ip_timer); - os_timer_setfn(get_ip_timer, tcpip_adapter_dhcpc_done, NULL); - os_timer_arm(get_ip_timer, 100, 1); - } -} - -/* - * @brief LWIP custom pbuf callback function, it is to free custom pbuf - * - * @param p LWIP pbuf pointer - * - * @return none - */ -static void tcpip_adapter_free_pbuf(struct pbuf *p) -{ - struct tcpip_adapter_pbuf *pa = (struct tcpip_adapter_pbuf *)p; - int s = (int)pa->netif->state; - - esp_free_pbuf(s, pa->base); - os_free(pa); -} - -/* - * @brief TCPIP adapter AI/O recieve callback function, it is to recieve input data - * and pass it to LWIP core - * - * @param aio AI/O control block pointer - * - * @return 0 if success or others if failed - */ -static int tcpip_adapter_recv_cb(struct esp_aio *aio) -{ - struct pbuf *pbuf = NULL; - struct tcpip_adapter_pbuf *p; - struct netif *netif = (struct netif *)aio->arg; - - extern void ethernetif_input(struct netif *netif, struct pbuf *p); - - p = os_malloc(sizeof(struct tcpip_adapter_pbuf)); - if (!p) - return -ENOMEM; - p->pbuf.custom_free_function = tcpip_adapter_free_pbuf; - p->base = (void *)aio->pbuf; - p->netif = netif; - - // PBUF_RAW means payload = (char *)aio->pbuf + offset(=0) - pbuf = pbuf_alloced_custom(PBUF_RAW, aio->len, PBUF_REF, &p->pbuf, (void *)aio->pbuf, aio->len); - if (!pbuf) - return -ENOMEM; - - ethernetif_input(netif, pbuf); - - return 0; -} - -/* - * @brief create a "esp_socket" and bind it to target net card - * - * @param name net card name pointer - * @param netif LWIP net interface pointer - * - * @return 0 if success or others if failed - */ -static int tcpip_adapter_bind_netcard(const char *name, struct netif *netif) -{ - int s, ret; - - s = esp_socket(AF_PACKET, SOCK_RAW, ETH_P_ALL); - if (s < 0) { - TCPIP_ATAPTER_LOG("create socket of (AF_PACKET, SOCK_RAW, ETH_P_ALL) error\n"); - return -1; - } - - ret = esp_ioctl(s, SIOCGIFINDEX, name); - if (ret) { - TCPIP_ATAPTER_LOG("bind socket %d to netcard %s error\n", s, name); - esp_close(s); - return -1; - } - - ret = esp_aio_event(s, ESP_SOCKET_RECV_EVENT, tcpip_adapter_recv_cb, netif); - if (ret) { - TCPIP_ATAPTER_LOG("socket %d register receive callback function %p error\n", s, tcpip_adapter_recv_cb); - esp_close(s); - return -1; - } - - return s; -} - -void tcpip_adapter_start(uint8_t netif_index, bool authed) -{ - if (!TCPIP_ADAPTER_IF_VALID(netif_index)) { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return; - } - - TCPIP_ATAPTER_LOG("start netif[%d]\n", netif_index); - - if (netif_index == TCPIP_ADAPTER_IF_STA) { - if (authed == 0) { - if (esp_netif[netif_index] == NULL) { - int s; - const char *netcard_name = "sta0"; - - esp_netif[netif_index] = (struct netif*)os_zalloc(sizeof(*esp_netif[netif_index])); - TCPIP_ATAPTER_LOG("Malloc netif:%d\n", netif_index); - TCPIP_ATAPTER_LOG("Add netif:%d\n", netif_index); - - s = tcpip_adapter_bind_netcard(netcard_name, esp_netif[netif_index]); - if (s < 0) { - TCPIP_ATAPTER_LOG("TCPIP adapter bind net card %s error\n", netcard_name); - return ; - } - - netif_add(esp_netif[netif_index], NULL, NULL, NULL, (void *)s, ethernetif_init, tcpip_input); - } - } else { - if (dhcpc_flag) { - printf("dhcp client start...\n"); - tcpip_adapter_station_dhcp_start(); - } else { - if (esp_ip[TCPIP_ADAPTER_IF_STA].ip.addr != 0) { - netif_set_addr(esp_netif[netif_index], &esp_ip[TCPIP_ADAPTER_IF_STA].ip, - &esp_ip[TCPIP_ADAPTER_IF_STA].netmask, &esp_ip[TCPIP_ADAPTER_IF_STA].gw); - netif_set_up(esp_netif[netif_index]); - system_station_got_ip_set(); - printf("ip: 0.0.0.0,mask: 0.0.0.0,gw: 0.0.0.0\n"); - } else { - printf("check your static ip\n"); - } - } - } - } else if (netif_index == TCPIP_ADAPTER_IF_AP) { - if (dhcps_flag) { - IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].ip, 192, 168 , 4, 1); - IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].gw, 192, 168 , 4, 1); - IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); - } - - if (esp_netif[netif_index] == NULL) { - int s; - const char *netcard_name = "ap0"; - - TCPIP_ATAPTER_LOG("Malloc netif:%d\n", netif_index); - esp_netif[netif_index] = (struct netif*)os_zalloc(sizeof(*esp_netif[netif_index])); - - s = tcpip_adapter_bind_netcard(netcard_name, esp_netif[netif_index]); - if (s < 0) { - TCPIP_ATAPTER_LOG("TCPIP adapter bind net card %s error\n", netcard_name); - return ; - } - - netif_add(esp_netif[netif_index], &esp_ip[TCPIP_ADAPTER_IF_AP].ip, - &esp_ip[TCPIP_ADAPTER_IF_AP].netmask, &esp_ip[TCPIP_ADAPTER_IF_AP].gw, (void *)s, ethernetif_init, tcpip_input); - } - - if (dhcps_flag) { - dhcps_start(&esp_ip[TCPIP_ADAPTER_IF_AP]); - printf("dhcp server start:("); - printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR, IP2STR((ip_2_ip4(&esp_netif[TCPIP_ADAPTER_IF_AP]->ip_addr))), - IP2STR((ip_2_ip4(&esp_netif[TCPIP_ADAPTER_IF_AP]->netmask))), IP2STR((ip_2_ip4(&esp_netif[TCPIP_ADAPTER_IF_AP]->gw)))); - printf(")\n"); - } - - netif_set_up(esp_netif[netif_index]); - netif_set_default(esp_netif[netif_index]); - } - - wifi_mode_t opmode; - esp_wifi_get_mode(&opmode); - - if (opmode == WIFI_MODE_STA) { - netif_set_default(esp_netif[netif_index]); - } -} - -void tcpip_adapter_stop(uint8_t netif_index) -{ - if (!TCPIP_ADAPTER_IF_VALID(netif_index)) { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return; - } - if (esp_netif[netif_index] == NULL) - return; - - if (netif_index == TCPIP_ADAPTER_IF_STA) { - TCPIP_ATAPTER_LOG("dhcp stop netif index:%d\n", netif_index); - dhcp_stop(esp_netif[netif_index]); - } - - if (netif_index == TCPIP_ADAPTER_IF_AP) { - if(dhcps_flag){ - TCPIP_ATAPTER_LOG("dhcp stop netif index:%d\n", netif_index); - dhcps_stop(); - } - } - - TCPIP_ATAPTER_LOG("stop netif[%d]\n", netif_index); - esp_close((int)esp_netif[netif_index]->state); - netif_remove(esp_netif[netif_index]); - os_free(esp_netif[netif_index]); - esp_netif[netif_index] = NULL; -} - -bool wifi_set_ip_info(wifi_interface_t netif_index, tcpip_adapter_ip_info_t* if_ip) -{ - if (!TCPIP_ADAPTER_IF_VALID((uint8_t)netif_index)) { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return false; - } - - TCPIP_ATAPTER_LOG("Set netif[%d] ip info\n", netif_index); - netif_set_addr(esp_netif[netif_index], &if_ip->ip, &if_ip->netmask, &if_ip->gw); - return true; -} - -bool wifi_get_ip_info(wifi_interface_t netif_index, tcpip_adapter_ip_info_t* if_ip) -{ - if (!TCPIP_ADAPTER_IF_VALID((uint8_t)netif_index)) { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return false; - } - - if(if_ip == NULL){ - TCPIP_ATAPTER_LOG("ERROR ip info is NULL\n"); - return false; - } - - TCPIP_ATAPTER_LOG("Get netif[%d] ip info\n", netif_index); - if_ip->ip.addr = ip_addr_get_ip4_u32(&esp_netif[netif_index]->ip_addr); - if_ip->netmask.addr = ip_addr_get_ip4_u32(&esp_netif[netif_index]->netmask); - if_ip->gw.addr = ip_addr_get_ip4_u32(&esp_netif[netif_index]->gw); - return true; -} - -bool wifi_create_linklocal_ip(uint8_t netif_index, bool ipv6) -{ - if (!TCPIP_ADAPTER_IF_VALID(netif_index)) { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return false; - } - - netif_create_ip6_linklocal_address(esp_netif[netif_index], ipv6); - return true; -} - -#if LWIP_IPV6 -bool wifi_get_linklocal_ip(uint8_t netif_index, ip6_addr_t* linklocal) -{ - if (TCPIP_ADAPTER_IF_VALID(netif_index)) { - memcpy(linklocal, ip_2_ip6(&esp_netif[netif_index]->ip6_addr[0]), sizeof(*linklocal)); - } else { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return false; - } - - return true; -} - -bool wifi_get_ipinfo_v6(uint8_t netif_index, uint8_t ip_index, ip6_addr_t* ipv6) -{ - - if (TCPIP_ADAPTER_IF_VALID(netif_index)) { - memcpy(ipv6, &esp_netif[netif_index]->ip6_addr[ip_index], sizeof(ip6_addr_t)); - } else { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return false; - } - - return true; -} -#endif - -bool wifi_softap_dhcps_start(void) -{ - wifi_mode_t opmode = WIFI_MODE_NULL; - TCPIP_ATAPTER_LOG("start softap dhcps\n"); - taskENTER_CRITICAL(); - esp_wifi_get_mode(&opmode); - - if ((opmode == WIFI_MODE_STA) || (opmode == WIFI_MODE_NULL)) { - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("ERROR you shoud enable wifi softap before start dhcp server\n"); - return false; - } - - if (dhcps_flag == false) { - tcpip_adapter_ip_info_t ipinfo; - wifi_get_ip_info(ESP_IF_WIFI_AP, &ipinfo); - TCPIP_ATAPTER_LOG("start softap dhcpserver\n"); - dhcps_start(&ipinfo); - } - - dhcps_flag = true; - taskEXIT_CRITICAL(); - return true; -} - -enum dhcp_status wifi_softap_dhcps_status() -{ - return dhcps_flag; -} - -void tcpip_adapter_sta_leave() -{ - TCPIP_ATAPTER_LOG("station leave\n"); - - if (esp_netif[TCPIP_ADAPTER_IF_STA] == NULL) { - return; - } - - netif_set_down(esp_netif[TCPIP_ADAPTER_IF_STA]); - - if (dhcpc_flag) { - dhcp_release(esp_netif[TCPIP_ADAPTER_IF_STA]); - dhcp_stop(esp_netif[TCPIP_ADAPTER_IF_STA]); - dhcp_cleanup(esp_netif[TCPIP_ADAPTER_IF_STA]); - } - - ip_addr_set_zero(&esp_netif[TCPIP_ADAPTER_IF_STA]->ip_addr); - ip_addr_set_zero(&esp_netif[TCPIP_ADAPTER_IF_STA]->netmask); - ip_addr_set_zero(&esp_netif[TCPIP_ADAPTER_IF_STA]->gw); -} - -bool wifi_softap_dhcps_stop() -{ - wifi_mode_t opmode = WIFI_MODE_NULL; - taskENTER_CRITICAL(); - esp_wifi_get_mode(&opmode); - - if ((opmode == WIFI_MODE_STA) || (opmode == WIFI_MODE_NULL)) { - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("ERROR you shoud enable wifi softap before start dhcp server\n"); - return false; - } - - if (dhcps_flag == true) { - TCPIP_ATAPTER_LOG("dhcps stop\n"); - dhcps_stop(); - } - - dhcps_flag = false; - taskEXIT_CRITICAL(); - return true; - -} - -bool wifi_station_dhcpc_start(void) -{ - wifi_mode_t opmode = WIFI_MODE_NULL; - err_t ret; - taskENTER_CRITICAL(); - esp_wifi_get_mode(&opmode); - - if ((opmode == WIFI_MODE_AP) || (opmode == WIFI_MODE_NULL)) { - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("ERROR you shoud enable wifi station mode before start dhcp client\n"); - return false; - } - - if (dhcpc_flag == false) { - if (netif_is_up(esp_netif[TCPIP_ADAPTER_IF_STA])) { - ip_addr_set_zero(&esp_netif[TCPIP_ADAPTER_IF_STA]->ip_addr); - ip_addr_set_zero(&esp_netif[TCPIP_ADAPTER_IF_STA]->netmask); - ip_addr_set_zero(&esp_netif[TCPIP_ADAPTER_IF_STA]->gw); - } else { - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("ERROR please init station netif\n"); - return false; - } - - ret = dhcp_start(esp_netif[TCPIP_ADAPTER_IF_STA]); - - if (ret != ERR_OK) { - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("ERROR start dhcp client failed.ret=%d\n", ret); - return false; - } - } - - dhcps_flag = true; - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("dhcp client start\n"); - return true; -} - -bool wifi_station_dhcpc_stop() -{ - wifi_mode_t opmode = WIFI_MODE_NULL; - taskENTER_CRITICAL(); - esp_wifi_get_mode(&opmode); - - if ((opmode == WIFI_MODE_AP) || (opmode == WIFI_MODE_NULL)) { - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("ERROR you shoud enable wifi station mode before stop dhcp client\n"); - return false; - } - - if (dhcpc_flag == true) { - dhcp_stop(esp_netif[TCPIP_ADAPTER_IF_STA]); - } else { - TCPIP_ATAPTER_LOG("WARING dhcp client have not start yet\n"); - } - - dhcpc_flag = false; - taskEXIT_CRITICAL(); - TCPIP_ATAPTER_LOG("stop dhcp client\n"); - return true; -} - -enum dhcp_status wifi_station_dhcpc_status() -{ - return dhcpc_flag; -} - -bool wifi_station_dhcpc_set_maxtry(uint8_t num) -{ - return true; -} - -bool tcpip_adapter_set_macaddr(uint8_t netif_index, uint8_t* macaddr) -{ - if (esp_netif[netif_index] == NULL || macaddr == NULL) { - TCPIP_ATAPTER_LOG("set macaddr fail\n"); - return false; - } - - memcpy(esp_netif[netif_index]->hwaddr, macaddr, 6); - TCPIP_ATAPTER_LOG("set macaddr ok\n"); - return true; -} - -bool tcpip_adapter_get_macaddr(uint8_t netif_index, uint8_t* macaddr) -{ - if (esp_netif[netif_index] == NULL || macaddr == NULL) { - return false; - } - - if (esp_netif[netif_index]->hwaddr[0] == 0 && esp_netif[netif_index]->hwaddr[1] == 0 - && esp_netif[netif_index]->hwaddr[2] == 0 && esp_netif[netif_index]->hwaddr[3] == 0 - && esp_netif[netif_index]->hwaddr[4] == 0 && esp_netif[netif_index]->hwaddr[5] == 0) - return false; - - memcpy(macaddr, esp_netif[netif_index]->hwaddr, 6); - return true; -} - - -bool wifi_station_set_hostname(char* name) -{ - if (name == NULL) { - return false; - } - - uint32_t len = strlen(name); - - if (len > 32) { - return false; - } - - wifi_mode_t opmode; - esp_wifi_get_mode(&opmode); - - if (opmode == WIFI_MODE_STA || opmode == WIFI_MODE_AP) { - default_hostname = 0; - - if (hostname != NULL) { - free(hostname); - hostname = NULL; - } - - hostname = (char*)malloc(len + 1); - - if (hostname != NULL) { - strcpy(hostname, name); - esp_netif[opmode - 1]->hostname = hostname; - } else { - return false; - } - } else { - return false; - } - - return true; -} - -struct netif* eagle_lwip_getif(uint8_t netif_index) -{ - if (TCPIP_ADAPTER_IF_VALID(netif_index)) { - return esp_netif[netif_index]; - } else { - TCPIP_ATAPTER_LOG("ERROR bad netif index:%d\n", netif_index); - return NULL; - } -} From 2caf744a72388a9a4fde1f2cd28383ec9942fdba Mon Sep 17 00:00:00 2001 From: Zhang Jun Hao Date: Tue, 26 Jun 2018 17:16:42 +0800 Subject: [PATCH 3/4] feat(lwip): Refactor dhcpserver APIs --- components/esp8266/include/esp_misc.h | 17 - components/lwip/apps/dhcpserver/dhcpserver.c | 1047 +++++++++-------- .../include/lwip/apps/dhcpserver/dhcpserver.h | 139 +-- .../lwip/apps/dhcpserver/dhcpserver_options.h | 134 +++ 4 files changed, 773 insertions(+), 564 deletions(-) create mode 100644 components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h diff --git a/components/esp8266/include/esp_misc.h b/components/esp8266/include/esp_misc.h index d7625305..990f5617 100644 --- a/components/esp8266/include/esp_misc.h +++ b/components/esp8266/include/esp_misc.h @@ -82,23 +82,6 @@ void os_install_putc1(void (*p)(char c)); */ void os_putc(char c); -enum dhcp_status { - DHCP_STOPPED, /**< disable DHCP */ - DHCP_STARTED /**< enable DHCP */ -}; - -struct dhcps_lease { - bool enable; /**< enable DHCP lease or not */ - struct ip4_addr start_ip; /**< start IP of IP range */ - struct ip4_addr end_ip; /**< end IP of IP range */ -}; - -enum dhcps_offer_option { - OFFER_START = 0x00, /**< DHCP offer option start */ - OFFER_ROUTER = 0x01, /**< DHCP offer router, only support this option now */ - OFFER_END /**< DHCP offer option start */ -}; - /** * @} */ diff --git a/components/lwip/apps/dhcpserver/dhcpserver.c b/components/lwip/apps/dhcpserver/dhcpserver.c index 690f315b..85e9ad20 100644 --- a/components/lwip/apps/dhcpserver/dhcpserver.c +++ b/components/lwip/apps/dhcpserver/dhcpserver.c @@ -27,38 +27,186 @@ #include "lwip/udp.h" #include "lwip/mem.h" #include "dhcpserver/dhcpserver.h" +#include "dhcpserver/dhcpserver_options.h" #include "FreeRTOS.h" -extern struct netif *esp_netif[2]; +#define BOOTP_BROADCAST 0x8000 + +#define DHCP_REQUEST 1 +#define DHCP_REPLY 2 +#define DHCP_HTYPE_ETHERNET 1 +#define DHCP_HLEN_ETHERNET 6 +#define DHCP_MSG_LEN 236 + +#define DHCPS_SERVER_PORT 67 +#define DHCPS_CLIENT_PORT 68 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 + +#define DHCP_OPTION_SUBNET_MASK 1 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_REQ_IPADDR 50 +#define DHCP_OPTION_LEASE_TIME 51 +#define DHCP_OPTION_MSG_TYPE 53 +#define DHCP_OPTION_SERVER_ID 54 +#define DHCP_OPTION_INTERFACE_MTU 26 +#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 +#define DHCP_OPTION_BROADCAST_ADDRESS 28 +#define DHCP_OPTION_REQ_LIST 55 +#define DHCP_OPTION_END 255 + +//#define USE_CLASS_B_NET 1 +#define DHCPS_DEBUG 0 +#define DHCPS_LOG printf + +#define MAX_STATION_NUM CONFIG_LWIP_DHCPS_MAX_STATION_NUM + +#define DHCPS_STATE_OFFER 1 +#define DHCPS_STATE_DECLINE 2 +#define DHCPS_STATE_ACK 3 +#define DHCPS_STATE_NAK 4 +#define DHCPS_STATE_IDLE 5 +#define DHCPS_STATE_RELEASE 6 + +typedef struct _list_node { + void *pnode; + struct _list_node *pnext; +} list_node; //////////////////////////////////////////////////////////////////////////////////// -//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23}; -//static u8_t old_xid[4] = {0}; -static const u32_t magic_cookie = 0x63538263; -static struct udp_pcb* pcb_dhcps = NULL; -static struct ip4_addr server_address; -static struct ip4_addr client_address;//added -static struct ip4_addr client_address_plus; -static struct dhcps_lease dhcps_lease; -//static bool dhcps_lease_flag = true; -static list_node* plist = NULL; -static u8_t offer = 0xFF; +static const u32_t magic_cookie = 0x63538263; + +static struct udp_pcb *pcb_dhcps = NULL; +static ip4_addr_t broadcast_dhcps; +static ip4_addr_t server_address; +static ip4_addr_t dns_server = {0}; +static ip4_addr_t client_address; //added +static ip4_addr_t client_address_plus; + +static list_node *plist = NULL; static bool renew = false; -#define DHCPS_LEASE_TIME_DEF CONFIG_LWIP_DHCPS_LEASE_UNIT -u32_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute + +static dhcps_lease_t dhcps_poll; +static dhcps_time_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute +static dhcps_offer_t dhcps_offer = 0xFF; +static dhcps_offer_t dhcps_dns = 0x00; +static dhcps_cb_t dhcps_cb; + +/****************************************************************************** + * FunctionName : dhcps_option_info + * Description : get the DHCP message option info + * Parameters : op_id -- DHCP message option id + * opt_len -- DHCP message option length + * Returns : DHCP message option addr +*******************************************************************************/ +void *dhcps_option_info(u8_t op_id, u32_t opt_len) +{ + void *option_arg = NULL; + + switch (op_id) { + case IP_ADDRESS_LEASE_TIME: + if (opt_len == sizeof(dhcps_time_t)) { + option_arg = &dhcps_lease_time; + } + + break; + + case REQUESTED_IP_ADDRESS: + if (opt_len == sizeof(dhcps_lease_t)) { + option_arg = &dhcps_poll; + } + + break; + + case ROUTER_SOLICITATION_ADDRESS: + if (opt_len == sizeof(dhcps_offer_t)) { + option_arg = &dhcps_offer; + } + + break; + + case DOMAIN_NAME_SERVER: + if (opt_len == sizeof(dhcps_offer_t)) { + option_arg = &dhcps_dns; + } + + break; + + default: + break; + } + + return option_arg; +} + +/****************************************************************************** + * FunctionName : dhcps_set_option_info + * Description : set the DHCP message option info + * Parameters : op_id -- DHCP message option id + * opt_info -- DHCP message option info + * opt_len -- DHCP message option length + * Returns : none +*******************************************************************************/ +void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len) +{ + if (opt_info == NULL) { + return; + } + switch (op_id) { + case IP_ADDRESS_LEASE_TIME: + if (opt_len == sizeof(dhcps_time_t)) { + dhcps_lease_time = *(dhcps_time_t *)opt_info; + } + + break; + + case REQUESTED_IP_ADDRESS: + if (opt_len == sizeof(dhcps_lease_t)) { + dhcps_poll = *(dhcps_lease_t *)opt_info; + } + + break; + + case ROUTER_SOLICITATION_ADDRESS: + if (opt_len == sizeof(dhcps_offer_t)) { + dhcps_offer = *(dhcps_offer_t *)opt_info; + } + + break; + + case DOMAIN_NAME_SERVER: + if (opt_len == sizeof(dhcps_offer_t)) { + dhcps_dns = *(dhcps_offer_t *)opt_info; + } + break; + + default: + break; + } + return; +} + /****************************************************************************** * FunctionName : node_insert_to_list * Description : insert the node to the list - * Parameters : arg -- Additional argument to pass to the callback function + * Parameters : phead -- the head node of the list + * pinsert -- the insert node of the list * Returns : none *******************************************************************************/ -void node_insert_to_list(list_node** phead, list_node* pinsert) +static void node_insert_to_list(list_node **phead, list_node *pinsert) { - list_node* plist = NULL; - struct dhcps_pool* pdhcps_pool = NULL; - struct dhcps_pool* pdhcps_node = NULL; + list_node *plist = NULL; + struct dhcps_pool *pdhcps_pool = NULL; + struct dhcps_pool *pdhcps_node = NULL; if (*phead == NULL) { *phead = pinsert; @@ -95,12 +243,13 @@ void node_insert_to_list(list_node** phead, list_node* pinsert) /****************************************************************************** * FunctionName : node_delete_from_list * Description : remove the node from list - * Parameters : arg -- Additional argument to pass to the callback function + * Parameters : phead -- the head node of the list + * pdelete -- the remove node of the list * Returns : none *******************************************************************************/ -void node_remove_from_list(list_node** phead, list_node* pdelete) +void node_remove_from_list(list_node **phead, list_node *pdelete) { - list_node* plist = NULL; + list_node *plist = NULL; plist = *phead; @@ -122,38 +271,32 @@ void node_remove_from_list(list_node** phead, list_node* pdelete) } } } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ��DHCP msg��Ϣ�ṹ���������� - * - * @param optptr -- DHCP msg��Ϣλ�� - * @param type -- Ҫ��ӵ�����option - * - * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ - */ -/////////////////////////////////////////////////////////////////////////////////// -static u8_t* add_msg_type(u8_t* optptr, u8_t type) -{ +/****************************************************************************** + * FunctionName : add_msg_type + * Description : add TYPE option of DHCP message + * Parameters : optptr -- the addr of DHCP message option + * Returns : the addr of DHCP message option +*******************************************************************************/ +static u8_t *add_msg_type(u8_t *optptr, u8_t type) +{ *optptr++ = DHCP_OPTION_MSG_TYPE; *optptr++ = 1; *optptr++ = type; return optptr; } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ��DHCP msg�ṹ������offerӦ������ - * - * @param optptr -- DHCP msg��Ϣλ�� - * - * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ - */ -/////////////////////////////////////////////////////////////////////////////////// -static u8_t* add_offer_options(u8_t* optptr) -{ - struct ip4_addr ipadd; - ipadd.addr = *((u32_t*) &server_address); +/****************************************************************************** + * FunctionName : add_offer_options + * Description : add OFFER option of DHCP message + * Parameters : optptr -- the addr of DHCP message option + * Returns : the addr of DHCP message option +*******************************************************************************/ +static u8_t *add_offer_options(u8_t *optptr) +{ + ip4_addr_t ipadd; + + ipadd.addr = *((u32_t *) &server_address); #ifdef USE_CLASS_B_NET *optptr++ = DHCP_OPTION_SUBNET_MASK; @@ -173,10 +316,10 @@ static u8_t* add_offer_options(u8_t* optptr) *optptr++ = DHCP_OPTION_LEASE_TIME; *optptr++ = 4; - *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 24) & 0xFF; - *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 16) & 0xFF; - *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 8) & 0xFF; - *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 0) & 0xFF; + *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 24) & 0xFF; + *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 16) & 0xFF; + *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 8) & 0xFF; + *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 0) & 0xFF; *optptr++ = DHCP_OPTION_SERVER_ID; *optptr++ = 4; @@ -185,27 +328,36 @@ static u8_t* add_offer_options(u8_t* optptr) *optptr++ = ip4_addr3(&ipadd); *optptr++ = ip4_addr4(&ipadd); - if (dhcps_router_enabled(offer)) { + if (dhcps_router_enabled(dhcps_offer)) { tcpip_adapter_ip_info_t if_ip; - bzero(&if_ip, sizeof(tcpip_adapter_ip_info_t)); - wifi_get_ip_info(ESP_IF_WIFI_AP, &if_ip); + //bzero(&if_ip, sizeof(struct ip_info)); + memset(&if_ip , 0x00, sizeof(tcpip_adapter_ip_info_t)); - *optptr++ = DHCP_OPTION_ROUTER; - *optptr++ = 4; - *optptr++ = ip4_addr1(&if_ip.gw); - *optptr++ = ip4_addr2(&if_ip.gw); - *optptr++ = ip4_addr3(&if_ip.gw); - *optptr++ = ip4_addr4(&if_ip.gw); + tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &if_ip); + + if (!ip4_addr_isany_val(if_ip.gw)) { + *optptr++ = DHCP_OPTION_ROUTER; + *optptr++ = 4; + *optptr++ = ip4_addr1(&if_ip.gw); + *optptr++ = ip4_addr2(&if_ip.gw); + *optptr++ = ip4_addr3(&if_ip.gw); + *optptr++ = ip4_addr4(&if_ip.gw); + } } -#ifdef USE_DNS *optptr++ = DHCP_OPTION_DNS_SERVER; *optptr++ = 4; - *optptr++ = ip4_addr1(&ipadd); - *optptr++ = ip4_addr2(&ipadd); - *optptr++ = ip4_addr3(&ipadd); - *optptr++ = ip4_addr4(&ipadd); -#endif + if (dhcps_dns_enabled(dhcps_dns)) { + *optptr++ = ip4_addr1(&dns_server); + *optptr++ = ip4_addr2(&dns_server); + *optptr++ = ip4_addr3(&dns_server); + *optptr++ = ip4_addr4(&dns_server); + }else { + *optptr++ = ip4_addr1(&ipadd); + *optptr++ = ip4_addr2(&ipadd); + *optptr++ = ip4_addr3(&ipadd); + *optptr++ = ip4_addr4(&ipadd); + } #ifdef CLASS_B_NET *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; @@ -225,13 +377,8 @@ static u8_t* add_offer_options(u8_t* optptr) *optptr++ = DHCP_OPTION_INTERFACE_MTU; *optptr++ = 2; -#ifdef CLASS_B_NET *optptr++ = 0x05; *optptr++ = 0xdc; -#else - *optptr++ = 0x02; - *optptr++ = 0x40; -#endif *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY; *optptr++ = 1; @@ -249,62 +396,87 @@ static u8_t* add_offer_options(u8_t* optptr) return optptr; } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ��DHCP msg�ṹ����ӽ����־���� - * - * @param optptr -- DHCP msg��Ϣλ�� - * - * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ - */ -/////////////////////////////////////////////////////////////////////////////////// -static u8_t* add_end(u8_t* optptr) -{ +/****************************************************************************** + * FunctionName : add_end + * Description : add end option of DHCP message + * Parameters : optptr -- the addr of DHCP message option + * Returns : the addr of DHCP message option +*******************************************************************************/ +static u8_t *add_end(u8_t *optptr) +{ *optptr++ = DHCP_OPTION_END; return optptr; } -/////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////// -static void create_msg(struct dhcps_msg* m) -{ - struct ip4_addr client; - client.addr = *((uint32_t*) &client_address); +/****************************************************************************** + * FunctionName : create_msg + * Description : create response message + * Parameters : m -- DHCP message info + * Returns : none +*******************************************************************************/ +static void create_msg(struct dhcps_msg *m) +{ + ip4_addr_t client; + + + client.addr = *((uint32_t *) &client_address); m->op = DHCP_REPLY; + m->htype = DHCP_HTYPE_ETHERNET; + m->hlen = 6; + m->hops = 0; // os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid)); m->secs = 0; m->flags = htons(BOOTP_BROADCAST); - memcpy((char*) m->yiaddr, (char*) &client.addr, sizeof(m->yiaddr)); + memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr)); - memset((char*) m->ciaddr, 0, sizeof(m->ciaddr)); - memset((char*) m->siaddr, 0, sizeof(m->siaddr)); - memset((char*) m->giaddr, 0, sizeof(m->giaddr)); - memset((char*) m->sname, 0, sizeof(m->sname)); - memset((char*) m->file, 0, sizeof(m->file)); + memset((char *) m->ciaddr, 0, sizeof(m->ciaddr)); - memset((char*) m->options, 0, sizeof(m->options)); + memset((char *) m->siaddr, 0, sizeof(m->siaddr)); - u32_t magic_cookie1 = magic_cookie; - memcpy((char*) m->options, &magic_cookie1, sizeof(magic_cookie1)); + memset((char *) m->giaddr, 0, sizeof(m->giaddr)); + + memset((char *) m->sname, 0, sizeof(m->sname)); + + memset((char *) m->file, 0, sizeof(m->file)); + + memset((char *) m->options, 0, sizeof(m->options)); + + u32_t magic_cookie_temp = magic_cookie; + + memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp)); } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ����һ��OFFER - * - * @param -- m ָ����Ҫ���͵�DHCP msg���� - */ -/////////////////////////////////////////////////////////////////////////////////// -static void send_offer(struct dhcps_msg* m) + +struct pbuf * dhcps_pbuf_alloc(u16_t len) { - u8_t* end; - struct pbuf* p, *q; - u8_t* data; + u16_t mlen = sizeof(struct dhcps_msg); + + if (len > mlen) { +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: len=%d mlen=%d", len, mlen); +#endif + mlen = len; + } + + return pbuf_alloc(PBUF_TRANSPORT, mlen, PBUF_RAM); +} + +/****************************************************************************** + * FunctionName : send_offer + * Description : DHCP message OFFER Response + * Parameters : m -- DHCP message info + * Returns : none +*******************************************************************************/ +static void send_offer(struct dhcps_msg *m, u16_t len) +{ + u8_t *end; + struct pbuf *p, *q; + u8_t *data; u16_t cnt = 0; u16_t i; #if DHCPS_DEBUG @@ -316,30 +488,30 @@ static void send_offer(struct dhcps_msg* m) end = add_offer_options(end); end = add_end(end); - p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM); + p = dhcps_pbuf_alloc(len); #if DHCPS_DEBUG - printf("udhcp: send_offer>>p->ref = %d\n", p->ref); + DHCPS_LOG("udhcp: send_offer>>p->ref = %d\n", p->ref); #endif if (p != NULL) { #if DHCPS_DEBUG - printf("dhcps: send_offer>>pbuf_alloc succeed\n"); - printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len); - printf("dhcps: send_offer>>p->len = %d\n", p->len); + DHCPS_LOG("dhcps: send_offer>>pbuf_alloc succeed\n"); + DHCPS_LOG("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len); + DHCPS_LOG("dhcps: send_offer>>p->len = %d\n", p->len); #endif q = p; while (q != NULL) { - data = (u8_t*)q->payload; + data = (u8_t *)q->payload; for (i = 0; i < q->len; i++) { - data[i] = ((u8_t*) m)[cnt++]; + data[i] = ((u8_t *) m)[cnt++]; #if DHCPS_DEBUG - printf("%02x ", data[i]); + DHCPS_LOG("%02x ", data[i]); if ((i + 1) % 16 == 0) { - printf("\n"); + DHCPS_LOG("\n"); } #endif @@ -350,38 +522,37 @@ static void send_offer(struct dhcps_msg* m) } else { #if DHCPS_DEBUG - printf("dhcps: send_offer>>pbuf_alloc failed\n"); + DHCPS_LOG("dhcps: send_offer>>pbuf_alloc failed\n"); #endif return; } #if DHCPS_DEBUG SendOffer_err_t = udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); - printf("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t); + DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t); #else udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); #endif if (p->ref != 0) { #if DHCPS_DEBUG - printf("udhcp: send_offer>>free pbuf\n"); + DHCPS_LOG("udhcp: send_offer>>free pbuf\n"); #endif pbuf_free(p); } } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ����һ��NAK��Ϣ - * - * @param m ָ����Ҫ���͵�DHCP msg���� - */ -/////////////////////////////////////////////////////////////////////////////////// -static void send_nak(struct dhcps_msg* m) -{ - u8_t* end; - struct pbuf* p, *q; - u8_t* data; +/****************************************************************************** + * FunctionName : send_nak + * Description : DHCP message NACK Response + * Parameters : m -- DHCP message info + * Returns : none +*******************************************************************************/ +static void send_nak(struct dhcps_msg *m, u16_t len) +{ + u8_t *end; + struct pbuf *p, *q; + u8_t *data; u16_t cnt = 0; u16_t i; #if DHCPS_DEBUG @@ -392,30 +563,30 @@ static void send_nak(struct dhcps_msg* m) end = add_msg_type(&m->options[4], DHCPNAK); end = add_end(end); - p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM); + p = dhcps_pbuf_alloc(len); #if DHCPS_DEBUG - printf("udhcp: send_nak>>p->ref = %d\n", p->ref); + DHCPS_LOG("udhcp: send_nak>>p->ref = %d\n", p->ref); #endif if (p != NULL) { #if DHCPS_DEBUG - printf("dhcps: send_nak>>pbuf_alloc succeed\n"); - printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len); - printf("dhcps: send_nak>>p->len = %d\n", p->len); + DHCPS_LOG("dhcps: send_nak>>pbuf_alloc succeed\n"); + DHCPS_LOG("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len); + DHCPS_LOG("dhcps: send_nak>>p->len = %d\n", p->len); #endif q = p; while (q != NULL) { - data = (u8_t*)q->payload; + data = (u8_t *)q->payload; for (i = 0; i < q->len; i++) { - data[i] = ((u8_t*) m)[cnt++]; + data[i] = ((u8_t *) m)[cnt++]; #if DHCPS_DEBUG - printf("%02x ", data[i]); + DHCPS_LOG("%02x ", data[i]); if ((i + 1) % 16 == 0) { - printf("\n"); + DHCPS_LOG("\n"); } #endif @@ -426,73 +597,70 @@ static void send_nak(struct dhcps_msg* m) } else { #if DHCPS_DEBUG - printf("dhcps: send_nak>>pbuf_alloc failed\n"); + DHCPS_LOG("dhcps: send_nak>>pbuf_alloc failed\n"); #endif return; } #if DHCPS_DEBUG SendNak_err_t = udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); - printf("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t); + DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t); #else udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); #endif if (p->ref != 0) { #if DHCPS_DEBUG - printf("udhcp: send_nak>>free pbuf\n"); + DHCPS_LOG("udhcp: send_nak>>free pbuf\n"); #endif pbuf_free(p); } } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ����һ��ACK��DHCP�ͻ��� - * - * @param m ָ����Ҫ���͵�DHCP msg���� - */ -/////////////////////////////////////////////////////////////////////////////////// -static void send_ack(struct dhcps_msg* m) -{ - u8_t* end; - struct pbuf* p, *q; - u8_t* data; +/****************************************************************************** + * FunctionName : send_ack + * Description : DHCP message ACK Response + * Parameters : m -- DHCP message info + * Returns : none +*******************************************************************************/ +static void send_ack(struct dhcps_msg *m, u16_t len) +{ + u8_t *end; + struct pbuf *p, *q; + u8_t *data; u16_t cnt = 0; u16_t i; -#if DHCPS_DEBUG err_t SendAck_err_t; -#endif create_msg(m); end = add_msg_type(&m->options[4], DHCPACK); end = add_offer_options(end); end = add_end(end); - p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM); + p = dhcps_pbuf_alloc(len); #if DHCPS_DEBUG - printf("udhcp: send_ack>>p->ref = %d\n", p->ref); + DHCPS_LOG("udhcp: send_ack>>p->ref = %d\n", p->ref); #endif if (p != NULL) { #if DHCPS_DEBUG - printf("dhcps: send_ack>>pbuf_alloc succeed\n"); - printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len); - printf("dhcps: send_ack>>p->len = %d\n", p->len); + DHCPS_LOG("dhcps: send_ack>>pbuf_alloc succeed\n"); + DHCPS_LOG("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len); + DHCPS_LOG("dhcps: send_ack>>p->len = %d\n", p->len); #endif q = p; while (q != NULL) { - data = (u8_t*)q->payload; + data = (u8_t *)q->payload; for (i = 0; i < q->len; i++) { - data[i] = ((u8_t*) m)[cnt++]; + data[i] = ((u8_t *) m)[cnt++]; #if DHCPS_DEBUG - printf("%02x ", data[i]); + DHCPS_LOG("%02x ", data[i]); if ((i + 1) % 16 == 0) { - printf("\n"); + DHCPS_LOG("\n"); } #endif @@ -503,51 +671,52 @@ static void send_ack(struct dhcps_msg* m) } else { #if DHCPS_DEBUG - printf("dhcps: send_ack>>pbuf_alloc failed\n"); + DHCPS_LOG("dhcps: send_ack>>pbuf_alloc failed\n"); #endif return; } -#if DHCPS_DEBUG SendAck_err_t = udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); - printf("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t); -#else + DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t); +#if DHCPS_DEBUG udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); #endif + if (SendAck_err_t == ERR_OK) { + dhcps_cb(m->yiaddr); + } + if (p->ref != 0) { #if DHCPS_DEBUG - printf("udhcp: send_ack>>free pbuf\n"); + DHCPS_LOG("udhcp: send_ack>>free pbuf\n"); #endif pbuf_free(p); } } -/////////////////////////////////////////////////////////////////////////////////// -/* - * ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ�� - * - * @param optptr DHCP msg�е��������� - * @param len ��������Ĵ��?(byte) - * - * @return uint8_t ���ش�����DHCP Server״ֵ̬ - */ -/////////////////////////////////////////////////////////////////////////////////// -static u8_t parse_options(u8_t* optptr, s16_t len) + +/****************************************************************************** + * FunctionName : parse_options + * Description : parse DHCP message options + * Parameters : optptr -- DHCP message option info + * len -- DHCP message option length + * Returns : none +*******************************************************************************/ +static u8_t parse_options(u8_t *optptr, s16_t len) { - struct ip4_addr client; + ip4_addr_t client; bool is_dhcp_parse_end = false; struct dhcps_state s; - client.addr = *((uint32_t*) &client_address); // Ҫ�����DHCP�ͻ��˵�IP + client.addr = *((uint32_t *) &client_address); - u8_t* end = optptr + len; + u8_t *end = optptr + len; u16_t type = 0; s.state = DHCPS_STATE_IDLE; while (optptr < end) { #if DHCPS_DEBUG - printf("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr); + DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr); #endif switch ((s16_t) *optptr) { @@ -557,14 +726,14 @@ static u8_t parse_options(u8_t* optptr, s16_t len) break; case DHCP_OPTION_REQ_IPADDR://50 - if (memcmp((char*) &client.addr, (char*) optptr + 2, 4) == 0) { + if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) { #if DHCPS_DEBUG - printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n"); + DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n"); #endif s.state = DHCPS_STATE_ACK; } else { #if DHCPS_DEBUG - printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n"); + DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n"); #endif s.state = DHCPS_STATE_NAK; } @@ -589,7 +758,7 @@ static u8_t parse_options(u8_t* optptr, s16_t len) case DHCPDISCOVER://1 s.state = DHCPS_STATE_OFFER; #if DHCPS_DEBUG - printf("dhcps: DHCPD_STATE_OFFER\n"); + DHCPS_LOG("dhcps: DHCPD_STATE_OFFER\n"); #endif break; @@ -602,7 +771,7 @@ static u8_t parse_options(u8_t* optptr, s16_t len) } #if DHCPS_DEBUG - printf("dhcps: DHCPD_STATE_NAK\n"); + DHCPS_LOG("dhcps: DHCPD_STATE_NAK\n"); #endif } @@ -611,83 +780,56 @@ static u8_t parse_options(u8_t* optptr, s16_t len) case DHCPDECLINE://4 s.state = DHCPS_STATE_IDLE; #if DHCPS_DEBUG - printf("dhcps: DHCPD_STATE_IDLE\n"); + DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n"); #endif break; case DHCPRELEASE://7 s.state = DHCPS_STATE_RELEASE; #if DHCPS_DEBUG - printf("dhcps: DHCPD_STATE_IDLE\n"); + DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n"); #endif break; } #if DHCPS_DEBUG - printf("dhcps: return s.state = %d\n", s.state); + DHCPS_LOG("dhcps: return s.state = %d\n", s.state); #endif return s.state; } -/////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////// -static s16_t parse_msg(struct dhcps_msg* m, u16_t len) + +/****************************************************************************** + * FunctionName : parse_msg + * Description : parse DHCP message from netif + * Parameters : m -- DHCP message info + * len -- DHCP message length + * Returns : DHCP message type +*******************************************************************************/ +static s16_t parse_msg(struct dhcps_msg *m, u16_t len) { - u32_t lease_timer = (dhcps_lease_time * 60) / DHCPS_COARSE_TIMER_SECS; + u32_t lease_timer = (dhcps_lease_time * DHCPS_LEASE_UNIT)/DHCPS_COARSE_TIMER_SECS; - if (memcmp((char*)m->options, - &magic_cookie, - sizeof(magic_cookie)) == 0) { + if (memcmp((char *)m->options, &magic_cookie, sizeof(magic_cookie)) == 0) { #if DHCPS_DEBUG - printf("dhcps: len = %d\n", len); + DHCPS_LOG("dhcps: len = %d\n", len); #endif - /* - * ��¼��ǰ��xid���ﴦ���? - * �˺�ΪDHCP�ͻ����������û�ͳһ��ȡIPʱ�� - */ -// if((old_xid[0] == 0) && -// (old_xid[1] == 0) && -// (old_xid[2] == 0) && -// (old_xid[3] == 0)){ -// /* -// * old_xidδ��¼�κ����? -// * �϶��ǵ�һ��ʹ�� -// */ -// memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid)); -// }else{ -// /* -// * ���δ����DHCP msg��Я���xid���ϴμ�¼�IJ�ͬ�� -// * �϶�Ϊ��ͬ��DHCP�ͻ��˷��ͣ���ʱ����Ҫ����Ŀͻ���IP -// * ���� 192.168.4.100(0x6404A8C0) <--> 192.168.4.200(0xC804A8C0) -// * -// */ -// if(memcmp((char *)old_xid, (char *)m->xid, sizeof(m->xid)) != 0){ - /* - * ��¼���ε�xid�ţ�ͬʱ�����IP���� - */ - struct ip4_addr addr_tmp; -// memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid)); + ip4_addr_t addr_tmp; -// { - struct dhcps_pool* pdhcps_pool = NULL; - list_node* pnode = NULL; - list_node* pback_node = NULL; - struct ip4_addr first_address; + struct dhcps_pool *pdhcps_pool = NULL; + list_node *pnode = NULL; + list_node *pback_node = NULL; + ip4_addr_t first_address; bool flag = false; -// POOL_START: - first_address.addr = dhcps_lease.start_ip.addr; + first_address.addr = dhcps_poll.start_ip.addr; client_address.addr = client_address_plus.addr; renew = false; -// addr_tmp.addr = htonl(client_address_plus.addr); -// addr_tmp.addr++; -// client_address_plus.addr = htonl(addr_tmp.addr); if (plist != NULL) { for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) { pdhcps_pool = pback_node->pnode; if (memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0) { -// printf("the same device request ip\n"); if (memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) { renew = true; } @@ -697,8 +839,6 @@ static s16_t parse_msg(struct dhcps_msg* m, u16_t len) pnode = pback_node; goto POOL_CHECK; } else if (pdhcps_pool->ip.addr == client_address_plus.addr) { -// client_address.addr = client_address_plus.addr; -// printf("the ip addr has been request\n"); addr_tmp.addr = htonl(client_address_plus.addr); addr_tmp.addr++; client_address_plus.addr = htonl(addr_tmp.addr); @@ -716,29 +856,33 @@ static s16_t parse_msg(struct dhcps_msg* m, u16_t len) } } } else { - client_address.addr = dhcps_lease.start_ip.addr; + client_address.addr = dhcps_poll.start_ip.addr; } - if (client_address_plus.addr > dhcps_lease.end_ip.addr) { + if (client_address_plus.addr > dhcps_poll.end_ip.addr) { client_address.addr = first_address.addr; } - if (client_address.addr > dhcps_lease.end_ip.addr) { - client_address_plus.addr = dhcps_lease.start_ip.addr; + if (client_address.addr > dhcps_poll.end_ip.addr) { + client_address_plus.addr = dhcps_poll.start_ip.addr; pdhcps_pool = NULL; pnode = NULL; } else { - pdhcps_pool = (struct dhcps_pool*)os_zalloc(sizeof(struct dhcps_pool)); + pdhcps_pool = (struct dhcps_pool *)mem_malloc(sizeof(struct dhcps_pool)); + memset(pdhcps_pool , 0x00 , sizeof(struct dhcps_pool)); + pdhcps_pool->ip.addr = client_address.addr; memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)); pdhcps_pool->lease_timer = lease_timer; - pnode = (list_node*)os_zalloc(sizeof(list_node)); + pnode = (list_node *)mem_malloc(sizeof(list_node)); + memset(pnode , 0x00 , sizeof(list_node)); + pnode->pnode = pdhcps_pool; pnode->pnext = NULL; node_insert_to_list(&plist, pnode); - if (client_address.addr == dhcps_lease.end_ip.addr) { - client_address_plus.addr = dhcps_lease.start_ip.addr; + if (client_address.addr == dhcps_poll.end_ip.addr) { + client_address_plus.addr = dhcps_poll.start_ip.addr; } else { addr_tmp.addr = htonl(client_address.addr); addr_tmp.addr++; @@ -748,7 +892,7 @@ static s16_t parse_msg(struct dhcps_msg* m, u16_t len) POOL_CHECK: - if ((client_address.addr > dhcps_lease.end_ip.addr) || (ip4_addr_isany(&client_address))) { + if ((client_address.addr > dhcps_poll.end_ip.addr) || (ip4_addr_isany(&client_address))) { if (pnode != NULL) { node_remove_from_list(&plist, pnode); os_free(pnode); @@ -760,7 +904,6 @@ POOL_CHECK: pdhcps_pool = NULL; } -// client_address_plus.addr = dhcps_lease.start_ip.addr; return 4; } @@ -780,82 +923,79 @@ POOL_CHECK: memset(&client_address, 0x0, sizeof(client_address)); } - extern bool wifi_softap_set_station_info(uint8_t*,ip4_addr_t*); - if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) { - return 0; - } - -// } #if DHCPS_DEBUG - printf("dhcps: xid changed\n"); - printf("dhcps: client_address.addr = %x\n", client_address.addr); + DHCPS_LOG("dhcps: xid changed\n"); + DHCPS_LOG("dhcps: client_address.addr = %x\n", client_address.addr); #endif - -// } - -// } return ret; } return 0; } -/////////////////////////////////////////////////////////////////////////////////// -/* - * DHCP ��������ݰ���մ���ص�����˺�����LWIP UDPģ������ʱ������ - * ��Ҫ����udp_recv()������LWIP����ע��. - * - * @param arg - * @param pcb ���յ�UDP��Ŀ��ƿ�? - * @param p ���յ���UDP�е��������? - * @param addr ���ʹ�UDP���Դ�����IP��ַ - * @param port ���ʹ�UDP���Դ�����UDPͨ���˿ں� - */ -/////////////////////////////////////////////////////////////////////////////////// -static void handle_dhcp(void* arg, - struct udp_pcb* pcb, - struct pbuf* p, - const ip_addr_t* addr, + +/****************************************************************************** + * FunctionName : handle_dhcp + * Description : If an incoming DHCP message is in response to us, then trigger the state machine + * Parameters : arg -- arg user supplied argument (udp_pcb.recv_arg) + * pcb -- the udp_pcb which received data + * p -- the packet buffer that was received + * addr -- the remote IP address from which the packet was received + * port -- the remote port from which the packet was received + * Returns : none +*******************************************************************************/ +static void handle_dhcp(void *arg, + struct udp_pcb *pcb, + struct pbuf *p, + const ip_addr_t *addr, u16_t port) { - struct dhcps_msg* pmsg_dhcps = NULL; - s16_t tlen; + struct dhcps_msg *pmsg_dhcps = NULL; + s16_t tlen, malloc_len; u16_t i; u16_t dhcps_msg_cnt = 0; - u8_t* p_dhcps_msg = NULL; - u8_t* data; + u8_t *p_dhcps_msg = NULL; + u8_t *data; #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> receive a packet\n"); + DHCPS_LOG("dhcps: handle_dhcp-> receive a packet\n"); #endif if (p == NULL) { return; } - pmsg_dhcps = (struct dhcps_msg*)os_zalloc(sizeof(struct dhcps_msg)); + malloc_len = sizeof(struct dhcps_msg); +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp malloc_len=%d rx_len=%d", malloc_len, p->tot_len); +#endif + if (malloc_len < p->tot_len) { + malloc_len = p->tot_len; + } + pmsg_dhcps = (struct dhcps_msg *)mem_malloc(malloc_len); if (NULL == pmsg_dhcps) { pbuf_free(p); return; } - p_dhcps_msg = (u8_t*)pmsg_dhcps; + memset(pmsg_dhcps , 0x00 , malloc_len); + p_dhcps_msg = (u8_t *)pmsg_dhcps; tlen = p->tot_len; data = p->payload; #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen); - printf("dhcps: handle_dhcp-> p->len = %d\n", p->len); + DHCPS_LOG("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen); + DHCPS_LOG("dhcps: handle_dhcp-> p->len = %d\n", p->len); #endif for (i = 0; i < p->len; i++) { p_dhcps_msg[dhcps_msg_cnt++] = data[i]; #if DHCPS_DEBUG - printf("%02x ", data[i]); + DHCPS_LOG("%02x ", data[i]); if ((i + 1) % 16 == 0) { - printf("\n"); + DHCPS_LOG("\n"); } #endif @@ -863,9 +1003,9 @@ static void handle_dhcp(void* arg, if (p->next != NULL) { #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> p->next != NULL\n"); - printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n", p->next->tot_len); - printf("dhcps: handle_dhcp-> p->next->len = %d\n", p->next->len); + DHCPS_LOG("dhcps: handle_dhcp-> p->next != NULL\n"); + DHCPS_LOG("dhcps: handle_dhcp-> p->next->tot_len = %d\n", p->next->tot_len); + DHCPS_LOG("dhcps: handle_dhcp-> p->next->len = %d\n", p->next->len); #endif data = p->next->payload; @@ -873,44 +1013,40 @@ static void handle_dhcp(void* arg, for (i = 0; i < p->next->len; i++) { p_dhcps_msg[dhcps_msg_cnt++] = data[i]; #if DHCPS_DEBUG - printf("%02x ", data[i]); + DHCPS_LOG("%02x ", data[i]); if ((i + 1) % 16 == 0) { - printf("\n"); + DHCPS_LOG("\n"); } #endif } } - /* - * DHCP �ͻ���������Ϣ���� - */ #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> parse_msg(p)\n"); + DHCPS_LOG("dhcps: handle_dhcp-> parse_msg(p)\n"); #endif switch (parse_msg(pmsg_dhcps, tlen - 240)) { - case DHCPS_STATE_OFFER://1 #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n"); + DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n"); #endif - send_offer(pmsg_dhcps); + send_offer(pmsg_dhcps, malloc_len); break; case DHCPS_STATE_ACK://3 #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n"); + DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n"); #endif - send_ack(pmsg_dhcps); + send_ack(pmsg_dhcps, malloc_len); break; case DHCPS_STATE_NAK://4 #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n"); + DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n"); #endif - send_nak(pmsg_dhcps); + send_nak(pmsg_dhcps, malloc_len); break; default : @@ -918,39 +1054,45 @@ static void handle_dhcp(void* arg, } #if DHCPS_DEBUG - printf("dhcps: handle_dhcp-> pbuf_free(p)\n"); + DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n"); #endif pbuf_free(p); os_free(pmsg_dhcps); pmsg_dhcps = NULL; } -/////////////////////////////////////////////////////////////////////////////////// -static void wifi_softap_init_dhcps_lease(u32_t ip) + +/****************************************************************************** + * FunctionName : dhcps_poll_set + * Description : set ip poll from start to end for station + * Parameters : ip -- The current ip addr + * Returns : none +*******************************************************************************/ +static void dhcps_poll_set(u32_t ip) { u32_t softap_ip = 0, local_ip = 0; u32_t start_ip = 0; u32_t end_ip = 0; - if (dhcps_lease.enable == true) { + if (dhcps_poll.enable == true) { softap_ip = htonl(ip); - start_ip = htonl(dhcps_lease.start_ip.addr); - end_ip = htonl(dhcps_lease.end_ip.addr); + start_ip = htonl(dhcps_poll.start_ip.addr); + end_ip = htonl(dhcps_poll.end_ip.addr); /*config ip information can't contain local ip*/ if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { - dhcps_lease.enable = false; + dhcps_poll.enable = false; } else { /*config ip information must be in the same segment as the local ip*/ softap_ip >>= 8; if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip)) || (end_ip - start_ip > DHCPS_MAX_LEASE)) { - dhcps_lease.enable = false; + dhcps_poll.enable = false; } } } - if (dhcps_lease.enable == false) { + if (dhcps_poll.enable == false) { local_ip = softap_ip = htonl(ip); softap_ip &= 0xFFFFFF00; local_ip &= 0xFF; @@ -961,17 +1103,36 @@ static void wifi_softap_init_dhcps_lease(u32_t ip) local_ip ++; } - bzero(&dhcps_lease, sizeof(dhcps_lease)); - dhcps_lease.start_ip.addr = softap_ip | local_ip; - dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1); - dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr); - dhcps_lease.end_ip.addr = htonl(dhcps_lease.end_ip.addr); + bzero(&dhcps_poll, sizeof(dhcps_poll)); + dhcps_poll.start_ip.addr = softap_ip | local_ip; + dhcps_poll.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1); + dhcps_poll.start_ip.addr = htonl(dhcps_poll.start_ip.addr); + dhcps_poll.end_ip.addr = htonl(dhcps_poll.end_ip.addr); } -// printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip); } -/////////////////////////////////////////////////////////////////////////////////// -void dhcps_start(tcpip_adapter_ip_info_t* info) + + +/****************************************************************************** + * FunctionName : dhcps_set_new_lease_cb + * Description : set callback for dhcp server when it assign an IP + * to the connected dhcp client + * Parameters : cb -- callback for dhcp server + * Returns : none +*******************************************************************************/ +void dhcps_set_new_lease_cb(dhcps_cb_t cb) +{ + dhcps_cb = cb; +} + +/****************************************************************************** + * FunctionName : dhcps_start + * Description : start dhcp server function + * Parameters : netif -- The current netif addr + * : info -- The current ip info + * Returns : none +*******************************************************************************/ +void dhcps_start(struct netif *netif, ip4_addr_t ip) { if (pcb_dhcps != NULL) { udp_remove(pcb_dhcps); @@ -979,34 +1140,48 @@ void dhcps_start(tcpip_adapter_ip_info_t* info) pcb_dhcps = udp_new(); - if (pcb_dhcps == NULL || info == NULL) { + if (pcb_dhcps == NULL || ip4_addr_isany_val(ip)) { printf("dhcps_start(): could not obtain pcb\n"); } - server_address = info->ip; - wifi_softap_init_dhcps_lease(server_address.addr); - client_address_plus.addr = dhcps_lease.start_ip.addr; - udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT); + IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255); + + server_address.addr = ip.addr; + dhcps_poll_set(server_address.addr); + + client_address_plus.addr = dhcps_poll.start_ip.addr; + + udp_bind(pcb_dhcps, &netif->ip_addr, DHCPS_SERVER_PORT); udp_recv(pcb_dhcps, handle_dhcp, NULL); #if DHCPS_DEBUG - printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n"); + DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n"); #endif } -void dhcps_stop(void) +/****************************************************************************** + * FunctionName : dhcps_stop + * Description : stop dhcp server function + * Parameters : netif -- The current netif addr + * Returns : none +*******************************************************************************/ +void dhcps_stop(struct netif *netif) { + struct netif *apnetif = netif; - udp_disconnect(pcb_dhcps); + if (apnetif == NULL) { + printf("dhcps_stop: apnetif == NULL\n"); + return; + } if (pcb_dhcps != NULL) { + udp_disconnect(pcb_dhcps); udp_remove(pcb_dhcps); pcb_dhcps = NULL; } - //udp_remove(pcb_dhcps); - list_node* pnode = NULL; - list_node* pback_node = NULL; + list_node *pnode = NULL; + list_node *pback_node = NULL; pnode = plist; while (pnode != NULL) { @@ -1020,97 +1195,17 @@ void dhcps_stop(void) } } -bool wifi_softap_set_dhcps_lease(struct dhcps_lease* please) -{ - tcpip_adapter_ip_info_t info; - u32_t softap_ip = 0; - u32_t start_ip = 0; - u32_t end_ip = 0; - - wifi_mode_t opmode; - esp_wifi_get_mode(&opmode); - - if (opmode == WIFI_MODE_STA || opmode == WIFI_MODE_NULL) { - return false; - } - - if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED) { - return false; - } - - if (please->enable) { - bzero(&info, sizeof(tcpip_adapter_ip_info_t)); - wifi_get_ip_info(ESP_IF_WIFI_AP, &info); - softap_ip = htonl(info.ip.addr); - start_ip = htonl(please->start_ip.addr); - end_ip = htonl(please->end_ip.addr); - - /*config ip information can't contain local ip*/ - if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { - return false; - } - - /*config ip information must be in the same segment as the local ip*/ - softap_ip >>= 8; - - if ((start_ip >> 8 != softap_ip) - || (end_ip >> 8 != softap_ip)) { - return false; - } - - if (end_ip - start_ip > DHCPS_MAX_LEASE) { - return false; - } - - bzero(&dhcps_lease, sizeof(dhcps_lease)); -// dhcps_lease.start_ip.addr = start_ip; -// dhcps_lease.end_ip.addr = end_ip; - dhcps_lease.start_ip.addr = please->start_ip.addr; - dhcps_lease.end_ip.addr = please->end_ip.addr; - } - - dhcps_lease.enable = please->enable; -// dhcps_lease_flag = false; - return true; -} - /****************************************************************************** - * FunctionName : wifi_softap_get_dhcps_lease - * Description : get the lease information of DHCP server - * Parameters : please -- Additional argument to get the lease information, - * Little-Endian. - * Returns : true or false + * FunctionName : kill_oldest_dhcps_pool + * Description : remove the oldest node from list + * Parameters : none + * Returns : none *******************************************************************************/ -bool wifi_softap_get_dhcps_lease(struct dhcps_lease* please) -{ - wifi_mode_t opmode; - esp_wifi_get_mode(&opmode); - - if (opmode == WIFI_MODE_STA || opmode == WIFI_MODE_NULL) { - return false; - } - - if (NULL == please) { - return false; - } - - if (dhcps_lease.enable == false) { - if (wifi_softap_dhcps_status() == DHCP_STOPPED) { - return false; - } - } else { - } - - please->start_ip.addr = dhcps_lease.start_ip.addr; - please->end_ip.addr = dhcps_lease.end_ip.addr; - return true; -} - static void kill_oldest_dhcps_pool(void) { - list_node* pre = NULL, *p = NULL; - list_node* minpre = NULL, *minp = NULL; - struct dhcps_pool* pdhcps_pool = NULL, *pmin_pool = NULL; + list_node *pre = NULL, *p = NULL; + list_node *minpre = NULL, *minp = NULL; + struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL; pre = plist; p = pre->pnext; minpre = pre; @@ -1136,12 +1231,18 @@ static void kill_oldest_dhcps_pool(void) minp = NULL; } +/****************************************************************************** + * FunctionName : dhcps_coarse_tmr + * Description : the lease time count + * Parameters : none + * Returns : none +*******************************************************************************/ void dhcps_coarse_tmr(void) { u8_t num_dhcps_pool = 0; - list_node* pback_node = NULL; - list_node* pnode = NULL; - struct dhcps_pool* pdhcps_pool = NULL; + list_node *pback_node = NULL; + list_node *pnode = NULL; + struct dhcps_pool *pdhcps_pool = NULL; pnode = plist; while (pnode != NULL) { @@ -1162,76 +1263,62 @@ void dhcps_coarse_tmr(void) } } - if (num_dhcps_pool >= MAX_STATION_NUM) { + if (num_dhcps_pool > MAX_STATION_NUM) { kill_oldest_dhcps_pool(); } } -bool wifi_softap_set_dhcps_offer_option(u8_t level, void* optarg) +/****************************************************************************** + * FunctionName : dhcp_search_ip_on_mac + * Description : Search ip address based on mac address + * Parameters : mac -- The MAC addr + * ip -- The IP info + * Returns : true or false +*******************************************************************************/ +bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip) { - bool offer_flag = true; + struct dhcps_pool *pdhcps_pool = NULL; + list_node *pback_node = NULL; + bool ret = false; - if (optarg == NULL && wifi_softap_dhcps_status() == false) { - return false; - } + for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) { + pdhcps_pool = pback_node->pnode; - if (level <= OFFER_START || level >= OFFER_END) { - return false; - } - - switch (level) { - case OFFER_ROUTER: - offer = (*(u8_t*)optarg) & 0x01; - offer_flag = true; - break; - - default : - offer_flag = false; + if (memcmp(pdhcps_pool->mac, mac, sizeof(pdhcps_pool->mac)) == 0) { + memcpy(&ip->addr, &pdhcps_pool->ip.addr, sizeof(pdhcps_pool->ip.addr)); + ret = true; break; + } } - return offer_flag; + return ret; } -bool wifi_softap_set_dhcps_lease_time(u32_t minute) +/****************************************************************************** + * FunctionName : dhcps_dns_setserver + * Description : set DNS server address for dhcpserver + * Parameters : dnsserver -- The DNS server address + * Returns : none +*******************************************************************************/ +void +dhcps_dns_setserver(const ip_addr_t *dnsserver) { - wifi_mode_t opmode; - esp_wifi_get_mode(&opmode); - - if (opmode == WIFI_MODE_STA || opmode == WIFI_MODE_NULL) { - return false; - } - - if (wifi_softap_dhcps_status() == DHCP_STARTED) { - return false; - } - - if (minute == 0) { - return false; - } - - dhcps_lease_time = minute; - return true; + if (dnsserver != NULL) { + dns_server = *(ip_2_ip4(dnsserver)); + } else { + dns_server = *(ip_2_ip4(IP_ADDR_ANY)); + } } -bool wifi_softap_reset_dhcps_lease_time(void) +/****************************************************************************** + * FunctionName : dhcps_dns_getserver + * Description : get DNS server address for dhcpserver + * Parameters : none + * Returns : ip4_addr_t +*******************************************************************************/ +ip4_addr_t +dhcps_dns_getserver() { - wifi_mode_t opmode; - esp_wifi_get_mode(&opmode); - - if (opmode == WIFI_MODE_STA || opmode == WIFI_MODE_NULL) { - return false; - } - - if (wifi_softap_dhcps_status() == DHCP_STARTED) { - return false; - } - - dhcps_lease_time = DHCPS_LEASE_TIME_DEF; - return true; + return dns_server; } -u32_t wifi_softap_get_dhcps_lease_time(void) // minute -{ - return dhcps_lease_time; -} diff --git a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h b/components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h index 22ea7238..258791f6 100644 --- a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h +++ b/components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h @@ -1,90 +1,95 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef __DHCPS_H__ #define __DHCPS_H__ -#define USE_DNS - #include "sdkconfig.h" -#include "esp_wifi.h" +#include "lwip/ip_addr.h" -typedef struct dhcps_state { - s16_t state; +typedef struct dhcps_state{ + s16_t state; } dhcps_state; -// ����dhcpclient�Զ����һ��DHCP msg�ṹ�� typedef struct dhcps_msg { - u8_t op, htype, hlen, hops; - u8_t xid[4]; - u16_t secs, flags; - u8_t ciaddr[4]; - u8_t yiaddr[4]; - u8_t siaddr[4]; - u8_t giaddr[4]; - u8_t chaddr[16]; - u8_t sname[64]; - u8_t file[128]; - u8_t options[312]; -} dhcps_msg; + u8_t op, htype, hlen, hops; + u8_t xid[4]; + u16_t secs, flags; + u8_t ciaddr[4]; + u8_t yiaddr[4]; + u8_t siaddr[4]; + u8_t giaddr[4]; + u8_t chaddr[16]; + u8_t sname[64]; + u8_t file[128]; + u8_t options[312]; +}dhcps_msg; -struct dhcps_pool { - struct ip4_addr ip; - u8_t mac[6]; - u32_t lease_timer; +/* Defined in esp_misc.h */ +typedef struct { + bool enable; + ip4_addr_t start_ip; + ip4_addr_t end_ip; +} dhcps_lease_t; + +enum dhcps_offer_option{ + OFFER_START = 0x00, + OFFER_ROUTER = 0x01, + OFFER_DNS = 0x02, + OFFER_END }; -typedef struct _list_node { - void* pnode; - struct _list_node* pnext; -} list_node; - -extern u32_t dhcps_lease_time; #define DHCPS_COARSE_TIMER_SECS 1 -#define DHCPS_LEASE_TIMER dhcps_lease_time //0x05A0 #define DHCPS_MAX_LEASE 0x64 -#define BOOTP_BROADCAST 0x8000 +#define DHCPS_LEASE_TIME_DEF (120) +#define DHCPS_LEASE_UNIT CONFIG_LWIP_DHCPS_LEASE_UNIT -#define DHCP_REPLY 2 -#define DHCP_HTYPE_ETHERNET 1 -#define DHCP_HLEN_ETHERNET 6 +struct dhcps_pool{ + ip4_addr_t ip; + u8_t mac[6]; + u32_t lease_timer; +}; -#define DHCPS_SERVER_PORT 67 -#define DHCPS_CLIENT_PORT 68 +typedef u32_t dhcps_time_t; +typedef u8_t dhcps_offer_t; -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 +typedef struct { + dhcps_offer_t dhcps_offer; + dhcps_offer_t dhcps_dns; + dhcps_time_t dhcps_time; + dhcps_lease_t dhcps_poll; +} dhcps_options_t; -#define DHCP_OPTION_SUBNET_MASK 1 -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DNS_SERVER 6 -#define DHCP_OPTION_REQ_IPADDR 50 -#define DHCP_OPTION_LEASE_TIME 51 -#define DHCP_OPTION_MSG_TYPE 53 -#define DHCP_OPTION_SERVER_ID 54 -#define DHCP_OPTION_INTERFACE_MTU 26 -#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 -#define DHCP_OPTION_BROADCAST_ADDRESS 28 -#define DHCP_OPTION_REQ_LIST 55 -#define DHCP_OPTION_END 255 +typedef void (*dhcps_cb_t)(u8_t client_ip[4]); -//#define USE_CLASS_B_NET 1 -#define DHCPS_DEBUG CONFIG_LWIP_DHCP_SERVER_DEBUG -#define MAX_STATION_NUM CONFIG_LWIP_DHCPS_MAX_STATION_NUM +static inline bool dhcps_router_enabled (dhcps_offer_t offer) +{ + return (offer & OFFER_ROUTER) != 0; +} -#define DHCPS_STATE_OFFER 1 -#define DHCPS_STATE_DECLINE 2 -#define DHCPS_STATE_ACK 3 -#define DHCPS_STATE_NAK 4 -#define DHCPS_STATE_IDLE 5 -#define DHCPS_STATE_RELEASE 6 +static inline bool dhcps_dns_enabled (dhcps_offer_t offer) +{ + return (offer & OFFER_DNS) != 0; +} -#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0) - -void dhcps_start(tcpip_adapter_ip_info_t* info); -void dhcps_stop(void); +void dhcps_start(struct netif *netif, ip4_addr_t ip); +void dhcps_stop(struct netif *netif); +void *dhcps_option_info(u8_t op_id, u32_t opt_len); +void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len); +bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip); +void dhcps_dns_setserver(const ip_addr_t *dnsserver); +ip4_addr_t dhcps_dns_getserver(); +void dhcps_set_new_lease_cb(dhcps_cb_t cb); #endif diff --git a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h b/components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h new file mode 100644 index 00000000..8a6f1845 --- /dev/null +++ b/components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h @@ -0,0 +1,134 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +/** DHCP Options + + This macros are not part of the public dhcpserver.h interface. + **/ +typedef enum +{ + /* RFC 1497 Vendor Extensions */ + + PAD = 0, + END = 255, + + SUBNET_MASK = 1, + TIME_OFFSET = 2, + ROUTER = 3, + TIME_SERVER = 4, + NAME_SERVER = 5, + DOMAIN_NAME_SERVER = 6, + LOG_SERVER = 7, + COOKIE_SERVER = 8, + LPR_SERVER = 9, + IMPRESS_SERVER = 10, + RESOURCE_LOCATION_SERVER = 11, + HOST_NAME = 12, + BOOT_FILE_SIZE = 13, + MERIT_DUMP_FILE = 14, + DOMAIN_NAME = 15, + SWAP_SERVER = 16, + ROOT_PATH = 17, + EXTENSIONS_PATH = 18, + + /* IP Layer Parameters per Host */ + + IP_FORWARDING = 19, + NON_LOCAL_SOURCE_ROUTING = 20, + POLICY_FILTER = 21, + MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22, + DEFAULT_IP_TIME_TO_LIVE = 23, + PATH_MTU_AGING_TIMEOUT = 24, + PATH_MTU_PLATEAU_TABLE = 25, + + /* IP Layer Parameters per Interface */ + + INTERFACE_MTU = 26, + ALL_SUBNETS_ARE_LOCAL = 27, + BROADCAST_ADDRESS = 28, + PERFORM_MASK_DISCOVERY = 29, + MASK_SUPPLIER = 30, + PERFORM_ROUTER_DISCOVERY = 31, + ROUTER_SOLICITATION_ADDRESS = 32, + STATIC_ROUTE = 33, + + /* Link Layer Parameters per Interface */ + + TRAILER_ENCAPSULATION = 34, + ARP_CACHE_TIMEOUT = 35, + ETHERNET_ENCAPSULATION = 36, + + /* TCP Parameters */ + + TCP_DEFAULT_TTL = 37, + TCP_KEEPALIVE_INTERVAL = 38, + TCP_KEEPALIVE_GARBAGE = 39, + + /* Application and Service Parameters */ + + NETWORK_INFORMATION_SERVICE_DOMAIN = 40, + NETWORK_INFORMATION_SERVERS = 41, + NETWORK_TIME_PROTOCOL_SERVERS = 42, + VENDOR_SPECIFIC_INFORMATION = 43, + NETBIOS_OVER_TCP_IP_NAME_SERVER = 44, + NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 45, + NETBIOS_OVER_TCP_IP_NODE_TYPE = 46, + NETBIOS_OVER_TCP_IP_SCOPE = 47, + X_WINDOW_SYSTEM_FONT_SERVER = 48, + X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49, + NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64, + NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65, + MOBILE_IP_HOME_AGENT = 68, + SMTP_SERVER = 69, + POP3_SERVER = 70, + NNTP_SERVER = 71, + DEFAULT_WWW_SERVER = 72, + DEFAULT_FINGER_SERVER = 73, + DEFAULT_IRC_SERVER = 74, + STREETTALK_SERVER = 75, + STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76, + + /* DHCP Extensions */ + + REQUESTED_IP_ADDRESS = 50, + IP_ADDRESS_LEASE_TIME = 51, + OPTION_OVERLOAD = 52, + TFTP_SERVER_NAME = 66, + BOOTFILE_NAME = 67, + DHCP_MESSAGE_TYPE = 53, + SERVER_IDENTIFIER = 54, + PARAMETER_REQUEST_LIST = 55, + MESSAGE = 56, + MAXIMUM_DHCP_MESSAGE_SIZE = 57, + RENEWAL_T1_TIME_VALUE = 58, + REBINDING_T2_TIME_VALUE = 59, + VENDOR_CLASS_IDENTIFIER = 60, + CLIENT_IDENTIFIER = 61, + + USER_CLASS = 77, + FQDN = 81, + DHCP_AGENT_OPTIONS = 82, + NDS_SERVERS = 85, + NDS_TREE_NAME = 86, + NDS_CONTEXT = 87, + CLIENT_LAST_TRANSACTION_TIME = 91, + ASSOCIATED_IP = 92, + USER_AUTHENTICATION_PROTOCOL = 98, + AUTO_CONFIGURE = 116, + NAME_SERVICE_SEARCH = 117, + SUBNET_SELECTION = 118, + DOMAIN_SEARCH = 119, + CLASSLESS_ROUTE = 121, +} dhcp_msg_option; From d2b71a50cf6091e06e1916a8c2ecb90ffc52b75b Mon Sep 17 00:00:00 2001 From: Zhang Jun Hao Date: Tue, 26 Jun 2018 17:36:12 +0800 Subject: [PATCH 4/4] feat(esp8266): Add wifi library after refactoring tcpip adapter APIs --- components/esp8266/lib/VERSION | 6 +++--- components/esp8266/lib/libcore.a | Bin 114478 -> 114318 bytes components/esp8266/lib/libnet80211.a | Bin 354138 -> 353678 bytes components/esp8266/lib/libwpa.a | Bin 129188 -> 129100 bytes 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index 80e383ab..72dbffdb 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -1,10 +1,10 @@ gwen: crypto: 137694e espnow: 137694e - core: 137694e - net80211: 137694e + core: 68ec0eb + net80211: 68ec0eb pp: 137694e pwm: 0181338 smartconfig:9ec59b5 - wpa: 137694e + wpa: 68ec0eb wps: 137694e \ No newline at end of file diff --git a/components/esp8266/lib/libcore.a b/components/esp8266/lib/libcore.a index 0df8c48d3b554b9ba10bacddef63377a2a101fc8..080f50d49338980f5ee2db6fc4b3fd5d869c833c 100644 GIT binary patch delta 33245 zcmcJY3v?FM*|ujA2!RO@4ssG92?#-gghL@BXh2l3Q34H!ih>*z6g40!Dmp9d*XXvouLnAq7Mk~+re(iZ3_x|sH z!)AM4$}db64#i{2Jn#SacgA4PbHC}Qc;5f~3;!L{f6x>DTfO|xbs+qo7tw#NakU-( z8|&!b>VSXNr{4eK*X93JXhT8z5$Wl3E-l|MA>-V%jtdvfnm%j(h0|x1UpD=`g>x26 zzjV%`>T};ctonn@A(5+N%lBJmx}B+}bei93Lso~s`zcb+Vdv!jNb0=d-eGS9Kax6a zs2uZYhZJeWl=`$3>4G!<)%?d&^I=1W4H{hCu0vmcL22AODinhrj&ZewvO}XE1jme zu&p+wp@IUnMuT3vxZ>jWo>!`HO^3MRU6#&O>vUk+Vd|vPw>x`YZ>1$&rkT3c{xYK>1?GKb}6OcvL2o{LuqYp+`*A~aYebN-E`nd()(;))|RxEcN<$UXk)=gni=*R#;lEw19#tO$8`iYvC?HS&L0>r+WlI7EP?rh z;tterIPRXqgJ^T{)v@*3WO^z)O~2R0zEaxRA=WaB^v}dC#9C(F*J36-ZgZoa@1%E< zMm_Ddc`@N}n(zU$sgx(khuF~;|0&bh7z%=Q_aRIMZOxtwg!Gzy!+xXW@*OnJ` zVoSo~wtGA;OK+|ABhxzxliMjU?Uz2$DjKDogDF!#x5MD6kUmcubG$F%aXS;91Jbq0 zN1pU7fhOu{7Ahddlr1<)OhqHaq?ksEyD4Rkr(o8E?)FZ~PLu8$xFq3mdoG?u(wR@{ zz1BR@`gglEre(@#Zl<3nDylTb1GAS>(R$~R4zo9-bBJKd)XyC*D7#(yPo?4M%<^{| zS{EHdbP$Z@vWJ+t$TYQ=6cPIR?jvSGHvv`Q{=Lrv-qxK_HTUymb zrP;>J8BE7%@Q8#5c1uV{-DsjL%mJ9Pv&A#Sl-(wFOZo*d+Y@^DVIreZ%=*jI?<+AA zmBJitDUcl<)~%!BL!A>-gt8p{nJDYd1axSm^wXqK&&}d=_J2&bD&T-X;SFNf(~V+X zOh)=AVkZ1BmEhkicB|(5gvXtFXt-D#&@u8-=1MjuP1JK`J1zf_0y3UXWWYM*MEYxD z^)xE*hIoSMIXb7gj^>Kp5*j6Dq5*f_qZ3uq$4aBEx5aF*d94305(QvaQEOJPCMtqC z3^T|5#jfE3F?$-77A5?!TgQ_UI(&lp?-GY@opEMnqA_=trq}DG_mf5ge@uAX863}E z=_TeFstrgd=cuC-#BRw=5>p2=P$s4-ap;||fQg3PCs z;s+X^#YUisdfep%^{ka%CymC(>CAMZQp(=SSxW6k1qfK*WIQA;Fn&|46L_TmQ_P~n zGg8+nQ;k=Mk2iix%tR;LwG5s3M*1LWbfTZm!pt-Ej0zRFb$Oh)r)8WiW}+h49o?=< z=y0L(sp!#!4%_1Oo=fPkJJW76Jv#mqPzk;JMC=yzKCxyx%4-snPltRhDrS^2UBqr~ z3dGS?Eqy$TQxkr7HOG=DmCl-?t~p&<{+ckkOFc~UWnvC6g<`jaDy%RK-z8?EEbNZ+ zcPDh%>GvjdcR3jy|92?E9Rsqo&v5pmfp+XanrHy#(2d?x>^hVq9&Gv~F&)NVCSGCs zUNI9o>~`Y}b`$2G40mDc=X+j`GR8=wvYBGHi!PvmCj9UKrF7`NgkEP%Juq`mJ!_mt zI_&h2D`_Swbyw9C-X?vBGz$Mi?B@6z@eFA+Je4DrCd$I@I`Q&^?yk_OvqE|=d8zXO zvFePE|7#Su4eB?E!tSy@>X3A@DBLI@r4xTi`1go88sa}7b_cGmY?YemXm?{g-H*`n zcZ(t?VS-&n1>)f(rAEt7$)Y%-Ou3JBmG!uczX8yq2U}c8$TU7CZUfIhn$beSgycb ze%&Uf5*nxyyMs(aLf+PaN%k6d=e~N@Go8SHR2l zyt_@mTg-&t-9Gv%v`)I)K6Z)pQK`EZrP8U=he}J+ zuTty|KEDv7MV%0{w3K-3^p9)caq&+~|BKii&Oa7&5>n!I(z??T-HX~kniZ*uN?{H- zY5I*y=*41=^K`B(;hB~2!0vo;rP$5oy$Mg9n0BaVZ7;2VdP8HcD1(&D?P4x0$@`-f zfIl)1yj#qK-`%ZK>0asVy43Ym!UMCbQ?Iy0_EHPJB=;1K-A5Am>b1h27II-L4rij^C&@WE-VRzsP z6MBWXnY=8mW#&m!d{@E)tJ9OBO7ByEflkzkNoj0tq5$ml^$8tzdOdpe)@P0lX`UJx zr(we3#%%n24Qoi}FooySga@W9t$&u#-8c_rzmo1Yl7k748v~Lj^on#pQ)CU4i`{Zs z%6*O|It1@hN@HhpnW+hVhL}_pd2_}6#B}tIgvX69;i;9*0UpoOkw=>q6}Z7COna1Z zgPGbFo#1Krdcb|1=)qGy^i^@H6$drFwda3fw+G)+2L zRCGha15cJlrSB*7UB;A!DaY^62~VS#4&d1<=Bg#cbT}KiCNkYH8>ZgUIql(DnDD@E zHC><3-OwCmE2WRJvcFGw;O5fv^n2|n4l9~ySizyi`=>;KMzOoX*e^a+UOIG4fBmD0 zvamazPDto(Y>*C3mCiw(vOhoMQTuM-5Yq}}a4N#IO&lntr>`F>pglrNqxg4<=_~%U z0{x?jJlL({wh7%0N>a9q^nT1gg-0h$Zp0E(iF9|)yguP^qnUUrrPDv^*_80Okxo1f z(vLS!Q^FIvQBX{o1AeGzh?pr;zoEu>;An284@-E85+2xjMkG8V6CPNeFftyOFuCDa z8rvp)td7Q1mO0S#PF9+y-vqHcNSBH^K%rkCW}?$>IG1|rrE@r;oP!>G=EVkWxfhP(ZI9niId zoG(q~f9hSx-l7SU8wEH9Kztz80)xEa%^;cK_ zRR7MdzBJ-{^zXFl=ePFFDA3{dU+p#=*g7~Z?7{M|DO+h_N<2Cxo}3cTQ9Lp|zBO;J z5r8ly|2D-llpm;W@*h%Mt~f7_L+?2Wt0XY%7~WC5<_ClKsp1`qCs}@TEuR7{vk4aG zDXvh=x}^LF#j6yv3W&=T>%VBdx6@t7xeC@OpKYbR7q;-0N>CjA+Nm42D&8jHN~_>e z#U<(;hXN|xta!8Hvy>9QrqoR=!FLoFs&&`lFBMlR=5T|*on}V=#T^ROqg*1Js9>OC z_F@(l1;#7hp$bk^9`RWz{tHv$t5V{d6nEF&)ziwebc+?UAB9x7C8faIil@rJo=X1T zQu4o3yeN_1mBnWhGtgggRU-d{l>BoP^GHZD6h;kPnqs&`v3u4-2Ue%#Z&a*>W9#(G zrmc#3?!zGw|67WAtTW!?zowM`T5q-lM|&urqjvtsvnhWtT_-NYOgr^IX@ zZX$n5N<2FyE_book8ZQBc7nyrQsOGb?pY8WdQh=@?nC^$6#v_bdE|4F>LdTJirr%z z; z^B)^Vq!><1iO)%iFHebYONnb!;wKdI#3jdOc&p;s43WQV!pA8E_NT<@ItI9jMc5%F zK0+~1LAEH5B{VW6|0Ko5?L6;$%RgIj$b*B9wn#6P;D+R>;OB}NerF*O-=mn3^A9cF zsF)G({&pmMTQP&t6Ro~46}ur>%D2-#&*&>BK;phFRW&1|!>qt@GPsF3oRkvJN{KI2 z%z);#@>1b7Dfzc4b_12D2ZQbsaaz%@+qs}lavbn+hX-k8)b7ZT?Z8g8abC! zL5|{Win(PcE>?`!`G2O^jTMrAnPSEW*|UgiLJ4jR5aDsfZej`iS~25)7mLY%EhYb5 z#WS?{wOaLSxVoE$$vAYYW!KEqrcc;WprNqyr#BV6(hP_suiO&BY zrx?Ch%w75YGSFZfT@Q0}?RK-iTp!!S9F0)yZlLi`QtWP)iO*Baeera8i9^NQ>rUj* zg0M;g_o=hY@GHeSc6jGTak}@iVmHy?pA@@$Q_6pvkw4vgL2I6&A$RtJk|KiX9a zQw*b0;t7f?)u8LZtd#tPDe(;{ag}0stHcccQnBueMjTpaJQa7hKp3_wR(p0R&G7ap zW}86cQ2hCZ=ikWnqZji&eRF*J|NZs70nNHr&wTd+T-6<09Xu=O%(&B7%xfi;sh^BaCw5cXZG91^>82V>fvJ4>5M8kW)#A4$gqVAI>NRmGUnm* zx3wWVopBVWS0!}DW1L==&`T5gUhQD6o;`5S=)~@Mj25}V%M&JsrktLW&>8M>`W_t? zT&0YaIlVNYGe+n1DjinTa5Po&f{cG*94seeeay>XEeY;L87Xvy-_}9P|6T0a0n4*Y z;da={Ho(7)J)6x##Au~!I7>(Cs9m=HOakjsGuYN8gCB0r7@&0?26~;&ShVAOokCnE zdc!tjIk45)9kx~6MH~_=)?9Y9j78#X<8pD9@q96l3GmMq^H{-E#PbQqYhat1x`aLs zwoZ&Sz24XQFHV|t7N#O)cw=F!sMvHCBae|>MQd_@@YKOJXFR`ho+_O+-5ya1n`b%P zljX08=Zvnv9$oDC_r`i7Y@OhFrStTLts)+#I?rBRi8-C8wf@Suo(9xx~z8vcu~d` z;7uI=ns_eP!dmP_ngibAaeBFKA>5qJH^ws;zNUKaXT7)?WSWX%T$gk@~E(z`kTW`Z`0-KF2%b?oKM1f`r=EXASFV@O*jg3rjQG$min78EI z;;U2#)CsL;Esx~{Ha8Wp9U+#$7sPY9IN@0Y>&H|Mt70ZzFm&sR7ZshSB1=3g_B4ZS z1DG4AegCXDV|F06MK=THA)cmb@EI{rO?b-Ssj*%PpB{5b!oxj*KPA@3!joezcAjFz zjjfbnbF&M!PVh#oo3nLrXsxBKYo^^t>2~A2O5aN8gH;R< zuLLhLrm70#Ql$+2MD-}GH>PPufY5o9_X}gX*Fp0kJ@n{z_c(~=r^1*8aJ?}L;6`H> zK&>$gay|NJ>6^x^S%!S@u=;x#XDZD# z&Qdzuc%o89eDIemWpoE-GwP@n1@nIFX~tti!43=92H!Jg+x*g)ZMK!J#wpAIeOF_) z>z>AqN{=#T+aGMqK5?!wJI+eu$CdI6sgwfmS;jK)K4W&S{l?!Y?WV@@AE|VnF?;53 zjoD+j7{9CZEo1iTUB+oT3Vdd)JwNomuz&(&(g25t*2Wvfyu*r4V^fVeoZMtwrSv}I zLZuHG4^_%lK4qU#T5pV}A!4n6OuH?EcT?x-m_-5Z|1UM>ICi=5^GbOq6%WU{WyTx> zpECYlX@fBb&{vHMbin16RLXLY-4$9u;SY^-lu`jE4zgJ)1atH~!kCJ9hZUV8ceOD` z^j{itq<_koGr)_+oLl~69CDiY%z_p=0r5U7m2xU+r5IkMG~2jL`jN(*dh(42D&^f) z{L`fW#CV?4V~uA>pODb?Zfh77n5_&Np)hB-WybTx44$ELc6`a0vt|pOQPDY@mKgJ% z>QZCQxc3@!CVs$pkWSZ+>lbzOFs=Vh7H}TFSx;}t;5E|YbdHDTN*`@JTl~E-*8rXM zmIWTJ4GN6WM;MRLHO5KCTuYQ0bB%E(%zF<7GF@RAuPc4n82wq}dzEf6{)f`t#=P12 zoiYAa`q3dSXoz7t#E>CeqIAA77enC^3vN~VjxkqE`;EDhO4oBu3Uj&D#`sgE-HmrC zEi&dZY^*V5CnP+J5_(n4VRWfhZ5cFhzwvtUgU0K`9~*zIw6CrK=@8e21;$(#jxpxi zaY{nJ*!Xs(yogCzt~IYb+>ZZTguZVXT%3MoJY5&CMfy>I3)soV=PSLzn2X$1#!Hme z89$Z2@#!GYqa*OdcrS-;C`ke7n zdEQFse=)vUI`vXN{^rIzxm(V(fKGHVULnpkE>*h7_$sBpFkY*)-gukRw~aqk`WNF> zs^>f7Om(76KRQt>{o;s2jld{i?p*JlbS9;*7;`K3hB3EjjmF*bbehnQvOSfaZOkp* zLSt_AE;Hs9u*R4d_iA~akHX`WK4N^hGCoY0i1ARkzwuk*vyF?D&M>Z2dZ{rtrJ*r5 ztBmMUPo2`ojYIBkU$WrON#!(bZ)&XjBi$Yt1)-gRmPi? z));f={fmTN*V~T&+@3#>$autCmdwK zHU&eCUlxxxW*lg|G2=s1j2SmN%b2o%FlKD&17pUV_8Bu4^|f)O(t|OF9-~(y`o%rs zm9%q>8R5FZn31pRj2o2l_8D_fru4sz87bo(D0D{9#v3!TR%XnI+a<<}ls;-SV<#m5=X5RW#VD;{q=dw}-;G7IJ_<1*uN z@ioSa#5Wr+7T;;SL|kjUOuX8-LcHF1x%g@0O7ZWEtHhr~to6S_fj=;wvsL08<67}i z#>~waV;U|oK3(Z^#td5TFlI1&r*VbS4~#1db(%M3ApCEk1&oA$W6WrImW-_9OO$p^ zaK7;hd5$*bt*hY)&zJ=BP8anomw%k`GVw&?kOt1Q06yEeQl|3~I6UTK z-!}6jkH2l^*|UF&_IphXTA-uBf$99MvtJT>(ptqHG&nH5i`aSc%!3BYqm4w}Ftv>1eQ`{%|5W}1!$2c~~)Izuko#Qxma|C#A%a9}!* zmDz^))8=-@`qSnx63F21oDa7QDt(zshsBlh3>ps_9GL!7)8{Cin&8ik`4i@Ejrp_X zcKY$Glc^KjOv|6YTjoatjPvlg80K%4i;Vdj<|UlbQU)^s#DFnzS?rzl;4Uzc}G zV@*ec1Jg@+woGGZC|yMXU3@bA%ycw3FufMf#j)os^Ps_j>2-K6i9HL=g9ZntFE%|~ zDp*5-^0>g&mVpKbrr%_GmD08N7sURXO-F+R)7Rly7<(wgOrpVo>FZhluBQ*1Nume4 zo^GU~OXG^3F%KFXn9i!A0fy@8@h^(~zcU>T4orXHkYDS6GX*Y-3%qI>XmDV91D?xc z&l~1Jg9FpI;khFAyl);fI57QN)A@V%{%zH11}XUa^(q2bTjyA@uj@Xh`%FiJ1JlRh zxhnQNW*#&+F#So>vsGt_*uOgVKVv#tNDx@YX3OA@;!E}Om&65LH60BOOn<}lMx|x? zxuYKAjm!)h><&az@z@M}5_>`qk-*K_{x~E0L;GoBH<$l19SwGK$?E_##$3+8uSLt$ z!gMs)bz-vV{N4QYY^{F^&rvYbG8m{V($DpDq3LL_>u6~DtxE5PuZ$c1rRf`$K9b*mY=u>5QNj=;xNiwWg!N zZb?vYbdkzvXFaBVaqoT$s{w{ndC|gE#PBRS8tf_>n((}99yHi_itsSEnljWL^+?kT z#R_;IsKpfzZCA+NS`6%Z)O*Ej-UmXt3MD2bj)>74{_jV@*eco&Q&!R z0(ZtM$7GjHyD`aw2D{6tMR@Eu-=S0NL4)0qG0${9=&(59A8a~WNZ<;LOcW?H<}(pz z8Z&gigo-YScgxUpG}z5Ro#}i%q5}W0*#Cs-Xt0)6ywxpBn6{e<4R(ukIUbwiUFJc9 z-3;t8ozGKLCj6h7js`pb-#e*&7BAnhsG@+)Sx?32Xt0~J6$#HU^Ps`bGsEdhS0(&c zn2rWVe&)Xx)3A6E-DV~<*v)-iqN2ylg9f{X*Caf@H4hr>Jh}EjgAZ@?(Jwmw^RbQS zOB|YGxL7}TnS25)oeyv9RYk6&rS1W2@;p^Ps_Qu`f4W-`WVh1Bn7vmVpMl z0xN$g;N4@)mp#@P^EHpJ67@V~IvVWisW+XEe7qa6mOq~k`O-3Y=JQYZhIn-}Q_S4+ z^^X?D1xmAx`Qk?|Z2sk@^AQdn`%tz*X_YY_;rQN|?`wFW{=r1h(wGlybbyz~o#yK_N_>3oo5Gk$Gz(f)U_WgxDi`#BmExZHA>$zZdCeyf)5&J>j75ST>mf! z1pAfYkBaBGmFZ}3VESm&rzstu;L{SEFZO>C*Yh*e(cr-Jn_^ur)C(%(AmZ6#caT|W zIvVVj%3M6PaRVF7g9Znt|JrmO>pf@8=ScSI=dX^-w(p_!&)g%n@1eq$kt;^$S>FKT z`AUbw=f{QjQ&C;aCz%Hg4op9Q=a;c(x_Qvx0A1~SEqca{c{y6t#ymi5ozS})^Zk-M zST_(%N1D#}OX^gqTXKb_qrq;;t-)g(^~uts<3A#S+e#-};jK#7CJM|l9SwH=3lsj! zjjNPiZOlW>>y4KyUG;+=dcXW3@E%R@(+Q>mR!3%zE-vYiT^+q*IvVV*j&_*N2UzwR zQ+7RNA7HuZLq3rn#v(yr8Q&)gw9bheK1}IG3fs6%Thq~CH=c92>AjWqfba97sV}S< z7^<|MdTa*zhn9iZU+m_f$n;T4H&eil6Q`Jt2D|mzkno&k9yHi_E;fC!(gnsL!8Qu7 z@uI21GSJ|_^czjTSLw_6AM~QB(sVR9F#R#pH!JTYSi`^?$;lK>IFyTHM%9Dtb8P z>E=O$1JmcAPl!Fc@Lw7;9bsnBU^h^8sp&ivZ^R!ihzne98HlhOM*GxsK9sXo?DpM% znT`g#T`^NW8ph8Pba;>QZ!+flIX^e9RT@5R0UyEnO@iMr=0iCp`ne78Gt<#vw{ex? zc{HAxgXTel1Jld!JQjPh)t)-1hg1>?0?WvcGd#ZBQzCYi@W3?bdQG*@$5C`13IVlj`hh(OA<_spYP$! zPVo80JmO#A^iXhx1$@)yDq}u~bB*x|rNmUq_ib)6=9@OW1AxxwYMwQw;dc{!&^Sw; z0t;fO-DTDXrhlrmi+*mX{?DeP!EUI&J05K(Onc0O2D|e`PKfE5*tFkFIZENc z^e;{4WrW^he^c!L&U7?5Fg-uvX`wPKIW*XLI+z}^hg9Fo7;du^^*8f^FA;LkFp^J_Dc+o9T+BLyF65P+2S2}i5sU7M1n~ny% zgH@U7^OWwwAKFoGmSrHq?r7DBX-hme7n%nR4orXAbYAgzF2T}~&5W8bQxZ5%i zVRsDp61^dA_*?S~R0Dy2Y*2jqXq9w#U)RQTG}ztN)#9;jh4E#|qQTl$;{7kjGH9TV z0=C=qG93+eyUiLrw%znI4;t*YrwY?~p=GLm{_&#~z}Ga1)LPhq32x=0Sr4 z)7Ro@j6L6&2MrEPUzhNt9UXT_nm!Jsz?s%#vPvH{6B_Iq+lc3*xUp}|g9ZntA2Bd) zAX8~Q{&QphP}9-i;9RYLrp=iC67xtip}~RaCz@WWv;qIF*nhg|XmDWqDzUFIU#3R$ zpuvIZpSYJ)_|g!crD8qtVoAC&Una^h9;CFTF<%-Y4?pjfbTBSc+R1pH(poy9QE?{P zz>fw8(xds$vkYFJ>2JJFX&r@cjtkQ`h0$QQf3LxFOYEUjc+g;XE;tSS#@MqKe@@Km zY&`ytNY4Yym_>p4v1vYhf6UjzYM@f-9mXuqbyV6e_Rw)WXmDWqQ>OEgr1kjqfFqj! zjh2B32T_I?lZH>3Hk$_xW~`s-JF(mH+YgExMuXi(&G#dmr-yma;9zWHRFAhPVY=B& zXt1kjal*6GJZLL7oj%0>BL7GK=Z!AugN}**zZ+@Zk=5&`ciZ&DG`}j%&)RhSbiZ@U znltD6ZNk@^8uaG-Lrs}knL9-Oc4GVYRrrg#rU7kFys^n&-IVEVS>5#Jj%IKE;k!g?ZPF%JP?@jk$kO?$4SgPHY;y z%OCuF#ncn?2Oo1sY2J1IRpjR1v7n@B<}QC;i{`pQm^8TVn%wbCSsnA!{6#f|7x9NzZ@V>4hF&6gA}*HTiSM${pV1&yGCN zzc*%iX<6l2!#>GLd$-Q-Q`q^=hHpDv+3Tr>e|9>&cU?|Hr@=>76gG5vzQ@dx@=FfEPR@kH(+&f$xr-K zXm9ipO}R(Jxd)4fWEU2VjtmEjix>GPU>MY;DYsKo(Fy)&qH#+%Z=Bku&*V)1IKn=8 znf@r?y!J=twrTQ@Z8}DQ=66J7zGIS>Wviw^t(x-36bbJvPp`T5LjUkEAJ6FT4^I5{;FuNOn91IY&AhCPnWdh(HEFshLctY72R}T|qOg$<9A+O7A3Tb@?4)HM2@>4Ep5YnENZT znrF5RW@Z-V?migxttM~2-^1TpGkU(?wb%D(e)R8+-J7!NvwpEKYr(m%AFQ~-pPAv8 zFCH}Ip_*&v`vu`iH#Dt0-@7#Yc9CRpXLv!dFdj5jQ_%> zRu}u-(vGzM_fEf@S(jW?K5zb<**V2Ir(AY%&fsA=g9`^0JWdBEh;_=3c!9X3@l^@W zjS2mB@pV_oPNmGyor^lzPUC zCmY|F@W6vj-;vOFgbI3E#^+)UR7Vx@XP8t@r5#!RnuuZbBhq__-O}on@W8G^rzUhb z+sdA8dPt=NuF~_xuG0Bt!UMAw=+I>e9d?!8kkH{Y^WP+Pbyg-k;y#Bm?nq?7Ztm|E zXVg4#jSj?ZtiHz+R+t4!zv>e@?EEh#blCOf)r1Z^ot=b<+flc}_RN=K)O-I~5K;ep-EEKBHcXHR=5h40z)*|q-Ibic4> z$aVhJY4^0Q&fb!jv227c{=3%fyw1<_8*0A2&hP72)bzUE@7w%2UHDF^{?(RV86DL3 zdcS(7?5}pxows-A*1U`*WxA&Fs`G`HcILoPT`F9xtys8tYhK!{-qp2R`()&3-pVto zU*4M6yh;awx=pt)^LM9(eCWVUYzHr-#M@Kik5b})q{L}yuC{o)%2J#oPqF0o+F|?s zI6w48{#fu%QQV-5(Y&aDzJ-{QKTq)i@ale)uj9wY z9|?L*DKL}AgJ0-p_CB7~tu1tyVNr~5|#IGKTwf>odKOGX{_|ug5yOg-6R*#z~ zKRhKKml97)iDxOU)dn%Ti#8N?i;GhX*KF!=i~m&g@uN+zR{D3O*PLJF&#QT}%0I)O zwW;6^zkjo?bK)L6sCxLm-(sb3FlSTwUHRct}DnuMcADDc|GU}A^YvVOyK14_Xu131)2d|aR zRS3LJe6sO+@qFWY@g>F^#XmRREWX>gLHuY-Z7Ed5CChHh-~*O?PZ0fO@#n_d#RrYK z8X2S?o*mMO;kU(HoxnTA=Ns=5UtruQUT(aXFRa{R!5%S}GZfx0e#!WN_!Z-?#2*=d zBmT_zJ8`y7Qj~3`)o7o-&{((5fu;{p$`21;+2qeGqQ@Rt3a+z^Z1EqAS;y}gca+{v z+Yg1gF3U0Ig6$MzR@0frT(Qhccorr+*BR>yB=mlsFx_TM;aX!Fd(@b#j;9m+e1iFt z2s(%74+-Y#0G&&QqqTFu>taSFiR5 zwwU}!Egj-6O5xzA@m|(l?3cv6&pc>wV0sRoQ)AEP=0W?srs*MFUVUv+Z>4Z>T5RRS zLX&e9wln5}mhYqb6Jk#{)6w9-^c>S!!3FqBV}HKsXmC*K)!g;4-!44bG76Oe2NUB0 zLlcEZnFkG4;b^#C_nD5iuV%tyT7X}gv`i8loE_J_oMMGB^H+#$DQIwDdWM}hxc6>p%%PkZ zKg|EB6+Ts)C4Z?1b5q(Q<}kYB>}?s`0v~O>Q`Z<{jX4`u(jl9Vb4^Es-OgH-@LXpe zG}w7oBs^98#UedItV)gAT@~4n^)+${^VcX$Wn~ny%9q~caISbb&{FJ92G&u5? zXbC@I88lW$0h`N>rlY}b4%Xl~Ctfw1&4aeNX5iymqi>kBRuUXckFEPm=j{E3F#{ay zsBT8=X{DGxqQQab$C^G?>2V1jZOq`vdg>WyhuMjife5<;#BB7UxUr2C7!&jP=0}4A z)A?dB9b&Ai9>1LrwwR6vyYs~67FwgeomgHn(`K1qcf#3iy04|M&zKP!{*05xva}fz zJN}39YU$q_GdPj1A07rIG}IUS`TtO~w1B}5wrNZZ=`=70w)t?JMn{9)=F`t~MrDpR z=Kt9{B*E@0UL3l&QKuc!i{*(f#t;eIv75b*#<(UbHDijN?yqZ)k22zMnv;wfj~Sm}_o1_$YKZY1I>*J^8OG?%#BKwe zWjY${Ho!|LMB(jPbTk4p$aAeR6=jP3nQ^agHXRKPOy`ebT_^4`-nr@cC;iV`{~s5-#Yty1d+m0GGu{_ivMZXLh1&N}^{wazR*_Vau9 zyDxK}*)th$`>f>QeI<(y%GV4TQZsPSfI;Qu)#Xgtf6L1U3>;jO$mJ8;L{aqfDC)H9 zfBzd;7exiXe4+4pJbXeF{r~>XIVOt2?}E`$^gsXd|BmVZ(3AhSdij6Xf&Blxi2m;y zSKIl2V;%il9f&6kjQ$tDuK!)3HGNwg(xT+DD=wRT(abfqB^MTTPWgg4^;0gKebEJz z>*riB_0o$jS^Q+_$Y3jL{hzH%!w$9Py^du?pGS+|>)3fs*8|S4_*_|Y&A^?x&!ZpC z8s6#iATci-x4xkGq;o!L`6W-wf!aT-7vC|icRXgz0~dVMBHps*p2?G2U!Ywz>iFcY z*8P81QC>cKLW@Cn9@76`&GX)9Dv!pu7VMRrfkOsdw5I!a|FcEDOx@_9<3_R4zDi4#PEp!HX_Mpa&flf9ll1Yq zC>o};ScNIqO)2%%JHE;3Qm5OMQtyPesege|9XXDZ#qMS~AX(|JlU>{d#_WnYP+iAvX2q#YbnnN~FZ(6l4#mEzy4lqJzYy&)}ETBUSp z&oq9+X=$%C?y7XK^5^DzrxmPnx|lo^i!S9GNcK;{NFpSfG?uvt`X!?m0M@Y%Z}nwzhQ? zsYFzy-)mwf+JUt!61`ZPi?)PCuc!WH&WYFa3rIiiNUGM=#i;#nrWr9D5$cvhJ4 zz}oPWdNu`5l@=NS`z;M{Fkqq+;lM!QH>7_}8lEF{fQap>7MF;boq=Lz20m5HN`uc8 zGf`(a$WZ4*>4$`sc6G)Cv!7D<+Ke8KOcdTBeW3D-^y}PCo3Q;o#Y{8?>sXZ3bBq`- z`f=hp)*s1d3Opia|DfTm;-k#1s9h6<;c}&TdS~=1Go6F!Hw_-0@xWmT>F}CNc`7B~ zP)p%?;)!AkZx@F}{a<3X9Q1!?^gUu$9~~;=V4#UQVGgVKt1>$LdFMK4`Kx?VnBzPX zg~KtQ4vmq1hBPW#E^cAZ{bKff8vcVgbab=0#`-=n6LrGWfuD^dT{YTi4`55tgejb4 zXn4HzA<`&xN5%smXZ@Ls4(r^K_}>(Vj{Z%2ruD%(d4-M+5p#}73XE02L?^--j!vwU zK0+Fuct@;rPcjFsS&^FX!(mbP%;>PrQHlRVacFpim>rEe^P@5a;INLrnbF}BUEn9; zu*x_EGtr4~I;PW`r1z0V10Q5O;Z%)>ji#1^Hl|tyIt?d1ohA;8?wexrEA^`rQx}{U zGtuyTF(H*M5ro6u6XHO|j97a=S;JY&S;&8x)6!?gc*1x!>Lu3G3s2VG_KmqsT} z5HpulG*%qevP0R)C04vQ1;G@4p&Q~o~Ojg{8NA+EZ!G01>kT_-Ja25DxraW z;;^V=EfN+Id0oWhQ~!Zt<`cbI?3u|&BNT+K`a&@i1;TY3OJcfo_E##qI^zk~ba)m> zX9n;zh{FasNalT2B-nE5B;kxT|0j{lEl^l;%wV>_jXV?Yn>GMxRWrw_Z2CT0NU z=#D-}96B^uTx0#4c?CrZC{QO};*4Z>unvd)_$%xt*2~4L5jr$jJX}m&SBk?fdUM7P z_ftL{ddzxq{9o^YieToRiZ)m;l@15JDd_UR9DFFdU3`?wwwD;@xPy42bQ-S5tf^E# zaXy(d8oMo%5w69lbgA@1m5=8a;!x=ZaoC{#m?;~s-;)kWCyTOs1f-Svee$_q>wm8T z4u=#d)s`5JT>aT9HPO=nW;}3M65Jaw;R*K%ct%JcB#j2I%6P&(1fB)bYuNuVJ*J?i zQhN8YILzgCaoD(C6Eo2mtn*6Z|1hJ6n-dx+(?+vM9_r_2g^9A^#syD)uQHC6h-pyw zFB%>!X5*(rXJz!!Vot~CjpA_m^&>HL(7;M@ILK_v=>I8ZRZ{jdv1T%#6xgRg8-J3~ zwLGl^Q@NOlN?}$T`f*|=bXceMr14sDxS$^^K1MqJ+r?ptE)s_&{b+e!xtgfx(ef{L zvp@5D#M5W=TlS=EQ50F-*-wJU%rC5Kaf6$Unh*?_b8}&~TGAmLOmBJiwiu4syM zmSyyZGWsepTRwF?DrTZiIP4KmWONuk&z${MLFmNq#OF#wKUDikXt;-%ODps<*nc$9 z0IciMM4u=Q8{I5%*j8@H_~CHiYUmk#m3oqj!f;5e#kI^PI`xxGVK~gqW8$L4Z$EZy zatfncTQW|V?xAnX=y1??WOTS#URq>8h6!I7oS|1crE`?RQ^c)@CV6xTtAN5ZR`Nwg z6h?F?TqZqiC7m;#FxrD>l=Q)>g9dIAhvoFWj33_aw&rk|srKnbG*lhM_46H|ck&G#aQ; zZ`k)JJeHnm!Via?c2Y(ULtE4{TRK_P^Zkqm9xE-`gg?w=>^4&vrXatMGoCPJhKKDs zT(%s=Hm-@zh4C~z$4Ng!8ui?g@rd)Eucv!58DS8P!YiZ?b>Y`C9=N6SO8wr<=x|uP z|H$ZJK#w|$509eLlRCBj&r-ldui9En-dxc(#h!$*JehiD&WA zr?y}7@GmzOm5f}V8>`}m?bpVYi|=k46aRVf`%Q*9l2*QgZJip9r1 z**jjlc(VTOx%k#6dzYM|GsWPjq1*LwWt?C9vXrfVRBOczbtvl=AO2MDl9k(3v`51R zDMjlpXxMRm+^b~vWYylTp=?21Su#S$=c0~lwmel+l&@e3dg`F`sDhY{FHGc*FNmir zKCVT2FW*r^2G%U}6*-!T^QxvRFK3iAEDBmhtAVG2R+fUtC zq%zpnP%{c{X6>m`mCn=Bk`~v^1g81r!_!h<8w3Bsr`3DpaQ`|{$o(eY> z6!??k@iMS$lmA{pezW4)nfz`nK2OZR5sDXO@=q?vzfkd7<)6n4(j~RXjj`4x;$CDW0wPRLAcWl>bC=`h-V^I|{VX`rM%cZC#+d z;_&2#{2>iz-x7DvkC7ZE`f+|iTvrg!Er_o#h!+;bOBIKQK{Wdl#iiO%8Q@Z!kA7QF zV7uZf8BR_O(ff*Le^DT6QxdwH-v3o74v%(d;Aq7xn{xg3i#}{VPH}jwL;fhm;So-< zvs^48Ji5VfqhcP@{D&$aUZFTlETM-KPt;Pa5R?D7^I3cBjhhSnFDu?5|0y!y{~(*M zQ(jcmO8%@FF=dY?r_w^;xd)6UAYumiz;?Ycnj%S&#Tg z#f+Q|wEtwqVPX!?Er>5Jh%ZyjK<71~hu+D5oO<7L#tVt>Qyj(yi62!Q zCYHdHiWwK2B_{u+g8Ww$Pb~5+$9}q@{JVrO&PRb#POqM*@W6t&ydbVp%n;zCK8KxD zkUy#*zBGwh{+eju_5#BX3*w(DX0+=&^3uW0iW#W-tK+{F`1cmX?Q~3G?C4bc`zmhA zO9<;^qy&a<=nM^9rZ^1A5I2(V3C~XyGaPfK)*1OvC}zB2r1FTLQ_P)ySjDd@4ma=Q zf1o(eoqA7K(1LS?CmQHn5Fe&E+>lej@Phnv3gUXj;pQCw%?0^CNM1F_H28Rd;nxN6 zpA~Z_zf5JQ@ZEy^mbxzHW_`Kyd7#Zr_ce}>3^!(YS%#M;ytsbnvB^!XYT%wd)YcVlpHv(% z01=o0i@=O<1nvua=VWvw=QECJUIAa6SfWOFb;`?N zb)s6Un=!>u_8lF@;$Nknov=I$6u!}0?T5nK$ao?(ZMBJrk4;{cm!{xA-L^s&0 zjG@`EBpAvK9>#=&&Zu?5%>OW*RzfF^gFR=1VOKf;_TsHJ&(&P^HP04Tnd`+p%ynX( zC{UJLZJt1cdU%wP55Wcnp{G1I3Hn6XotR*Ky(;1%&F3DSm|^q@u$Rhs>nuf{IE8vP zRDABqN9zeZXFTf)rjQX26!YH{Cjo%6Mvtkv^~N0@Mtr5j)Pqf&s}v( zmKNYuf{?+3-T1Cl-v+xPo)8Dm5_oay;i+?IV56=QgNH}lp=`DF)mlP*;e~10s(i-O z1NNdWcL8jhb?uu}TBH*$T#^>v0K0R%Wf02pdPC589U}1FF5(tx**)fD{�GcEPTc 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 R3_5YYdFQ(OR>$wR{eN^8*AD;y diff --git a/components/esp8266/lib/libnet80211.a b/components/esp8266/lib/libnet80211.a index 3e5dbbb68ba2ae19651bd3f8e88f512b752e9f33..5117c589be1deac55d6f002a4d9813a89b121bdf 100644 GIT binary patch delta 11783 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 delta 11889 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 N9|TVKw7*~Xe*k>MD5wAc diff --git a/components/esp8266/lib/libwpa.a b/components/esp8266/lib/libwpa.a index d74f7fe9460cce4399bf19f4faf7f31038bb6e8c..37e96efa188d9aa3fc12df7b9bd07cbae5a4c5ac 100644 GIT binary patch delta 1651 zcmZ9Me@I(b6vyv*`C(|H#>ARVG)uQ1<+J7p8k)0D?t=WO^Ip6bn z_uY5zHykzXm(#I^XIJPfPuJelpFr z^A>LjIKmgxp4<17glcla@%_2>R3cZtZQLQ@P>ofh3Hg`DnvxZ2&xwsY(85bR#c+zl zpB@N`iV^U@8U7MBZ;12MT;!t81HF6{^B{kS`6Hg`^T04ag83`nig}X1kNGzL0`qTt z9&>~ze8=FP7}tTFcgL*!wfZus-EPNXPJS)!;`b2y;%%bqV^H|Jes7kCF=j&9k}|P_ zeAHi>T%2D;_ z;5%+ugPfg$3^j+V6&G(f;Q@;}{UeO(`rI1{+xW=$LEB_tHkc)sl}JJR zg1j2EJ_=?=BKlW;w`|4|0omz2!~%Mw`$58c+XS)17-P?`muJ93auutIrgUr`B%9?# zq{+2%&;_f>b|F#RI2(u+XU<9k>mPbU{HW|LD+z>*u!PTZm^+fNWUtOjCo}xWEdwo0 z9OgvP6ckp@&;-T#-l;aZq0rJHj~Btugm9Iz?35*=+)!E$@B^{SZ@Rxtz=R0>1Wt8m z3i<*3YUvErOR}Fa2E~j~9Yjf}DC%{TjA{fv(wVCcMPSh&Z9O9{%)yIb6~D|uGx&vj z9-6rl(~F*Ycmb-#IQGyZvKF9O`ZZ6qFW}%0#7%6035Y@|G>Y;l6d2xd;^M{2WdG1J z=HSq37gwTSg^;)&1&jg#(5T17jUYtSsW_Nzt$f9w~0%-FtJy zdxT_hmC!A>=rTc$h!DFV?jtiC#~n?GaT654v!Y@N$z3~cU7TKm0%P7j+&S>iV+zlR zD|{wy<$uR*s_8Bi>I{B73Z1A}hEqOVF2lF*nisO`fJO@|)*ILtVr@j(*a4>g@A(7> zp9S*O$IEaY)XVq5Wa#tb*z7%+FxpY%>1WiXdHP;8f>=Klau5t7&d delta 1697 zcmY+Ee@t6d6vyv*v`}n;j&^h+bnS!DIm(3RL^`09Uw;@^##qz@69EUC#$`6FSv1oi zxIc_B>bP;2WxBA0KNf$ERP&56K(iUMz$$KW{L*bKlK}yh#Hd+J>N(E`Yfo~{`JT@` z@4kEQyY0juX+vvi@8_BnpHC^TDEAG^FF^LHg+a3OwT!&T*I)zb<)e|9bi%;*rP($f z;>~rA$eU?TY`ISceL0ckt+@$3MC3=0rEc^@27Oiu=i`yeAf=S5gml8 z>`FvAs^K_{D9Py7XYjl+8MQ}1wkIK@@3Ha<7q4yfK%RQ#dl*gOA*(@h|1RDg2WQj8e{+z-Pr^L`g*8`be0#n!(Jt2(S~}(EHn>bk_U@2n zr!1w)wZ$a>-w}JK+x<-(E^5PrOc?}-iowg^R8LL734jLmp%~Oiasy)wwlhZgG`fWT z3;Hp18GS$S3thSDsY#eMO5R-2eI1&hK}4^^UI>d#Q<#QC2c^Sen9_Lx)38@E<%^bS zZ2eZ8!xDChwP`4Z{UUz`3XGpR8QUWoN&abI%)z0}Cf=9Ql7b7%45q`@o_p>)xYMTD8)#JlO^0Y;n`|b znprUp0b{s)hST7^E@WR}y>2uC3qe5iEy5Y77tSScY@<7b=0XR$9B8fRcKrA*U7H)! T)+IQclK9W%P=8&4L+1YgL^_Ja