Merge branch 'feature/modify_dhcp_offer_and_ack_to_unicast' into 'master'

fix(lwip): Modify the DHCP offer and DHCP ack from broadcast to unicast

Closes WIFI-68

See merge request espressif/esp-idf!26379
pull/12486/head
Jiang Jiang Jian 2023-10-11 18:26:21 +08:00
commit c7eb0d22a8
3 zmienionych plików z 105 dodań i 23 usunięć

Wyświetl plik

@ -387,6 +387,14 @@ menu "LWIP"
After this number is exceeded, DHCP server removes of the oldest device
from it's address pool, without notification.
config LWIP_DHCPS_STATIC_ENTRIES
bool "Enable ARP static entries"
default y
depends on LWIP_DHCPS
help
Enabling this option allows DHCP server to support temporary static ARP entries
for DHCP Client. This will help the DHCP server to send the DHCP OFFER and DHCP ACK using IP unicast.
endmenu # DHCPS
menuconfig LWIP_AUTOIP

Wyświetl plik

@ -13,6 +13,8 @@
#include "lwip/mem.h"
#include "lwip/ip_addr.h"
#include "lwip/timeouts.h"
#include "lwip/etharp.h"
#include "lwip/prot/ethernet.h"
#include "dhcpserver/dhcpserver.h"
#include "dhcpserver/dhcpserver_options.h"
@ -28,6 +30,7 @@
#endif
#define BOOTP_BROADCAST 0x8000
#define BROADCAST_BIT_IS_SET(flag) (flag & BOOTP_BROADCAST)
#define DHCP_REQUEST 1
#define DHCP_REPLY 2
@ -508,35 +511,67 @@ static void create_msg(dhcps_t *dhcps, struct dhcps_msg *m)
client.addr = *((uint32_t *) &dhcps->client_address);
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;
#if !ETHARP_SUPPORT_STATIC_ENTRIES
/* If the DHCP server does not support sending unicast message to the client,
* need to set the 'flags' field to broadcast */
m->flags = htons(BOOTP_BROADCAST);
#endif
memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
memset((char *) m->siaddr, 0, sizeof(m->siaddr));
memset((char *) m->giaddr, 0, sizeof(m->giaddr));
memset((char *) m->sname, 0, sizeof(m->sname));
memset((char *) m->file, 0, sizeof(m->file));
memset((char *) m->options, 0, sizeof(m->options));
u32_t magic_cookie_temp = magic_cookie;
memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp));
memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie));
}
/******************************************************************************
* FunctionName : dhcps_response_ip_set
* Description : set the ip address for sending to the DHCP client
* Parameters : m -- DHCP message info
* ip4_out -- ip address for sending
* Returns : none
*******************************************************************************/
static void dhcps_response_ip_set(dhcps_t *dhcps, struct dhcps_msg *m, ip4_addr_t *ip4_out)
{
#if ETHARP_SUPPORT_STATIC_ENTRIES
ip4_addr_t ip4_giaddr;
ip4_addr_t ip4_ciaddr;
ip4_addr_t ip4_yiaddr;
struct eth_addr chaddr;
memcpy(chaddr.addr, m->chaddr, sizeof(chaddr.addr));
memcpy((char *)&ip4_giaddr.addr, (char *)m->giaddr, sizeof(m->giaddr));
memcpy((char *)&ip4_ciaddr.addr, (char *)m->ciaddr, sizeof(m->ciaddr));
memcpy((char *)&ip4_yiaddr.addr, (char *)m->yiaddr, sizeof(m->yiaddr));
if (!ip4_addr_isany_val(ip4_giaddr)) {
/* If the 'giaddr' field is non-zero, send return message to the address in 'giaddr'. (RFC 2131)*/
ip4_addr_set(ip4_out, &ip4_giaddr);
/* add the IP<->MAC as static entry into the arp table. */
etharp_add_static_entry(&ip4_giaddr, &chaddr);
} else {
if (!ip4_addr_isany_val(ip4_ciaddr)) {
/* If the 'giaddr' field is zero and the 'ciaddr' is nonzero,
* the server unicasts DHCPOFFER and DHCPACK message to the address in 'ciaddr'*/
ip4_addr_set(ip4_out, &ip4_ciaddr);
etharp_add_static_entry(&ip4_ciaddr, &chaddr);
} else if (!BROADCAST_BIT_IS_SET(htons(m->flags))) {
/* If the 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is not set,
* the server unicasts DHCPOFFER and DHCPACK message to the client's hardware address and
* 'yiaddr' address. */
ip4_addr_set(ip4_out, &ip4_yiaddr);
etharp_add_static_entry(&ip4_yiaddr, &chaddr);
} else {
/* The server broadcast DHCPOFFER and DHCPACK message to 0xffffffff*/
ip4_addr_set(ip4_out, &dhcps->broadcast_dhcps);
}
}
#else
ip4_addr_set(ip4_out, &dhcps->broadcast_dhcps);
#endif
}
struct pbuf * dhcps_pbuf_alloc(u16_t len)
{
u16_t mlen = sizeof(struct dhcps_msg);
@ -614,7 +649,7 @@ static void send_offer(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
}
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
dhcps_response_ip_set(dhcps, m, ip_2_ip4(&ip_temp));
#if DHCPS_DEBUG
SendOffer_err_t = udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
@ -622,6 +657,11 @@ static void send_offer(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
#endif
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* remove the IP<->MAC from the arp table. */
etharp_remove_static_entry(ip_2_ip4(&ip_temp));
#endif
if (p->ref != 0) {
#if DHCPS_DEBUG
DHCPS_LOG("udhcp: send_offer>>free pbuf\n");
@ -692,7 +732,25 @@ static void send_nak(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
}
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
#if ETHARP_SUPPORT_STATIC_ENTRIES
ip4_addr_t ip4_giaddr;
struct eth_addr chaddr;
memcpy(chaddr.addr, m->chaddr, sizeof(chaddr.addr));
memcpy((char *)&ip4_giaddr.addr, (char *)m->giaddr, sizeof(m->giaddr));
if (!ip4_addr_isany_val(ip4_giaddr)) {
ip4_addr_set(ip_2_ip4(&ip_temp), &ip4_giaddr);
/* add the IP<->MAC as static entry into the arp table. */
etharp_add_static_entry(&ip4_giaddr, &chaddr);
} else {
/* when 'giaddr' is zero, the server broadcasts any DHCPNAK message to 0xffffffff. (RFC 2131)*/
ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
}
#else
ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
#endif
#if DHCPS_DEBUG
SendNak_err_t = udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
@ -700,6 +758,11 @@ static void send_nak(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
#endif
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* remove the IP<->MAC from the arp table. */
etharp_remove_static_entry(ip_2_ip4(&ip_temp));
#endif
if (p->ref != 0) {
#if DHCPS_DEBUG
DHCPS_LOG("udhcp: send_nak>>free pbuf\n");
@ -769,12 +832,17 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
}
ip_addr_t ip_temp = IPADDR4_INIT(0x0);
ip4_addr_set(ip_2_ip4(&ip_temp), &dhcps->broadcast_dhcps);
dhcps_response_ip_set(dhcps, m, ip_2_ip4(&ip_temp));
SendAck_err_t = udp_sendto(dhcps->dhcps_pcb, p, &ip_temp, DHCPS_CLIENT_PORT);
#if DHCPS_DEBUG
DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t);
#endif
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* remove the IP<->MAC from the arp table. */
etharp_remove_static_entry(ip_2_ip4(&ip_temp));
#endif
if (SendAck_err_t == ERR_OK) {
dhcps->dhcps_cb(dhcps->dhcps_cb_arg, m->yiaddr, m->chaddr);
}

Wyświetl plik

@ -162,6 +162,12 @@ extern "C" {
*/
#define ARP_QUEUEING 1
#ifdef CONFIG_LWIP_DHCPS_STATIC_ENTRIES
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
#else
#define ETHARP_SUPPORT_STATIC_ENTRIES 0
#endif
/*
--------------------------------
---------- IP options ----------