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:
commit
b81070ff13
@ -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>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user