1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 06:25:37 +03:00

Merge pull request #21129 from yuwata/network-dhcp6-pd-vs-ndisc

network: several follow-ups for DHCPv6-PD
This commit is contained in:
Yu Watanabe 2021-10-27 12:15:18 +09:00 committed by GitHub
commit b81070ff13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 59 deletions

View File

@ -2089,28 +2089,16 @@ 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>

View File

@ -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));
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_is_running(link->dhcp6_client);
if (r < 0)
return r;
running = r;
r = sd_dhcp6_client_get_prefix_delegation(link->dhcp6_client, &pd);
if (r < 0)
return r;
if (r > 0) {
int inf_req;
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");
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;

View File

@ -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);

View File

@ -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:

View File

@ -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

View File

@ -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,

View File

@ -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;