1

Related to this question

How do you get systemd-networkd to honor the [DHCPv4] setting FallbackLeaseLifetimeSec=forever? (Or more probably, what am I doing wrong that is preventing this?)

When it receives a reply with no DHCP lease, it logs:

enp0s1: DHCPv4 client: received lease lacks address, server address or lease lifetime, ignoring

Background

We have a prospective customer with a requirement that our device can operate in a BOOTP (i.e. non-DHCP) environment. Specifically, we must not require DHCP Option 51 (Lease Time) to be present, and must treat replies as permanent IP assignments.

We use systemd-networkd for everything else, so ideally we'd like to use its built-in DHCP client for this as well. The primary issue is that systemd-networkd is rejecting BOOTP replies that do not contain DHCP Option 51 (IP Address Lease Time). It appears that the entire purpose of FallbackLeaseLifetimeSec=forever is to bypass this constraint. However, whether we set it or not, we get the same log message (above), and the systemd does not configure the interface.

Details/what I've tried

  • networkctl --version reports systemd 252. The doc say this option was added in 246.
  • We are running Debian 12 (Bookworm) as a testbed client, w/ a 6.1.0 kernel.
  • We are running the Debian bootpd package on a separate device, w/ the same Debian & Linux
    • Probably irrelevant, but the server is using /etc/network/interfaces and ifup/ifdown for network config.
  • I've captured the replies via tcpdump and verified the following:
    • They contain yiaddr, aka Your (client) IP Address
    • They contain siaddr, aka Server Ip Address
    • They do also contain option 54 (DHCP Server Identifier)
  • I've captured replies from a normal DHCP server, and compared as well. The only substantive differences I can see are:
    • The expected IP Address Lease Time is present
    • The options are in a different order (53,54,51,1,3,6,42,255 vs 1,3,53,54,6,12,255)
  • Our network config file is in /etc/systemd/network/20-enp0s1.network
  • We have no other network config files, except /etc/systemd/networkd.conf which is untouched, and effectively blank (it has only comments and some empty sections)
  • I have verified that our config file, and the FallbackLeaseLifetimeSec option in particular, are being parsed as follows:
    • I set the options's value to garbage, and restarted systemd-networkd.
    • journalctl reports Invalid LeaseLifetime= value, ignoring: garbage.
    • When I switch it back to forever, journalctl doesn't mention it
      • I found the error message in the source code, and it's clear that it is quiet if it finds an acceptable value.
  • Here is 20-enp0s1.network:
[Match]
Name=enp0s1

[Network]
DHCP=ipv4

[DHCPv4]
FallbackLeaseLifetimeSec=forever

ClientIdentifier=mac  

# Padding b/c `bootpd` rejects packets that it thinks are too short
SendOption=254:string:"UUUUUUUUUUUUUUUUUUUUUUUUUUU"
1
  • I see in sd-dhcp-client.c, the error is coming from client_handle_offer(), specifically if (lease->address == 0 || lease->server_address == 0 || lease->lifetime == 0), so one of those is obviously 0. address should be coming from yiaddr which is in my packet; lease should be set to non-zero on line 1478; server_address should be set to my server's ip during dhcp_option_parse() on line 1468 from opt 54 which I've verified in the packet. Commented Nov 13, 2024 at 2:23

1 Answer 1

3

The FallbackLeaseLifetimeSec=forever option fundamentally has nothing to do with BOOTP compatibility. Systemd's built-in DHCP client still depends on a 4-message exchange. Even with the newer RapidCommit 2-message option (added in v255), systemd still depends on the server sending DHCP/vendor option 53 (DHCP Message Type), and it processes DHCP_OFFER differently from DHCP_ACK. True bootp only has one response, and it has no DHCP Message Type.

In the normal "happy path" flow, replies have to be either a DHCP_OFFER or a DHCP_ACK. The FallbackLeaseLifetimeSec option is only applied during DHCP_OFFER processing. If RapidCommit is used, the server only ever sends a DHCP_ACK. In both cases, there must be a DHCP type 51 IP Address Lease Time in the DHCP_ACK packet, or systemd will issue the subject error message due to the 0 lease.

Part of the problem was that I've been using bootpd as the bootp server in my testbed, and it is much closer to being a DHCP server than a real BOOTP server: It does a 4-message exchange, and it processes and emits most of the DHCP optional message types.

The FallbackLeaseLifetimeSec=forever was working correctly on DHCP_OFFER packets, these were not causing the error message. I hadn't realized yet amidst all of the retries that only half of the server's replies were caused by retries - the other half were the expected DHCP_ACKs coming back from the server in response to the DHCP_REQUESTs from the client (the 2nd two messages of the 4-message exchange).

My breakthrough came in trying to understand the state machine in the client, and finding where the different state-change log messages came from in the code. The client goes through these states before I get the error message:

  • DISCOVER
  • OFFER
  • REQUEST

This led me to realize that the error message can come from two different places in the code, OFFER or ACK processing. The conditions are different, or rather the setup of the conditions is different.

In v252 of systemd, there is a pair of functions, client_handle_offer() and client_handle_ack().

  • client_handle_offer looks at fallback_lease_lifetime, and if lease->lifetime is 0, and fallback_lease_lifetime is non-zero, it overrides lease->lifetime.
    • This is working correctly, we do not get an error upon processing the OFFER.
  • client_handle_ack does NOT consider fallback_lease_lifetime or override lease->lifetime.
    • So since lease->lifetime is still zero (b/c the bootp server is still not sending a lease time in the ACK), this is where we're getting the error message.

I'm curious what the use-case is for this option then, if anybody knows.

From what I can tell in RFC2131, IP address lease time is required in both DHCP_OFFER and DHCP_ACK packets. Is there a stable situation out there somewhere in which a DHCP server does not include a lease time in the OFFER, but then does include one in the DHCP_ACK?

3
  • 1
    Excellent writeup, but then you finished with a new question. Better to do as you did at the top of your question, post a new question and reference this one. Commented Nov 15, 2024 at 18:07
  • Also note the low number of watchers for both your tags. Try to find some other appropriate tags with higher numbers of watchers. Maybe include a tag for your underlying OS (unix|linux|macOS|MSwin (only one!) ). Commented Nov 15, 2024 at 18:09
  • 1
    @shellter thanks for the feedback. My follow-up question was really just meant for discussion, I don't need to know the answer, so I didn't feel like I had a valid case to post a full new question. Tags added. Commented Nov 22, 2024 at 15:57

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.