diff --git a/man/systemd.network.xml b/man/systemd.network.xml index d7c3eeadef..75a581816d 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1824,11 +1824,11 @@ DHCPv6Client= - Takes a boolean. When true (the default), the DHCPv6 client will be started when the - RA has the managed or other information flag. + Takes a boolean, or the special value always. When true (the default), the DHCPv6 client will be started when the + RA has the managed or other information flag. If set to always, the DHCPv6 client will be started even if there is no + managed or other information flag in the RA. - diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index fe1de6387e..8af7b3c0c3 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -13,6 +13,7 @@ #include "networkd-manager.h" #include "networkd-ndisc.h" #include "networkd-route.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" @@ -794,10 +795,14 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_warning_errno(link, r, "Failed to get RA flags: %m"); - if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) && - link->network->ipv6_accept_ra_start_dhcp6_client) { - /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */ - r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED)); + if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) && link->network->ipv6_accept_ra_start_dhcp6_client)) { + + if (link->network->ipv6_accept_ra_start_dhcp6_client == IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS) + r = dhcp6_request_address(link, false); + else + /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */ + r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED)); + if (r < 0 && r != -EBUSY) log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); else { @@ -1065,3 +1070,13 @@ int config_parse_address_generation_type( return 0; } + +DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, + "Failed to parse DHCPv6Client= setting") +static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = { + [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no", + [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always", + [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES); diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 02c2f8afda..68cd1c2bd7 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -15,6 +15,14 @@ typedef enum IPv6TokenAddressGeneration { _IPV6_TOKEN_ADDRESS_GENERATION_INVALID = -1, } IPv6TokenAddressGeneration; +typedef enum IPv6AcceptRAStartDHCP6Client { + IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO, + IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS, + IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES, + _IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX, + _IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -1, +} IPv6AcceptRAStartDHCP6Client; + typedef struct NDiscRDNSS { usec_t valid_until; struct in6_addr address; @@ -45,3 +53,7 @@ void ndisc_flush(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_black_listed_prefix); CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type); +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client); + +const char* ipv6_accept_ra_start_dhcp6_client_to_string(IPv6AcceptRAStartDHCP6Client i) _const_; +IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client_from_string(const char *s) _pure_; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index c63f57f962..9597176b1c 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -199,7 +199,7 @@ IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix) IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) -IPv6AcceptRA.DHCPv6Client, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client) +IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client) IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0 IPv6AcceptRA.BlackList, config_parse_ndisc_black_listed_prefix, 0, 0 DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 1c600ae7bd..240f6689dd 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -230,12 +230,12 @@ struct Network { bool ipv6_accept_ra_use_dns; bool ipv6_accept_ra_use_autonomous_prefix; bool ipv6_accept_ra_use_onlink_prefix; - bool ipv6_accept_ra_start_dhcp6_client; bool active_slave; bool primary_slave; - DHCPUseDomains ipv6_accept_ra_use_domains; - uint32_t ipv6_accept_ra_route_table; bool ipv6_accept_ra_route_table_set; + DHCPUseDomains ipv6_accept_ra_use_domains; + IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client; + uint32_t ipv6_accept_ra_route_table; Set *ndisc_black_listed_prefix; OrderedHashmap *ipv6_tokens;