This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 4ca4c700ddc5058088ef80e34f2e11301408cd26
Author: Erik Englund <[email protected]>
AuthorDate: Fri Oct 2 19:34:25 2026 +0200

    netutils/dhcpc: Send the REQUEST before using the offered address.
    
    dhcpc_request() assigned the offered address to the interface as soon
    as the OFFER arrived, so that it could receive a unicast ACK.  The
    REQUEST then went out with the offered address as IP source, while
    RFC 2131 section 4.1 requires 0.0.0.0 until the server has assigned
    the address.  Some routers treat such a client as one with a static
    address; TP-Link Deco mesh routers, for example, list it as offline
    and do not offer address reservation for it.
    
    Send each REQUEST from the address the interface had before and only
    then use the offered address while waiting for the ACK, so unicast ACKs
    are still received.  Also restore the old address when no ACK arrives
    instead of leaving the unconfirmed offered address in place.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Erik Englund <[email protected]>
---
 netutils/dhcpc/dhcpc.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c
index a449c96ca..8d3d4df22 100644
--- a/netutils/dhcpc/dhcpc.c
+++ b/netutils/dhcpc/dhcpc.c
@@ -866,13 +866,6 @@ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state 
*presult)
                         (uint32_t)ntohl(presult->serverid.s_addr));
                   pdhcpc->ipaddr.s_addr   = presult->ipaddr.s_addr;
                   pdhcpc->serverid.s_addr = presult->serverid.s_addr;
-
-                  /* Temporarily use the address offered by the server
-                   * and break out of the loop.
-                   */
-
-                  netlib_set_ipv4addr(pdhcpc->interface,
-                                      &presult->ipaddr);
                   state = STATE_HAVE_OFFER;
                 }
             }
@@ -916,15 +909,25 @@ int dhcpc_request(FAR void *handle, FAR struct 
dhcpc_state *presult)
         }
 
       /* Send the REQUEST message to obtain the lease that was offered to
-       * us.
+       * us.  The offered address must not be used before the server has
+       * acknowledged it, so the REQUEST is sent from the address we had
+       * before (0.0.0.0 when unconfigured), as RFC 2131 requires.
        */
 
+      netlib_set_ipv4addr(pdhcpc->interface, &oldaddr);
+
       ninfo("Send REQUEST\n");
       if (dhcpc_sendmsg(pdhcpc, presult, DHCPREQUEST) < 0)
         {
           return ERROR;
         }
 
+      /* Temporarily use the offered address so that a unicast ACK can be
+       * received.  Without UDP write buffers sendto() has returned only
+       * after the REQUEST was sent with the old source address.
+       */
+
+      netlib_set_ipv4addr(pdhcpc->interface, &pdhcpc->ipaddr);
       retries++;
 
       /* Get the ACK/NAK response to the REQUEST (or timeout) */
@@ -1001,10 +1004,13 @@ int dhcpc_request(FAR void *handle, FAR struct 
dhcpc_state *presult)
   while (state == STATE_HAVE_OFFER &&
          retries < CONFIG_NETUTILS_DHCPC_RETRIES);
 
-  /* If no DHCPLEASE received here, error out */
+  /* If no DHCPLEASE received here, drop the offered address and error
+   * out.
+   */
 
   if (state != STATE_HAVE_LEASE)
     {
+      netlib_set_ipv4addr(pdhcpc->interface, &oldaddr);
       return ERROR;
     }
 

Reply via email to