Merge pull request #21346 from yuwata/network-token-prefixstable

network: extend Token=prefixstable setting
This commit is contained in:
Yu Watanabe
2021-11-15 08:16:48 +09:00
committed by GitHub
5 changed files with 299 additions and 211 deletions
+219 -185
View File
@@ -2185,219 +2185,253 @@ Table=1234</programlisting></para>
<refsect1>
<title>[IPv6AcceptRA] Section Options</title>
<para>The [IPv6AcceptRA] section configures the IPv6 Router Advertisement (RA) client, if it is enabled
with the <varname>IPv6AcceptRA=</varname> setting described above:</para>
<para>The [IPv6AcceptRA] section configures the IPv6 Router Advertisement (RA) client, if it is enabled
with the <varname>IPv6AcceptRA=</varname> setting described above:</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>Token=</varname></term>
<listitem>
<para>Specifies an optional address generation mode for the Stateless Address
Autoconfiguration (SLAAC). Supported modes are <literal>eui64</literal>,
<literal>static</literal>, and <literal>prefixstable</literal>.</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>Token=</varname></term>
<listitem>
<para>Specifies an optional address generation mode for the Stateless Address
Autoconfiguration (SLAAC). The following values are supported:</para>
<para>When the mode is set to <literal>eui64</literal>, then the EUI-64 algorithm will be
used to generate an address for that prefix.</para>
<variablelist>
<varlistentry>
<term><option>eui64</option></term>
<listitem>
<para>
The EUI-64 algorithm will be used to generate an address for that prefix.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>static:<replaceable>ADDRESS</replaceable></option></term>
<listitem>
<para>
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>
</listitem>
</varlistentry>
<varlistentry>
<term><option>prefixstable[:<replaceable>ADDRESS</replaceable>][,<replaceable>UUID</replaceable>]</option></term>
<listitem>
<para>
The algorithm specified in
<ulink url="https://tools.ietf.org/html/rfc7217">RFC 7217</ulink> will be used to
generate interface identifiers. 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>
This mode can also optionally take a non-null UUID in the format which
<function>sd_id128_from_string()</function> accepts, e.g.
<literal>86b123b969ba4b7eb8b3d8605123525a</literal> or
<literal>86b123b9-69ba-4b7e-b8b3-d8605123525a</literal>. If a UUID is specified, the
value is used as the secret key to generate interface identifiers. If not specified,
then an application specific ID generated with the system's machine-ID will be used
as the secret key. See
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_id128_from_string</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
and
<citerefentry><refentrytitle>sd_id128_get_machine</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
</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 be changed, even if the prefix received in the RA message has not been
changed.
</para>
</listitem>
</varlistentry>
</variablelist>
<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>
<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.</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>This setting can be specified multiple times. If an empty string is assigned, then
the all previous assignments are cleared.</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.</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 be changed, even
if the prefix received in the RA message has not been 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>Token=eui64
<para>Examples:
<programlisting>Token=eui64
Token=::1a:2b:3c:4d
Token=static:::1a:2b:3c:4d
Token=prefixstable
Token=prefixstable:2002:da8:1::</programlisting></para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseDNS=</varname></term>
<listitem>
<para>When true (the default), the DNS servers received in the Router Advertisement will be used.</para>
<varlistentry>
<term><varname>UseDNS=</varname></term>
<listitem>
<para>When true (the default), the DNS servers received in the Router Advertisement will be used.</para>
<para>This corresponds to the <option>nameserver</option> option in <citerefentry
project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<para>This corresponds to the <option>nameserver</option> option in <citerefentry
project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseDomains=</varname></term>
<listitem>
<para>Takes a boolean, or the special value <literal>route</literal>. When true, the domain name
received via IPv6 Router Advertisement (RA) will be used as DNS search domain over this link, similar to
the effect of the <option>Domains=</option> setting. If set to <literal>route</literal>, the domain name
received via IPv6 RA will be used for routing DNS queries only, but not for searching, similar to the
effect of the <option>Domains=</option> setting when the argument is prefixed with
<literal>~</literal>. Defaults to false.</para>
<varlistentry>
<term><varname>UseDomains=</varname></term>
<listitem>
<para>Takes a boolean, or the special value <literal>route</literal>. When true, the domain name
received via IPv6 Router Advertisement (RA) will be used as DNS search domain over this link, similar to
the effect of the <option>Domains=</option> setting. If set to <literal>route</literal>, the domain name
received via IPv6 RA will be used for routing DNS queries only, but not for searching, similar to the
effect of the <option>Domains=</option> setting when the argument is prefixed with
<literal>~</literal>. Defaults to false.</para>
<para>It is recommended to enable this option only on trusted networks, as setting this affects resolution
of all hostnames, in particular of single-label names. It is generally safer to use the supplied domain
only as routing domain, rather than as search domain, in order to not have it affect local resolution of
single-label names.</para>
<para>It is recommended to enable this option only on trusted networks, as setting this affects resolution
of all hostnames, in particular of single-label names. It is generally safer to use the supplied domain
only as routing domain, rather than as search domain, in order to not have it affect local resolution of
single-label names.</para>
<para>When set to true, this setting corresponds to the <option>domain</option> option in <citerefentry
project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<para>When set to true, this setting corresponds to the <option>domain</option> option in <citerefentry
project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteTable=<replaceable>num</replaceable></varname></term>
<listitem>
<para>The table identifier for the routes received in the Router Advertisement
(a number between 1 and 4294967295, or 0 to unset).
The table can be retrieved using <command>ip route show table <replaceable>num</replaceable></command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteTable=<replaceable>num</replaceable></varname></term>
<listitem>
<para>The table identifier for the routes received in the Router Advertisement
(a number between 1 and 4294967295, or 0 to unset).
The table can be retrieved using <command>ip route show table <replaceable>num</replaceable></command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>
<para>Set the routing metric for the routes received in the Router Advertisement. Takes an
unsigned integer in the range 0…4294967295. Defaults to 1024.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>
<para>Set the routing metric for the routes received in the Router Advertisement. Takes an
unsigned integer in the range 0…4294967295. Defaults to 1024.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseMTU=</varname></term>
<listitem>
<para>Takes a boolean. When true, the MTU received in the Router Advertisement will be
used. Defaults to true.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseMTU=</varname></term>
<listitem>
<para>Takes a boolean. When true, the MTU received in the Router Advertisement will be
used. Defaults to true.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseGateway=</varname></term>
<listitem>
<para>When true (the default), the router address will be configured as the default gateway.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseGateway=</varname></term>
<listitem>
<para>When true (the default), the router address will be configured as the default gateway.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseRoutePrefix=</varname></term>
<listitem>
<para>When true (the default), the routes corresponding to the route prefixes received in
the Router Advertisement will be configured.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseRoutePrefix=</varname></term>
<listitem>
<para>When true (the default), the routes corresponding to the route prefixes received in
the Router Advertisement will be configured.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseAutonomousPrefix=</varname></term>
<listitem>
<para>When true (the default), the autonomous prefix received in the Router Advertisement will be used and take
precedence over any statically configured ones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseAutonomousPrefix=</varname></term>
<listitem>
<para>When true (the default), the autonomous prefix received in the Router Advertisement will be used and take
precedence over any statically configured ones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseOnLinkPrefix=</varname></term>
<listitem>
<para>When true (the default), the onlink prefix received in the Router Advertisement will be
used and takes precedence over any statically configured ones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseOnLinkPrefix=</varname></term>
<listitem>
<para>When true (the default), the onlink prefix received in the Router Advertisement will be
used and takes precedence over any statically configured ones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouterDenyList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 router addresses. Each address can optionally
take a prefix length after <literal>/</literal>. Any information advertised by the listed
router is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouterDenyList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 router addresses. Each address can optionally
take a prefix length after <literal>/</literal>. Any information advertised by the listed
router is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouterAllowList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 router addresses. Each address can optionally
take a prefix length after <literal>/</literal>. Only information advertised by the listed
router is accepted. Note that if <varname>RouterAllowList=</varname> is configured then
<varname>RouterDenyList=</varname> is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouterAllowList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 router addresses. Each address can optionally
take a prefix length after <literal>/</literal>. Only information advertised by the listed
router is accepted. Note that if <varname>RouterAllowList=</varname> is configured then
<varname>RouterDenyList=</varname> is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PrefixDenyList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 prefixes. Each prefix can optionally take its
prefix length after <literal>/</literal>. IPv6 prefixes supplied via router advertisements
in the list are ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PrefixDenyList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 prefixes. Each prefix can optionally take its
prefix length after <literal>/</literal>. IPv6 prefixes supplied via router advertisements
in the list are ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PrefixAllowList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 prefixes. Each prefix can optionally take its
prefix length after <literal>/</literal>. IPv6 prefixes supplied via router advertisements
in the list are allowed. Note that if <varname>PrefixAllowList=</varname> is configured
then <varname>PrefixDenyList=</varname> is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PrefixAllowList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 prefixes. Each prefix can optionally take its
prefix length after <literal>/</literal>. IPv6 prefixes supplied via router advertisements
in the list are allowed. Note that if <varname>PrefixAllowList=</varname> is configured
then <varname>PrefixDenyList=</varname> is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteDenyList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 route prefixes. Each prefix can optionally take
its prefix length after <literal>/</literal>. IPv6 route prefixes supplied via router
advertisements in the list are ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteDenyList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 route prefixes. Each prefix can optionally take
its prefix length after <literal>/</literal>. IPv6 route prefixes supplied via router
advertisements in the list are ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteAllowList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 route prefixes. Each prefix can optionally take
its prefix length after <literal>/</literal>. IPv6 route prefixes supplied via router
advertisements in the list are allowed. Note that if <varname>RouteAllowList=</varname> is
configured then <varname>RouteDenyList=</varname> is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteAllowList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 route prefixes. Each prefix can optionally take
its prefix length after <literal>/</literal>. IPv6 route prefixes supplied via router
advertisements in the list are allowed. Note that if <varname>RouteAllowList=</varname> is
configured then <varname>RouteDenyList=</varname> is ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>DHCPv6Client=</varname></term>
<listitem>
<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>
<varlistentry>
<term><varname>DHCPv6Client=</varname></term>
<listitem>
<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>
</refsect1>
<refsect1>
+70 -22
View File
@@ -4,6 +4,7 @@
#include "sd-id128.h"
#include "id128-util.h"
#include "memory-util.h"
#include "networkd-address-generation.h"
#include "networkd-link.h"
@@ -35,6 +36,7 @@ typedef enum AddressGenerationType {
typedef struct IPv6Token {
AddressGenerationType type;
struct in6_addr address;
sd_id128_t secret_key;
} IPv6Token;
static void generate_eui64_address(const Link *link, const struct in6_addr *prefix, struct in6_addr *ret) {
@@ -117,29 +119,35 @@ static void generate_stable_private_address_one(
static int generate_stable_private_address(
Link *link,
const sd_id128_t *app_id,
const sd_id128_t *secret_key,
const struct in6_addr *prefix,
struct in6_addr *ret) {
sd_id128_t secret_machine_key;
struct in6_addr addr;
sd_id128_t secret_key;
uint8_t i;
int r;
assert(link);
assert(app_id);
assert(secret_key);
assert(prefix);
assert(ret);
r = sd_id128_get_machine_app_specific(*app_id, &secret_key);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to generate secret key for IPv6 stable private address: %m");
if (sd_id128_is_null(*secret_key)) {
r = sd_id128_get_machine_app_specific(*app_id, &secret_machine_key);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to generate secret key for IPv6 stable private address: %m");
secret_key = &secret_machine_key;
}
/* 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 (i = 0; i < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; i++) {
generate_stable_private_address_one(link, &secret_key, prefix, i, &addr);
generate_stable_private_address_one(link, secret_key, prefix, i, &addr);
if (stable_private_address_is_valid(&addr))
break;
@@ -192,7 +200,7 @@ static int generate_addresses(
if (in6_addr_is_set(&j->address) && !in6_addr_equal(&j->address, &masked))
continue;
if (generate_stable_private_address(link, app_id, &masked, &addr) < 0)
if (generate_stable_private_address(link, app_id, &j->secret_key, &masked, &addr) < 0)
continue;
break;
@@ -244,6 +252,7 @@ int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *pref
static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) {
siphash24_compress(&p->type, sizeof(p->type), state);
siphash24_compress(&p->address, sizeof(p->address), state);
id128_hash_func(&p->secret_key, state);
}
static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
@@ -253,7 +262,11 @@ static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
if (r != 0)
return r;
return memcmp(&a->address, &b->address, sizeof(struct in6_addr));
r = memcmp(&a->address, &b->address, sizeof(struct in6_addr));
if (r != 0)
return r;
return id128_compare_func(&a->secret_key, &b->secret_key);
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
@@ -263,12 +276,13 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ipv6_token_compare_func,
free);
static int ipv6_token_add(Set **tokens, AddressGenerationType type, const struct in6_addr *addr) {
static int ipv6_token_add(Set **tokens, AddressGenerationType type, const struct in6_addr *addr, const sd_id128_t *secret_key) {
IPv6Token *p;
assert(tokens);
assert(type >= 0 && type < _ADDRESS_GENERATION_TYPE_MAX);
assert(addr);
assert(secret_key);
p = new(IPv6Token, 1);
if (!p)
@@ -277,6 +291,7 @@ static int ipv6_token_add(Set **tokens, AddressGenerationType type, const struct
*p = (IPv6Token) {
.type = type,
.address = *addr,
.secret_key = *secret_key,
};
return set_ensure_consume(tokens, &ipv6_token_hash_ops, p);
@@ -294,10 +309,12 @@ int config_parse_address_generation_type(
void *data,
void *userdata) {
_cleanup_free_ char *addr_alloc = NULL;
sd_id128_t secret_key = SD_ID128_NULL;
union in_addr_union buffer = {};
AddressGenerationType type;
Set **tokens = data;
const char *p;
const char *addr;
int r;
assert(filename);
@@ -310,33 +327,64 @@ int config_parse_address_generation_type(
return 0;
}
if ((p = startswith(rvalue, "prefixstable"))) {
if ((addr = startswith(rvalue, "prefixstable"))) {
const char *comma;
type = ADDRESS_GENERATION_PREFIXSTABLE;
if (*p == ':')
p++;
else if (*p == '\0')
p = NULL;
else {
if (*addr == ':') {
addr++;
comma = strchr(addr, ',');
if (comma) {
addr_alloc = strndup(addr, comma - addr);
if (!addr_alloc)
return log_oom();
addr = addr_alloc;
}
} else if (*addr == ',') {
comma = addr;
addr = NULL;
} else if (*addr == '\0') {
comma = NULL;
addr = NULL;
} else {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid IPv6 token mode in %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (comma) {
r = sd_id128_from_string(comma + 1, &secret_key);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse secret key in %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sd_id128_is_null(secret_key)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Secret key in %s= cannot be null, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
}
} else if (streq(rvalue, "eui64")) {
type = ADDRESS_GENERATION_EUI64;
p = NULL;
addr = NULL;
} else {
type = ADDRESS_GENERATION_STATIC;
p = startswith(rvalue, "static:");
if (!p)
p = rvalue;
addr = startswith(rvalue, "static:");
if (!addr)
addr = rvalue;
}
if (p) {
r = in_addr_from_string(AF_INET6, p, &buffer);
if (addr) {
r = in_addr_from_string(AF_INET6, addr, &buffer);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse IP address in %s=, ignoring assignment: %s",
@@ -371,7 +419,7 @@ int config_parse_address_generation_type(
assert_not_reached();
}
r = ipv6_token_add(tokens, type, &buffer.in6);
r = ipv6_token_add(tokens, type, &buffer.in6, &secret_key);
if (r < 0)
return log_oom();
@@ -7,3 +7,4 @@ IPv6AcceptRA=true
[IPv6AcceptRA]
Token=prefixstable
Token=prefixstable,86b123b969ba4b7eb8b3d8605123525a
@@ -7,7 +7,12 @@ IPv6AcceptRA=true
[IPv6AcceptRA]
Token=prefixstable:2002:da8:1::
Token=prefixstable:2002:da8:1::,86b123b969ba4b7eb8b3d8605123525a
# invalid tokens
Token=prefixstable:2002:da8:1::,00000000000000000000000000000000
Token=prefixstable:2002:da8:1::,
Token=prefixstable,00000000000000000000000000000000
Token=prefixstable,
Token=prefixstable@
Token=static
Token=static:
+4 -4
View File
@@ -3951,8 +3951,8 @@ class NetworkdRATests(unittest.TestCase, Utilities):
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
print(output)
self.assertRegex(output, '2002:da8:1:0')
self.assertRegex(output, '2002:da8:2:0.*78:9abc') # EUI
self.assertIn('2002:da8:1:0:b47e:7975:fc7a:7d6e', output)
self.assertIn('2002:da8:2:0:1034:56ff:fe78:9abc', output) # EUI64
def test_ipv6_token_prefixstable_without_address(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable-without-address.network')
@@ -3961,8 +3961,8 @@ class NetworkdRATests(unittest.TestCase, Utilities):
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
print(output)
self.assertRegex(output, '2002:da8:1:0')
self.assertRegex(output, '2002:da8:2:0')
self.assertIn('2002:da8:1:0:b47e:7975:fc7a:7d6e', output)
self.assertIn('2002:da8:2:0:f689:561a:8eda:7443', output)
class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
links = [