diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-10-27 12:15:18 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-27 12:15:18 +0900 |
commit | b81070ff13c1f9647e771c09c9e8c37e4e206807 (patch) | |
tree | bdd7aee67da2fe1b6ced6860c77ad9e5e45281c7 | |
parent | 8f1daefce6e952f2fad9510e5101b5fc675d363f (diff) | |
parent | 149cda85bfd8e6d2fd5c0137ff76b074c9e6cf3f (diff) | |
download | systemd-b81070ff13c1f9647e771c09c9e8c37e4e206807.tar.gz |
Merge pull request #21129 from yuwata/network-dhcp6-pd-vs-ndisc
network: several follow-ups for DHCPv6-PD
-rw-r--r-- | man/systemd.network.xml | 45 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.c | 68 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.h | 2 | ||||
-rw-r--r-- | src/network/networkd-ndisc.c | 4 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 6 | ||||
-rw-r--r-- | src/network/networkd-network.c | 1 | ||||
-rw-r--r-- | src/network/networkd-network.h | 4 |
7 files changed, 71 insertions, 59 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml index b6bf993adc..41a58b36eb 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2090,27 +2090,15 @@ Table=1234</programlisting></para> <!-- How to communicate with the server --> <varlistentry> - <term><varname>ForceDHCPv6PDOtherInformation=</varname></term> - <listitem> - <para>Takes a boolean that enforces DHCPv6 stateful mode when the 'Other information' bit is set in - Router Advertisement messages. By default setting only the 'O' bit in Router Advertisements - makes DHCPv6 request network information in a stateless manner using a two-message Information - Request and Information Reply message exchange. - <ulink url="https://tools.ietf.org/html/rfc7084">RFC 7084</ulink>, requirement WPD-4, updates - this behavior for a Customer Edge router so that stateful DHCPv6 Prefix Delegation is also - requested when only the 'O' bit is set in Router Advertisements. This option enables such a CE - behavior as it is impossible to automatically distinguish the intention of the 'O' bit otherwise. - By default this option is set to false, enable it if no prefixes are delegated when the device - should be acting as a CE router.</para> - </listitem> - </varlistentry> - - <varlistentry> <term><varname>WithoutRA=</varname></term> <listitem> - <para>Allows DHCPv6 client to start without router advertisements's managed or other address - configuration flag. Takes one of <literal>solicit</literal> or - <literal>information-request</literal>. Defaults to unset.</para> + <para>Allows DHCPv6 client to start without router advertisements's managed or other + address configuration flag. Takes one of <literal>no</literal>, <literal>solicit</literal> + or <literal>information-request</literal>. When this is not specified and + <varname>UplinkInterface=:self</varname> is specified, then <literal>solicit</literal> is + implied. Otherwise, defaults to <literal>no</literal>, and the DHCPv6 client will be + started when an RA is received. See also <varname>DHCPv6Client=</varname> setting in the + [IPv6AcceptRA] section.</para> </listitem> </varlistentry> </variablelist> @@ -2128,9 +2116,10 @@ Table=1234</programlisting></para> <listitem> <para>Specifies the name or the index of the uplink interface, or one of the special values <literal>:self</literal> and <literal>:auto</literal>. When <literal>:self</literal>, the - interface itself is considered the uplink interface. When <literal>:auto</literal>, the first - link which acquired prefixes to be delegated from the DHCPv6 server is selected. Defaults to - <literal>:auto</literal>.</para> + interface itself is considered the uplink interface, and + <varname>WithoutRA=solicit</varname> is implied if the setting is not explicitly specified. + When <literal>:auto</literal>, the first link which acquired prefixes to be delegated from + the DHCPv6 server is selected. Defaults to <literal>:auto</literal>.</para> </listitem> </varlistentry> @@ -2382,11 +2371,13 @@ Token=prefixstable:2002:da8:1::</programlisting></para> <varlistentry> <term><varname>DHCPv6Client=</varname></term> <listitem> - <para>Takes a boolean, or the special value <literal>always</literal>. When true or - <literal>always</literal>, the DHCPv6 client will be started when the RA has the managed or - other information flag. If set to <literal>always</literal>, the DHCPv6 client will also be - started in managed mode when neither managed nor other information flag is set in the RA. - Defaults to true.</para> + <para>Takes a boolean, or the special value <literal>always</literal>. When true, the + DHCPv6 client will be started when the RA has the managed or other information flag. If set + to <literal>always</literal>, the DHCPv6 client will be started in managed mode when an RA + is received, even if neither managed nor other information flag is set in the RA. This will + be ignored when <varname>WithoutRA=</varname> in the [DHCPv6] section is enabled, or + <varname>UplinkInterface=:self</varname> in the [DHCPv6PrefixDelegation] section is + specified. Defaults to true.</para> </listitem> </varlistentry> </variablelist> diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 52ff5eb3aa..3cc457a02d 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -58,6 +58,25 @@ static int dhcp6_pd_resolve_uplink(Link *link, Link **ret) { return -ENOENT; } +static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) { + Link *uplink; + + assert(link); + + if (!link->network) + return DHCP6_CLIENT_START_MODE_NO; + + /* When WithoutRA= is explicitly specified, then honor it. */ + if (link->network->dhcp6_client_start_mode >= 0) + return link->network->dhcp6_client_start_mode; + + if (dhcp6_pd_resolve_uplink(link, &uplink) < 0) + return DHCP6_CLIENT_START_MODE_NO; + + /* When this interface itself is an uplink interface, then start dhcp6 client in managed mode */ + return uplink == link ? DHCP6_CLIENT_START_MODE_SOLICIT : DHCP6_CLIENT_START_MODE_NO; +} + static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { uint32_t lifetime_preferred_sec, lifetime_valid_sec; struct in6_addr pd_prefix; @@ -1311,40 +1330,31 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { } } -int dhcp6_request_information(Link *link, int ir) { - int r, inf_req, pd; - bool running; +int dhcp6_start_on_ra(Link *link, bool information_request) { + int r; assert(link); assert(link->dhcp6_client); assert(link->network); assert(in6_addr_is_link_local(&link->ipv6ll_address)); - r = sd_dhcp6_client_is_running(link->dhcp6_client); - if (r < 0) - return r; - running = r; + if (link_get_dhcp6_client_start_mode(link) != DHCP6_CLIENT_START_MODE_NO) + /* When WithoutRA= is specified, then the DHCPv6 client should be already runnging in + * the requested mode. Hence, ignore the requests by RA. */ + return 0; - r = sd_dhcp6_client_get_prefix_delegation(link->dhcp6_client, &pd); + r = sd_dhcp6_client_is_running(link->dhcp6_client); if (r < 0) return r; - if (pd && ir && link->network->dhcp6_force_pd_other_information) { - log_link_debug(link, "Enabling managed mode to request DHCPv6 PD with 'Other Information' set"); + if (r > 0) { + int inf_req; - r = sd_dhcp6_client_set_address_request(link->dhcp6_client, false); - if (r < 0) - return r; - - ir = false; - } - - if (running) { r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req); if (r < 0) return r; - if (inf_req == ir) + if (inf_req == information_request) return 0; r = sd_dhcp6_client_stop(link->dhcp6_client); @@ -1356,7 +1366,7 @@ int dhcp6_request_information(Link *link, int ir) { return r; } - r = sd_dhcp6_client_set_information_request(link->dhcp6_client, ir); + r = sd_dhcp6_client_set_information_request(link->dhcp6_client, information_request); if (r < 0) return r; @@ -1368,9 +1378,11 @@ int dhcp6_request_information(Link *link, int ir) { } int dhcp6_start(Link *link) { + DHCP6ClientStartMode start_mode; int r; assert(link); + assert(link->network); if (!link->dhcp6_client) return 0; @@ -1381,7 +1393,7 @@ int dhcp6_start(Link *link) { if (!link_has_carrier(link)) return 0; - if (link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_NO) + if (sd_dhcp6_client_is_running(link->dhcp6_client) > 0) return 0; if (!in6_addr_is_link_local(&link->ipv6ll_address)) { @@ -1389,10 +1401,20 @@ int dhcp6_start(Link *link) { return 0; } - if (sd_dhcp6_client_is_running(link->dhcp6_client) > 0) + r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address); + if (r < 0) + return r; + + start_mode = link_get_dhcp6_client_start_mode(link); + if (start_mode == DHCP6_CLIENT_START_MODE_NO) return 0; - r = dhcp6_request_information(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); + r = sd_dhcp6_client_set_information_request(link->dhcp6_client, + start_mode == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); + if (r < 0) + return r; + + r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) return r; diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index a08d03b614..4a522aebcf 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -21,7 +21,7 @@ bool link_dhcp6_pd_is_enabled(Link *link); int dhcp6_pd_remove(Link *link, bool only_marked); int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); -int dhcp6_request_information(Link *link, int ir); +int dhcp6_start_on_ra(Link *link, bool information_request); int dhcp6_request_prefix_delegation(Link *link); int request_process_dhcp6_client(Request *req); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index d7b79f7416..5f831b58a4 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -906,13 +906,13 @@ static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) { /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags. * Note, if both managed and other information bits are set, then ignore other * information bit. See RFC 4861. */ - r = dhcp6_request_information(link, !(flags & ND_RA_FLAG_MANAGED)); + r = dhcp6_start_on_ra(link, !(flags & ND_RA_FLAG_MANAGED)); break; } case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS: /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode * even if the router flags have neither M nor O flags. */ - r = dhcp6_request_information(link, false); + r = dhcp6_start_on_ra(link, /* information_request = */ false); break; default: diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index ccbf02b99d..6631f5bc3e 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -248,9 +248,8 @@ DHCPv6.RequestOptions, config_parse_dhcp_request_options, DHCPv6.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET6, offsetof(Network, dhcp6_user_class) DHCPv6.VendorClass, config_parse_dhcp_user_or_vendor_class, AF_INET6, offsetof(Network, dhcp6_vendor_class) DHCPv6.SendVendorOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_vendor_options) -DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_prefix_hint, 0, 0 -DHCPv6.WithoutRA, config_parse_dhcp6_client_start_mode, 0, offsetof(Network, dhcp6_without_ra) +DHCPv6.WithoutRA, config_parse_dhcp6_client_start_mode, 0, offsetof(Network, dhcp6_client_start_mode) DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options) DHCPv6.IAID, config_parse_iaid, AF_INET6, 0 DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Network, dhcp6_duid) @@ -530,11 +529,12 @@ DHCP.RouteTable, config_parse_dhcp_or_ra_route_table DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCP.RapidCommit, config_parse_warn_compat, DISABLED_LEGACY, 0 -DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) +DHCP.ForceDHCPv6PDOtherInformation, config_parse_warn_compat, DISABLED_LEGACY, 0 DHCPv4.UseDomainName, config_parse_dhcp_use_domains, AF_INET, 0 DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) DHCPv6.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0 DHCPv6.RapidCommit, config_parse_warn_compat, DISABLED_LEGACY, 0 +DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_warn_compat, DISABLED_LEGACY, 0 IPv6AcceptRA.DenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) IPv6AcceptRA.BlackList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c3c792eb49..5469cb4560 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -405,6 +405,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .dhcp6_use_hostname = true, .dhcp6_use_ntp = true, .dhcp6_duid.type = _DUID_TYPE_INVALID, + .dhcp6_client_start_mode = _DHCP6_CLIENT_START_MODE_INVALID, .dhcp6_pd = -1, .dhcp6_pd_announce = true, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index bd9758c899..d10119f58c 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -185,12 +185,10 @@ struct Network { char *dhcp6_mudurl; char **dhcp6_user_class; char **dhcp6_vendor_class; - DHCP6ClientStartMode dhcp6_without_ra; + DHCP6ClientStartMode dhcp6_client_start_mode; OrderedHashmap *dhcp6_client_send_options; OrderedHashmap *dhcp6_client_send_vendor_options; Set *dhcp6_request_options; - /* Start DHCPv6 PD also when 'O' RA flag is set, see RFC 7084, WPD-4 */ - bool dhcp6_force_pd_other_information; /* DHCP Server Support */ bool dhcp_server; |