mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-26 09:57:26 +03:00
network: make prefixstable mode of IPv6Token= can be applied to any received prefixes
Closes #4625.
This commit is contained in:
parent
6743a1caf4
commit
b27caa34f6
@ -408,36 +408,48 @@
|
||||
<varlistentry>
|
||||
<term><varname>IPv6Token=</varname></term>
|
||||
<listitem>
|
||||
<para>Specifies an optional address generation mode and a required IPv6 address. If
|
||||
the mode is present, the two parts must be separated with a colon
|
||||
<literal><replaceable>mode</replaceable>:<replaceable>address</replaceable></literal>. The
|
||||
address generation mode may be either <constant>prefixstable</constant> or
|
||||
<constant>static</constant>. If not specified, <constant>static</constant> is assumed.
|
||||
</para>
|
||||
<para>When the mode is set to <constant>static</constant>, or unspecified, the lower bits of
|
||||
the supplied address are combined with the upper bits of a prefix received in a Router Advertisement
|
||||
message to form a complete address. Note that if multiple prefixes are received in an RA message, or in
|
||||
multiple RA messages, addresses will be formed from each of them using the supplied address. This
|
||||
mode implements SLAAC but uses a static interface identifier instead of an identifier generated
|
||||
using the EUI-64 algorithm. Because the interface identifier is static, if Duplicate Address Detection
|
||||
detects that the computed address is a duplicate (in use by another node on the link), then this
|
||||
mode will fail to provide an address for that prefix.
|
||||
</para>
|
||||
<para>When the mode is set to <literal>prefixstable</literal> the RFC 7217 algorithm for generating
|
||||
interface identifiers will be used, but only when a prefix received in an RA message matches the supplied address.
|
||||
See <ulink url="https://tools.ietf.org/html/rfc7217">RFC 7217</ulink>. Prefix matching will be attempted
|
||||
against each <constant>prefixstable</constant> IPv6Token variable provided in the configuration; if a received
|
||||
prefix does not match any of the provided addresses, then the EUI-64 algorithm will be used to form
|
||||
an interface identifier for that prefix. This mode is also SLAAC, but with a potentially stable interface
|
||||
identifier which does not directly map to the interface's hardware address.
|
||||
<para>Specifies an optional address generation mode for the Stateless Address
|
||||
Autoconfiguration (SLAAC). Supported modes are <literal>prefixstable</literal> and
|
||||
<literal>static</literal>.</para>
|
||||
|
||||
Note that the <constant>prefixstable</constant> algorithm includes both the interface's name and
|
||||
MAC address in the hash used to compute the interface identifier, so if either of those are changed the resulting
|
||||
interface identifier (and address) will change, even if the prefix received in the RA message has not changed.
|
||||
<para>When the mode is set to <literal>static</literal>, an IPv6 address must be
|
||||
specified after a colon (<literal>:</literal>), and the lower bits of the supplied
|
||||
address are combined with the upper bits of a prefix received in a Router Advertisement
|
||||
(RA) message to form a complete address. Note that if multiple prefixes are received in an
|
||||
RA message, or in multiple RA messages, addresses will be formed from each of them using
|
||||
the supplied address. This mode implements SLAAC but uses a static interface identifier
|
||||
instead of an identifier generated by using the EUI-64 algorithm. Because the interface
|
||||
identifier is static, if Duplicate Address Detection detects that the computed address is a
|
||||
duplicate (in use by another node on the link), then this mode will fail to provide an
|
||||
address for that prefix. If an IPv6 address without mode is specified, then
|
||||
<literal>static</literal> mode is assumed.</para>
|
||||
|
||||
Note that if multiple <constant>prefixstable</constant> IPv6Token variables are supplied with addresses that
|
||||
match a prefix received in an RA message, only the first one will be used to generate addresses.
|
||||
</para>
|
||||
<para>When the mode is set to <literal>prefixstable</literal> the
|
||||
<ulink url="https://tools.ietf.org/html/rfc7217">RFC 7217</ulink> algorithm for generating
|
||||
interface identifiers will be used. This mode can optionally take an IPv6 address separated
|
||||
with a colon (<literal>:</literal>). If an IPv6 address is specified, then an interface
|
||||
identifier is generated only when a prefix received in an RA message matches the supplied
|
||||
address.</para>
|
||||
|
||||
<para>If no address generation mode is specified (which is the default), or a received
|
||||
prefix does not match any of the addresses provided in <literal>prefixstable</literal>
|
||||
mode, then the EUI-64 algorithm will be used to form an interface identifier for that
|
||||
prefix. This mode is also SLAAC, but with a potentially stable interface identifier which
|
||||
does not directly map to the interface's hardware address.</para>
|
||||
|
||||
<para>Note that the <literal>prefixstable</literal> algorithm uses both the interface
|
||||
name and MAC address as input to the hash to compute the interface identifier, so if either
|
||||
of those are changed the resulting interface identifier (and address) will change, even if
|
||||
the prefix received in the RA message has not changed.</para>
|
||||
|
||||
<para>This setting can be specified multiple times. If an empty string is assigned, then
|
||||
the all previous assignments are cleared.</para>
|
||||
|
||||
<para>Examples:
|
||||
<programlisting>IPv6Token=::1a:2b:3c:4d
|
||||
IPv6Token=static:::1a:2b:3c:4d
|
||||
IPv6Token=prefixstable
|
||||
IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
@ -384,14 +384,14 @@ static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address,
|
||||
_cleanup_free_ struct in6_addr *new_address = NULL;
|
||||
|
||||
if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
|
||||
&& IN6_ARE_ADDR_EQUAL(&j->prefix, address)) {
|
||||
&& (IN6_IS_ADDR_UNSPECIFIED(&j->prefix) || IN6_ARE_ADDR_EQUAL(&j->prefix, address))) {
|
||||
/* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
|
||||
does not actually attempt Duplicate Address Detection; the counter will be incremented
|
||||
only when the address generation algorithm produces an invalid address, and the loop
|
||||
may exit with an address which ends up being unusable due to duplication on the link.
|
||||
*/
|
||||
for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
|
||||
r = make_stableprivate_address(link, &j->prefix, prefixlen, j->dad_counter, &new_address);
|
||||
r = make_stableprivate_address(link, address, prefixlen, j->dad_counter, &new_address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
@ -1176,30 +1176,43 @@ int config_parse_address_generation_type(
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
if ((p = startswith(rvalue, "static:")))
|
||||
token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
|
||||
else if ((p = startswith(rvalue, "prefixstable:")))
|
||||
if ((p = startswith(rvalue, "prefixstable"))) {
|
||||
token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE;
|
||||
else {
|
||||
if (*p == ':')
|
||||
p++;
|
||||
else if (*p == '\0')
|
||||
p = NULL;
|
||||
else {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Invalid IPv6 token mode in %s=, ignoring assignment: %s",
|
||||
lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
|
||||
p = rvalue;
|
||||
p = startswith(rvalue, "static:");
|
||||
if (!p)
|
||||
p = rvalue;
|
||||
}
|
||||
|
||||
r = in_addr_from_string(AF_INET6, p, &buffer);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse IPv6 %s, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
if (p) {
|
||||
r = in_addr_from_string(AF_INET6, p, &buffer);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse IP address in %s=, ignoring assignment: %s",
|
||||
lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (token->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC &&
|
||||
in_addr_is_null(AF_INET6, &buffer)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
|
||||
lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
token->prefix = buffer.in6;
|
||||
}
|
||||
|
||||
if (in_addr_is_null(AF_INET6, &buffer)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"IPv6 %s cannot be the ANY address, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
token->prefix = buffer.in6;
|
||||
|
||||
r = ordered_set_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
Loading…
x
Reference in New Issue
Block a user