507 changes: 456 additions & 51 deletions component/common/network/dhcp/dhcps.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

#include "dhcps.h"
#include "tcpip.h"

#include "wifi_constants.h"
extern rtw_mode_t wifi_mode;
//static struct dhcp_server_state dhcp_server_state_machine;
static uint8_t dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE;
/* recorded the client MAC addr(default sudo mac) */
Expand All @@ -11,6 +12,7 @@ static uint8_t dhcp_recorded_xid[4] = {0xff, 0xff, 0xff, 0xff};

/* UDP Protocol Control Block(PCB) */
static struct udp_pcb *dhcps_pcb;
static struct udp_pcb *dns_server_pcb;

static struct ip_addr dhcps_send_broadcast_address;
static struct ip_addr dhcps_local_address;
Expand All @@ -20,6 +22,7 @@ static struct ip_addr dhcps_local_mask;
static struct ip_addr dhcps_local_gateway;
static struct ip_addr dhcps_network_id;
static struct ip_addr dhcps_subnet_broadcast;
static struct eth_addr dhcps_allocated_client_ethaddr;
static struct ip_addr dhcps_allocated_client_address;
static int dhcps_addr_pool_set = 0;
static struct ip_addr dhcps_addr_pool_start;
Expand Down Expand Up @@ -73,7 +76,7 @@ static void mark_ip_in_table(uint8_t d)
printf("\r\n ip_table.ip_range[3] = 0x%x\r\n",ip_table.ip_range[3]);
#endif
} else if(128 < d && d <= 160) {
ip_table.ip_range[4] = MARK_RANGE5_IP_BIT(ip_table, d);
ip_table.ip_range[4] = MARK_RANGE5_IP_BIT(ip_table, (d - 128));
#if (debug_dhcps)
printf("\r\n ip_table.ip_range[4] = 0x%x\r\n",ip_table.ip_range[4]);
#endif
Expand Down Expand Up @@ -101,15 +104,24 @@ static void mark_ip_in_table(uint8_t d)
#ifdef CONFIG_DHCPS_KEPT_CLIENT_INFO
static void save_client_addr(struct ip_addr *client_ip, uint8_t *hwaddr)
{
#if LWIP_VERSION_MAJOR >= 2
uint8_t d = (uint8_t)ip4_addr4(ip_2_ip4(client_ip));
#else
uint8_t d = (uint8_t)ip4_addr4(client_ip);
#endif
xSemaphoreTake(dhcps_ip_table_semaphore, portMAX_DELAY);
memcpy(ip_table.client_mac[d], hwaddr, 6);
#if (debug_dhcps)
printf("\r\n%s: ip %d.%d.%d.%d, hwaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", __func__,
#if LWIP_VERSION_MAJOR >= 2
printf("\r\n%s: ip %d.%d.%d.%d, hwaddr 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", __func__,
ip4_addr1(ip_2_ip4(client_ip)), ip4_addr2(ip_2_ip4(client_ip)), ip4_addr3(ip_2_ip4(client_ip)), ip4_addr4(ip_2_ip4(client_ip)),
hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
#else
printf("\r\n%s: ip %d.%d.%d.%d, hwaddr 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", __func__,
ip4_addr1(client_ip), ip4_addr2(client_ip), ip4_addr3(client_ip), ip4_addr4(client_ip),
hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
#endif
#endif
#endif
xSemaphoreGive(dhcps_ip_table_semaphore);
}

Expand Down Expand Up @@ -142,6 +154,82 @@ static uint8_t check_client_request_ip(struct ip_addr *client_req_ip, uint8_t *h
Exit:
return ip_addr4;
}

static uint8_t check_client_direct_request_ip(struct ip_addr *client_req_ip, uint8_t *hwaddr)
{
int ip_addr4 = 0, i;

#if (debug_dhcps)
#if LWIP_VERSION_MAJOR >= 2
printf("\r\n%s: ip %d.%d.%d.%d, hwaddr 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", __func__,
ip4_addr1(ip_2_ip4(client_req_ip)), ip4_addr2(ip_2_ip4(client_req_ip)), ip4_addr3(ip_2_ip4(client_req_ip)), ip4_addr4(ip_2_ip4(client_req_ip)),
hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
#else
printf("\r\n%s: ip %d.%d.%d.%d, hwaddr 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", __func__,
ip4_addr1(client_req_ip), ip4_addr2(client_req_ip), ip4_addr3(client_req_ip), ip4_addr4(client_req_ip),
hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
#endif
#endif

#if LWIP_VERSION_MAJOR >= 2
if( (ip4_addr1(ip_2_ip4(&dhcps_network_id)) != ip4_addr1(ip_2_ip4(client_req_ip))) ||
(ip4_addr2(ip_2_ip4(&dhcps_network_id)) != ip4_addr2(ip_2_ip4(client_req_ip))) ||
(ip4_addr3(ip_2_ip4(&dhcps_network_id)) != ip4_addr3(ip_2_ip4(client_req_ip))))
#else
if( (ip4_addr1(&dhcps_network_id) != ip4_addr1(client_req_ip)) ||
(ip4_addr2(&dhcps_network_id) != ip4_addr2(client_req_ip)) ||
(ip4_addr3(&dhcps_network_id) != ip4_addr3(client_req_ip)))
#endif

{
ip_addr4 = 0;
goto Exit;
}

// check if the requested ip is available
#if LWIP_VERSION_MAJOR >= 2
ip_addr4 = ip4_addr4(ip_2_ip4(client_req_ip));
#else
ip_addr4 = ip4_addr4(client_req_ip);
#endif

if (ip_addr4 < DHCP_POOL_START || ip_addr4 > DHCP_POOL_END) {
ip_addr4 = 0;
goto Exit;
}
xSemaphoreTake(dhcps_ip_table_semaphore, portMAX_DELAY);
printf("ip_table[%d] = %x,%x,%x,%x,%x,%x\n",ip_addr4,ip_table.client_mac[ip_addr4][0],
ip_table.client_mac[ip_addr4][1],
ip_table.client_mac[ip_addr4][2],
ip_table.client_mac[ip_addr4][3],
ip_table.client_mac[ip_addr4][4],
ip_table.client_mac[ip_addr4][5]);
if( ( ip_table.client_mac[ip_addr4][0] == 0 &&
ip_table.client_mac[ip_addr4][1] == 0 &&
ip_table.client_mac[ip_addr4][2] == 0 &&
ip_table.client_mac[ip_addr4][3] == 0 &&
ip_table.client_mac[ip_addr4][4] == 0 &&
ip_table.client_mac[ip_addr4][5] == 0) ||
( ip_table.client_mac[ip_addr4][0] == hwaddr[0] &&
ip_table.client_mac[ip_addr4][1] == hwaddr[1] &&
ip_table.client_mac[ip_addr4][2] == hwaddr[2] &&
ip_table.client_mac[ip_addr4][3] == hwaddr[3] &&
ip_table.client_mac[ip_addr4][4] == hwaddr[4] &&
ip_table.client_mac[ip_addr4][5] == hwaddr[5]))
{
// the ip is available or already allocated to this client
}
else
{
ip_addr4 = 0; // the ip is used
}

xSemaphoreGive(dhcps_ip_table_semaphore);

Exit:
return ip_addr4;
}

static void dump_client_table()
{
#if 0
Expand Down Expand Up @@ -174,8 +262,14 @@ static uint8_t search_next_ip(void)
uint8_t start, end;
uint8_t max_count;
if(dhcps_addr_pool_set){
#if LWIP_VERSION_MAJOR >= 2
start = (uint8_t)ip4_addr4(ip_2_ip4(&dhcps_addr_pool_start));
end = (uint8_t)ip4_addr4(ip_2_ip4(&dhcps_addr_pool_end));
#else
start = (uint8_t)ip4_addr4(&dhcps_addr_pool_start);
end = (uint8_t)ip4_addr4(&dhcps_addr_pool_end);
#endif

}else{
start = 0;
end = 255;
Expand Down Expand Up @@ -244,55 +338,101 @@ static uint8_t *fill_one_option_content(uint8_t *option_base_addr,
/**
* @brief fill in the needed content of the dhcp offer message.
* @param optptr the addr which the tail of dhcp magic field.
* @retval the addr represent to add the end of option.
* @retval 0, add ok
* -1, add fail
*/
static void add_offer_options(uint8_t *option_start_address)
static int8_t add_offer_options(uint8_t *option_start_address)
{
uint8_t *temp_option_addr;
// Total minimum len = 6+6+6+6+6+6+4+3+1 = 44
uint8_t *temp_option_addr = option_start_address;
int max_addable_option_len = dhcp_message_total_options_lenth - 4 - 3; // -magic-type

if(option_start_address == NULL)
goto ERROR;

/* add DHCP options 1.
The subnet mask option specifies the client's subnet mask */
temp_option_addr = fill_one_option_content(option_start_address,
DHCP_OPTION_CODE_SUBNET_MASK, DHCP_OPTION_LENGTH_FOUR,
(void *)&dhcps_local_mask);
if(temp_option_addr + 6 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(option_start_address, DHCP_OPTION_CODE_SUBNET_MASK,
DHCP_OPTION_LENGTH_FOUR,(void *)&dhcps_local_mask);
}else{
goto ERROR;
}

/* add DHCP options 3 (i.e router(gateway)). The time server option
specifies a list of RFC 868 [6] time servers available to the client. */
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_ROUTER, DHCP_OPTION_LENGTH_FOUR,
(void *)&dhcps_local_address);
if(temp_option_addr + 6 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_ROUTER,
DHCP_OPTION_LENGTH_FOUR, (void *)&dhcps_local_address);
}else{
goto ERROR;
}

/* add DHCP options 6 (i.e DNS).
The option specifies a list of DNS servers available to the client. */
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_DNS_SERVER, DHCP_OPTION_LENGTH_FOUR,
(void *)&dhcps_local_address);
if(temp_option_addr + 6 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_DNS_SERVER,
DHCP_OPTION_LENGTH_FOUR, (void *)&dhcps_local_address);
}else{
goto ERROR;
}

/* add DHCP options 51.
This option is used to request a lease time for the IP address. */
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_LEASE_TIME, DHCP_OPTION_LENGTH_FOUR,
(void *)&dhcp_option_lease_time);
if(temp_option_addr + 6 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_LEASE_TIME,
DHCP_OPTION_LENGTH_FOUR, (void *)&dhcp_option_lease_time);
}else{
goto ERROR;
}

/* add DHCP options 54.
The identifier is the IP address of the selected server. */
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_SERVER_ID, DHCP_OPTION_LENGTH_FOUR,
(void *)&dhcps_local_address);
if(temp_option_addr + 6 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_SERVER_ID,
DHCP_OPTION_LENGTH_FOUR, (void *)&dhcps_local_address);
}else{
goto ERROR;
}

/* add DHCP options 28.
This option specifies the broadcast address in use on client's subnet.*/
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_BROADCAST_ADDRESS, DHCP_OPTION_LENGTH_FOUR,
(void *)&dhcps_subnet_broadcast);
if(temp_option_addr + 6 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_BROADCAST_ADDRESS,
DHCP_OPTION_LENGTH_FOUR, (void *)&dhcps_subnet_broadcast);
}else{
goto ERROR;
}

/* add DHCP options 26.
This option specifies the Maximum transmission unit to use */
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_INTERFACE_MTU, DHCP_OPTION_LENGTH_TWO,
(void *) &dhcp_option_interface_mtu);//dhcp_option_interface_mtu_576);
if(temp_option_addr + 4 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_INTERFACE_MTU,
DHCP_OPTION_LENGTH_TWO, (void *) &dhcp_option_interface_mtu);//dhcp_option_interface_mtu_576);
}else{
goto ERROR;
}

/* add DHCP options 31.
This option specifies whether or not the client should solicit routers */
temp_option_addr = fill_one_option_content(temp_option_addr,
DHCP_OPTION_CODE_PERFORM_ROUTER_DISCOVERY, DHCP_OPTION_LENGTH_ONE,
NULL);
if(temp_option_addr + 3 -option_start_address <= max_addable_option_len) {
temp_option_addr = fill_one_option_content(temp_option_addr, DHCP_OPTION_CODE_PERFORM_ROUTER_DISCOVERY,
DHCP_OPTION_LENGTH_ONE, NULL);
}else{
goto ERROR;
}

// END
if(temp_option_addr + 1 -option_start_address <= max_addable_option_len) {
*temp_option_addr++ = DHCP_OPTION_CODE_END;
}else{
goto ERROR;
}
return 0;

ERROR:
printf("\r\n[%s] error: add options fail !!", __func__);
return -1;
}


Expand All @@ -311,7 +451,6 @@ static void dhcps_initialize_message(struct dhcp_msg *dhcp_message_repository)
memcpy((char *)dhcp_recorded_xid, (char *) dhcp_message_repository->xid,
sizeof(dhcp_message_repository->xid));
dhcp_message_repository->secs = 0;
dhcp_message_repository->flags = htons(BOOTP_BROADCAST);

memcpy((char *)dhcp_message_repository->yiaddr,
(char *)&dhcps_allocated_client_address,
Expand Down Expand Up @@ -341,9 +480,27 @@ static void dhcps_initialize_message(struct dhcp_msg *dhcp_message_repository)
static void dhcps_send_offer(struct pbuf *packet_buffer)
{
uint8_t temp_ip = 0;
dhcp_message_repository = (struct dhcp_msg *)packet_buffer->payload;
#if (!IS_USE_FIXED_IP)
struct pbuf *newly_malloc_packet_buffer = NULL;

// newly malloc a longer pbuf for dhcp offer rather than using the short pbuf from dhcp discover
newly_malloc_packet_buffer = pbuf_alloc(PBUF_TRANSPORT, DHCP_MSG_LEN + DHCP_OPTION_TOTAL_LENGTH_MAX, PBUF_RAM);
if(newly_malloc_packet_buffer == NULL)
{
printf("\r\n[%s] error: pbuf alloc fail !", __func__);
return;
}
if(pbuf_copy(newly_malloc_packet_buffer, packet_buffer) != ERR_OK)
{
printf("\r\n[%s] error: pbuf copy fail !", __func__);
pbuf_free(newly_malloc_packet_buffer);
return;
}
dhcp_message_total_options_lenth = DHCP_OPTION_TOTAL_LENGTH_MAX;
dhcp_message_repository = (struct dhcp_msg *)newly_malloc_packet_buffer->payload;
#if (!IS_USE_FIXED_IP)
#ifdef CONFIG_DHCPS_KEPT_CLIENT_INFO
temp_ip = check_client_request_ip(&client_request_ip, client_addr);
#endif
/* create new client ip */
if(temp_ip == 0)
temp_ip = search_next_ip();
Expand All @@ -358,15 +515,55 @@ static void dhcps_send_offer(struct pbuf *packet_buffer)
#endif
printf("\r\n No useable ip!!!!\r\n");
}
printf("\n\r[%d]DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(&dhcps_network_id),ip4_addr2(&dhcps_network_id),ip4_addr3(&dhcps_network_id),temp_ip);
#if LWIP_VERSION_MAJOR >= 2
printf("\n\r[%d]DHCP assign ip = %d.%d.%d.%d, hwaddr 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
xTaskGetTickCount(), ip4_addr1(ip_2_ip4(&dhcps_network_id)), \
ip4_addr2(ip_2_ip4(&dhcps_network_id)), \
ip4_addr3(ip_2_ip4(&dhcps_network_id)), temp_ip, \
client_addr[0], client_addr[1], client_addr[2], \
client_addr[3], client_addr[4], client_addr[5]);
IP4_ADDR(ip_2_ip4(&dhcps_allocated_client_address), (ip4_addr1(ip_2_ip4(&dhcps_network_id))),
ip4_addr2(ip_2_ip4(&dhcps_network_id)), ip4_addr3(ip_2_ip4(&dhcps_network_id)), temp_ip);
#else
printf("\n\r[%d]DHCP assign ip = %d.%d.%d.%d, hwaddr 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
xTaskGetTickCount(), ip4_addr1(&dhcps_network_id), \
ip4_addr2(&dhcps_network_id), ip4_addr3(&dhcps_network_id), temp_ip, \
client_addr[0], client_addr[1], client_addr[2], \
client_addr[3], client_addr[4], client_addr[5]);
IP4_ADDR(&dhcps_allocated_client_address, (ip4_addr1(&dhcps_network_id)),
ip4_addr2(&dhcps_network_id), ip4_addr3(&dhcps_network_id), temp_ip);
#endif

#endif
dhcps_initialize_message(dhcp_message_repository);
add_offer_options(add_msg_type(&dhcp_message_repository->options[4],
DHCP_MESSAGE_TYPE_OFFER));
udp_sendto_if(dhcps_pcb, packet_buffer,
&dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif);
if(add_offer_options(add_msg_type(&dhcp_message_repository->options[4], DHCP_MESSAGE_TYPE_OFFER)) == 0){
if(dhcp_message_repository->flags == 0x0){
// unicast
for(int i=0;i<6;i++)
dhcps_allocated_client_ethaddr.addr[i] = dhcp_message_repository->chaddr[i];
#if ETHARP_SUPPORT_STATIC_ENTRIES
#if LWIP_VERSION_MAJOR >= 2
etharp_add_static_entry(ip_2_ip4(&dhcps_allocated_client_address), &dhcps_allocated_client_ethaddr);
#else
etharp_add_static_entry(&dhcps_allocated_client_address, &dhcps_allocated_client_ethaddr);
#endif
#endif
udp_sendto_if(dhcps_pcb, newly_malloc_packet_buffer, &dhcps_allocated_client_address, DHCP_CLIENT_PORT, dhcps_netif);
#if ETHARP_SUPPORT_STATIC_ENTRIES
#if LWIP_VERSION_MAJOR >= 2
etharp_remove_static_entry(ip_2_ip4(&dhcps_allocated_client_address));
#else
etharp_remove_static_entry(&dhcps_allocated_client_address);
#endif
#endif

}
else
// broadcast
udp_sendto_if(dhcps_pcb, newly_malloc_packet_buffer, &dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif);
}

pbuf_free(newly_malloc_packet_buffer);
}

/**
Expand All @@ -390,12 +587,50 @@ static void dhcps_send_nak(struct pbuf *packet_buffer)
*/
static void dhcps_send_ack(struct pbuf *packet_buffer)
{
dhcp_message_repository = (struct dhcp_msg *)packet_buffer->payload;
struct pbuf *newly_malloc_packet_buffer = NULL;

// newly malloc a longer pbuf for dhcp ack rather than using the short pbuf from dhcp request
newly_malloc_packet_buffer = pbuf_alloc(PBUF_TRANSPORT, DHCP_MSG_LEN + DHCP_OPTION_TOTAL_LENGTH_MAX, PBUF_RAM);
if(newly_malloc_packet_buffer == NULL)
{
printf("\r\n[%s] error: pbuf alloc fail !", __func__);
return;
}
if(pbuf_copy(newly_malloc_packet_buffer, packet_buffer) != ERR_OK)
{
printf("\r\n[%s] error: pbuf copy fail !", __func__);
pbuf_free(newly_malloc_packet_buffer);
return;
}
dhcp_message_total_options_lenth = DHCP_OPTION_TOTAL_LENGTH_MAX;
dhcp_message_repository = (struct dhcp_msg *)newly_malloc_packet_buffer->payload;
dhcps_initialize_message(dhcp_message_repository);
add_offer_options(add_msg_type(&dhcp_message_repository->options[4],
DHCP_MESSAGE_TYPE_ACK));
udp_sendto_if(dhcps_pcb, packet_buffer,
&dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif);
if(add_offer_options(add_msg_type(&dhcp_message_repository->options[4], DHCP_MESSAGE_TYPE_ACK)) == 0){
if(dhcp_message_repository->flags == 0x0){
// unicast
for(int i=0;i<6;i++)
dhcps_allocated_client_ethaddr.addr[i] = dhcp_message_repository->chaddr[i];
#if ETHARP_SUPPORT_STATIC_ENTRIES
#if LWIP_VERSION_MAJOR >= 2
etharp_add_static_entry(ip_2_ip4(&dhcps_allocated_client_address), &dhcps_allocated_client_ethaddr);
#else
etharp_add_static_entry(&dhcps_allocated_client_address, &dhcps_allocated_client_ethaddr);
#endif
#endif
udp_sendto_if(dhcps_pcb, newly_malloc_packet_buffer, &dhcps_allocated_client_address, DHCP_CLIENT_PORT, dhcps_netif);
#if ETHARP_SUPPORT_STATIC_ENTRIES
#if LWIP_VERSION_MAJOR >= 2
etharp_remove_static_entry(ip_2_ip4(&dhcps_allocated_client_address));
#else
etharp_remove_static_entry(&dhcps_allocated_client_address);
#endif
#endif
}
else
// broadcast
udp_sendto_if(dhcps_pcb, newly_malloc_packet_buffer, &dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif);
}
pbuf_free(newly_malloc_packet_buffer);
}

/**
Expand Down Expand Up @@ -427,6 +662,18 @@ uint8_t dhcps_handle_state_machine_change(uint8_t option_message_type)
#if (!IS_USE_FIXED_IP)
#if (debug_dhcps)
printf("\r\ndhcp_server_state_machine=%d", dhcp_server_state_machine);
#if LWIP_VERSION_MAJOR >= 2
printf("\r\ndhcps_allocated_client_address=%d.%d.%d.%d",
ip4_addr1(ip_2_ip4(&dhcps_allocated_client_address)),
ip4_addr2(ip_2_ip4(&dhcps_allocated_client_address)),
ip4_addr3(ip_2_ip4(&dhcps_allocated_client_address)),
ip4_addr4(ip_2_ip4(&dhcps_allocated_client_address)));
printf("\r\nclient_request_ip=%d.%d.%d.%d\n",
ip4_addr1(ip_2_ip4(&client_request_ip)),
ip4_addr2(ip_2_ip4(&client_request_ip)),
ip4_addr3(ip_2_ip4(&client_request_ip)),
ip4_addr4(ip_2_ip4(&client_request_ip)));
#else
printf("\r\ndhcps_allocated_client_address=%d.%d.%d.%d",
ip4_addr1(&dhcps_allocated_client_address),
ip4_addr2(&dhcps_allocated_client_address),
Expand All @@ -437,26 +684,71 @@ uint8_t dhcps_handle_state_machine_change(uint8_t option_message_type)
ip4_addr2(&client_request_ip),
ip4_addr3(&client_request_ip),
ip4_addr4(&client_request_ip));
#endif

#endif

// for renew
if((*(uint32_t *) dhcp_message_repository->ciaddr != 0) && (*(uint32_t *)&client_request_ip == 0)) {
memcpy(&client_request_ip, dhcp_message_repository->ciaddr, sizeof(client_request_ip));
}

if (dhcp_server_state_machine == DHCP_SERVER_STATE_OFFER) {
if (ip4_addr4(&dhcps_allocated_client_address) != 0) {
if (memcmp((void *)&dhcps_allocated_client_address, (void *)&client_request_ip, 4) == 0) {
uint8_t ip_addr4 = check_client_direct_request_ip(&client_request_ip, client_addr);

if(ip_addr4 > 0){
#if LWIP_VERSION_MAJOR >= 2
printf("\n\r[%d] DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(ip_2_ip4(&dhcps_network_id)),ip4_addr2(ip_2_ip4(&dhcps_network_id)),ip4_addr3(ip_2_ip4(&dhcps_network_id)),ip_addr4);
IP4_ADDR(ip_2_ip4(&dhcps_allocated_client_address), (ip4_addr1(ip_2_ip4(&dhcps_network_id))),
ip4_addr2(ip_2_ip4(&dhcps_network_id)), ip4_addr3(ip_2_ip4(&dhcps_network_id)), ip_addr4);
#else
printf("\n\r[%d] DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(&dhcps_network_id),ip4_addr2(&dhcps_network_id),ip4_addr3(&dhcps_network_id),ip_addr4);
IP4_ADDR(&dhcps_allocated_client_address, (ip4_addr1(&dhcps_network_id)),
ip4_addr2(&dhcps_network_id), ip4_addr3(&dhcps_network_id), ip_addr4);
#endif
dhcp_server_state_machine = DHCP_SERVER_STATE_ACK;
break;
}

#if LWIP_VERSION_MAJOR >= 2
if (ip4_addr4(ip_2_ip4(&dhcps_allocated_client_address)) != 0)
#else
if (ip4_addr4(&dhcps_allocated_client_address) != 0)
#endif
{
if (memcmp((void *)&dhcps_allocated_client_address, (void *)&client_request_ip, 4) == 0) {
#if LWIP_VERSION_MAJOR >= 2
printf("\n\r[%d] DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(ip_2_ip4(&dhcps_network_id)),ip4_addr2(ip_2_ip4(&dhcps_network_id)),ip4_addr3(ip_2_ip4(&dhcps_network_id)),ip4_addr4(ip_2_ip4(&dhcps_allocated_client_address)));
#else
printf("\n\r[%d] DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(&dhcps_network_id),ip4_addr2(&dhcps_network_id),ip4_addr3(&dhcps_network_id),ip4_addr4(&dhcps_allocated_client_address));
#endif
dhcp_server_state_machine = DHCP_SERVER_STATE_ACK;
} else {
dhcp_server_state_machine = DHCP_SERVER_STATE_NAK;
}
} else {
dhcp_server_state_machine = DHCP_SERVER_STATE_NAK;
}
#ifdef CONFIG_DHCPS_KEPT_CLIENT_INFO
} else if(dhcp_server_state_machine == DHCP_SERVER_STATE_IDLE){
uint8_t ip_addr4 = check_client_request_ip(&client_request_ip, client_addr);
if(ip_addr4 > 0){
uint8_t ip_addr4 = check_client_direct_request_ip(&client_request_ip, client_addr);

if(ip_addr4 > 0){
#if LWIP_VERSION_MAJOR >= 2
printf("\n\r[%d] DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(ip_2_ip4(&dhcps_network_id)),ip4_addr2(ip_2_ip4(&dhcps_network_id)),ip4_addr3(ip_2_ip4(&dhcps_network_id)),ip_addr4);
IP4_ADDR(ip_2_ip4(&dhcps_allocated_client_address), (ip4_addr1(ip_2_ip4(&dhcps_network_id))),
ip4_addr2(ip_2_ip4(&dhcps_network_id)), ip4_addr3(ip_2_ip4(&dhcps_network_id)), ip_addr4);
#else
printf("\n\r[%d] DHCP assign ip = %d.%d.%d.%d\n", xTaskGetTickCount(), ip4_addr1(&dhcps_network_id),ip4_addr2(&dhcps_network_id),ip4_addr3(&dhcps_network_id),ip_addr4);
IP4_ADDR(&dhcps_allocated_client_address, (ip4_addr1(&dhcps_network_id)),
ip4_addr2(&dhcps_network_id), ip4_addr3(&dhcps_network_id), ip_addr4);
#endif

dhcp_server_state_machine = DHCP_SERVER_STATE_ACK;
}else{
dhcp_server_state_machine = DHCP_SERVER_STATE_NAK;
}
#endif
} else {
dhcp_server_state_machine = DHCP_SERVER_STATE_NAK;
}
Expand Down Expand Up @@ -556,6 +848,15 @@ struct pbuf *udp_packet_buffer, struct ip_addr *sender_addr, uint16_t sender_por
return;
}
if (sender_port == DHCP_CLIENT_PORT) {
#if LWIP_VERSION_MAJOR >= 2
if(netif_get_idx(ip_current_input_netif()) == 0 && wifi_mode == RTW_MODE_STA_AP)
#else
if(netif_get_idx(ip_current_netif()) == 0 && wifi_mode == RTW_MODE_STA_AP)
#endif
{
pbuf_free(udp_packet_buffer);
return;
}
total_length_of_packet_buffer = udp_packet_buffer->tot_len;
if (udp_packet_buffer->next != NULL) {
merged_packet_buffer = pbuf_coalesce(udp_packet_buffer,
Expand All @@ -565,6 +866,7 @@ struct pbuf *udp_packet_buffer, struct ip_addr *sender_addr, uint16_t sender_por
pbuf_free(udp_packet_buffer);
return;
}
udp_packet_buffer = merged_packet_buffer;
}
switch (dhcps_check_msg_and_handle_options(udp_packet_buffer)) {
case DHCP_SERVER_STATE_OFFER:
Expand All @@ -579,7 +881,11 @@ struct pbuf *udp_packet_buffer, struct ip_addr *sender_addr, uint16_t sender_por
#endif
dhcps_send_ack(udp_packet_buffer);
#if (!IS_USE_FIXED_IP)
mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_allocated_client_address));
#if LWIP_VERSION_MAJOR >= 2
mark_ip_in_table((uint8_t)ip4_addr4(ip_2_ip4(&dhcps_allocated_client_address)));
#else
mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_allocated_client_address));
#endif
#ifdef CONFIG_DHCPS_KEPT_CLIENT_INFO
save_client_addr(&dhcps_allocated_client_address, client_addr);
memset(&client_request_ip, 0, sizeof(client_request_ip));
Expand Down Expand Up @@ -635,6 +941,65 @@ void dhcps_set_addr_pool(int addr_pool_set, struct ip_addr * addr_pool_start, st
dhcps_addr_pool_set = 0;
}
}


static void dnss_receive_udp_packet_handler(void *arg, struct udp_pcb *udp_pcb,
struct pbuf *udp_packet_buffer, struct ip_addr *sender_addr, uint16_t sender_port)
{
int ret=0;
struct dns_hdr *dns_rsp;

/*
printf("\n%s: Receive DNS query,ip = %d.%d.%d.%d, port = %d(%x)\n",__func__,\
sender_addr->addr & 0xff,\
sender_addr->addr>>8 & 0xff,\
sender_addr->addr>>16 & 0xff,\
sender_addr->addr>>24 & 0xff,\
sender_port,sender_port);
*/

dns_rsp = (struct dns_hdr*) udp_packet_buffer->payload;

dns_rsp->flags1 |= 0x80; // 0x80 : Response;
dns_rsp->flags2 = 0x05; //0x05 : Reply code (Query Refused)

ret = udp_sendto(udp_pcb, udp_packet_buffer, sender_addr, sender_port);

/* free the UDP connection, so we can accept new clients */
udp_disconnect(udp_pcb);

/* Free the packet buffer */
pbuf_free(udp_packet_buffer);
}


void dns_server_init(struct netif * pnetif)
{
uint8_t *ip;

if (dns_server_pcb != NULL) {
udp_remove(dns_server_pcb);
dns_server_pcb = NULL;
}

dns_server_pcb = udp_new();
if (dns_server_pcb == NULL) {
printf("\n\r Error!!!upd_new error \n\r");
return;
}

udp_bind(dns_server_pcb, IP_ADDR_ANY, DNS_SERVER_PORT);
udp_recv(dns_server_pcb, dnss_receive_udp_packet_handler, NULL);
}

void dns_server_deinit(void)
{
if (dns_server_pcb != NULL) {
udp_remove(dns_server_pcb);
dns_server_pcb = NULL;
}
}

/**
* @brief Initialize dhcp server.
* @param None.
Expand Down Expand Up @@ -666,7 +1031,12 @@ void dhcps_init(struct netif * pnetif)
printf("\n\r Error!!!upd_new error \n\r");
return;
}
#if LWIP_VERSION_MAJOR >= 2
IP4_ADDR(ip_2_ip4(&dhcps_send_broadcast_address), 255, 255, 255, 255);
#else
IP4_ADDR(&dhcps_send_broadcast_address, 255, 255, 255, 255);
#endif

/* get net info from net interface */

memcpy(&dhcps_local_address, &pnetif->ip_addr,
Expand All @@ -678,6 +1048,15 @@ void dhcps_init(struct netif * pnetif)
sizeof(struct ip_addr));

/* calculate the usable network ip range */
#if LWIP_VERSION_MAJOR >= 2
ip4_addr_set_u32(ip_2_ip4(&dhcps_network_id), (ip_addr_get_ip4_u32(netif_ip_addr4(pnetif))&(ip_addr_get_ip4_u32(netif_ip_netmask4(pnetif)))));
ip4_addr_set_u32(ip_2_ip4(&dhcps_subnet_broadcast), (ip4_addr_get_u32(ip_2_ip4(&dhcps_network_id)) | ~(ip_addr_get_ip4_u32(netif_ip_netmask4(pnetif)))));
#if 1
ip4_addr_set_u32(ip_2_ip4(&dhcps_owned_first_ip), htonl(ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcps_network_id))) + 1));
ip4_addr_set_u32(ip_2_ip4(&dhcps_owned_last_ip), htonl(ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcps_subnet_broadcast))) - 1));
dhcps_num_of_available_ips = (ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcps_owned_last_ip))) - ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcps_owned_first_ip)))) + 1;
#endif
#else
dhcps_network_id.addr = ((pnetif->ip_addr.addr) &
(pnetif->netmask.addr));

Expand All @@ -689,6 +1068,8 @@ void dhcps_init(struct netif * pnetif)
dhcps_num_of_available_ips = ((ntohl(dhcps_owned_last_ip.addr)
- ntohl(dhcps_owned_first_ip.addr)) + 1);
#endif
#endif


#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
#if IP_SOF_BROADCAST
Expand All @@ -697,9 +1078,16 @@ void dhcps_init(struct netif * pnetif)
#endif

#if IS_USE_FIXED_IP
#if LWIP_VERSION_MAJOR >= 2
IP4_ADDR(ip_2_ip4(&dhcps_allocated_client_address), ip4_addr1(ip_2_ip4(&dhcps_local_address))
, ip4_addr2(ip_2_ip4(&dhcps_local_address)), ip4_addr3(ip_2_ip4(&dhcps_local_address)),
(ip4_addr4(ip_2_ip4(&dhcps_local_address))) + 1 );
#else
IP4_ADDR(&dhcps_allocated_client_address, ip4_addr1(&dhcps_local_address)
, ip4_addr2(&dhcps_local_address), ip4_addr3(&dhcps_local_address),
(ip4_addr4(&dhcps_local_address)) + 1 );
#endif

#else
if (dhcps_ip_table_semaphore != NULL) {
vSemaphoreDelete(dhcps_ip_table_semaphore);
Expand All @@ -709,15 +1097,26 @@ void dhcps_init(struct netif * pnetif)

//dhcps_ip_table = (struct ip_table *)(pvPortMalloc(sizeof(struct ip_table)));
memset(&ip_table, 0, sizeof(struct table));
#if LWIP_VERSION_MAJOR >= 2
mark_ip_in_table((uint8_t)ip4_addr4(ip_2_ip4(&dhcps_local_address)));
mark_ip_in_table((uint8_t)ip4_addr4(ip_2_ip4(&dhcps_local_gateway)));
#else
mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_local_address));
mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_local_gateway));
#endif

#if 0
for (i = 1; i < ip4_addr4(&dhcps_local_address); i++) {
mark_ip_in_table(i);
}
#endif
#endif
#if LWIP_VERSION_MAJOR >= 2
if(ip4_addr_get_u32(ip_2_ip4(&dhcps_addr_pool_start)) == 0 && ip4_addr_get_u32(ip_2_ip4(&dhcps_addr_pool_end)) == 0)
#else
if(dhcps_addr_pool_start.addr== 0 && dhcps_addr_pool_end.addr == 0)
#endif

{
memcpy(&dhcps_pool_start,&dhcps_local_address,sizeof(struct ip_addr));
ip = (uint8_t *)&dhcps_pool_start;
Expand All @@ -729,6 +1128,10 @@ void dhcps_init(struct netif * pnetif)
}
udp_bind(dhcps_pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
udp_recv(dhcps_pcb, dhcps_receive_udp_packet_handler, NULL);

//DNS server init
dns_server_init(pnetif);

}

void dhcps_deinit(void)
Expand All @@ -740,5 +1143,7 @@ void dhcps_deinit(void)
if (dhcps_ip_table_semaphore != NULL) {
vSemaphoreDelete(dhcps_ip_table_semaphore);
dhcps_ip_table_semaphore = NULL;
}
}
//DNS server deinit
dns_server_deinit();
}
19 changes: 19 additions & 0 deletions component/common/network/dhcp/dhcps.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "lwip/udp.h"
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "netif/etharp.h"

#include <platform/platform_stdlib.h>

Expand Down Expand Up @@ -36,6 +37,7 @@
#define DHCP_MESSAGE_HTYPE (1)
#define DHCP_MESSAGE_HLEN (6)

#define DNS_SERVER_PORT (53)
#define DHCP_SERVER_PORT (67)
#define DHCP_CLIENT_PORT (68)

Expand All @@ -51,6 +53,10 @@
#define DHCP_OPTION_LENGTH_TWO (2)
#define DHCP_OPTION_LENGTH_THREE (3)
#define DHCP_OPTION_LENGTH_FOUR (4)
#ifndef DHCP_MSG_LEN
#define DHCP_MSG_LEN 236
#endif
#define DHCP_OPTION_TOTAL_LENGTH_MAX 312 //(51)= 4(magic)+3(type)+44(option code: 1,3,6,51,54,28,26,32,end)

#define DHCP_OPTION_CODE_SUBNET_MASK (1)
#define DHCP_OPTION_CODE_ROUTER (3)
Expand Down Expand Up @@ -115,6 +121,19 @@ struct address_pool{
uint32_t end;
};

PACK_STRUCT_BEGIN
/** DNS message header */
struct dns_hdr {
PACK_STRUCT_FIELD(u16_t id);
PACK_STRUCT_FIELD(u8_t flags1);
PACK_STRUCT_FIELD(u8_t flags2);
PACK_STRUCT_FIELD(u16_t numquestions);
PACK_STRUCT_FIELD(u16_t numanswers);
PACK_STRUCT_FIELD(u16_t numauthrr);
PACK_STRUCT_FIELD(u16_t numextrarr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END

/* 01~32 */
#define MARK_RANGE1_IP_BIT(table, ip) ((table.ip_range[0]) | (1 << ((ip) - 1)))
/* 33~64 */
Expand Down