diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 6e5a2702ba..1aa9b132df 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1623,6 +1623,15 @@ + + FallbackLeaseLifetimeSec= + + Allows to set DHCPv4 lease lifetime when DHCPv4 server does not send the lease lifetime. + Takes one of forever or infinity means that the address + never expires. Defaults to unset. + + + SendRelease= diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 78d93382e7..ce83a86aa9 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -87,6 +87,7 @@ struct sd_dhcp_client { char *mudurl; char **user_class; uint32_t mtu; + uint32_t fallback_lease_lifetime; uint32_t xid; usec_t start_time; uint64_t attempt; @@ -612,6 +613,15 @@ int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { return 0; } +int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) { + assert_return(client, -EINVAL); + assert_return(fallback_lease_lifetime > 0, -EINVAL); + + client->fallback_lease_lifetime = fallback_lease_lifetime; + + return 0; +} + static int client_notify(sd_dhcp_client *client, int event) { assert(client); @@ -1405,6 +1415,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_ lease->next_server = offer->siaddr; lease->address = offer->yiaddr; + if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0) + lease->lifetime = client->fallback_lease_lifetime; + if (lease->address == 0 || lease->server_address == 0 || lease->lifetime == 0) { diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 6bfa6e6dd0..42e6b5aef2 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1488,6 +1488,12 @@ int dhcp4_configure(Link *link) { return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ip service type: %m"); } + if (link->network->dhcp_fallback_lease_lifetime > 0) { + r = sd_dhcp_client_set_fallback_lease_lifetime(link->dhcp_client, link->network->dhcp_fallback_lease_lifetime); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed set to lease lifetime: %m"); + } + if (link->network->dhcp_send_decline) { r = configure_dhcpv4_duplicate_address_detection(link); if (r < 0) @@ -1674,6 +1680,44 @@ int config_parse_dhcp_mud_url( return free_and_strdup_warn(&network->dhcp_mudurl, unescaped); } +int config_parse_dhcp_fallback_lease_lifetime(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + unsigned k; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + network->dhcp_fallback_lease_lifetime = 0; + return 0; + } + + /* We accept only "forever" or "infinity". */ + if (STR_IN_SET(rvalue, "forever", "infinity")) + k = CACHE_INFO_INFINITY_LIFE_TIME; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid LeaseLifetime= value, ignoring: %s", rvalue); + return 0; + } + + network->dhcp_fallback_lease_lifetime = k; + + return 0; +} + static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = { [DHCP_CLIENT_ID_MAC] = "mac", [DHCP_CLIENT_ID_DUID] = "duid", diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 93fa7d372c..a6e24be78d 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -27,3 +27,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_fallback_lease_lifetime); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 28bb705190..3749ff6b8d 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -189,6 +189,7 @@ DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options) DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options) DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu) +DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0 DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns) DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp) DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 82810bcce1..6811658fcc 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -97,6 +97,7 @@ struct Network { uint64_t dhcp_max_attempts; unsigned dhcp_route_metric; uint32_t dhcp_route_table; + uint32_t dhcp_fallback_lease_lifetime; uint32_t dhcp_route_mtu; uint16_t dhcp_client_port; int dhcp_critical; diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index 032afc9f12..85b49bae74 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -185,6 +185,9 @@ int sd_dhcp_client_get_lease( int sd_dhcp_client_set_service_type( sd_dhcp_client *client, int type); +int sd_dhcp_client_set_fallback_lease_lifetime( + sd_dhcp_client *client, + uint32_t fallback_lease_lifetime); int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v); int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 918fb3ac8a..625842a9ba 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -105,6 +105,7 @@ SendVendorOption= SendDecline= MUDURL= RouteMTUBytes= +FallbackLeaseLifetimeSec= [DHCPv6] UseNTP= UseDNS=