Files

586 lines
17 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 "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 struct ip_info esp_ip[TCPIP_ADAPTER_IF_MAX];
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(&(esp_netif[0]->ip_addr.u_addr.ip4)),
IP2STR(&(esp_netif[0]->netmask.u_addr.ip4)), IP2STR(&(esp_netif[0]->gw.u_addr.ip4)));
} 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 {
wifi_station_dhcpc_event();
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(&(esp_netif[TCPIP_ADAPTER_IF_AP]->ip_addr.u_addr.ip4)),
IP2STR(&(esp_netif[TCPIP_ADAPTER_IF_AP]->netmask.u_addr.ip4)), IP2STR(&(esp_netif[TCPIP_ADAPTER_IF_AP]->gw.u_addr.ip4)));
printf(")\n");
}
netif_set_up(esp_netif[netif_index]);
netif_set_default(esp_netif[netif_index]);
}
uint8_t opmode = wifi_get_opmode();
if (opmode == STATION_MODE) {
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 netif_index, struct ip_info* 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 netif_index, struct ip_info* 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("Get netif[%d] ip info\n", netif_index);
if_ip->ip = esp_netif[netif_index]->ip_addr.u_addr.ip4;
if_ip->netmask = esp_netif[netif_index]->netmask.u_addr.ip4;
if_ip->gw = esp_netif[netif_index]->gw.u_addr.ip4;
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;
}
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 LWIP_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;
}
#endif
return true;
}
bool wifi_softap_dhcps_start(void)
{
uint8_t opmode = NULL_MODE;
TCPIP_ATAPTER_LOG("start softap dhcps\n");
taskENTER_CRITICAL();
opmode = wifi_get_opmode();
if ((opmode == STATION_MODE) || (opmode == NULL_MODE)) {
taskEXIT_CRITICAL();
TCPIP_ATAPTER_LOG("ERROR you shoud enable wifi softap before start dhcp server\n");
return false;
}
if (dhcps_flag == false) {
struct ip_info ipinfo;
wifi_get_ip_info(SOFTAP_IF, &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()
{
uint8_t opmode = NULL_MODE;
taskENTER_CRITICAL();
opmode = wifi_get_opmode();
if ((opmode == STATION_MODE) || (opmode == NULL_MODE)) {
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()
{
uint8_t opmode = NULL_MODE;
s8 ret;
taskENTER_CRITICAL();
opmode = wifi_get_opmode();
if ((opmode == SOFTAP_MODE) || (opmode == NULL_MODE)) {
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()
{
uint8_t opmode = NULL_MODE;
taskENTER_CRITICAL();
opmode = wifi_get_opmode();
if ((opmode == SOFTAP_MODE) || (opmode == NULL_MODE)) {
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 len = strlen(name);
if (len > 32) {
return false;
}
uint8_t opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == STATIONAP_MODE) {
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;
}
}