Commit Graph
2142 Commits
Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek cd79e5620b dhcp: update test and header cleanup (#42256) 2026-05-27 14:23:34 +02:00
Chris Mason 3f0aa5852e libsystemd-network: propagate sd_event_default() failure
Four *_attach_event helpers swallow sd_event_default() failures and
return success while leaving obj->event NULL:

    sd_dhcp_client_attach_event   (sd-dhcp-client.c)
    sd_dhcp6_client_attach_event  (sd-dhcp6-client.c)
    sd_ndisc_attach_event         (sd-ndisc.c)
    sd_radv_attach_event          (sd-radv.c)

Each contains the same copy-pasted typo in the NULL-event branch:

    r = sd_event_default(&obj->event);
    if (r < 0)
            return 0;          /* swallows -ENOMEM / -ECHILD */

The caller is told the attach succeeded, but obj->event is still
NULL. A subsequent *_start() then trips assert_return(obj->event,
-EINVAL) and returns a spurious -EINVAL (or aborts on assert-abort
builds), and any consumer of *_get_event() dereferences NULL.

The sibling helper sd_dhcp_server_attach_event already uses the
correct pattern:

    r = sd_event_default(&server->event);
    if (r < 0)
            return r;

Fix by returning r instead of 0 at each of the four sites so the
sd_event_default() errno is propagated to the caller and ownership
stays with the caller.

Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
2026-05-22 22:20:03 +02:00
Chris Mason 700d8e73d4 sd-dhcp6-client: fix ref leak on duplicate option add
sd_dhcp6_client_add_option() and sd_dhcp6_client_add_vendor_option()
store the caller's sd_dhcp6_option in an ordered container whose value
destructor is sd_dhcp6_option_unref, registered via
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR in dhcp6_option_hash_ops. The
container therefore owns exactly one ref per stored slot.

Both helpers guarded the ref bump only on r < 0:

    r = ordered_{hashmap,set}_ensure_put(..., v);
    if (r < 0)
            return r;
    sd_dhcp6_option_ref(v);

ordered_hashmap_ensure_put() (and the ordered_set wrapper) forward the
underlying hashmap_put_boldly tri-state verbatim: 1 on fresh insert, 0
when the identical key+value pair is already stored (no new slot
allocated), <0 on error. The r == 0 path fell through and bumped the
refcount without a corresponding slot.

The extra ref is permanently stranded once the container's destructor
runs. In a long-running networkd that reapplies .network files on
reload this leaks one sd_dhcp6_option allocation per duplicate-add.

Fix by tightening the guard to r <= 0 in both helpers, so
sd_dhcp6_option_ref(v) is reached only on a genuine new slot (r == 1).
Propagate the tri-valued result by returning r from both helpers
instead of a hard-coded constant.

sd_dhcp6_client_add_vendor_option() is a public libsystemd sd_ API;
its success return changes from a constant 1 to {0, 1}.
sd_dhcp6_client_add_option() now also propagates the tri-valued
result (previously a hard-coded 0 on success), giving the two parallel
helpers identical return contracts.

The sole non-fuzz in-tree callers are both in dhcp6_configure()
(src/network/networkd-dhcp6.c), which treat any r >= 0 as success and
do not distinguish 0 from 1, so the contract widening is caller-safe.

Fixes: e7d5fe17db ("DHCP client: make SendOption work for DHCPv6 too.")
Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
2026-05-22 22:17:28 +02:00
Yu Watanabe 76ae87e222 dhcp: introduce dhcp-forward.h
Then, rework header inclusions for DHCP related files.
2026-05-22 23:06:54 +09:00
Yu Watanabe db8f504afb dhcp: drop unused functions and macros
This removes the legacy functions for manipulating DHCP message.

This also moves the definition of struct sd_dhcp_message into
dhcp-message.h.
2026-05-22 23:06:53 +09:00
Yu Watanabe f1c47ab00b test-dhcp-server: use sd_dhcp_message object to build test message 2026-05-22 23:06:53 +09:00
Yu Watanabe e75c406448 sd-dhcp-server-lease: always update all information in bound lease
We manage bound leases by their client ID. Hence, potentially, other
fields may be changed. Let's always update all information.
2026-05-22 22:11:45 +09:00
Yu Watanabe c130068ebd sd-dhcp-server: update conditions when we should send DHCPNAK (#42252) 2026-05-22 20:02:17 +09:00
Yu Watanabe d69d919379 dhcp-server-request: drop unused value in DHCPRequest 2026-05-22 19:47:48 +09:00
Yu Watanabe b4f7e30d0b dhcp-server-request: rename dhcp_server_handle_message() -> dhcp_server_process_message()
Then, make it take struct iovec.
No functional change, just refactoring.
2026-05-22 15:57:06 +09:00
Yu Watanabe e294a8eada dhcp-server-request: rework when we should reply DHCPNAK
Previously, DHCPNAK was sent only when the client is in INIT-REBOOT
state. But, on selecting or renewing, the request is directed to a
specific server, so we can safely reply with DHCPNAK.

Also, verify existing bound lease even when there is no static lease for
the client.
2026-05-22 15:57:06 +09:00
Yu Watanabe 94b39d22dd dhcp-server-request: logs more when received invalid messages 2026-05-22 15:57:06 +09:00
Yu Watanabe c73478d49f dhcp-server-request: also save IP_PKTINFO of received message
It will be used later.

This also drops redundant ifindex check, as the socket is already
initialized with socket_bind_to_ifindex().
2026-05-22 15:57:06 +09:00
Yu Watanabe dced69aba5 sd-dhcp-server: use sd_dhcp_message to parse/build DHCP messages (#42240) 2026-05-22 15:28:52 +09:00
Yu Watanabe 30200eee52 sd-dhcp-server: drop unused enum
Follow-up for 2e5580a8c1.
2026-05-22 06:58:45 +02:00
Yu Watanabe 15103b697d sd-dhcp-server: use sd_dhcp_message object on sending reply
This also makes the conditions in dhcp_server_send_message() uses
the message that will be sent, rather than we received.

This does not change basic functionality, but changes/fixes several
minor behaviors, e.g.
- fix when the broadcast flag assignment,
- set server identifier in DHCPFORCERENEW.
2026-05-22 09:38:29 +09:00
Yu Watanabe 5e08ff899e sd-dhcp-server: use sd_dhcp_message to parse received messages
This is mostly refactoring. This does not change basic behavior, but
changes/fixes some minor/corner cases, e.g.

- extend the minimum default lease time from 1 second to 30 seconds, as
  1 second is too short and causes the network unstable (though 30
  seconds is stll too short, but hopefully that does not make the
  network unstable).
- error code on broken/malicious message received may be changed.
2026-05-22 09:33:15 +09:00
Yu Watanabe 8c09b8f128 dhcp-server-request: drop invalid short-cut logic
Even if no pool is allocated, the server may have a static lease
matching with the DHCPDISCOVER message.
2026-05-22 08:34:42 +09:00
Yu Watanabe 05c295d269 dhcp: move definition of enum DHCPState to dhcp-protocol.[ch]
It will be also used in DHCP server, later.
2026-05-22 08:34:22 +09:00
Yu Watanabe d40d021ca5 dhcp-server-request: check server address in DHCPDECLINE and DHCPRELEASE
Otherwise, we may do something wrong by messages for another DHCP server.
Let's silently ignore messages with unmatching server identifier.

Also, logs something when we receive DHCPRELEASE but found lease does
not match the reported address.
2026-05-22 04:30:34 +09:00
Yu Watanabe e359c6df65 sd-dhcp-server: store more information in DHCPRequest
This makes DHCPRequest stores
- the message type of the received message,
- acquired address,
- found static DHCP lease,

This also moves call of dhcp_request_get_lifetime_timestamp() from
dhcp_server_ack() to dhcp_server_set_lease(), and rename
DHCPRequest.server_id -> .server_address.

No functional change, just refactoring.
2026-05-22 04:30:34 +09:00
Yu Watanabe 252f3855fe sd-dhcp-server: use struct hw_addr_data to manage client hardware address parsed from DHCP message
Then, this drops garbage in DHCP server lease in DBus and Varlink message.

This also drops fallback to use client ID as hardware address when chaddr
field is not set. In that case, we should broadcast reply.
2026-05-22 04:30:34 +09:00
Yu Watanabe dae51cc08e dhcp-server-send: rework sending DHCP reply message
This should mostly not change anything, except for some corner cases.
Just refactoring.
2026-05-22 04:30:34 +09:00
Yu Watanabe 29b662184b sd-dhcp-server: make IP service type (TOS) configurable 2026-05-22 04:30:34 +09:00
Yu Watanabe 0bb26684d0 sd-dhcp-server: refactoring for socket fd handling
This makes
- UDP socket fd is owned by IO event source,
- open RAW socket fd just before sending first packet,
- set TOS and socket priority,
- use AF_UNIX soxket pair in the unit test and fuzzer, so the unit test
  can now run by unprivileged user.
2026-05-22 04:30:34 +09:00
Yu Watanabe 27d99475b6 dhcp-serve-request: move message size check to dhcp_server_handle_message() 2026-05-22 04:30:34 +09:00
Yu Watanabe 45a3a3b92c dhcp-server-request: modernize server_receive_message() 2026-05-22 04:30:34 +09:00
Yu Watanabe 3f8d0004e9 sd-dhcp-server: split into small pieaces
No functional change, just several functions are moved/split/renamed.
2026-05-22 04:30:34 +09:00
Yu Watanabe 0e07870f59 test-dhcp-server: several cleanups
No effective change, just rafactoring.
2026-05-22 04:30:34 +09:00
Yu Watanabe 54c97ce6a4 sd-dhcp-server: drop legacy DHCP relay mode 2026-05-21 16:55:59 +09:00
Yu Watanabe 0ff6bace59 fuzz: introduce fuzzer for DHCP relay agent 2026-05-21 16:55:59 +09:00
Yu Watanabe 0325022c15 test: add unit test for DHCP relay agent 2026-05-21 16:55:59 +09:00
Yu Watanabe 06ce0f90a5 sd-dhcp-relay: introduce new DHCP relay agent
Previously, sd-dhcp-server can be run as a DHCP relay agent.
But, DHCP server and DHCP relay agent behave completely differently,
hence there is almost no code that can be shared between the two modes.
Let's split out the DHCP relay agent feature from sd-dhcp-server.

The new DHCP relay agent supports:
- multiple upstream and downstream interfaces,
- gateway address (giaddr field in DHCP message header) is configurable,
- supports more DHCP relay agent information sub-options,
- each interface has their own socket fd, and each socket is bound to
  the interface, so that we can enable/disable each interface
  safely without affecting other interfaces, and we can filter out any
  unexpected packets from unmanaged interfaces,

networkd integration and test cases will be added later.
2026-05-21 16:55:58 +09:00
Daan De Meyer 74d392ed1b tree-wide: standardize header names across src/fundamental, src/basic and src/shared
Drop the -fundamental suffix from src/fundamental/ headers in favor of names
that match their src/basic/ or src/shared/ counterparts (e.g.
macro-fundamental.h -> macro.h, assert-fundamental.h -> assert-util.h,
cleanup-fundamental.h -> cleanup-util.h). Rename src/basic/{btrfs,label}.{c,h}
to use the -util suffix to match the existing shared/btrfs-util and
shared/label-util siblings. Rename src/shared/mkdir-label.{c,h} to mkdir.{c,h}
and src/shared/tmpfile-util-label.{c,h} to tmpfile-util.{c,h} to match the
corresponding src/basic names.

This saves us from having to come up with separate names for files that do
the same thing across tiers, and it makes it easier to move stuff between
src/fundamental, src/basic and src/shared: consumers just #include "foo.h"
and pick up whichever tier their -I path resolves to first, so call sites
don't need to be updated when an API moves between layers.

Where a higher-tier wrapper exists (e.g. src/basic/macro.h wrapping
src/fundamental/macro.h), the wrapper uses an explicit "../fundamental/foo.h"
or "../basic/foo.h" relative include for the lower-tier header. We can't use
GCC's #include_next directive for this — when the wrapper is reachable both
via same-dir-as-source lookup and via -I (e.g. -Isrc/shared) for the
directory it lives in, #include_next advances by exactly one slot in libcpp's
internal directory chain and lands on the same physical directory it was
already in, never reaching the lower-tier sibling (see make_cpp_dir() in
gcc/libcpp/files.cc:1986).

To make sure the right headers are always picked up, the include directories
are reordered so that e.g. src/shared always takes priority over src/basic and
similar for the other directories.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 10:33:03 +09:00
Patrick Rohr b131473ce5 networkd: fix race condition in per-interface ICMPv6 processing
There exists a small window of time in icmp6_bind() between creating the
ICMPv6 socket and binding it to an ifindex, where the link-scoped socket
can process an ICMPv6 packet received on any interface. The applies to
both sd-radv and sd-ndisc codepaths.

This change adds an explicit check for ifindex on the receive path and
ignores packets received on other interfaces.

Co-developed-by: OpenAI Codex <noreply@openai.com>
2026-05-20 10:26:39 +09:00
Luca Boccassi 6fa5ebc506 dhcp-client: reject messages larger than the maximum UDP payload
dhcp_message_verify_header() only enforced a lower bound on the input
length, so dhcp_message_parse() happily accepted arbitrarily large
buffers. Such inputs could never have been received via UDP and would
later fail in dhcp_message_build() with -E2BIG once the parsed options'
combined size exceeds UDP_PAYLOAD_MAX_SIZE, which the fuzzer surfaced as
an assertion failure.

Reject inputs above UDP_PAYLOAD_MAX_SIZE up front, so the parse stage
mirrors what the wire format can actually carry.

Follow-up for 8c18bb6547

Fixes https://github.com/systemd/systemd/issues/42147

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 01:43:25 +09:00
Yu Watanabe a0177d96dc dhcp-message: introduce dhcp_message_{payload,packet}_size() 2026-05-18 09:34:32 +09:00
Luca Boccassi 1d73c5f04f dhcp-client: clear overloaded sname/file fields after parsing
When SD_DHCP_OPTION_OVERLOAD indicates that the sname and/or file header
fields are overloaded with extra DHCP options, dhcp_message_parse() merges
those options into message->options but leaves the raw bytes untouched in
the header. As a result, dhcp_message_build() emits the header (including
the overloaded bytes) verbatim, and the next parse re-parses those bytes,
appending duplicate entries to the options map (each tag's iov list grows).
Subsequent builds then differ from the first, breaking the parse/build
roundtrip.

This was caught by fuzz-dhcp-client, which asserts that two consecutive
build calls produce identical output.

Zero out the overloaded fields after parsing them, since their content has
already been merged into the options map. This makes the roundtrip
idempotent and avoids re-emitting stale overloaded data in the rebuilt
header. The JSON build/parse path was already correct (it omits sname/file
from the JSON when the overload bit is set), so only the binary path needed
fixing.

Fixes https://github.com/systemd/systemd/issues/42139

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 04:52:25 +09:00
Yu Watanabe aa0f03eb03 networkctl: introduce 'dhcp-lease' command to dump acquired DHCP lease (#42137) 2026-05-18 01:28:11 +09:00
Yu Watanabe a72f23d2b8 sd-dhcp-client: drop unused data in sd_dhcp_client
With the previous commit, now sd_dhcp_client.link is not used anymore.
Let's drop it.
2026-05-17 22:44:17 +09:00
Yu Watanabe 0c69b24741 dhcp-client-send: move/update BPF code and socket initialization from dhcp-network.c
- BPF code now supports the case when IP header has IP packet options,
- also set socket priority to UDP socket.

Co-developed-by: Google Gemini Pro
2026-05-17 22:44:17 +09:00
Yu Watanabe 89cf6d81f7 dhcp-client-send: use dhcp_message_send_{udp,raw}() 2026-05-17 22:44:17 +09:00
Yu Watanabe 149adb2fdc dhcp-message-dump: introduce dump_dhcp_message()
It dumps DHCP messages in a human friendly format.
It will be used in networkctl in a later commit.
2026-05-17 20:09:47 +09:00
Yu Watanabe 335ac4a71d fuzz-dhcp-client: externally set socket fd, rather than override functions 2026-05-17 15:20:29 +09:00
Yu Watanabe acdaee339f test-dhcp-client: add test cases for discover attempt counter 2026-05-17 15:20:29 +09:00
Yu Watanabe 115c354b57 test-dhcp-client: add test cases for IPv6-only mode 2026-05-17 15:20:29 +09:00
Yu Watanabe 7df9210283 test-dhcp-client: add test case for BOOTP client mode 2026-05-17 15:20:29 +09:00
Yu Watanabe 9bd6b949d3 test-dhcp-client: add test case for INIT-REBOOT sequence 2026-05-17 15:20:29 +09:00
Yu Watanabe f7c144b9c7 test-dhcp-client: add test case for rapid commit mode 2026-05-17 15:20:24 +09:00
Yu Watanabe 3eba8d6265 test-dhcp-client: add test case for anonymized mode 2026-05-17 15:18:41 +09:00