1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

DHCP custom option (#8582)

* works

* fixup! works

* back to callbacks

* names

* daisy chain

* seconds

* less inline

* fix dns setter

* might as well keep using initlist

/to d-a-v it has automatic storage, here it's the same stack based one
(just one less line for us)

* shift blame

* naming

* fix impl

* revert to ip4 dns

* merge fix

* restyle

* masking done wrong
This commit is contained in:
Max Prokhorov 2022-06-09 00:19:59 +03:00 committed by GitHub
parent 9e2103f27e
commit b7c1cfbc45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 328 additions and 385 deletions

View File

@ -71,19 +71,21 @@ extern "C"
uint32 wifi_softap_get_dhcps_lease_time()
{
auto& server = getNonOSDhcpServer();
return server.get_dhcps_lease_time();
return server.getLeaseTime();
}
bool wifi_softap_set_dhcps_lease_time(uint32 minutes)
{
auto& server = getNonOSDhcpServer();
return server.set_dhcps_lease_time(minutes);
server.setLeaseTime(minutes);
return true;
}
bool wifi_softap_reset_dhcps_lease_time()
{
auto& server = getNonOSDhcpServer();
return server.reset_dhcps_lease_time();
server.resetLeaseTime();
return true;
}
bool wifi_softap_add_dhcps_lease(uint8* macaddr)

View File

@ -50,6 +50,9 @@
#include "user_interface.h"
#include "mem.h"
#include <cstring>
#include <sys/pgmspace.h>
typedef struct dhcps_state
{
sint16_t state;
@ -78,12 +81,6 @@ struct dhcps_lease
struct ipv4_addr end_ip;
};
enum dhcps_offer_option
{
OFFER_START = 0x00,
OFFER_ROUTER = 0x01,
OFFER_END
};
#endif
typedef enum
@ -107,7 +104,6 @@ struct dhcps_pool
dhcps_state_t state;
};
#define DHCPS_LEASE_TIMER dhcps_lease_time // 0x05A0
#define DHCPS_MAX_LEASE 0x64
#define BOOTP_BROADCAST 0x8000
@ -120,13 +116,13 @@ struct dhcps_pool
#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
static constexpr uint8_t DHCPDISCOVER = 1;
static constexpr uint8_t DHCPOFFER = 2;
static constexpr uint8_t DHCPREQUEST = 3;
static constexpr uint8_t DHCPDECLINE = 4;
static constexpr uint8_t DHCPACK = 5;
static constexpr uint8_t DHCPNAK = 6;
static constexpr uint8_t DHCPRELEASE = 7;
#define DHCP_OPTION_SUBNET_MASK 1
#define DHCP_OPTION_ROUTER 3
@ -152,8 +148,6 @@ struct dhcps_pool
#define DHCPS_STATE_IDLE 5
#define DHCPS_STATE_RELEASE 6
#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0)
#ifdef MEMLEAK_DEBUG
const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
@ -175,20 +169,35 @@ const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
////////////////////////////////////////////////////////////////////////////////////
DhcpServer::OptionsBuffer& DhcpServer::OptionsBuffer::add(uint8_t code, const uint8_t* data,
size_t size)
{
if (size >= UINT8_MAX)
{
return *this;
}
if ((size_t)(_end - _it) < (size + 2))
{
return *this;
}
*_it++ = code;
*_it++ = size;
memcpy_P(_it, data, size);
_it += size;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////
DhcpServer::DhcpServer(netif* netif) : _netif(netif) { }
// wifi_softap_set_station_info is missing in user_interface.h:
extern "C" void wifi_softap_set_station_info(uint8_t* mac, struct ipv4_addr*);
void DhcpServer::dhcps_set_dns(int num, const ipv4_addr_t* dns)
{
(void)num;
if (!ip4_addr_isany(dns))
{
ip4_addr_copy(dns_address, *dns);
}
}
/******************************************************************************
FunctionName : node_insert_to_list
Description : insert the node to the list
@ -286,8 +295,8 @@ bool DhcpServer::add_dhcps_lease(uint8* macaddr)
struct dhcps_pool* pdhcps_pool = nullptr;
list_node* pback_node = nullptr;
uint32 start_ip = dhcps_lease.start_ip.addr;
uint32 end_ip = dhcps_lease.end_ip.addr;
uint32 start_ip = lease.start_ip.addr;
uint32 end_ip = lease.end_ip.addr;
for (pback_node = plist; pback_node != nullptr; pback_node = pback_node->pnext)
{
@ -316,7 +325,7 @@ bool DhcpServer::add_dhcps_lease(uint8* macaddr)
pdhcps_pool = (struct dhcps_pool*)zalloc(sizeof(struct dhcps_pool));
pdhcps_pool->ip.addr = start_ip;
memcpy(pdhcps_pool->mac, macaddr, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->lease_timer = this->lease_time;
pdhcps_pool->type = DHCPS_TYPE_STATIC;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
pback_node = (list_node*)zalloc(sizeof(list_node));
@ -329,145 +338,50 @@ bool DhcpServer::add_dhcps_lease(uint8* macaddr)
///////////////////////////////////////////////////////////////////////////////////
/*
DHCP msg
Set DHCP msg offer options for the given server
@param optptr -- DHCP msg
@param type -- option
@return uint8_t* DHCP msg
@param buffer -- DHCP options buffer
@param server -- DHCP server instance
*/
///////////////////////////////////////////////////////////////////////////////////
uint8_t* DhcpServer::add_msg_type(uint8_t* optptr, uint8_t type)
void DhcpServer::add_offer_options(OptionsBuffer& options)
{
*optptr++ = DHCP_OPTION_MSG_TYPE;
*optptr++ = 1;
*optptr++ = type;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
DHCP msg offer
options.add(DHCP_OPTION_SUBNET_MASK, ip_2_ip4(&_netif->netmask))
.add(DHCP_OPTION_SERVER_ID, ip_2_ip4(&_netif->ip_addr));
@param optptr -- DHCP msg
// option units are seconds, while server opt is minutes
const uint32_t lease_time_seconds = lease_time * 60;
options.add(DHCP_OPTION_LEASE_TIME, lease_time_seconds);
@return uint8_t* DHCP msg
*/
///////////////////////////////////////////////////////////////////////////////////
uint8_t* DhcpServer::add_offer_options(uint8_t* optptr)
{
// struct ipv4_addr ipadd;
// ipadd.addr = server_address.addr;
#define ipadd (_netif->ip_addr)
// struct ip_info if_ip;
// bzero(&if_ip, sizeof(struct ip_info));
// wifi_get_ip_info(SOFTAP_IF, &if_ip);
#define if_ip (*_netif)
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = 4;
*optptr++ = ip4_addr1(ip_2_ip4(&if_ip.netmask));
*optptr++ = ip4_addr2(ip_2_ip4(&if_ip.netmask));
*optptr++ = ip4_addr3(ip_2_ip4(&if_ip.netmask));
*optptr++ = ip4_addr4(ip_2_ip4(&if_ip.netmask));
*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(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr2(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr3(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr4(ip_2_ip4(&ipadd));
if (dhcps_router_enabled(offer) && ip_2_ip4(&if_ip.gw)->addr)
if (offer_router && !ip4_addr_isany_val(*ip_2_ip4(&_netif->gw)))
{
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = 4;
*optptr++ = ip4_addr1(ip_2_ip4(&if_ip.gw));
*optptr++ = ip4_addr2(ip_2_ip4(&if_ip.gw));
*optptr++ = ip4_addr3(ip_2_ip4(&if_ip.gw));
*optptr++ = ip4_addr4(ip_2_ip4(&if_ip.gw));
options.add(DHCP_OPTION_ROUTER, ip_2_ip4(&_netif->gw));
}
#ifdef USE_DNS
*optptr++ = DHCP_OPTION_DNS_SERVER;
*optptr++ = 4;
if (dns_address.addr == 0)
options.add(DHCP_OPTION_DNS_SERVER,
!ip4_addr_isany_val(dns_address) ? &dns_address : ip_2_ip4(&_netif->ip_addr));
#endif
{
*optptr++ = ip4_addr1(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr2(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr3(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr4(ip_2_ip4(&ipadd));
const auto* addr = ip_2_ip4(&_netif->ip_addr);
const auto* mask = ip_2_ip4(&_netif->netmask);
const auto broadcast = ip4_addr_t { .addr = (addr->addr & mask->addr) | ~mask->addr };
options.add(DHCP_OPTION_BROADCAST_ADDRESS, &broadcast);
}
else
{
*optptr++ = ip4_addr1(&dns_address);
*optptr++ = ip4_addr2(&dns_address);
*optptr++ = ip4_addr3(&dns_address);
*optptr++ = ip4_addr4(&dns_address);
}
#endif
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
*optptr++ = 4;
// XXXFIXME do better than that, we have netmask
*optptr++ = ip4_addr1(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr2(ip_2_ip4(&ipadd));
*optptr++ = ip4_addr3(ip_2_ip4(&ipadd));
*optptr++ = 255;
// TODO: _netif->mtu ?
static constexpr uint16_t Mtu { 1500 };
options.add(DHCP_OPTION_INTERFACE_MTU, Mtu);
*optptr++ = DHCP_OPTION_INTERFACE_MTU;
*optptr++ = 2;
*optptr++ = 0x05;
*optptr++ = 0xdc; // 1500
*optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
*optptr++ = 1;
*optptr++ = 0x00;
#if 0 // vendor specific uninitialized (??)
*optptr++ = 43; // vendor specific
*optptr++ = 6;
// uninitialized ?
#endif
#if 0 // already set (DHCP_OPTION_SUBNET_MASK==1) (??)
*optptr++ = 0x01;
*optptr++ = 4;
*optptr++ = 0;
*optptr++ = 0;
*optptr++ = 0;
*optptr++ = 2;
#endif
return optptr;
#undef ipadd
#undef if_ip
static constexpr uint8_t RouterDiscovery { 0 };
options.add(DHCP_OPTION_PERFORM_ROUTER_DISCOVERY, RouterDiscovery);
}
///////////////////////////////////////////////////////////////////////////////////
/*
DHCP msg
@param optptr -- DHCP msg
@return uint8_t* DHCP msg
*/
///////////////////////////////////////////////////////////////////////////////////
uint8_t* DhcpServer::add_end(uint8_t* optptr)
{
*optptr++ = DHCP_OPTION_END;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
void DhcpServer::create_msg(struct dhcps_msg* m)
DhcpServer::OptionsBuffer DhcpServer::create_msg(struct dhcps_msg* m)
{
struct ipv4_addr client;
@ -488,6 +402,8 @@ void DhcpServer::create_msg(struct dhcps_msg* m)
memset((char*)m->file, 0, sizeof(m->file));
memset((char*)m->options, 0, sizeof(m->options));
memcpy((char*)m->options, &MagicCookie, sizeof(MagicCookie));
return { &m->options[sizeof(magic_cookie)], std::end(m->options) };
}
///////////////////////////////////////////////////////////////////////////////////
/*
@ -498,16 +414,18 @@ void DhcpServer::create_msg(struct dhcps_msg* m)
///////////////////////////////////////////////////////////////////////////////////
void DhcpServer::send_offer(struct dhcps_msg* m)
{
uint8_t* end;
struct pbuf *p, *q;
u8_t* data;
u16_t cnt = 0;
u16_t i;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPOFFER);
end = add_offer_options(end);
end = add_end(end);
auto options = create_msg(m);
options.add(DHCP_OPTION_MSG_TYPE, DHCPOFFER);
add_offer_options(options);
if (custom_offer_options)
{
custom_offer_options(*this, options);
}
options.add(DHCP_OPTION_END);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
@ -523,12 +441,7 @@ void DhcpServer::send_offer(struct dhcps_msg* m)
q = p;
while (q != nullptr)
{
data = (u8_t*)q->payload;
for (i = 0; i < q->len; i++)
{
data[i] = ((u8_t*)m)[cnt++];
}
std::memcpy((u8_t*)q->payload, reinterpret_cast<u8_t*>(&m), q->len);
q = q->next;
}
}
@ -562,15 +475,11 @@ void DhcpServer::send_offer(struct dhcps_msg* m)
///////////////////////////////////////////////////////////////////////////////////
void DhcpServer::send_nak(struct dhcps_msg* m)
{
u8_t* end;
struct pbuf *p, *q;
u8_t* data;
u16_t cnt = 0;
u16_t i;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPNAK);
end = add_end(end);
auto options = create_msg(m);
options.add(DHCP_OPTION_MSG_TYPE, DHCPNAK);
options.add(DHCP_OPTION_END);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
@ -586,12 +495,7 @@ void DhcpServer::send_nak(struct dhcps_msg* m)
q = p;
while (q != nullptr)
{
data = (u8_t*)q->payload;
for (i = 0; i < q->len; i++)
{
data[i] = ((u8_t*)m)[cnt++];
}
std::memcpy((u8_t*)q->payload, (u8_t*)m, q->len);
q = q->next;
}
}
@ -620,16 +524,18 @@ void DhcpServer::send_nak(struct dhcps_msg* m)
///////////////////////////////////////////////////////////////////////////////////
void DhcpServer::send_ack(struct dhcps_msg* m)
{
u8_t* end;
struct pbuf *p, *q;
u8_t* data;
u16_t cnt = 0;
u16_t i;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPACK);
end = add_offer_options(end);
end = add_end(end);
auto options = create_msg(m);
options.add(DHCP_OPTION_MSG_TYPE, DHCPACK);
add_offer_options(options);
if (custom_offer_options)
{
custom_offer_options(*this, options);
}
options.add(DHCP_OPTION_END);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
@ -645,12 +551,7 @@ void DhcpServer::send_ack(struct dhcps_msg* m)
q = p;
while (q != nullptr)
{
data = (u8_t*)q->payload;
for (i = 0; i < q->len; i++)
{
data[i] = ((u8_t*)m)[cnt++];
}
std::memcpy((u8_t*)q->payload, (u8_t*)m, q->len);
q = q->next;
}
}
@ -931,15 +832,15 @@ void DhcpServer::init_dhcps_lease(uint32 ip)
uint32 softap_ip = 0, local_ip = 0;
uint32 start_ip = 0;
uint32 end_ip = 0;
if (dhcps_lease.enable == true)
if (lease.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(lease.start_ip.addr);
end_ip = htonl(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;
lease.enable = false;
}
else
{
@ -948,12 +849,12 @@ void DhcpServer::init_dhcps_lease(uint32 ip)
if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
|| (end_ip - start_ip > DHCPS_MAX_LEASE))
{
dhcps_lease.enable = false;
lease.enable = false;
}
}
}
if (dhcps_lease.enable == false)
if (lease.enable == false)
{
local_ip = softap_ip = htonl(ip);
softap_ip &= 0xFFFFFF00;
@ -967,15 +868,15 @@ void DhcpServer::init_dhcps_lease(uint32 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(&lease, sizeof(lease));
lease.start_ip.addr = softap_ip | local_ip;
lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
lease.start_ip.addr = htonl(lease.start_ip.addr);
lease.end_ip.addr = htonl(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);
// lease.start_ip.addr = htonl(lease.start_ip.addr);
// lease.end_ip.addr= htonl(lease.end_ip.addr);
// os_printf("start_ip = 0x%x, end_ip = 0x%x\n",lease.start_ip, lease.end_ip);
}
///////////////////////////////////////////////////////////////////////////////////
@ -1116,13 +1017,13 @@ bool DhcpServer::set_dhcps_lease(struct dhcps_lease* please)
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;
bzero(&lease, sizeof(lease));
// lease.start_ip.addr = start_ip;
// lease.end_ip.addr = end_ip;
lease.start_ip.addr = please->start_ip.addr;
lease.end_ip.addr = please->end_ip.addr;
}
dhcps_lease.enable = please->enable;
lease.enable = please->enable;
// dhcps_lease_flag = false;
return true;
}
@ -1151,7 +1052,7 @@ bool DhcpServer::get_dhcps_lease(struct dhcps_lease* please)
}
// if (dhcps_lease_flag){
if (dhcps_lease.enable == false)
if (lease.enable == false)
{
if (isRunning())
{
@ -1160,20 +1061,20 @@ bool DhcpServer::get_dhcps_lease(struct dhcps_lease* please)
}
else
{
// bzero(please, sizeof(dhcps_lease));
// bzero(please, sizeof(*please));
// if (!isRunning()){
// please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
// please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
// please->start_ip.addr = htonl(lease.start_ip.addr);
// please->end_ip.addr = htonl(lease.end_ip.addr);
// }
}
// if (isRunning()){
// bzero(please, sizeof(dhcps_lease));
// please->start_ip.addr = dhcps_lease.start_ip.addr;
// please->end_ip.addr = dhcps_lease.end_ip.addr;
// bzero(please, sizeof(*please));
// please->start_ip.addr = lease.start_ip.addr;
// please->end_ip.addr = lease.end_ip.addr;
// }
please->start_ip.addr = dhcps_lease.start_ip.addr;
please->end_ip.addr = dhcps_lease.end_ip.addr;
please->start_ip.addr = lease.start_ip.addr;
please->end_ip.addr = lease.end_ip.addr;
return true;
}
@ -1243,81 +1144,6 @@ void DhcpServer::dhcps_coarse_tmr(void)
}
}
bool DhcpServer::set_dhcps_offer_option(uint8 level, void* optarg)
{
bool offer_flag = true;
// uint8 option = 0;
if (optarg == nullptr && !isRunning())
{
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 DhcpServer::set_dhcps_lease_time(uint32 minute)
{
if (_netif->num == SOFTAP_IF)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE)
{
return false;
}
}
if (isRunning())
{
return false;
}
if (minute == 0)
{
return false;
}
dhcps_lease_time = minute;
return true;
}
bool DhcpServer::reset_dhcps_lease_time(void)
{
if (_netif->num == SOFTAP_IF)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE)
{
return false;
}
}
if (isRunning())
{
return false;
}
dhcps_lease_time = DefaultLeaseTime;
return true;
}
uint32 DhcpServer::get_dhcps_lease_time(void) // minute
{
return dhcps_lease_time;
}
void DhcpServer::dhcps_client_leave(u8* bssid, struct ipv4_addr* ip, bool force)
{
struct dhcps_pool* pdhcps_pool = nullptr;
@ -1374,8 +1200,8 @@ uint32 DhcpServer::dhcps_client_update(u8* bssid, struct ipv4_addr* ip)
list_node* pmac_node = nullptr;
list_node* pip_node = nullptr;
bool flag = false;
uint32 start_ip = dhcps_lease.start_ip.addr;
uint32 end_ip = dhcps_lease.end_ip.addr;
uint32 start_ip = lease.start_ip.addr;
uint32 end_ip = lease.end_ip.addr;
dhcps_type_t type = DHCPS_TYPE_DYNAMIC;
if (bssid == nullptr)
{
@ -1483,7 +1309,7 @@ uint32 DhcpServer::dhcps_client_update(u8* bssid, struct ipv4_addr* ip)
type = DHCPS_TYPE_DYNAMIC;
}
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->lease_timer = this->lease_time;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
}
@ -1504,7 +1330,7 @@ uint32 DhcpServer::dhcps_client_update(u8* bssid, struct ipv4_addr* ip)
}
node_remove_from_list(&plist, pmac_node);
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->lease_timer = this->lease_time;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
node_insert_to_list(&plist, pmac_node);
@ -1520,7 +1346,7 @@ uint32 DhcpServer::dhcps_client_update(u8* bssid, struct ipv4_addr* ip)
return IPADDR_ANY;
}
memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->lease_timer = this->lease_time;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
}
@ -1546,7 +1372,7 @@ uint32 DhcpServer::dhcps_client_update(u8* bssid, struct ipv4_addr* ip)
return IPADDR_ANY;
}
memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->lease_timer = this->lease_time;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
pback_node = (list_node*)zalloc(sizeof(list_node));

View File

@ -30,18 +30,141 @@
#pragma once
#include <lwip/init.h> // LWIP_VERSION
#include <lwip/init.h>
#include <cstdint>
#include <cstddef>
#include <cstring>
#include <array>
#include <initializer_list>
class DhcpServer
{
public:
static constexpr int DefaultLeaseTime = 720; // minutes
static constexpr uint32 MagicCookie = 0x63538263; // https://tools.ietf.org/html/rfc1497
//
struct OptionsBuffer
{
OptionsBuffer(uint8_t* begin, uint8_t* end) : _it(begin), _begin(begin), _end(end) { }
DhcpServer(netif*);
OptionsBuffer& add(uint8_t code, const uint8_t* data, size_t size);
OptionsBuffer& add(uint8_t code, const char* data, size_t size)
{
return add(code, reinterpret_cast<const uint8_t*>(data), size);
}
template<size_t Size>
OptionsBuffer& add(uint8_t code, const char (&data)[Size])
{
return add(code, &data[0], Size - 1);
}
template<size_t Size>
OptionsBuffer& add(uint8_t code, const uint8_t (&data)[Size])
{
return add(code, &data[0], Size);
}
OptionsBuffer& add(uint8_t code, std::initializer_list<uint8_t> data)
{
return add(code, data.begin(), data.size());
}
OptionsBuffer& add(uint8_t code, const ip4_addr_t* addr)
{
return add(code,
{ ip4_addr1(addr), ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr) });
}
OptionsBuffer& add(uint8_t code, uint8_t value)
{
return add(code, { value });
}
OptionsBuffer& add(uint8_t code, uint16_t value)
{
return add(code, { static_cast<uint8_t>((value >> 8) & 0xff),
static_cast<uint8_t>(value & 0xff) });
}
OptionsBuffer& add(uint8_t code, uint32_t value)
{
return add(code, { static_cast<uint8_t>((value >> 24) & 0xff),
static_cast<uint8_t>((value >> 16) & 0xff),
static_cast<uint8_t>((value >> 8) & 0xff),
static_cast<uint8_t>((value & 0xff)) });
}
OptionsBuffer& add(uint8_t code)
{
if (_it != _end)
{
*_it++ = code;
}
return *this;
}
private:
uint8_t* _it;
uint8_t* _begin;
uint8_t* _end;
};
using OptionsBufferHandler = void (*)(const DhcpServer&, OptionsBuffer&);
DhcpServer(netif* netif);
~DhcpServer();
void setDns(int num, const ipv4_addr_t* dns);
netif* getNetif() const
{
return _netif;
}
void setRouter(bool value)
{
offer_router = value;
}
bool getRouter() const
{
return offer_router;
}
void setDns(ip4_addr_t addr)
{
dns_address = addr;
}
ip4_addr_t getDns() const
{
return dns_address;
}
void resetLeaseTime()
{
lease_time = DefaultLeaseTime;
}
void setLeaseTime(uint32_t minutes)
{
lease_time = minutes;
}
uint32_t getLeaseTime() const
{
return lease_time;
}
// Will use provided callback for ACK and OFFER replies
// `options.add(...)` to append to the options list
// (does not check for duplicates!)
void onSendOptions(OptionsBufferHandler handler)
{
custom_offer_options = handler;
}
bool begin();
void end();
@ -54,18 +177,16 @@ public:
// legacy public C structure and API to eventually turn into C++
void init_dhcps_lease(uint32 ip);
bool set_dhcps_lease(struct dhcps_lease* please);
bool get_dhcps_lease(struct dhcps_lease* please);
bool set_dhcps_offer_option(uint8 level, void* optarg);
bool set_dhcps_lease_time(uint32 minute);
bool reset_dhcps_lease_time(void);
uint32 get_dhcps_lease_time(void);
bool add_dhcps_lease(uint8* macaddr);
void init_dhcps_lease(uint32 ip);
bool set_dhcps_lease(struct dhcps_lease* please);
bool get_dhcps_lease(struct dhcps_lease* please);
bool add_dhcps_lease(uint8* macaddr);
void dhcps_set_dns(int num, const ipv4_addr_t* dns);
void offers();
protected:
void add_offer_options(OptionsBuffer&);
// legacy C structure and API to eventually turn into C++
typedef struct _list_node
@ -74,12 +195,11 @@ protected:
struct _list_node* pnext;
} list_node;
void node_insert_to_list(list_node** phead, list_node* pinsert);
void node_remove_from_list(list_node** phead, list_node* pdelete);
uint8_t* add_msg_type(uint8_t* optptr, uint8_t type);
uint8_t* add_offer_options(uint8_t* optptr);
uint8_t* add_end(uint8_t* optptr);
void create_msg(struct dhcps_msg* m);
void node_insert_to_list(list_node** phead, list_node* pinsert);
void node_remove_from_list(list_node** phead, list_node* pdelete);
OptionsBuffer create_msg(struct dhcps_msg* m);
void send_offer(struct dhcps_msg* m);
void send_nak(struct dhcps_msg* m);
void send_ack(struct dhcps_msg* m);
@ -95,15 +215,22 @@ protected:
netif* _netif = nullptr;
udp_pcb* pcb_dhcps = nullptr;
ip_addr_t broadcast_dhcps {};
ipv4_addr server_address {};
ipv4_addr client_address {};
ipv4_addr dns_address {};
uint32 dhcps_lease_time = DefaultLeaseTime;
struct udp_pcb* pcb_dhcps = nullptr;
ip_addr_t broadcast_dhcps {};
ip4_addr_t server_address {};
ip4_addr_t client_address {};
struct dhcps_lease dhcps_lease;
list_node* plist;
uint8 offer;
bool renew;
uint32_t lease_time = DefaultLeaseTime;
bool offer_router = true;
ip4_addr_t dns_address {};
dhcps_lease lease {};
list_node* plist = nullptr;
bool renew = false;
OptionsBufferHandler custom_offer_options = nullptr;
static const uint32 magic_cookie;
};

View File

@ -0,0 +1,20 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
void setup() {
auto& server = WiFi.softAPDhcpServer();
server.onSendOptions([](const DhcpServer& server, auto& options) {
// VENDOR is... vendor specific
options.add(43, { 0xca, 0xfe, 0xca, 0xfe, 0xfe });
// Captive Portal URI
const IPAddress gateway = netif_ip4_addr(server.getNetif());
const String captive = F("http://") + gateway.toString();
options.add(114, captive.c_str(), captive.length());
});
WiFi.softAP("TEST", "testtesttest");
}
void loop() {
delay(100);
}

View File

@ -52,10 +52,13 @@ void setup() {
}
Serial.printf("\nSTA: %s (dns: %s / %s)\n", WiFi.localIP().toString().c_str(), WiFi.dnsIP(0).toString().c_str(), WiFi.dnsIP(1).toString().c_str());
// give DNS servers to AP side
// By default, DNS option will point to the interface IP
// Instead, point it to the real DNS server.
// Notice that:
// - DhcpServer class only supports IPv4
// - Only a single IP can be set
auto& server = WiFi.softAPDhcpServer();
server.dhcps_set_dns(0, WiFi.dnsIP(0));
server.dhcps_set_dns(1, WiFi.dnsIP(1));
server.setDns(WiFi.dnsIP(0));
WiFi.softAPConfig( // enable AP, with android-compatible google domain
IPAddress(172, 217, 28, 254), IPAddress(172, 217, 28, 254), IPAddress(255, 255, 255, 0));

View File

@ -176,9 +176,9 @@ bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* psk, int channel,
if(ip.ip.addr == 0x00000000) {
DEBUG_WIFI("[AP] IP config Invalid resetting...\n");
ret = softAPConfig(
0x0104A8C0 /* 192.168.4.1 */,
0x0104A8C0 /* 192.168.4.1 */,
0x00FFFFFF /* 255.255.255.0 */);
IPAddress(192, 168, 4, 1),
IPAddress(192, 168, 4, 1),
IPAddress(255, 255, 255, 0));
if(!ret) {
DEBUG_WIFI("[AP] softAPConfig failed!\n");
ret = false;
@ -227,9 +227,8 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
info.gw.addr = gateway.v4();
info.netmask.addr = subnet.v4();
if(!wifi_softap_dhcps_stop()) {
DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n");
}
auto& server = softAPDhcpServer();
server.end();
if(!wifi_set_ip_info(SOFTAP_IF, &info)) {
DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
@ -247,24 +246,14 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
dhcp_lease.end_ip.addr = ip.v4();
DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());
auto& server = softAPDhcpServer();
if(!server.set_dhcps_lease(&dhcp_lease))
{
DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
ret = false;
}
uint8 mode = info.gw.addr ? 1 : 0;
if(!server.set_dhcps_offer_option(OFFER_ROUTER, &mode))
{
DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_offer_option failed!\n");
ret = false;
}
if(!wifi_softap_dhcps_start()) {
DEBUG_WIFI("[APConfig] wifi_softap_dhcps_start failed!\n");
ret = false;
}
server.setRouter(true); // send ROUTER option with netif's gateway IP
server.begin();
// check config
if(wifi_get_ip_info(SOFTAP_IF, &info)) {

View File

@ -13,19 +13,6 @@ bool DhcpServer::set_dhcps_lease(struct dhcps_lease* please)
return false;
}
bool DhcpServer::set_dhcps_lease_time(uint32 minute)
{
(void)minute;
return false;
}
bool DhcpServer::set_dhcps_offer_option(uint8 level, void* optarg)
{
(void)level;
(void)optarg;
return false;
}
void DhcpServer::end() { }
bool DhcpServer::begin()
@ -64,17 +51,4 @@ extern "C"
(void)please;
return true;
}
bool wifi_softap_set_dhcps_lease_time(uint32 minute)
{
(void)minute;
return true;
}
bool wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
{
(void)level;
(void)optarg;
return true;
}
}

View File

@ -54,11 +54,13 @@ done
# TODO should not be matched, these are formatted externally
# exclude=$(git submodule --quiet foreach git rev-parse --show-toplevel | grep libraries)
style=$(makeClangFormatStyle ${root}/tests/clang-format-arduino.yaml)
find libraries \
-path libraries/ESP8266SdFat -prune -o \
-path libraries/Ethernet -prune -o \
-path libraries/SoftwareSerial -prune -o \
-name '*.ino' -exec $CLANG_FORMAT --verbose --style="$style" -i {} \;
if [ -z $1 ] ; then
style=$(makeClangFormatStyle ${root}/tests/clang-format-arduino.yaml)
find libraries \
-path libraries/ESP8266SdFat -prune -o \
-path libraries/Ethernet -prune -o \
-path libraries/SoftwareSerial -prune -o \
-name '*.ino' -exec $CLANG_FORMAT --verbose --style="$style" -i {} \;
fi
#########################################

View File

@ -190,7 +190,7 @@ typedef uintptr_t mem_ptr_t;
* sys/types or unistd.h are available).
* Being like that, we define it to 'int' if SSIZE_MAX is not defined.
*/
#ifdef SSIZE_MAX
#if !defined(SSIZE_MAX) || !defined(_SSIZE_T_DECLARED)
/* If SSIZE_MAX is defined, unistd.h should provide the type as well */
#ifndef LWIP_NO_UNISTD_H
#define LWIP_NO_UNISTD_H 0