dhcpserver: Add expiry, DHCPNAK packets
This commit is contained in:
parent
4c98f575e7
commit
9fc223b3c2
2 changed files with 47 additions and 2 deletions
|
@ -29,6 +29,9 @@ typedef struct {
|
||||||
/* Handlers for various kinds of incoming DHCP messages */
|
/* Handlers for various kinds of incoming DHCP messages */
|
||||||
static void handle_dhcp_discover(server_state_t *state, struct dhcp_msg *received);
|
static void handle_dhcp_discover(server_state_t *state, struct dhcp_msg *received);
|
||||||
static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg);
|
static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg);
|
||||||
|
static void handle_dhcp_release(server_state_t *state, struct dhcp_msg *dhcpmsg);
|
||||||
|
|
||||||
|
static void send_dhcp_nak(server_state_t *state, struct dhcp_msg *dhcpmsg);
|
||||||
|
|
||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length);
|
static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length);
|
||||||
|
@ -62,12 +65,22 @@ static void dhcpserver_task(void *pxParameter)
|
||||||
{
|
{
|
||||||
struct netbuf *netbuf;
|
struct netbuf *netbuf;
|
||||||
struct dhcp_msg received = { 0 };
|
struct dhcp_msg received = { 0 };
|
||||||
|
|
||||||
|
/* Receive a DHCP packet */
|
||||||
err_t err = netconn_recv(state.nc, &netbuf);
|
err_t err = netconn_recv(state.nc, &netbuf);
|
||||||
if(err != ERR_OK) {
|
if(err != ERR_OK) {
|
||||||
printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err);
|
printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* expire any leases that have passed */
|
||||||
|
uint32_t now = xTaskGetTickCount();
|
||||||
|
for(int i = 0; i < DHCPSERVER_MAXCLIENTS; i++) {
|
||||||
|
uint32_t expires = state.leases[i].expires;
|
||||||
|
if(expires && expires < now)
|
||||||
|
state.leases[i].expires = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ip_addr_t received_ip;
|
ip_addr_t received_ip;
|
||||||
u16_t port;
|
u16_t port;
|
||||||
netconn_addr(state.nc, &received_ip, &port);
|
netconn_addr(state.nc, &received_ip, &port);
|
||||||
|
@ -98,6 +111,8 @@ static void dhcpserver_task(void *pxParameter)
|
||||||
case DHCP_REQUEST:
|
case DHCP_REQUEST:
|
||||||
handle_dhcp_request(&state, &received);
|
handle_dhcp_request(&state, &received);
|
||||||
break;
|
break;
|
||||||
|
case DHCP_RELEASE:
|
||||||
|
handle_dhcp_release(&state, &received);
|
||||||
default:
|
default:
|
||||||
printf("DHCP Server Error: Unsupported message type %d\r\n", *message_type);
|
printf("DHCP Server Error: Unsupported message type %d\r\n", *message_type);
|
||||||
break;
|
break;
|
||||||
|
@ -155,6 +170,7 @@ static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
ip_addr_copy(requested_ip, dhcpmsg->ciaddr);
|
ip_addr_copy(requested_ip, dhcpmsg->ciaddr);
|
||||||
} else {
|
} else {
|
||||||
printf("DHCP Server Error: No requested IP\r\n");
|
printf("DHCP Server Error: No requested IP\r\n");
|
||||||
|
send_dhcp_nak(state, dhcpmsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ip_addr_t first_client_ip;
|
ip_addr_t first_client_ip;
|
||||||
|
@ -165,12 +181,14 @@ static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
|| ip4_addr2(&requested_ip) != ip4_addr2(&first_client_ip)
|
|| ip4_addr2(&requested_ip) != ip4_addr2(&first_client_ip)
|
||||||
|| ip4_addr3(&requested_ip) != ip4_addr3(&first_client_ip)) {
|
|| ip4_addr3(&requested_ip) != ip4_addr3(&first_client_ip)) {
|
||||||
printf("DHCP Server Error: 0x%08lx Not an allowed IP\r\n", requested_ip.addr);
|
printf("DHCP Server Error: 0x%08lx Not an allowed IP\r\n", requested_ip.addr);
|
||||||
|
send_dhcp_nak(state, dhcpmsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Test the last octet is in the MAXCLIENTS range */
|
/* Test the last octet is in the MAXCLIENTS range */
|
||||||
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&first_client_ip);
|
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&first_client_ip);
|
||||||
if(octet_offs < 0 || octet_offs >= DHCPSERVER_MAXCLIENTS) {
|
if(octet_offs < 0 || octet_offs >= DHCPSERVER_MAXCLIENTS) {
|
||||||
printf("DHCP Server Error: Address out of range\r\n");
|
printf("DHCP Server Error: Address out of range\r\n");
|
||||||
|
send_dhcp_nak(state, dhcpmsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +196,7 @@ static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||||
{
|
{
|
||||||
printf("DHCP Server Error: Lease for address already taken\r\n");
|
printf("DHCP Server Error: Lease for address already taken\r\n");
|
||||||
|
send_dhcp_nak(state, dhcpmsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +204,7 @@ static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
printf("DHCP lease addr 0x%08lx assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", requested_ip.addr, requested_lease->hwaddr[0],
|
printf("DHCP lease addr 0x%08lx assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", requested_ip.addr, requested_lease->hwaddr[0],
|
||||||
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
|
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
|
||||||
requested_lease->hwaddr[5]);
|
requested_lease->hwaddr[5]);
|
||||||
requested_lease->expires = 1;
|
requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||||
|
|
||||||
/* Reuse the REQUEST message as the ACK message */
|
/* Reuse the REQUEST message as the ACK message */
|
||||||
dhcpmsg->op = DHCP_BOOTREPLY;
|
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||||
|
@ -207,6 +226,32 @@ static void handle_dhcp_request(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
netbuf_delete(netbuf);
|
netbuf_delete(netbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_dhcp_release(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
|
{
|
||||||
|
dhcp_lease_t *lease = find_lease_slot(state->leases, dhcpmsg->chaddr);
|
||||||
|
if(lease) {
|
||||||
|
lease->expires = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_dhcp_nak(server_state_t *state, struct dhcp_msg *dhcpmsg)
|
||||||
|
{
|
||||||
|
/* Reuse 'dhcpmsg' for the NAK */
|
||||||
|
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||||
|
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
|
||||||
|
|
||||||
|
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
|
||||||
|
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_NAK);
|
||||||
|
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||||
|
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||||
|
|
||||||
|
struct netbuf *netbuf = netbuf_new();
|
||||||
|
netbuf_alloc(netbuf, sizeof(struct dhcp_msg));
|
||||||
|
netbuf_take(netbuf, dhcpmsg, sizeof(struct dhcp_msg));
|
||||||
|
netconn_sendto(state->nc, netbuf, IP_ADDR_BROADCAST, 68);
|
||||||
|
netbuf_delete(netbuf);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length)
|
static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8_t min_length, uint8_t *length)
|
||||||
{
|
{
|
||||||
uint8_t *start = (uint8_t *)&msg->options;
|
uint8_t *start = (uint8_t *)&msg->options;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DHCPSERVER_LEASE_TIME
|
#ifndef DHCPSERVER_LEASE_TIME
|
||||||
#define DHCPSERVER_LEASE_TIME 30
|
#define DHCPSERVER_LEASE_TIME 3600
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Start DHCP server.
|
/* Start DHCP server.
|
||||||
|
|
Loading…
Reference in a new issue