ErikkEnglund opened a new pull request, #3806: URL: https://github.com/apache/nuttx-apps/pull/3806
*Note: Please adhere to [Contributing Guidelines](https://github.com/apache/nuttx/blob/master/CONTRIBUTING.md).* ## Summary `dhcpc_request()` assigned the offered address to the interface as soon as the OFFER arrived, so that it could receive a unicast ACK. As a side effect the REQUEST went out with the offered address as IP source. RFC 2131 [section 4.1](https://www.rfc-editor.org/rfc/rfc2131#section-4.1) says: > DHCP messages broadcast by a client prior to that client obtaining its IP address must have the source address field in the IP header set to 0. and the client only obtains the address with the DHCPACK ([section 3.1](https://www.rfc-editor.org/rfc/rfc2131#section-3.1), step 5). Most servers accept the REQUEST anyway, but some routers treat such a client as one with a statically configured address. A TP-Link Deco mesh router, for example, lists the device as offline and does not offer address reservation for it, even though it serves the lease. This PR: * sends each REQUEST from the address the interface had before (0.0.0.0 on first configuration) and only then sets the offered address while waiting for the ACK, so a unicast ACK is still received; * restores the old address when no ACK arrives, instead of leaving the unconfirmed offered address on the interface; * fixes the existing nxstyle issues in `dhcpc.c` in a separate commit (no functional change). Setting `CONFIG_NETUTILS_DHCPC_BOOTP_FLAGS=0x8000` and not using the offered address at all would also avoid the wrong source address, but then the OFFER and ACK are broadcast, and broadcast frames on Wi-Fi are not retransmitted. In testing that made DHCP noticeably less reliable (see below), so this change keeps the unicast ACK. ## Impact * Users of `dhcpc_request()` (netinit, `netlib_obtain_ipv4addr()`, the `renew` command): the REQUEST is sent from 0.0.0.0 on first configuration, or from the current address when renewing. No API or Kconfig changes. * When no ACK arrives, the interface goes back to its previous address instead of keeping the offered one. * The fix relies on `sendto()` returning only after the REQUEST has been sent, which holds without `CONFIG_NET_UDP_WRITE_BUFFERS`. With UDP write buffers the REQUEST may still go out from the offered address, i.e. the same behaviour as before this change. * Build, hardware, documentation, security: none. ## Testing Host: Fedora 44 (Linux 7.2.7, x86_64), xPack riscv-none-elf-gcc 13.2.0-2. Target: ESP32-C3-DevKitC-02 (ESP32-C3 rev v0.3), `esp32c3-devkit:wifi` with netinit DHCP (`CONFIG_NETINIT_DHCPC=y`, `CONFIG_NETINIT_THREAD=y`, `CONFIG_NET_UDP_WRITE_BUFFERS` not set), Wi-Fi station on a TP-Link Deco mesh (3 units) that runs the DHCP server. Base: nuttx c046c337c1, nuttx-apps 00b6e5912. DHCP was captured with tcpdump on another host on the same LAN. Before, at boot: the REQUEST is sent from the offered address. The Deco app lists the device as offline and offers no address reservation. ``` 192.168.10.60.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 7c:df:a1:ba:46:dc, xid 0xbc1aa1a8, Flags [none] (0x0000) DHCP-Message (53): Request Server-ID (54): 192.168.10.1 Requested-IP (50): 192.168.10.60 ``` After, at boot: DISCOVER and REQUEST are sent from 0.0.0.0, the unicast ACK is received and the address configured. The Deco app lists the device as online, and an address reservation could be created for it. ``` 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 7c:df:a1:ba:46:dc, xid 0xed3192cb, Flags [none] (0x0000) DHCP-Message (53): Discover 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 7c:df:a1:ba:46:dc, xid 0xed3192cb, Flags [none] (0x0000) DHCP-Message (53): Request Server-ID (54): 192.168.10.1 Requested-IP (50): 192.168.10.60 ``` Reliability with this change: * `renew wlan0` 10 times in a row: 10/10 succeeded, about 0.1 s each. * 3 hard resets: an address was configured each time, already at the first check 3 s after reset. * An application calling `dhcpc_request()` to renew the lease while the interface has its address (REQUEST from the current address) renewed successfully at the T1 time the server sent (3600 s for a 7200 s lease). For comparison, the broadcast-flag-only variant described in the summary: `renew wlan0` succeeded 8/10 times, and a boot-time attempt failed with the board never seeing the broadcast OFFER. Not exercised on hardware: the new path that restores the old address when no ACK arrives at all. `tools/nxstyle` reports no issues for `netutils/dhcpc/dhcpc.c` after the second commit (six pre-existing issues before it). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
