Files
2018-06-26 21:50:11 +08:00

1101 lines
35 KiB
C

// 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 <stdlib.h>
#include <string.h>
#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 */