This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 4ef1d605448 Documentation/netutils: add comprehensive guide for dhcpc
4ef1d605448 is described below
commit 4ef1d605448a6e75c085a476d708bf6f6e18ba72
Author: Swatantra Yadav <[email protected]>
AuthorDate: Thu Oct 8 16:45:56 2026 +0530
Documentation/netutils: add comprehensive guide for dhcpc
Provide a complete documentation guide for the dhcpc (DHCP client) network
utility in Documentation/applications/netutils/dhcpc/index.rst, replacing
the previous 7-line placeholder stub.
Includes:
- Protocol architecture overview and RFC 2131 / RFC 1542 finite state
machine
(DISCOVER, OFFER, REQUEST, ACK, RELEASE)
- Security considerations regarding plaintext DHCPv4, rogue servers, and
network isolation
- Configuration options table and networking prerequisites including
CONFIG_NET_BROADCAST
- NSH usage for dynamic interface configuration (ifconfig <ifname> dhcp)
and verification
- Public C API reference for data structures (struct dhcpc_state) and
lifecycle
functions with documented POSIX ERROR/errno contracts (dhcpc_open,
dhcpc_request,
dhcpc_request_async, dhcpc_release, dhcpc_close)
- Complete, runnable C application examples demonstrating synchronous
interface
configuration and graceful lease release
- Embedded design and tuning guidelines (lease renewal scheduling, wireless
retransmission tuning, and SO_BINDTODEVICE multihomed operation)
Addresses #11081
Signed-off-by: Swatantra Yadav <[email protected]>
---
.../applications/netutils/dhcpc/index.rst | 433 ++++++++++++++++++++-
1 file changed, 430 insertions(+), 3 deletions(-)
diff --git a/Documentation/applications/netutils/dhcpc/index.rst
b/Documentation/applications/netutils/dhcpc/index.rst
index a9984c8fe85..0ae0de507ba 100644
--- a/Documentation/applications/netutils/dhcpc/index.rst
+++ b/Documentation/applications/netutils/dhcpc/index.rst
@@ -1,6 +1,433 @@
=====================
-``dhcpc`` DHCP client
+``dhcpc`` DHCP Client
=====================
-Dynamic Host Configuration Protocol (DHCP) client. See
-``apps/include/netutils/dhcpc.h`` for interface information.
+The ``dhcpc`` utility is a lightweight Dynamic Host Configuration Protocol
(DHCP)
+client for Apache NuttX, implementing the client protocol defined in
:rfc:`2131`
+with BOOTP relay interoperability per :rfc:`1542`.
+
+It provides embedded systems with automated IPv4 address acquisition, subnet
mask
+assignment, default gateway discovery, Domain Name System (DNS) resolver
+configuration, and Network Time Protocol (NTP) server discovery over local
Ethernet
+or wireless (Wi-Fi) interfaces.
+
+.. note::
+
+ **Security Consideration**: Standard DHCPv4 (:rfc:`2131`) transmits
messages in
+ plaintext without cryptographic authentication. In untrusted or shared
network
+ environments, malicious actors may deploy rogue DHCP servers to inject
spoofed
+ default gateways or malicious DNS resolvers (enabling Man-in-the-Middle
attacks)
+ or conduct DHCP starvation attacks. On managed networks, switch-level
protections
+ (such as DHCP Snooping and Port Security) should be enabled. When operating
on
+ untrusted links, secure transport protocols (e.g., TLS, IPsec, or
WireGuard) and
+ authenticated DNS (DNS-over-TLS / DNSSEC) should be employed to protect
application
+ data regardless of the assigned network parameters.
+
+Operational Roles
+=================
+
+The DHCP client library serves multiple key functions across the NuttX
ecosystem:
+
+1. **System Initialization (``netinit``)**: Automatically acquires an IP
address at
+ system startup when ``CONFIG_NETINIT_DHCPC`` is enabled.
+2. **Interactive NSH Command**: Enables runtime dynamic configuration via the
NuttShell
+ ``ifconfig <interface> dhcp`` command.
+3. **High-Level Network Helper (``netlib``)**: Powers
``netlib_obtain_ipv4addr()`` in
+ ``apps/netutils/netlib/`` to configure network interfaces with minimal
application
+ boilerplate.
+4. **Programmatic C API**: Offers both synchronous (blocking) and asynchronous
+ (callback-driven) APIs for custom application-level interface management
and lease
+ lifecycles.
+
+Key Features
+============
+
+- **RFC 2131 & RFC 1542 Compliance**: Standard four-step message handshake
+ (``DISCOVER``, ``OFFER``, ``REQUEST``, ``ACK``) with optional ``RELEASE``
handling.
+- **Interface Binding**: Binds client sockets directly to the target network
device
+ using ``SO_BINDTODEVICE``, ensuring reliable operation on multihomed devices.
+- **Lease Timing & Lifetime Tracking**: Computes renewal timer :math:`T_1`
(typically
+ 50% of lease time), rebinding timer :math:`T_2` (typically 87.5% of lease
time), and
+ expiration time for lease renewal scheduling.
+- **DNS & NTP Server Discovery**: Parses option 6 (Domain Name Server) and
option 42
+ (Network Time Protocol Servers) into structured address arrays.
+- **Graceful Address Release**: Implements ``dhcpc_release()`` with
configurable
+ transmission delays and retry mechanisms to inform the DHCP server when an
address
+ is surrendered.
+- **Dual Execution Modes**: Supports both synchronous operation
(``dhcpc_request()``
+ blocking until negotiation completes or retries are exhausted) and
asynchronous
+ operation (``dhcpc_request_async()`` running in a dedicated worker thread
with
+ user callback notification).
+
+Protocol Architecture & State Machine
+=====================================
+
+The DHCP client follows the finite state machine defined by :rfc:`2131`:
+
+1. **INIT**: The client initializes on an unconfigured interface (IP
``0.0.0.0``) and
+ broadcasts a ``DHCPDISCOVER`` message to ``255.255.255.255`` on UDP
destination
+ port 67.
+2. **SELECTING**: The client listens for ``DHCPOFFER`` messages from one or
more DHCP
+ servers on UDP port 68. The first valid offer matching the transaction ID
(``xid``)
+ is selected.
+3. **REQUESTING**: The client broadcasts a ``DHCPREQUEST`` message containing
the
+ server's identifier and requested IP address, confirming selection to all
listening
+ servers.
+4. **BOUND**: Upon receipt of a valid ``DHCPACK`` message, the client enters
the
+ ``BOUND`` state. The assigned IP, netmask, gateway, lease time, and DNS
servers are
+ recorded.
+5. **RENEWING / REBINDING**: At time :math:`T_1`, the client attempts unicast
renewal
+ with the original server. If unacknowledged by time :math:`T_2`, the client
broadcasts
+ to any available DHCP server.
+6. **RELEASE**: When the interface is brought down or the application shuts
down,
+ ``dhcpc_release()`` transmits a unicast ``DHCPRELEASE`` message to the
server,
+ allowing the server to reclaim the address immediately.
+
+Requirements & Dependencies
+===========================
+
+To use ``dhcpc``, ensure the following core networking and socket options are
enabled
+in your board configuration:
+
+- Core Networking: ``CONFIG_NET=y``
+- IPv4 Support: ``CONFIG_NET_IPv4=y``
+- UDP Sockets: ``CONFIG_NET_UDP=y``
+- UDP Broadcast Support: ``CONFIG_NET_BROADCAST=y`` (required for sending
``DHCPDISCOVER`` broadcast)
+- Interface Socket Binding: ``CONFIG_NET_BINDTODEVICE=y`` (selected
automatically by ``CONFIG_NETUTILS_DHCPC``)
+- Client Library: ``CONFIG_NETUTILS_DHCPC=y``
+- DNS Client (Optional, for DNS resolution): ``CONFIG_NETDB_DNSCLIENT=y``
+
+Configuration Options
+=====================
+
+The DHCP client behavior can be fine-tuned via Kconfig under
+``Application Configuration -> Network Utilities -> DHCP client``:
+
+.. list-table::
+ :widths: 35 15 50
+ :header-rows: 1
+
+ * - Kconfig Option
+ - Default
+ - Description
+ * - ``CONFIG_NETUTILS_DHCPC``
+ - ``n``
+ - Enables compilation of the DHCP client library in
``apps/netutils/dhcpc``.
+ * - ``CONFIG_NETUTILS_DHCPC_HOST_NAME``
+ - ``"nuttx"``
+ - Client hostname sent in DHCP option 12 to identify the device on the
network.
+ * - ``CONFIG_NETUTILS_DHCPC_RECV_TIMEOUT_MS``
+ - ``3000``
+ - Socket receive timeout in milliseconds when awaiting server responses.
+ * - ``CONFIG_NETUTILS_DHCPC_RETRIES``
+ - ``3``
+ - Number of transmission attempts for ``DISCOVER`` and ``REQUEST`` before
failing.
+ * - ``CONFIG_NETUTILS_DHCPC_BOOTP_FLAGS``
+ - ``0x0000``
+ - BOOTP broadcast flags (:rfc:`1542`). Set to ``0x8000`` (broadcast) when
IP
+ forwarding is active or the device cannot accept unicast traffic before
being
+ configured.
+ * - ``CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES``
+ - ``3``
+ - Number of retry attempts when transmitting a ``DHCPRELEASE`` message.
+ * - ``CONFIG_NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS``
+ - ``10``
+ - Delay in milliseconds between release retries and before socket closure,
+ allowing the network stack to flush connectionless UDP packets.
+ * - ``CONFIG_NETUTILS_DHCPC_RELEASE_ENSURE_TRANSMISSION``
+ - ``y``
+ - Inserts a transmission delay after sending ``DHCPRELEASE`` before
closing the
+ socket, ensuring the packet reaches the physical MAC driver.
+ * - ``CONFIG_NETUTILS_DHCPC_RELEASE_CLEAR_IP``
+ - ``n``
+ - Clears the interface IP address, subnet mask, and default router
immediately
+ upon successful release transmission.
+ * - ``CONFIG_NETUTILS_DHCPC_NTP_SERVERS``
+ - ``1``
+ - Maximum number of NTP server addresses to parse and record from DHCP
option 42.
+ * - ``CONFIG_NETDB_DNSSERVER_NAMESERVERS``
+ - ``1``
+ - Maximum number of DNS server addresses to parse and record from DHCP
option 6.
+
+NSH Usage
+=========
+
+When ``CONFIG_NETUTILS_DHCPC`` and ``CONFIG_NSH_NETLOCAL`` are enabled, the
NuttShell
+provides native runtime commands to request dynamic network addresses.
+
+Configuring an Interface via DHCP
+---------------------------------
+
+To dynamically request an IP address on a specific network interface (e.g.,
``eth0``
+or ``wlan0``), issue the ``ifconfig`` command with the ``dhcp`` keyword:
+
+.. code-block:: console
+
+ nsh> ifconfig eth0 dhcp
+
+NSH will invoke ``netlib_obtain_ipv4addr()``, which executes the DHCP exchange,
+assigns the acquired IP address and subnet mask to ``eth0``, and updates the
system
+default gateway and DNS resolver entries.
+
+Verifying the Acquired Configuration
+------------------------------------
+
+To display the active network parameters after DHCP completion:
+
+.. code-block:: console
+
+ nsh> ifconfig eth0
+ eth0 HWaddr 00:e0:de:ad:be:ef at UP
+ inet addr:192.168.1.150 DRaddr:192.168.1.1 Mask:255.255.255.0
+
+Testing Network Reachability
+----------------------------
+
+Once the lease is acquired, verify reachability to local and external hosts:
+
+.. code-block:: console
+
+ nsh> ping 192.168.1.1
+ nsh> ping 8.8.8.8
+
+C API Reference
+===============
+
+The public C interface for ``dhcpc`` is declared in
``apps/include/netutils/dhcpc.h``.
+
+Data Structures
+---------------
+
+.. code-block:: c
+
+ struct dhcpc_state
+ {
+ struct in_addr serverid; /* DHCP Server
IPv4 address */
+ struct in_addr ipaddr; /* Client
assigned IPv4 address */
+ struct in_addr netmask; /* Assigned
subnet mask */
+ struct in_addr dnsaddr[CONFIG_NETDB_DNSSERVER_NAMESERVERS]; /* Discovered
DNS server(s) */
+ uint8_t num_dnsaddr; /* Count of
valid DNS addresses */
+ struct in_addr ntpaddr[CONFIG_NETUTILS_DHCPC_NTP_SERVERS]; /* Discovered
NTP server(s) */
+ uint8_t num_ntpaddr; /* Count of
valid NTP addresses */
+ struct in_addr default_router; /* Default
gateway router address */
+ uint32_t lease_time; /* Total lease
lifetime in seconds */
+ uint32_t renewal_time; /* T1: Seconds
until RENEW state */
+ uint32_t rebinding_time; /* T2: Seconds
until REBIND state */
+ };
+
+ typedef void (*dhcpc_callback_t)(FAR struct dhcpc_state *presult);
+
+Core Functions
+--------------
+
+Initialization & Teardown
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ FAR void *dhcpc_open(FAR const char *interface,
+ FAR const void *mac_addr, int mac_len);
+ void dhcpc_close(FAR void *handle);
+
+- ``dhcpc_open()``: Allocates and initializes an internal DHCP client state
context
+ bound to the specified network interface name (e.g., ``"eth0"``).
+
+ - ``interface``: Network device name (used with ``SO_BINDTODEVICE``).
+ - ``mac_addr``: Pointer to the hardware (MAC) address buffer.
+ - ``mac_len``: Length of the hardware address (typically ``IFHWADDRLEN``, 6
bytes).
+ - *Returns*: An opaque context handle on success, or ``NULL`` if socket
+ creation or memory allocation fails.
+
+- ``dhcpc_close()``: Frees all allocated memory and closes active client
sockets
+ associated with the handle.
+
+Synchronous Lease Request
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult);
+
+- Executes the blocking four-way DHCP handshake.
+- ``handle``: Context handle returned by ``dhcpc_open()``.
+- ``presult``: Pointer to a caller-allocated ``struct dhcpc_state`` structure
that
+ receives the negotiated network parameters.
+- *Returns*: ``OK`` (0) on success, or ``ERROR`` (-1) on failure with
``errno`` set
+ appropriately to indicate the cause of the failure:
+
+ - ``ETIMEDOUT``: Retries exhausted without receiving a valid ``DHCPOFFER``
or ``DHCPACK``.
+ - ``ECONNREFUSED``: The DHCP server rejected the request with a ``DHCPNAK``.
+ - ``EINTR``: The request was interrupted or canceled via ``dhcpc_cancel()``.
+
+Asynchronous Lease Request & Cancellation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ int dhcpc_request_async(FAR void *handle, dhcpc_callback_t callback);
+ void dhcpc_cancel(FAR void *handle);
+
+- ``dhcpc_request_async()``: Spawns a dedicated background pthread that
executes the
+ DHCP exchange non-blockingly. When the lease is obtained, the specified
``callback``
+ is invoked with the populated ``struct dhcpc_state`` pointer.
+- *Returns*: ``OK`` (0) on success, or ``ERROR`` (-1) on failure with
``errno`` set
+ (e.g., ``EINVAL`` if parameters are invalid, or ``EALREADY`` if a DHCP
thread is
+ already running).
+- ``dhcpc_cancel()``: Aborts a running asynchronous DHCP request thread.
+
+Graceful Address Release
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ int dhcpc_release(FAR void *handle, FAR struct dhcpc_state *presult);
+
+- Transmits a unicast ``DHCPRELEASE`` message to the server identified by
+ ``presult->serverid`` for the assigned IP ``presult->ipaddr``.
+- *Returns*: ``OK`` (0) on success, or ``ERROR`` (-1) on failure with
``errno`` set.
+
+Application Examples
+====================
+
+Example 1: Synchronous IP Acquisition and Interface Configuration
+-----------------------------------------------------------------
+
+Below is a complete, production-grade example illustrating how an embedded
application
+queries the MAC address of an Ethernet adapter, executes a synchronous DHCP
handshake,
+and applies the negotiated parameters to the NuttX network stack:
+
+.. code-block:: c
+
+ #include <nuttx/config.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <errno.h>
+ #include <arpa/inet.h>
+ #include <net/if.h>
+
+ #include <netutils/netlib.h>
+ #include <netutils/dhcpc.h>
+
+ int configure_dhcp(FAR const char *ifname)
+ {
+ struct dhcpc_state state;
+ uint8_t mac[IFHWADDRLEN];
+ FAR void *handle;
+ int ret;
+
+ /* 1. Retrieve the hardware MAC address of the interface */
+
+ ret = netlib_getmacaddr(ifname, mac);
+ if (ret < 0)
+ {
+ fprintf(stderr, "Failed to get MAC address for %s: %d\n", ifname,
ret);
+ return ret;
+ }
+
+ /* 2. Open DHCP client session bound to the interface */
+
+ handle = dhcpc_open(ifname, mac, sizeof(mac));
+ if (handle == NULL)
+ {
+ fprintf(stderr, "Failed to initialize DHCP client handle\n");
+ return -ENOMEM;
+ }
+
+ /* 3. Execute synchronous DHCP negotiation */
+
+ printf("Sending DHCP request on %s...\n", ifname);
+ ret = dhcpc_request(handle, &state);
+ if (ret != OK)
+ {
+ int errcode = errno;
+ fprintf(stderr, "DHCP request failed (errno %d: %s)\n",
+ errcode, strerror(errcode));
+ dhcpc_close(handle);
+ return -errcode;
+ }
+
+ /* 4. Apply negotiated parameters to the network stack */
+
+ netlib_set_ipv4addr(ifname, &state.ipaddr);
+ netlib_set_ipv4netmask(ifname, &state.netmask);
+ netlib_set_dripv4addr(ifname, &state.default_router);
+
+ #if defined(CONFIG_NETDB_DNSCLIENT)
+ if (state.num_dnsaddr > 0)
+ {
+ netlib_set_ipv4dnsaddr(&state.dnsaddr[0]);
+ }
+ #endif
+
+ printf("DHCP lease acquired successfully:\n");
+ printf(" IP Address: %s\n", inet_ntoa(state.ipaddr));
+ printf(" Subnet Mask: %s\n", inet_ntoa(state.netmask));
+ printf(" Default Router: %s\n", inet_ntoa(state.default_router));
+ printf(" Lease Lifetime: %lu seconds\n", (unsigned
long)state.lease_time);
+
+ /* 5. Clean up DHCP client session handle */
+
+ dhcpc_close(handle);
+ return OK;
+ }
+
+Example 2: Graceful Release on System Shutdown
+----------------------------------------------
+
+Before putting an embedded device into deep sleep or tearing down an active
network
+session, releasing the lease allows the DHCP server to reallocate the IP
address
+immediately:
+
+.. code-block:: c
+
+ int release_dhcp(FAR const char *ifname, FAR struct dhcpc_state *lease)
+ {
+ uint8_t mac[IFHWADDRLEN];
+ FAR void *handle;
+ int ret;
+
+ if (netlib_getmacaddr(ifname, mac) < 0)
+ {
+ return -EINVAL;
+ }
+
+ handle = dhcpc_open(ifname, mac, sizeof(mac));
+ if (handle == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ printf("Releasing DHCP lease for %s...\n", inet_ntoa(lease->ipaddr));
+ ret = dhcpc_release(handle, lease);
+ if (ret != OK)
+ {
+ int errcode = errno;
+ fprintf(stderr, "DHCP release failed (errno %d: %s)\n",
+ errcode, strerror(errcode));
+ dhcpc_close(handle);
+ return -errcode;
+ }
+
+ dhcpc_close(handle);
+ return OK;
+ }
+
+Embedded Design & Tuning Guidelines
+===================================
+
+When deploying ``dhcpc`` in real-world embedded and IoT systems, consider the
following
+operational factors:
+
+1. **Lease Renewal Strategy**: The ``dhcpc_request()`` function performs
initial
+ lease acquisition but does not maintain a permanent daemon thread. For
long-running
+ systems where lease durations are finite (e.g., cloud or office DHCP pools
with
+ 1-hour or 24-hour leases), the application should maintain a software timer
set
+ to ``state.renewal_time`` (T1) to initiate renewal before expiration.
+2. **Wireless Retransmission Tuning**: On lossy or congested Wi-Fi channels,
+ increasing ``CONFIG_NETUTILS_DHCPC_RETRIES`` (e.g., from 3 to 5) and
+ ``CONFIG_NETUTILS_DHCPC_RECV_TIMEOUT_MS`` (e.g., to 5000ms) improves
connection
+ reliability during initial radio association.
+3. **Multihomed Network Binding**: Because ``dhcpc_open()`` sets
+ ``SO_BINDTODEVICE`` on the underlying UDP socket, multiple interfaces (such
as
+ an Ethernet fallback and a primary Wi-Fi station) can execute independent
DHCP
+ sessions simultaneously without packet cross-talk.