Backport dhcpserver changes from ourairquality's LwIP2 work
https://github.com/ourairquality/esp-open-rtos/blob/ourairquality/extras/dhcpserver/dhcpserver.c
This commit is contained in:
parent
9523e872f8
commit
b979169e61
2 changed files with 90 additions and 42 deletions
|
@ -14,17 +14,20 @@
|
|||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/api.h>
|
||||
#include "esplibs/libmain.h"
|
||||
|
||||
/* Grow the size of the lwip dhcp_msg struct's options field, as LWIP
|
||||
defaults to a 68 octet options field for its DHCP client, and most
|
||||
full-sized clients send us more than this. */
|
||||
#define DHCP_OPTIONS_LEN 312
|
||||
|
||||
#include <lwip/ip.h>
|
||||
#include <lwip/dhcp.h>
|
||||
|
||||
_Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 312, "dhcp_msg_t should have extended options size");
|
||||
|
@ -35,6 +38,7 @@ _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 3
|
|||
|
||||
typedef struct {
|
||||
uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||
uint8_t active;
|
||||
uint32_t expires;
|
||||
} dhcp_lease_t;
|
||||
|
||||
|
@ -44,6 +48,10 @@ typedef struct {
|
|||
ip_addr_t first_client_addr;
|
||||
struct netif *server_if;
|
||||
dhcp_lease_t *leases; /* length max_leases */
|
||||
/* Optional router */
|
||||
ip_addr_t router;
|
||||
/* Optional DNS server */
|
||||
ip_addr_t dns;
|
||||
} server_state_t;
|
||||
|
||||
/* Only one DHCP server task can run at once, so we have global state
|
||||
|
@ -86,10 +94,15 @@ void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases)
|
|||
state = malloc(sizeof(server_state_t));
|
||||
state->max_leases = max_leases;
|
||||
state->leases = calloc(max_leases, sizeof(dhcp_lease_t));
|
||||
bzero(state->leases, max_leases * sizeof(dhcp_lease_t));
|
||||
// state->server_if is assigned once the task is running - see comment in dhcpserver_task()
|
||||
ip_addr_copy(state->first_client_addr, *first_client_addr);
|
||||
|
||||
xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle);
|
||||
/* Clear options */
|
||||
ip_addr_set_zero(&state->router);
|
||||
ip_addr_set_zero(&state->dns);
|
||||
|
||||
xTaskCreate(dhcpserver_task, "DHCP Server", 448, NULL, 2, &dhcpserver_task_handle);
|
||||
}
|
||||
|
||||
void dhcpserver_stop(void)
|
||||
|
@ -101,6 +114,16 @@ void dhcpserver_stop(void)
|
|||
}
|
||||
}
|
||||
|
||||
void dhcpserver_set_router(const ip_addr_t *router)
|
||||
{
|
||||
ip_addr_copy(state->router, *router);
|
||||
}
|
||||
|
||||
void dhcpserver_set_dns(const ip_addr_t *dns)
|
||||
{
|
||||
ip_addr_copy(state->dns, *dns);
|
||||
}
|
||||
|
||||
static void dhcpserver_task(void *pxParameter)
|
||||
{
|
||||
/* netif_list isn't assigned until after user_init completes, which is why we do it inside the task */
|
||||
|
@ -129,9 +152,12 @@ static void dhcpserver_task(void *pxParameter)
|
|||
/* expire any leases that have passed */
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
uint32_t expires = state->leases[i].expires;
|
||||
if(expires && expires < now)
|
||||
state->leases[i].expires = 0;
|
||||
if (state->leases[i].active) {
|
||||
uint32_t expires = state->leases[i].expires - now;
|
||||
if (expires >= 0x80000000) {
|
||||
state->leases[i].active = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_t received_ip;
|
||||
|
@ -157,13 +183,13 @@ static void dhcpserver_task(void *pxParameter)
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
printf("State dump. Message type %d\n", *message_type);
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
dhcp_lease_t *lease = &state->leases[i];
|
||||
printf("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, lease->expires, lease->hwaddr[0],
|
||||
lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
|
||||
lease->hwaddr[5]);
|
||||
printf("lease slot %d active %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i,
|
||||
lease->active, lease->expires - now,
|
||||
lease->hwaddr[0], lease->hwaddr[1], lease->hwaddr[2],
|
||||
lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[5]);
|
||||
}
|
||||
|
||||
switch(*message_type) {
|
||||
|
@ -199,13 +225,19 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
|||
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
|
||||
|
||||
ip_addr_copy(dhcpmsg->yiaddr, state->first_client_addr);
|
||||
ip4_addr4(&(dhcpmsg->yiaddr)) += (freelease - state->leases);
|
||||
dhcpmsg->yiaddr.addr = lwip_htonl(lwip_ntohl(state->first_client_addr.addr) + (freelease - state->leases));
|
||||
|
||||
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
|
||||
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
|
||||
if (!ip_addr_isany(&state->router)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
|
||||
}
|
||||
if (!ip_addr_isany(&state->dns)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
|
||||
}
|
||||
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||
|
||||
struct netbuf *netbuf = netbuf_new();
|
||||
|
@ -253,7 +285,7 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
}
|
||||
|
||||
dhcp_lease_t *requested_lease = state->leases + octet_offs;
|
||||
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||
if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||
{
|
||||
printf("DHCP Server Error: Lease for address already taken\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
|
@ -265,7 +297,9 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
|
||||
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
|
||||
requested_lease->hwaddr[5]);
|
||||
requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||
requested_lease->active = 1;
|
||||
|
||||
/* Reuse the REQUEST message as the ACK message */
|
||||
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||
|
@ -279,6 +313,13 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
|
||||
if (!ip_addr_isany(&state->router)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
|
||||
}
|
||||
if (!ip_addr_isany(&state->dns)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
|
||||
}
|
||||
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||
|
||||
struct netbuf *netbuf = netbuf_new();
|
||||
|
@ -292,6 +333,7 @@ static void handle_dhcp_release(struct dhcp_msg *dhcpmsg)
|
|||
{
|
||||
dhcp_lease_t *lease = find_lease_slot(dhcpmsg->chaddr);
|
||||
if (lease) {
|
||||
lease->active = 0;
|
||||
lease->expires = 0;
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +403,7 @@ static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr)
|
|||
{
|
||||
dhcp_lease_t *empty_lease = NULL;
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
if(state->leases[i].expires == 0 && !empty_lease)
|
||||
if (!state->leases[i].active && !empty_lease)
|
||||
empty_lease = &state->leases[i];
|
||||
else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
|
||||
return &state->leases[i];
|
||||
|
|
|
@ -34,6 +34,12 @@ void dhcpserver_get_lease(const ip_addr_t *first_client_addr, uint8_t max_leases
|
|||
*/
|
||||
void dhcpserver_stop(void);
|
||||
|
||||
/* Set a router address to send as an option. */
|
||||
void dhcpserver_set_router(const ip_addr_t *router);
|
||||
|
||||
/* Set a DNS address to send as an option. */
|
||||
void dhcpserver_set_dns(const ip_addr_t *dns);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue