diff --git a/man/systemd.network.xml b/man/systemd.network.xml index dce81692df..a4fe1b4dde 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1840,8 +1840,8 @@ WithoutRA= - When true, DHCPv6 client starts without router advertisements's managed or other address configuration flag. - Defaults to false. + Allows DHCPv6 client to start without router advertisements's managed or other address configuration flag. + Takes one of solicit or information-request. Defaults to unset. diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 27b74407af..ecf8a32691 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -19,6 +19,7 @@ #include "networkd-link.h" #include "networkd-manager.h" #include "siphash24.h" +#include "string-table.h" #include "string-util.h" #include "radv-internal.h" #include "web-util.h" @@ -1205,3 +1206,14 @@ int config_parse_dhcp6_delegated_prefix_token( return 0; } + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp6_client_start_mode, dhcp6_client_start_mode, DHCP6ClientStartMode, + "Failed to parse WithoutRA= setting"); + +static const char* const dhcp6_client_start_mode_table[_DHCP6_CLIENT_START_MODE_MAX] = { + [DHCP6_CLIENT_START_MODE_NO] = "no", + [DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST] = "information-request", + [DHCP6_CLIENT_START_MODE_SOLICIT] = "solicit", +}; + +DEFINE_STRING_TABLE_LOOKUP(dhcp6_client_start_mode, DHCP6ClientStartMode); diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 913410fe77..858559a1e0 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -4,6 +4,15 @@ #include "sd-dhcp6-client.h" #include "conf-parser.h" +#include "macro.h" + +typedef enum DHCP6ClientStartMode { + DHCP6_CLIENT_START_MODE_NO, + DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST, + DHCP6_CLIENT_START_MODE_SOLICIT, + _DHCP6_CLIENT_START_MODE_MAX, + _DHCP6_CLIENT_START_MODE_INVALID = -1, +} DHCP6ClientStartMode; typedef struct Link Link; typedef struct Manager Manager; @@ -17,3 +26,7 @@ int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_delegated_prefix_token); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode); + +const char* dhcp6_client_start_mode_to_string(DHCP6ClientStartMode i) _const_; +DHCP6ClientStartMode dhcp6_client_start_mode_from_string(const char *s) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b3c0224034..bc26cd2c3e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1559,11 +1559,13 @@ static int link_acquire_ipv6_conf(Link *link) { return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m"); } - if (link_dhcp6_enabled(link) && link->network->dhcp6_without_ra) { + if (link_dhcp6_enabled(link) && IN_SET(link->network->dhcp6_without_ra, + DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST, + DHCP6_CLIENT_START_MODE_SOLICIT)) { assert(link->dhcp6_client); assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); - r = dhcp6_request_address(link, true); + r = dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); if (r < 0 && r != -EBUSY) return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m"); else diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5a0c86b5b3..d6f23fe5f0 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -206,7 +206,7 @@ DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, DHCPv6.AssignAcquiredDelegatedPrefixAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign_prefix) DHCPv6.AssignAcquiredDelegatedPrefixToken, config_parse_dhcp6_delegated_prefix_token, 0, 0 DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0 -DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra) +DHCPv6.WithoutRA, config_parse_dhcp6_client_start_mode, 0, offsetof(Network, dhcp6_without_ra) DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options) DHCPv6.RouteMetric, config_parse_dhcp_route_metric, 0, 0 IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 916bfdc9a8..47fceee0b8 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -17,6 +17,7 @@ #include "networkd-brvlan.h" #include "networkd-dhcp-common.h" #include "networkd-dhcp4.h" +#include "networkd-dhcp6.h" #include "networkd-dhcp-server.h" #include "networkd-fdb.h" #include "networkd-ipv6-proxy-ndp.h" @@ -150,7 +151,6 @@ struct Network { bool dhcp6_use_dns_set; bool dhcp6_use_ntp; bool dhcp6_use_ntp_set; - bool dhcp6_without_ra; uint8_t dhcp6_pd_length; uint32_t dhcp6_route_metric; bool dhcp6_route_metric_set; @@ -158,6 +158,7 @@ struct Network { char **dhcp6_user_class; char **dhcp6_vendor_class; struct in6_addr dhcp6_pd_address; + DHCP6ClientStartMode dhcp6_without_ra; OrderedHashmap *dhcp6_client_send_options; OrderedHashmap *dhcp6_client_send_vendor_options; Set *dhcp6_request_options;