1206 lines
36 KiB
C
1206 lines
36 KiB
C
#include "lwip/inet.h"
|
||
#include "lwip/err.h"
|
||
#include "lwip/pbuf.h"
|
||
#include "lwip/udp.h"
|
||
#include "lwip/mem.h"
|
||
//#include "crypto/common.h"
|
||
#include "osapi.h"
|
||
#include "lwip/app/dhcpserver.h"
|
||
|
||
#ifndef LWIP_OPEN_SRC
|
||
#include "net80211/ieee80211_var.h"
|
||
#endif
|
||
|
||
#include "user_interface.h"
|
||
|
||
#ifdef MEMLEAK_DEBUG
|
||
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
|
||
#endif
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////
|
||
//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
|
||
//static u8_t old_xid[4] = {0};
|
||
static const uint32 magic_cookie ICACHE_RODATA_ATTR = 0x63538263;
|
||
static struct udp_pcb *pcb_dhcps = NULL;
|
||
static struct ip_addr broadcast_dhcps;
|
||
static struct ip_addr server_address;
|
||
static struct ip_addr client_address;//added
|
||
|
||
static struct dhcps_lease dhcps_lease;
|
||
//static bool dhcps_lease_flag = true;
|
||
static list_node *plist = NULL;
|
||
static uint8 offer = 0xFF;
|
||
static bool renew = false;
|
||
#define DHCPS_LEASE_TIME_DEF (120)
|
||
uint32 dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
|
||
|
||
void wifi_softap_dhcps_client_leave(u8 *bssid, struct ip_addr *ip,bool force);
|
||
uint32 wifi_softap_dhcps_client_update(u8 *bssid, struct ip_addr *ip);
|
||
|
||
/******************************************************************************
|
||
* FunctionName : node_insert_to_list
|
||
* Description : insert the node to the list
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
void ICACHE_FLASH_ATTR 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;
|
||
if (*phead == NULL)
|
||
*phead = pinsert;
|
||
else {
|
||
plist = *phead;
|
||
pdhcps_node = pinsert->pnode;
|
||
pdhcps_pool = plist->pnode;
|
||
|
||
if(pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
|
||
pinsert->pnext = plist;
|
||
*phead = pinsert;
|
||
} else {
|
||
while (plist->pnext != NULL) {
|
||
pdhcps_pool = plist->pnext->pnode;
|
||
if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
|
||
pinsert->pnext = plist->pnext;
|
||
plist->pnext = pinsert;
|
||
break;
|
||
}
|
||
plist = plist->pnext;
|
||
}
|
||
|
||
if(plist->pnext == NULL) {
|
||
plist->pnext = pinsert;
|
||
}
|
||
}
|
||
}
|
||
// pinsert->pnext = NULL;
|
||
}
|
||
|
||
/******************************************************************************
|
||
* FunctionName : node_delete_from_list
|
||
* Description : remove the node from list
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdelete)
|
||
{
|
||
list_node *plist = NULL;
|
||
|
||
plist = *phead;
|
||
if (plist == NULL){
|
||
*phead = NULL;
|
||
} else {
|
||
if (plist == pdelete){
|
||
*phead = plist->pnext;
|
||
pdelete->pnext = NULL;
|
||
} else {
|
||
while (plist != NULL) {
|
||
if (plist->pnext == pdelete){
|
||
plist->pnext = pdelete->pnext;
|
||
pdelete->pnext = NULL;
|
||
}
|
||
plist = plist->pnext;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><>DHCP msg<73><67>Ϣ<EFBFBD>ṹ<EFBFBD><E1B9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* @param optptr -- DHCP msg<73><67>Ϣλ<CFA2><CEBB>
|
||
* @param type -- Ҫ<><D2AA>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>option
|
||
*
|
||
* @return uint8_t* <20><><EFBFBD><EFBFBD>DHCP msgƫ<67>Ƶ<EFBFBD>ַ
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static uint8_t* ICACHE_FLASH_ATTR add_msg_type(uint8_t *optptr, uint8_t type)
|
||
{
|
||
|
||
*optptr++ = DHCP_OPTION_MSG_TYPE;
|
||
*optptr++ = 1;
|
||
*optptr++ = type;
|
||
return optptr;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><>DHCP msg<73>ṹ<EFBFBD><E1B9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>offerӦ<72><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* @param optptr -- DHCP msg<73><67>Ϣλ<CFA2><CEBB>
|
||
*
|
||
* @return uint8_t* <20><><EFBFBD><EFBFBD>DHCP msgƫ<67>Ƶ<EFBFBD>ַ
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
|
||
{
|
||
struct ip_addr ipadd;
|
||
|
||
ipadd.addr = *( (uint32_t *) &server_address);
|
||
|
||
#ifdef USE_CLASS_B_NET
|
||
*optptr++ = DHCP_OPTION_SUBNET_MASK;
|
||
*optptr++ = 4; //length
|
||
*optptr++ = 255;
|
||
*optptr++ = 240;
|
||
*optptr++ = 0;
|
||
*optptr++ = 0;
|
||
#else
|
||
*optptr++ = DHCP_OPTION_SUBNET_MASK;
|
||
*optptr++ = 4;
|
||
*optptr++ = 255;
|
||
*optptr++ = 255;
|
||
*optptr++ = 255;
|
||
*optptr++ = 0;
|
||
#endif
|
||
|
||
*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++ = DHCP_OPTION_SERVER_ID;
|
||
*optptr++ = 4;
|
||
*optptr++ = ip4_addr1( &ipadd);
|
||
*optptr++ = ip4_addr2( &ipadd);
|
||
*optptr++ = ip4_addr3( &ipadd);
|
||
*optptr++ = ip4_addr4( &ipadd);
|
||
|
||
if (dhcps_router_enabled(offer)){
|
||
struct ip_info if_ip;
|
||
os_bzero(&if_ip, sizeof(struct ip_info));
|
||
wifi_get_ip_info(SOFTAP_IF, &if_ip);
|
||
|
||
*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
|
||
|
||
#ifdef CLASS_B_NET
|
||
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
|
||
*optptr++ = 4;
|
||
*optptr++ = ip4_addr1( &ipadd);
|
||
*optptr++ = 255;
|
||
*optptr++ = 255;
|
||
*optptr++ = 255;
|
||
#else
|
||
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
|
||
*optptr++ = 4;
|
||
*optptr++ = ip4_addr1( &ipadd);
|
||
*optptr++ = ip4_addr2( &ipadd);
|
||
*optptr++ = ip4_addr3( &ipadd);
|
||
*optptr++ = 255;
|
||
#endif
|
||
|
||
*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;
|
||
*optptr++ = 0x00;
|
||
|
||
*optptr++ = 43;
|
||
*optptr++ = 6;
|
||
|
||
*optptr++ = 0x01;
|
||
*optptr++ = 4;
|
||
*optptr++ = 0x00;
|
||
*optptr++ = 0x00;
|
||
*optptr++ = 0x00;
|
||
*optptr++ = 0x02;
|
||
|
||
return optptr;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><>DHCP msg<73>ṹ<EFBFBD><E1B9B9><EFBFBD><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>
|
||
*
|
||
* @param optptr -- DHCP msg<73><67>Ϣλ<CFA2><CEBB>
|
||
*
|
||
* @return uint8_t* <20><><EFBFBD><EFBFBD>DHCP msgƫ<67>Ƶ<EFBFBD>ַ
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
|
||
{
|
||
|
||
*optptr++ = DHCP_OPTION_END;
|
||
return optptr;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
|
||
{
|
||
struct ip_addr client;
|
||
|
||
client.addr = client_address.addr;
|
||
|
||
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);
|
||
|
||
os_memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
|
||
|
||
os_memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
|
||
os_memset((char *) m->siaddr, 0, sizeof(m->siaddr));
|
||
os_memset((char *) m->giaddr, 0, sizeof(m->giaddr));
|
||
os_memset((char *) m->sname, 0, sizeof(m->sname));
|
||
os_memset((char *) m->file, 0, sizeof(m->file));
|
||
|
||
os_memset((char *) m->options, 0, sizeof(m->options));
|
||
|
||
//For xiaomi crash bug
|
||
uint32 magic_cookie1 = magic_cookie;
|
||
os_memcpy((char *) m->options, &magic_cookie1, sizeof(magic_cookie1));
|
||
}
|
||
|
||
struct pbuf * dhcps_pbuf_alloc(u16_t len)
|
||
{
|
||
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);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>OFFER
|
||
*
|
||
* @param -- m ָ<><D6B8><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>DHCP msg<73><67><EFBFBD><EFBFBD>
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m, u16_t len)
|
||
{
|
||
uint8_t *end;
|
||
struct pbuf *p, *q;
|
||
u8_t *data;
|
||
u16_t cnt=0;
|
||
u16_t i;
|
||
err_t SendOffer_err_t;
|
||
create_msg(m);
|
||
|
||
end = add_msg_type(&m->options[4], DHCPOFFER);
|
||
end = add_offer_options(end);
|
||
end = add_end(end);
|
||
|
||
p = dhcps_pbuf_alloc(len);
|
||
#if DHCPS_DEBUG
|
||
os_printf("udhcp: send_offer>>p->ref = %d\n", p->ref);
|
||
#endif
|
||
if(p != NULL){
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_offer>>pbuf_alloc succeed\n");
|
||
os_printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
|
||
os_printf("dhcps: send_offer>>p->len = %d\n", p->len);
|
||
#endif
|
||
q = p;
|
||
while(q != NULL){
|
||
data = (u8_t *)q->payload;
|
||
for(i=0; i<q->len; i++)
|
||
{
|
||
data[i] = ((u8_t *) m)[cnt++];
|
||
}
|
||
|
||
q = q->next;
|
||
}
|
||
}else{
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_offer>>pbuf_alloc failed\n");
|
||
#endif
|
||
return;
|
||
}
|
||
SendOffer_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t);
|
||
#endif
|
||
if(p->ref != 0){
|
||
#if DHCPS_DEBUG
|
||
os_printf("udhcp: send_offer>>free pbuf\n");
|
||
#endif
|
||
pbuf_free(p);
|
||
}
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>NAK<41><4B>Ϣ
|
||
*
|
||
* @param m ָ<><D6B8><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>DHCP msg<73><67><EFBFBD><EFBFBD>
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static void ICACHE_FLASH_ATTR 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;
|
||
err_t SendNak_err_t;
|
||
create_msg(m);
|
||
|
||
end = add_msg_type(&m->options[4], DHCPNAK);
|
||
end = add_end(end);
|
||
|
||
p = dhcps_pbuf_alloc(len);
|
||
#if DHCPS_DEBUG
|
||
os_printf("udhcp: send_nak>>p->ref = %d\n", p->ref);
|
||
#endif
|
||
if(p != NULL){
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_nak>>pbuf_alloc succeed\n");
|
||
os_printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
|
||
os_printf("dhcps: send_nak>>p->len = %d\n", p->len);
|
||
#endif
|
||
q = p;
|
||
while(q != NULL){
|
||
data = (u8_t *)q->payload;
|
||
for(i=0; i<q->len; i++)
|
||
{
|
||
data[i] = ((u8_t *) m)[cnt++];
|
||
}
|
||
|
||
q = q->next;
|
||
}
|
||
}else{
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_nak>>pbuf_alloc failed\n");
|
||
#endif
|
||
return;
|
||
}
|
||
SendNak_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t);
|
||
#endif
|
||
if(p->ref != 0){
|
||
#if DHCPS_DEBUG
|
||
os_printf("udhcp: send_nak>>free pbuf\n");
|
||
#endif
|
||
pbuf_free(p);
|
||
}
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ACK<43><4B>DHCP<43>ͻ<EFBFBD><CDBB><EFBFBD>
|
||
*
|
||
* @param m ָ<><D6B8><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>DHCP msg<73><67><EFBFBD><EFBFBD>
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static void ICACHE_FLASH_ATTR 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;
|
||
err_t SendAck_err_t;
|
||
create_msg(m);
|
||
|
||
end = add_msg_type(&m->options[4], DHCPACK);
|
||
end = add_offer_options(end);
|
||
end = add_end(end);
|
||
|
||
p = dhcps_pbuf_alloc(len);
|
||
#if DHCPS_DEBUG
|
||
os_printf("udhcp: send_ack>>p->ref = %d\n", p->ref);
|
||
#endif
|
||
if(p != NULL){
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_ack>>pbuf_alloc succeed\n");
|
||
os_printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
|
||
os_printf("dhcps: send_ack>>p->len = %d\n", p->len);
|
||
#endif
|
||
q = p;
|
||
while(q != NULL){
|
||
data = (u8_t *)q->payload;
|
||
for(i=0; i<q->len; i++)
|
||
{
|
||
data[i] = ((u8_t *) m)[cnt++];
|
||
}
|
||
|
||
q = q->next;
|
||
}
|
||
}else{
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_ack>>pbuf_alloc failed\n");
|
||
#endif
|
||
return;
|
||
}
|
||
SendAck_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t);
|
||
#endif
|
||
|
||
if(p->ref != 0){
|
||
#if DHCPS_DEBUG
|
||
os_printf("udhcp: send_ack>>free pbuf\n");
|
||
#endif
|
||
pbuf_free(p);
|
||
}
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* <20><><EFBFBD><EFBFBD>DHCP<43>ͻ<EFBFBD><CDBB>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD>DHCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>ͬ<EFBFBD><CDAC>DHCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>Ӧ<EFBFBD><D3A6>
|
||
*
|
||
* @param optptr DHCP msg<73>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* @param len <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4>?(byte)
|
||
*
|
||
* @return uint8_t <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD>DHCP Server״ֵ̬
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
|
||
{
|
||
struct ip_addr client;
|
||
bool is_dhcp_parse_end = false;
|
||
struct dhcps_state s;
|
||
|
||
client.addr = *( (uint32_t *) &client_address);// Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD>DHCP<43>ͻ<EFBFBD><CDBB>˵<EFBFBD>IP
|
||
|
||
u8_t *end = optptr + len;
|
||
u16_t type = 0;
|
||
|
||
s.state = DHCPS_STATE_IDLE;
|
||
|
||
while (optptr < end) {
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: (sint16_t)*optptr = %d\n", (sint16_t)*optptr);
|
||
#endif
|
||
switch ((sint16_t) *optptr) {
|
||
|
||
case DHCP_OPTION_MSG_TYPE: //53
|
||
type = *(optptr + 2);
|
||
break;
|
||
|
||
case DHCP_OPTION_REQ_IPADDR://50
|
||
//os_printf("dhcps:0x%08x,0x%08x\n",client.addr,*(uint32*)(optptr+2));
|
||
if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
|
||
#endif
|
||
s.state = DHCPS_STATE_ACK;
|
||
}else {
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
|
||
#endif
|
||
s.state = DHCPS_STATE_NAK;
|
||
}
|
||
break;
|
||
case DHCP_OPTION_END:
|
||
{
|
||
is_dhcp_parse_end = true;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if(is_dhcp_parse_end){
|
||
break;
|
||
}
|
||
|
||
optptr += optptr[1] + 2;
|
||
}
|
||
|
||
switch (type){
|
||
|
||
case DHCPDISCOVER://1
|
||
s.state = DHCPS_STATE_OFFER;
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: DHCPD_STATE_OFFER\n");
|
||
#endif
|
||
break;
|
||
|
||
case DHCPREQUEST://3
|
||
if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
|
||
if(renew == true) {
|
||
s.state = DHCPS_STATE_ACK;
|
||
} else {
|
||
s.state = DHCPS_STATE_NAK;
|
||
}
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: DHCPD_STATE_NAK\n");
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case DHCPDECLINE://4
|
||
s.state = DHCPS_STATE_IDLE;
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: DHCPD_STATE_IDLE\n");
|
||
#endif
|
||
break;
|
||
|
||
case DHCPRELEASE://7
|
||
s.state = DHCPS_STATE_RELEASE;
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: DHCPD_STATE_IDLE\n");
|
||
#endif
|
||
break;
|
||
}
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: return s.state = %d\n", s.state);
|
||
#endif
|
||
return s.state;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
|
||
{
|
||
if(os_memcmp((char *)m->options,
|
||
&magic_cookie,
|
||
sizeof(magic_cookie)) == 0){
|
||
struct ip_addr ip;
|
||
os_memcpy(&ip.addr,m->ciaddr,sizeof(ip.addr));
|
||
client_address.addr = wifi_softap_dhcps_client_update(m->chaddr,&ip);
|
||
|
||
sint16_t ret = parse_options(&m->options[4], len);
|
||
|
||
if(ret == DHCPS_STATE_RELEASE) {
|
||
wifi_softap_dhcps_client_leave(m->chaddr,&ip,TRUE); // force to delete
|
||
client_address.addr = ip.addr;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
return 0;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
* DHCP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD>մ<EFBFBD><D5B4><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD>LWIP UDPģ<50><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>udp_recv()<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>LWIP<49><50><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>.
|
||
*
|
||
* @param arg
|
||
* @param pcb <20><><EFBFBD>յ<EFBFBD>UDP<44><50>Ŀ<EFBFBD><C4BF>ƿ<EFBFBD>?
|
||
* @param p <20><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>UDP<44>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||
* @param addr <20><><EFBFBD>ʹ<EFBFBD>UDP<44><50><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>IP<49><50>ַ
|
||
* @param port <20><><EFBFBD>ʹ<EFBFBD>UDP<44><50><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>UDPͨ<50><CDA8><EFBFBD>˿ں<CBBF>
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
|
||
struct udp_pcb *pcb,
|
||
struct pbuf *p,
|
||
struct ip_addr *addr,
|
||
uint16_t port)
|
||
{
|
||
struct dhcps_msg *pmsg_dhcps = NULL;
|
||
sint16_t tlen = 0, malloc_len;
|
||
u16_t i = 0;
|
||
u16_t dhcps_msg_cnt = 0;
|
||
u8_t *p_dhcps_msg = NULL;
|
||
u8_t *data = NULL;
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> receive a packet\n");
|
||
#endif
|
||
if (p==NULL) return;
|
||
|
||
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 *)os_malloc(malloc_len);
|
||
if (NULL == pmsg_dhcps){
|
||
pbuf_free(p);
|
||
return;
|
||
}
|
||
memset(pmsg_dhcps , 0x00 , malloc_len);
|
||
|
||
p_dhcps_msg = (u8_t *)pmsg_dhcps;
|
||
tlen = p->tot_len;
|
||
data = p->payload;
|
||
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
|
||
os_printf("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(p->next != NULL) {
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
|
||
os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
|
||
os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
|
||
#endif
|
||
|
||
data = p->next->payload;
|
||
for(i=0; i<p->next->len; i++){
|
||
p_dhcps_msg[dhcps_msg_cnt++] = data[i];
|
||
}
|
||
}
|
||
|
||
/*
|
||
* DHCP <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>
|
||
*/
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
|
||
#endif
|
||
|
||
switch(parse_msg(pmsg_dhcps, tlen - 240)) {
|
||
|
||
case DHCPS_STATE_OFFER://1
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
|
||
#endif
|
||
send_offer(pmsg_dhcps, malloc_len);
|
||
break;
|
||
case DHCPS_STATE_ACK://3
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
|
||
#endif
|
||
send_ack(pmsg_dhcps, malloc_len);
|
||
wifi_softap_set_station_info(pmsg_dhcps->chaddr, &client_address.addr);
|
||
break;
|
||
case DHCPS_STATE_NAK://4
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
|
||
#endif
|
||
send_nak(pmsg_dhcps, malloc_len);
|
||
break;
|
||
default :
|
||
break;
|
||
}
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
|
||
#endif
|
||
pbuf_free(p);
|
||
os_free(pmsg_dhcps);
|
||
pmsg_dhcps = NULL;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
|
||
{
|
||
uint32 softap_ip = 0,local_ip = 0;
|
||
uint32 start_ip = 0;
|
||
uint32 end_ip = 0;
|
||
// if (dhcps_lease_flag) {
|
||
if (dhcps_lease.enable == TRUE) {
|
||
softap_ip = htonl(ip);
|
||
start_ip = htonl(dhcps_lease.start_ip.addr);
|
||
end_ip = htonl(dhcps_lease.end_ip.addr);
|
||
/*config ip information can't contain local ip*/
|
||
if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
|
||
dhcps_lease.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;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (dhcps_lease.enable == FALSE) {
|
||
local_ip = softap_ip = htonl(ip);
|
||
softap_ip &= 0xFFFFFF00;
|
||
local_ip &= 0xFF;
|
||
if (local_ip >= 0x80)
|
||
local_ip -= DHCPS_MAX_LEASE;
|
||
else
|
||
local_ip ++;
|
||
|
||
os_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);
|
||
}
|
||
// dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
|
||
// dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
|
||
// os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
|
||
}
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
|
||
{
|
||
struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
|
||
|
||
if(apnetif->dhcps_pcb != NULL) {
|
||
udp_remove(apnetif->dhcps_pcb);
|
||
}
|
||
|
||
pcb_dhcps = udp_new();
|
||
if (pcb_dhcps == NULL || info ==NULL) {
|
||
os_printf("dhcps_start(): could not obtain pcb\n");
|
||
}
|
||
|
||
apnetif->dhcps_pcb = pcb_dhcps;
|
||
|
||
IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
|
||
|
||
server_address = info->ip;
|
||
wifi_softap_init_dhcps_lease(server_address.addr);
|
||
|
||
udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
|
||
udp_recv(pcb_dhcps, handle_dhcp, NULL);
|
||
#if DHCPS_DEBUG
|
||
os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
|
||
#endif
|
||
|
||
}
|
||
|
||
void ICACHE_FLASH_ATTR dhcps_stop(void)
|
||
{
|
||
struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
|
||
|
||
udp_disconnect(pcb_dhcps);
|
||
// dhcps_lease_flag = true;
|
||
if(apnetif->dhcps_pcb != NULL) {
|
||
udp_remove(apnetif->dhcps_pcb);
|
||
apnetif->dhcps_pcb = NULL;
|
||
}
|
||
|
||
//udp_remove(pcb_dhcps);
|
||
list_node *pnode = NULL;
|
||
list_node *pback_node = NULL;
|
||
struct dhcps_pool* dhcp_node = NULL;
|
||
struct ip_addr ip_zero;
|
||
|
||
os_memset(&ip_zero,0x0,sizeof(ip_zero));
|
||
pnode = plist;
|
||
while (pnode != NULL) {
|
||
pback_node = pnode;
|
||
pnode = pback_node->pnext;
|
||
node_remove_from_list(&plist, pback_node);
|
||
dhcp_node = (struct dhcps_pool*)pback_node->pnode;
|
||
//wifi_softap_dhcps_client_leave(dhcp_node->mac,&dhcp_node->ip,TRUE); // force to delete
|
||
wifi_softap_set_station_info(dhcp_node->mac, &ip_zero);
|
||
os_free(pback_node->pnode);
|
||
pback_node->pnode = NULL;
|
||
os_free(pback_node);
|
||
pback_node = NULL;
|
||
}
|
||
}
|
||
|
||
/******************************************************************************
|
||
* FunctionName : wifi_softap_set_dhcps_lease
|
||
* Description : set the lease information of DHCP server
|
||
* Parameters : please -- Additional argument to set the lease information,
|
||
* Little-Endian.
|
||
* Returns : true or false
|
||
*******************************************************************************/
|
||
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
|
||
{
|
||
struct ip_info info;
|
||
uint32 softap_ip = 0;
|
||
uint32 start_ip = 0;
|
||
uint32 end_ip = 0;
|
||
|
||
uint8 opmode = wifi_get_opmode();
|
||
|
||
if (opmode == STATION_MODE || opmode == NULL_MODE) {
|
||
return false;
|
||
}
|
||
|
||
if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED)
|
||
return false;
|
||
|
||
if(please->enable) {
|
||
os_bzero(&info, sizeof(struct ip_info));
|
||
wifi_get_ip_info(SOFTAP_IF, &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;
|
||
|
||
os_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
|
||
*******************************************************************************/
|
||
bool ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease(struct dhcps_lease *please)
|
||
{
|
||
uint8 opmode = wifi_get_opmode();
|
||
|
||
if (opmode == STATION_MODE || opmode == NULL_MODE) {
|
||
return false;
|
||
}
|
||
|
||
if (NULL == please)
|
||
return false;
|
||
|
||
// if (dhcps_lease_flag){
|
||
if (dhcps_lease.enable == FALSE){
|
||
if (wifi_softap_dhcps_status() == DHCP_STOPPED)
|
||
return false;
|
||
} else {
|
||
// os_bzero(please, sizeof(dhcps_lease));
|
||
// if (wifi_softap_dhcps_status() == DHCP_STOPPED){
|
||
// please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
|
||
// please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
|
||
// }
|
||
}
|
||
|
||
// if (wifi_softap_dhcps_status() == DHCP_STARTED){
|
||
// os_bzero(please, sizeof(dhcps_lease));
|
||
// please->start_ip.addr = dhcps_lease.start_ip.addr;
|
||
// please->end_ip.addr = dhcps_lease.end_ip.addr;
|
||
// }
|
||
please->start_ip.addr = dhcps_lease.start_ip.addr;
|
||
please->end_ip.addr = dhcps_lease.end_ip.addr;
|
||
return true;
|
||
}
|
||
|
||
static void ICACHE_FLASH_ATTR 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;
|
||
pre = plist;
|
||
p = pre->pnext;
|
||
minpre = pre;
|
||
minp = p;
|
||
while (p != NULL){
|
||
pdhcps_pool = p->pnode;
|
||
pmin_pool = minp->pnode;
|
||
if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){
|
||
minp = p;
|
||
minpre = pre;
|
||
}
|
||
pre = p;
|
||
p = p->pnext;
|
||
}
|
||
minpre->pnext = minp->pnext;
|
||
os_free(minp->pnode);
|
||
minp->pnode = NULL;
|
||
os_free(minp);
|
||
minp = NULL;
|
||
}
|
||
|
||
void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
|
||
{
|
||
uint8 num_dhcps_pool = 0;
|
||
list_node *pback_node = NULL;
|
||
list_node *pnode = NULL;
|
||
struct dhcps_pool *pdhcps_pool = NULL;
|
||
pnode = plist;
|
||
while (pnode != NULL) {
|
||
pdhcps_pool = pnode->pnode;
|
||
if ( pdhcps_pool->type == DHCPS_TYPE_DYNAMIC) {
|
||
pdhcps_pool->lease_timer --;
|
||
}
|
||
if (pdhcps_pool->lease_timer == 0){
|
||
pback_node = pnode;
|
||
pnode = pback_node->pnext;
|
||
node_remove_from_list(&plist,pback_node);
|
||
os_free(pback_node->pnode);
|
||
pback_node->pnode = NULL;
|
||
os_free(pback_node);
|
||
pback_node = NULL;
|
||
} else {
|
||
pnode = pnode ->pnext;
|
||
num_dhcps_pool ++;
|
||
}
|
||
}
|
||
|
||
if (num_dhcps_pool >= MAX_STATION_NUM)
|
||
kill_oldest_dhcps_pool();
|
||
}
|
||
|
||
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
|
||
{
|
||
bool offer_flag = true;
|
||
uint8 option = 0;
|
||
if (optarg == NULL && wifi_softap_dhcps_status() == false)
|
||
return false;
|
||
|
||
if (level <= OFFER_START || level >= OFFER_END)
|
||
return false;
|
||
|
||
switch (level){
|
||
case OFFER_ROUTER:
|
||
offer = (*(uint8 *)optarg) & 0x01;
|
||
offer_flag = true;
|
||
break;
|
||
default :
|
||
offer_flag = false;
|
||
break;
|
||
}
|
||
return offer_flag;
|
||
}
|
||
|
||
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease_time(uint32 minute)
|
||
{
|
||
uint8 opmode = wifi_get_opmode();
|
||
|
||
if (opmode == STATION_MODE || opmode == NULL_MODE) {
|
||
return false;
|
||
}
|
||
|
||
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
|
||
return false;
|
||
}
|
||
|
||
if(minute == 0) {
|
||
return false;
|
||
}
|
||
dhcps_lease_time = minute;
|
||
return true;
|
||
}
|
||
|
||
bool ICACHE_FLASH_ATTR wifi_softap_reset_dhcps_lease_time(void)
|
||
{
|
||
uint8 opmode = wifi_get_opmode();
|
||
|
||
if (opmode == STATION_MODE || opmode == NULL_MODE) {
|
||
return false;
|
||
}
|
||
|
||
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
|
||
return false;
|
||
}
|
||
dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
|
||
return true;
|
||
}
|
||
|
||
uint32 ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease_time(void) // minute
|
||
{
|
||
return dhcps_lease_time;
|
||
}
|
||
|
||
void ICACHE_FLASH_ATTR wifi_softap_dhcps_client_leave(u8 *bssid, struct ip_addr *ip,bool force)
|
||
{
|
||
struct dhcps_pool *pdhcps_pool = NULL;
|
||
list_node *pback_node = NULL;
|
||
|
||
if ((bssid == NULL) || (ip == NULL)) {
|
||
return;
|
||
}
|
||
|
||
for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
|
||
pdhcps_pool = pback_node->pnode;
|
||
if (os_memcmp(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac)) == 0){
|
||
if (os_memcmp(&pdhcps_pool->ip.addr, &ip->addr, sizeof(pdhcps_pool->ip.addr)) == 0) {
|
||
if ((pdhcps_pool->type == DHCPS_TYPE_STATIC) || (force)) {
|
||
if(pback_node != NULL) {
|
||
node_remove_from_list(&plist,pback_node);
|
||
os_free(pback_node);
|
||
pback_node = NULL;
|
||
}
|
||
|
||
if (pdhcps_pool != NULL) {
|
||
os_free(pdhcps_pool);
|
||
pdhcps_pool = NULL;
|
||
}
|
||
} else {
|
||
pdhcps_pool->state = DHCPS_STATE_OFFLINE;
|
||
}
|
||
|
||
struct ip_addr ip_zero;
|
||
os_memset(&ip_zero,0x0,sizeof(ip_zero));
|
||
wifi_softap_set_station_info(bssid, &ip_zero);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
uint32 ICACHE_FLASH_ATTR wifi_softap_dhcps_client_update(u8 *bssid, struct ip_addr *ip)
|
||
{
|
||
struct dhcps_pool *pdhcps_pool = NULL;
|
||
list_node *pback_node = NULL;
|
||
list_node *pmac_node = NULL;
|
||
list_node *pip_node = NULL;
|
||
bool flag = FALSE;
|
||
uint32 start_ip = dhcps_lease.start_ip.addr;
|
||
uint32 end_ip = dhcps_lease.end_ip.addr;
|
||
dhcps_type_t type = DHCPS_TYPE_DYNAMIC;
|
||
if (bssid == NULL) {
|
||
return IPADDR_ANY;
|
||
}
|
||
|
||
if (ip) {
|
||
if (IPADDR_BROADCAST == ip->addr) {
|
||
return IPADDR_ANY;
|
||
} else if (IPADDR_ANY == ip->addr) {
|
||
ip = NULL;
|
||
} else {
|
||
type = DHCPS_TYPE_STATIC;
|
||
}
|
||
}
|
||
|
||
renew = FALSE;
|
||
for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
|
||
pdhcps_pool = pback_node->pnode;
|
||
//os_printf("mac:"MACSTR"bssid:"MACSTR"\r\n",MAC2STR(pdhcps_pool->mac),MAC2STR(bssid));
|
||
if (os_memcmp(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac)) == 0){
|
||
pmac_node = pback_node;
|
||
if (ip == NULL) {
|
||
flag = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
if (ip != NULL) {
|
||
if (os_memcmp(&pdhcps_pool->ip.addr, &ip->addr, sizeof(pdhcps_pool->ip.addr)) == 0) {
|
||
pip_node = pback_node;
|
||
}
|
||
} else if (flag == FALSE){
|
||
if (os_memcmp(&pdhcps_pool->ip.addr, &start_ip, sizeof(pdhcps_pool->ip.addr)) != 0) {
|
||
flag = TRUE;
|
||
} else {
|
||
start_ip = htonl((ntohl(start_ip) + 1));
|
||
}
|
||
}
|
||
}
|
||
|
||
if ((ip == NULL) && (flag == FALSE)) {
|
||
if (plist == NULL) {
|
||
if (start_ip <= end_ip) {
|
||
flag = TRUE;
|
||
} else {
|
||
return IPADDR_ANY;
|
||
}
|
||
} else {
|
||
if (start_ip > end_ip) {
|
||
return IPADDR_ANY;
|
||
}
|
||
//start_ip = htonl((ntohl(start_ip) + 1));
|
||
flag = TRUE;
|
||
}
|
||
}
|
||
|
||
if (pmac_node != NULL) { // update new ip
|
||
if (pip_node != NULL){
|
||
pdhcps_pool = pip_node->pnode;
|
||
|
||
if (pip_node != pmac_node) {
|
||
if(pdhcps_pool->state != DHCPS_STATE_OFFLINE) { // ip is used
|
||
return IPADDR_ANY;
|
||
}
|
||
|
||
// mac exists and ip exists in other node,delete mac
|
||
node_remove_from_list(&plist,pmac_node);
|
||
os_free(pmac_node->pnode);
|
||
pmac_node->pnode = NULL;
|
||
os_free(pmac_node);
|
||
pmac_node = pip_node;
|
||
os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
|
||
} else {
|
||
renew = true;
|
||
type = DHCPS_TYPE_DYNAMIC;
|
||
}
|
||
|
||
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
|
||
pdhcps_pool->type = type;
|
||
pdhcps_pool->state = DHCPS_STATE_ONLINE;
|
||
|
||
} else {
|
||
pdhcps_pool = pmac_node->pnode;
|
||
if (ip != NULL) {
|
||
pdhcps_pool->ip.addr = ip->addr;
|
||
} else if (flag == TRUE) {
|
||
pdhcps_pool->ip.addr = start_ip;
|
||
} else { // no ip to distribute
|
||
return IPADDR_ANY;
|
||
}
|
||
|
||
node_remove_from_list(&plist,pmac_node);
|
||
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
|
||
pdhcps_pool->type = type;
|
||
pdhcps_pool->state = DHCPS_STATE_ONLINE;
|
||
node_insert_to_list(&plist,pmac_node);
|
||
}
|
||
} else { // new station
|
||
if (pip_node != NULL) { // maybe ip has used
|
||
pdhcps_pool = pip_node->pnode;
|
||
if (pdhcps_pool->state != DHCPS_STATE_OFFLINE) {
|
||
return IPADDR_ANY;
|
||
}
|
||
os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
|
||
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
|
||
pdhcps_pool->type = type;
|
||
pdhcps_pool->state = DHCPS_STATE_ONLINE;
|
||
} else {
|
||
pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
|
||
if (ip != NULL) {
|
||
pdhcps_pool->ip.addr = ip->addr;
|
||
} else if (flag == TRUE) {
|
||
pdhcps_pool->ip.addr = start_ip;
|
||
} else { // no ip to distribute
|
||
os_free(pdhcps_pool);
|
||
return IPADDR_ANY;
|
||
}
|
||
if (pdhcps_pool->ip.addr > end_ip) {
|
||
os_free(pdhcps_pool);
|
||
return IPADDR_ANY;
|
||
}
|
||
os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
|
||
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
|
||
pdhcps_pool->type = type;
|
||
pdhcps_pool->state = DHCPS_STATE_ONLINE;
|
||
pback_node = (list_node *)os_zalloc(sizeof(list_node ));
|
||
pback_node->pnode = pdhcps_pool;
|
||
pback_node->pnext = NULL;
|
||
node_insert_to_list(&plist,pback_node);
|
||
}
|
||
}
|
||
|
||
return pdhcps_pool->ip.addr;
|
||
}
|