mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
fix(lwip): Use ACD light module for simple DHCP-ARP check
This commit is contained in:
parent
720b74026c
commit
c098388a2f
@ -57,7 +57,6 @@ if(CONFIG_LWIP_ENABLE)
|
||||
"lwip/src/core/ipv4/ip4_napt.c"
|
||||
"lwip/src/core/ipv4/ip4_addr.c"
|
||||
"lwip/src/core/ipv4/ip4_frag.c"
|
||||
"lwip/src/core/ipv4/acd.c"
|
||||
"lwip/src/core/ipv6/dhcp6.c"
|
||||
"lwip/src/core/ipv6/ethip6.c"
|
||||
"lwip/src/core/ipv6/icmp6.c"
|
||||
@ -136,7 +135,13 @@ if(CONFIG_LWIP_ENABLE)
|
||||
"lwip/src/netif/ppp/vj.c")
|
||||
endif()
|
||||
|
||||
if(NOT ${target} STREQUAL "linux")
|
||||
if(CONFIG_LWIP_DHCP_DOES_ARP_CHECK)
|
||||
list(APPEND srcs "port/acd_dhcp_check.c")
|
||||
elseif(CONFIG_LWIP_DHCP_DOES_ACD_CHECK)
|
||||
list(APPEND srcs "lwip/src/core/ipv4/acd.c")
|
||||
endif()
|
||||
|
||||
if(NOT ${target} STREQUAL "linux")
|
||||
# Support for vfs and linker fragments only for target builds
|
||||
set(linker_fragments linker.lf)
|
||||
if(CONFIG_VFS_SUPPORT_IO)
|
||||
|
@ -318,13 +318,29 @@ menu "LWIP"
|
||||
Set TCPIP task receive mail box size. Generally bigger value means higher throughput
|
||||
but more memory. The value should be bigger than UDP/TCP mail box size.
|
||||
|
||||
config LWIP_DHCP_DOES_ARP_CHECK
|
||||
bool "DHCP: Perform ARP check on any offered address"
|
||||
default y
|
||||
choice LWIP_DHCP_CHECKS_OFFERED_ADDRESS
|
||||
prompt "Choose how DHCP validates offered IP"
|
||||
default LWIP_DHCP_DOES_ARP_CHECK
|
||||
depends on LWIP_IPV4
|
||||
help
|
||||
Enabling this option performs a check (via ARP request) if the offered IP address
|
||||
is not already in use by another host on the network.
|
||||
Choose the preferred way of DHCP client to check if the offered address
|
||||
is available:
|
||||
* Using Address Conflict Detection (ACD) module assures that the offered IP address
|
||||
is properly probed and announced before binding in DHCP. This conforms to RFC5227,
|
||||
but takes several seconds.
|
||||
* Using ARP check, we only send two ARP requests to check for replies. This process
|
||||
lasts 1 - 2 seconds.
|
||||
* No conflict detection: We directly bind the offered address.
|
||||
|
||||
config LWIP_DHCP_DOES_ARP_CHECK
|
||||
bool "DHCP provides simple ARP check"
|
||||
depends on !LWIP_AUTOIP
|
||||
config LWIP_DHCP_DOES_ACD_CHECK
|
||||
bool "DHCP provides Address Conflict Detection (ACD)"
|
||||
config LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP
|
||||
bool "DHCP does not detect conflict on the offered IP"
|
||||
|
||||
endchoice
|
||||
|
||||
config LWIP_DHCP_DISABLE_CLIENT_ID
|
||||
bool "DHCP: Disable Use of HW address as client identification"
|
||||
|
138
components/lwip/port/acd_dhcp_check.c
Normal file
138
components/lwip/port/acd_dhcp_check.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/* don't build if not configured for use in lwipopts.h */
|
||||
#if LWIP_IPV4 && DHCP_DOES_ARP_CHECK
|
||||
|
||||
#include "lwip/acd.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/prot/dhcp.h"
|
||||
#include "lwip/timeouts.h"
|
||||
|
||||
#define ACD_DHCP_ARP_REPLY_TIMEOUT_MS 500
|
||||
|
||||
static void
|
||||
acd_dhcp_check_timeout_cb(void *arg);
|
||||
|
||||
static void
|
||||
acd_suspend(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp;
|
||||
struct acd *acd;
|
||||
if (netif == NULL || (dhcp = netif_dhcp_data(netif)) == NULL) {
|
||||
return;
|
||||
}
|
||||
acd = &dhcp->acd;
|
||||
acd->state = ACD_STATE_OFF;
|
||||
sys_untimeout(acd_dhcp_check_timeout_cb, (void *)netif);
|
||||
}
|
||||
|
||||
void
|
||||
acd_remove(struct netif *netif, struct acd *acd)
|
||||
{
|
||||
acd_suspend(netif);
|
||||
acd->acd_conflict_callback = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
acd_netif_ip_addr_changed(struct netif *netif, const ip_addr_t *old_addr,
|
||||
const ip_addr_t *new_addr)
|
||||
{
|
||||
acd_suspend(netif);
|
||||
}
|
||||
|
||||
void
|
||||
acd_network_changed_link_down(struct netif *netif)
|
||||
{
|
||||
acd_suspend(netif);
|
||||
}
|
||||
|
||||
void
|
||||
acd_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
{
|
||||
struct dhcp *dhcp;
|
||||
ip4_addr_t sipaddr;
|
||||
struct eth_addr netifaddr;
|
||||
struct acd *acd;
|
||||
if (netif == NULL || (dhcp = netif_dhcp_data(netif)) == NULL) {
|
||||
return;
|
||||
}
|
||||
acd = &dhcp->acd;
|
||||
// Check that we're looking for ARP reply in ACD_PROBING state and DHCP_CHECKING state
|
||||
if (hdr->opcode != PP_HTONS(ARP_REPLY) || dhcp->state != DHCP_STATE_CHECKING ||
|
||||
acd->state != ACD_STATE_PROBING || acd->acd_conflict_callback == NULL) {
|
||||
return;
|
||||
}
|
||||
SMEMCPY(netifaddr.addr, netif->hwaddr, ETH_HWADDR_LEN);
|
||||
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr);
|
||||
LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("acd_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
|
||||
ip4_addr_get_u32(&sipaddr)));
|
||||
/* did another host (not our mac addr) respond with the address we were offered by the DHCP server? */
|
||||
if (ip4_addr_eq(&sipaddr, &dhcp->offered_ip_addr) &&
|
||||
!eth_addr_eq(&netifaddr, &hdr->shwaddr)) {
|
||||
LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("acd_arp_reply(): arp reply matched with offered address, declining\n"));
|
||||
dhcp->acd.acd_conflict_callback(netif, ACD_DECLINE);
|
||||
}
|
||||
}
|
||||
|
||||
err_t
|
||||
acd_add(struct netif *netif, struct acd *acd,
|
||||
acd_conflict_callback_t acd_conflict_callback)
|
||||
{
|
||||
acd->acd_conflict_callback = acd_conflict_callback;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void send_probe_once(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||
if (etharp_query(netif, &dhcp->offered_ip_addr, NULL) != ERR_OK) {
|
||||
LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("acd_send_probe_once(): could not perform ARP query\n"));
|
||||
return;
|
||||
}
|
||||
if (dhcp->tries < 255) {
|
||||
dhcp->tries++;
|
||||
}
|
||||
LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("acd_send_probe_once(): set request timeout %"U16_F" msecs\n", ACD_DHCP_ARP_REPLY_TIMEOUT_MS));
|
||||
sys_timeout(ACD_DHCP_ARP_REPLY_TIMEOUT_MS, acd_dhcp_check_timeout_cb, (void *)netif);
|
||||
}
|
||||
|
||||
static void
|
||||
acd_dhcp_check_timeout_cb(void *arg)
|
||||
{
|
||||
struct netif *netif = (struct netif *)arg;
|
||||
struct dhcp *dhcp;
|
||||
struct acd *acd;
|
||||
if (netif == NULL || (dhcp = netif_dhcp_data(netif)) == NULL) {
|
||||
return;
|
||||
}
|
||||
acd = &dhcp->acd;
|
||||
if (acd->state != ACD_STATE_PROBING || acd->acd_conflict_callback == NULL || dhcp->state != DHCP_STATE_CHECKING) {
|
||||
return;
|
||||
}
|
||||
LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("acd_dhcp_check_timeout_cb(): CHECKING, ARP request timed out\n"));
|
||||
if (dhcp->tries <= 1) {
|
||||
send_probe_once(netif);
|
||||
} else {
|
||||
// No conflict detected
|
||||
dhcp->acd.acd_conflict_callback(netif, ACD_IP_OK);
|
||||
}
|
||||
}
|
||||
|
||||
err_t
|
||||
acd_start(struct netif *netif, struct acd *acd, ip4_addr_t ipaddr)
|
||||
{
|
||||
if (netif == NULL || netif_dhcp_data(netif) == NULL) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
acd->state = ACD_STATE_PROBING;
|
||||
send_probe_once(netif);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV4 && DHCP_DOES_ARP_CHECK */
|
@ -308,12 +308,23 @@ extern "C" {
|
||||
#define LWIP_DHCP 1
|
||||
|
||||
/**
|
||||
* DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address.
|
||||
* LWIP_DHCP_CHECKS_OFFERED_ADDRESS:
|
||||
* - Using Address Conflict Detection (ACD) module assures that the offered IP address
|
||||
* is properly probed and announced before binding in DHCP. This conforms to RFC5227,
|
||||
* but takes several seconds.
|
||||
* - Using ARP check, we only send two ARP requests to check for replies. This process
|
||||
* lasts 1 - 2 seconds.
|
||||
* - No conflict detection: We directly bind the offered address.
|
||||
*/
|
||||
#ifdef CONFIG_LWIP_DHCP_DOES_ARP_CHECK
|
||||
#define DHCP_DOES_ARP_CHECK 1
|
||||
#define LWIP_DHCP_DOES_ACD_CHECK 1
|
||||
#elif CONFIG_LWIP_DHCP_DOES_ACD_CHECK
|
||||
#define DHCP_DOES_ARP_CHECK 0
|
||||
#define LWIP_DHCP_DOES_ACD_CHECK 1
|
||||
#else
|
||||
#define DHCP_DOES_ARP_CHECK 0
|
||||
#define LWIP_DHCP_DOES_ACD_CHECK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user