dmdhcp DMOD library module.
dmdhcp is a DHCP client (RFC 2131/2132) for the DMOD network stack. It does not implement a DHCP server.
One dmdhcp_lease_t represents the whole lease lifecycle (DISCOVER/OFFER/
REQUEST/ACK, renewal, rebinding, release) for one interface. On acquiring
or renewing a lease, dmdhcp applies it to the interface itself
(address/netmask/broadcast plus a default route) and reverts that on
release/expiry - a caller does not need to configure the interface by
hand. Address-conflict detection (RFC 2131 §4.4.1, an ARP probe before
committing an address) is included.
dmdhcp keeps no thread of its own: inbound messages are processed inline
on whatever thread is already pumping the interface (via dmudp_bind()),
and time-driven behavior (retransmission backoff, the conflict probe,
lease timers) runs on dmosi_timer_t callbacks. See
docs/dmdhcp.md for the full architecture.
mkdir -p build
cd build
cmake ..
cmake --build .Pass -DDMOD_DIR=/path/to/local/dmod to build against a local dmod checkout
instead of fetching develop from GitHub.
make DMOD_MODE=DMOD_MODULE DMOD_DIR=/path/to/dmodTests are built automatically alongside the module (see tests/). Once built,
run them with ctest:
cd build
ctest --output-on-failurectest installs the test module's dependencies with dmf-get and then runs
it through dmod_loader. To run it manually instead:
export DMOD_DMF_DIR=$(pwd)/build/dmf
dmf-get install -d ${DMOD_DMF_DIR}/test_dmdhcp-local.dmd -y
dmod_loader build/dmf/test_dmdhcp.dmf#include "dmdhcp.h"
static void on_bound(dmdhcp_lease_t lease, bool is_renewal, void* user_data)
{
dmdhcp_lease_info_t info;
dmdhcp_get_lease_info(lease, &info);
/* info.ip_address / .netmask / .gateway are already applied to the
* interface at this point - nothing further to configure. */
}
static void on_lost(dmdhcp_lease_t lease, void* user_data)
{
/* NAK'd or the lease fully expired - the interface has already been
* de-configured. dmdhcp restarts DISCOVER on its own. */
}
dmdhcp_callbacks_t callbacks = { .on_bound = on_bound, .on_expired_or_lost = on_lost };
dmdhcp_lease_t lease = dmdhcp_start(iface, &callbacks, NULL, NULL);- tools/dhcpc - Starts a lease on one interface
by calling
dmdhcp_start(), then exits. It's its own Application-type DMOD module (dhcpc), released alongsidedmdhcpitself in every tagged release, and is what actually turns "dmdhcp is loaded" into "this interface has an address" - see "Running as a service" below.
dmdhcp is a Library-type module, like
dmicmp - it has no main()
to spawn on its own, so something still needs to load it. Unlike dmicmp
(which starts answering pings the moment it's loaded), loading dmdhcp alone
doesn't start acquiring a lease on any interface either -
dmdhcp_start(iface, ...) still needs to be called per interface.
tools/dhcpc covers both: it links dmdhcp_if
directly, so loading it also loads and enables dmdhcp as its own module
dependency (no separate dhcp.ini-style unit needed anywhere in this
repo), and it's the thing that actually calls dmdhcp_start(). It ships a
per-interface unit template plus a device rule
(tools/dhcpc/configs/dhcp@.ini /
dhcp.rules) that auto-starts one
instance for every interface
dmnet's networkd
also reacts to - both fire from the same dmnetif device event. See
docs/service.md for the full setup.
| Function | Description |
|---|---|
dmdhcp_start() |
Begin acquiring a lease on an interface; keeps renewing/rebinding/restarting automatically. |
dmdhcp_set_callbacks() |
Replace a lease's callbacks/user_data. |
dmdhcp_renew() |
Force an immediate renewal attempt. |
dmdhcp_release() |
Send DHCPRELEASE, de-configure the interface, free the lease. |
dmdhcp_stop() |
De-configure and free the lease without sending DHCPRELEASE. |
dmdhcp_get_state() / _get_iface() / _get_user_data() / _get_xid() |
Simple accessors. |
dmdhcp_get_lease_info() |
Snapshot of the active lease's address/netmask/gateway/server/lease-time. |
dmdhcp_get_dns_server_count() / _get_dns_server() |
The DHCP-offered DNS server list. |
dmdhcp_build_message() / _parse_message() |
DHCP/BOOTP fixed header codec (RFC 2131 §2). |
dmdhcp_options_write() / _options_find() / _option_get_*() |
RFC 2132 TLV options codec. |
See include/dmdhcp.h for the full declarations and docs/api-reference.md for the complete reference.
See the docs/ directory:
- api-reference.md - Complete API documentation
- service.md - Running DHCP as a
dmsystemservice
View documentation using dmf-man dmdhcp.
dmdhcp/
├── docs/ # Documentation (markdown format)
│ ├── README.md
│ ├── api-reference.md
│ ├── dmdhcp.md # Architecture: threading, locking, state machine
│ └── service.md # Running DHCP as a dmsystem service
├── include/ # Public headers
│ └── dmdhcp.h
├── src/
│ ├── dmdhcp_internal.h # Private struct dmdhcp_lease, constants
│ ├── dmdhcp.c # dmod_init()/_deinit(), _start()/_stop()/_release()/_renew()
│ ├── dmdhcp_registrations.c # DMOD_ENABLE_REGISTRATION (must stand alone)
│ ├── dmdhcp_lease_table.c # Lease table CRUD, teardown, simple accessors
│ ├── dmdhcp_wire.c # DHCP/BOOTP fixed header codec
│ ├── dmdhcp_options.c # RFC 2132 TLV options codec
│ ├── dmdhcp_output.c # Message senders + retransmit/probe timer
│ ├── dmdhcp_input.c # dmudp_bind() registration + dispatch
│ └── dmdhcp_lifecycle.c # Apply/unapply to interface + lease timer
├── tests/
│ ├── CMakeLists.txt
│ └── dmdhcp_test.c
├── tools/
│ ├── CMakeLists.txt
│ └── dhcpc/ # dhcpc CLI + its unit template/device rule, see tools/dhcpc/README.md
├── CMakeLists.txt
├── Makefile
├── dmdhcp.dmr
└── manifest.dmm
Patryk Kubiak
MIT