mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
netutils/dhcpc/dhcpc.c:Implement a dedicated interface to send
DHCPRELEASE, According to RFC 2131 section 3.1, DHCPRELEASE is used by a client to relinquish a network address and cancel any remaining lease time Signed-off-by: nuttxs <zhaoqing.zhang@sony.com>
This commit is contained in:
parent
227d3ec35b
commit
dfeeef41ed
3 changed files with 150 additions and 0 deletions
|
|
@ -78,6 +78,7 @@ FAR void *dhcpc_open(FAR const char *interface,
|
|||
FAR const void *mac_addr, int mac_len);
|
||||
int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult);
|
||||
int dhcpc_request_async(FAR void *handle, dhcpc_callback_t callback);
|
||||
int dhcpc_release(FAR void *handle, FAR struct dhcpc_state *presult);
|
||||
void dhcpc_cancel(FAR void *handle);
|
||||
void dhcpc_close(FAR void *handle);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,4 +43,42 @@ config NETUTILS_DHCPC_BOOTP_FLAGS
|
|||
being fully configured, e.g. with forward enabled. Then we need
|
||||
to enable the broadcast flag under these situations.
|
||||
|
||||
config NETUTILS_DHCPC_RELEASE_RETRIES
|
||||
int "DHCP Release send retries"
|
||||
default 3
|
||||
---help---
|
||||
Number of times to retry sending DHCPRELEASE message if sendto() fails.
|
||||
Default is 3 attempts.
|
||||
|
||||
config NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS
|
||||
int "DHCP Release transmission delay (milliseconds)"
|
||||
default 10
|
||||
---help---
|
||||
Delay in milliseconds used for:
|
||||
1. Between DHCPRELEASE retry attempts when sendto() fails
|
||||
2. To ensure packet transmission before socket closure (if IP clearing enabled)
|
||||
Since UDP is connectionless, this delay gives the network stack
|
||||
time to actually send the packet. Set to 0 to disable delays
|
||||
(not recommended). Default is 10ms.
|
||||
|
||||
config NETUTILS_DHCPC_RELEASE_ENSURE_TRANSMISSION
|
||||
bool "Ensure DHCP Release message transmission"
|
||||
default y
|
||||
---help---
|
||||
Add a delay after successfully sending DHCPRELEASE message to ensure
|
||||
the packet is actually transmitted before the function returns.
|
||||
Since DHCP RELEASE has no ACK response from server, this delay helps
|
||||
ensure the release message reaches the server before closing the socket.
|
||||
Uses the same delay value as CONFIG_NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS.
|
||||
|
||||
config NETUTILS_DHCPC_RELEASE_CLEAR_IP
|
||||
bool "Clear IP address after DHCP release"
|
||||
default n
|
||||
---help---
|
||||
Clear all network configuration from the interface after sending
|
||||
DHCPRELEASE message. This includes IP address, subnet mask, default
|
||||
gateway. RFC 2131 doesn't mandate immediate clearing, so this is
|
||||
disabled by default to maintain connectivity.
|
||||
Enable this for scenarios where complete network reset is required.
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -303,6 +303,16 @@ static int dhcpc_sendmsg(FAR struct dhcpc_state_s *pdhcpc,
|
|||
serverid = presult->serverid.s_addr;
|
||||
break;
|
||||
|
||||
/* Send RELEASE message to the server to relinquish the lease */
|
||||
|
||||
case DHCPRELEASE:
|
||||
|
||||
memcpy(pdhcpc->packet.ciaddr, &presult->ipaddr.s_addr, 4);
|
||||
pend = dhcpc_addserverid(&presult->serverid, pend);
|
||||
pend = dhcpc_addclientid(pdhcpc->macaddr, pdhcpc->maclen, pend);
|
||||
serverid = presult->serverid.s_addr;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return ERROR;
|
||||
|
|
@ -950,3 +960,104 @@ int dhcpc_request_async(FAR void *handle, dhcpc_callback_t callback)
|
|||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dhcpc_release
|
||||
****************************************************************************/
|
||||
|
||||
int dhcpc_release(FAR void *handle, FAR struct dhcpc_state *presult)
|
||||
{
|
||||
FAR struct dhcpc_state_s *pdhcpc = (FAR struct dhcpc_state_s *)handle;
|
||||
int ret;
|
||||
int retries = 0;
|
||||
#ifdef CONFIG_NETUTILS_DHCPC_RELEASE_CLEAR_IP
|
||||
struct in_addr zero_addr;
|
||||
#endif
|
||||
|
||||
if (!handle || !presult)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Check that we have valid IP address and server ID to release */
|
||||
|
||||
if (presult->ipaddr.s_addr == 0 || presult->serverid.s_addr == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Increment transaction ID for the release message */
|
||||
|
||||
pdhcpc->xid[3]++;
|
||||
|
||||
/* Send DHCPRELEASE message to the server with retry mechanism.
|
||||
* According to RFC 2131, no response is expected from the server.
|
||||
*/
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
ret = dhcpc_sendmsg(pdhcpc, presult, DHCPRELEASE);
|
||||
if (ret > 0)
|
||||
{
|
||||
ninfo("DHCPRELEASE message sent successfully (%d bytes)\n", ret);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
retries++;
|
||||
nerr("Failed send DHCPRELEASE (attempt %d/%d), ret=%d, errno=%d\n",
|
||||
retries, CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES, ret, errno);
|
||||
|
||||
if (retries >= CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES)
|
||||
{
|
||||
nerr("ERROR: Failed to send DHCPRELEASE after %d attempts\n",
|
||||
CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
usleep(1000 * CONFIG_NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETUTILS_DHCPC_RELEASE_ENSURE_TRANSMISSION
|
||||
/* Ensure the DHCPRELEASE packet has time to be transmitted.
|
||||
* Since DHCP RELEASE has no ACK response and UDP is connectionless,
|
||||
* we use a delay to give the network stack time to actually send
|
||||
* the packet before the function returns.
|
||||
*/
|
||||
|
||||
usleep(1000 * CONFIG_NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETUTILS_DHCPC_RELEASE_CLEAR_IP
|
||||
/* Clear all network configuration that was obtained via DHCP */
|
||||
|
||||
zero_addr.s_addr = INADDR_ANY;
|
||||
|
||||
ret = netlib_set_ipv4addr(pdhcpc->interface, &zero_addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("Warning: Failed clear IP address from interface (errno=%d)\n",
|
||||
errno);
|
||||
}
|
||||
|
||||
ret = netlib_set_ipv4netmask(pdhcpc->interface, &zero_addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("Warning: Failed clear netmask from interface (errno=%d)\n",
|
||||
errno);
|
||||
}
|
||||
|
||||
ret = netlib_set_dripv4addr(pdhcpc->interface, &zero_addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("Warning: Failed clear gateway from interface (errno=%d)\n",
|
||||
errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
ninfo("DHCP released successfully\n");
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue