</varlistentry>
<varlistentry>
<term><varname>IPv6PrivacyExtensions=</varname></term>
- <listitem><para>Configures use of stateless temporary addresses that change over time
- (see <ulink url="https://tools.ietf.org/html/rfc4941">RFC 4941</ulink>, Privacy Extensions for Stateless Address
- Autoconfiguration in IPv6). A boolean or <literal>prefer-temporary</literal>. When true or <literal>prefer-public</literal>
- enables privacy extensions, but prefer public addresses over temporary addresses.
- <literal>prefer-temporary</literal> prefers temporary addresses over public addresses.
- Defaults to
+ <listitem><para>Configures use of stateless temporary
+ addresses that change over time (see <ulink
+ url="https://tools.ietf.org/html/rfc4941">RFC 4941</ulink>,
+ Privacy Extensions for Stateless Address Autoconfiguration
+ in IPv6). Takes a boolean or the special values
+ <literal>prefer-public</literal> and
+ <literal>kernel</literal>. When true enables the privacy
+ extensions and prefers temporary addresses over public
+ addresses. When <literal>prefer-public</literal> enables the
+ privacy extensions, but prefers public addresses over
+ temporary addresses. When false, the privacy extensions
+ remain disabled. When <literal>kernel</literal> the kernel's
+ default setting will be left in place. Defaults to
<literal>no</literal>.</para></listitem>
</varlistentry>
<varlistentry>
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
}
-static bool link_ipv6_privacy_extensions_enabled(Link *link) {
+static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
if (link->flags & IFF_LOOPBACK)
- return false;
+ return _IPV6_PRIVACY_EXTENSIONS_INVALID;
if (!link->network)
- return false;
-
- if (link->network->ipv6_privacy_extensions == _IPV6_PRIVACY_EXTENSIONS_INVALID)
- return false;
+ return _IPV6_PRIVACY_EXTENSIONS_INVALID;
return link->network->ipv6_privacy_extensions;
}
}
static int link_set_ipv6_privacy_extensions(Link *link) {
- char buf[2 * DECIMAL_STR_MAX(unsigned) + 1];
+ char buf[DECIMAL_STR_MAX(unsigned) + 1];
+ IPv6PrivacyExtensions s;
const char *p = NULL;
int r;
if (!socket_ipv6_is_supported())
return 0;
- if (!link_ipv6_privacy_extensions_enabled(link))
+ s = link_ipv6_privacy_extensions(link);
+ if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
r = write_string_file_no_create(p, buf);
- if (r < 0)
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, buf) > 0)
+ return 0;
+
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
+ }
return 0;
}
network->link_local = ADDRESS_FAMILY_IPV6;
- network->ipv6_privacy_extensions = _IPV6_PRIVACY_EXTENSIONS_INVALID;
+ network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
r = config_parse(NULL, filename, file,
"Match\0"
}
static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
- [IPV6_PRIVACY_EXTENSIONS_DISABLE] = "no",
- [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "yes",
- [IPV6_PRIVACY_EXTENSIONS_PREFER_TEMPORARY] = "prefer-temporary",
+ [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
+ [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
+ [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
};
DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
k = parse_boolean(rvalue);
if (k > 0)
- *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC;
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
else if (k == 0)
- *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_DISABLE;
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
else {
- IPv6PrivacyExtensions s;
+ IPv6PrivacyExtensions s;
s = ipv6_privacy_extensions_from_string(rvalue);
- if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
- return 0;
+ if (s < 0) {
+
+ if (streq(rvalue, "kernel"))
+ s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
+ return 0;
+ }
}
*ipv6_privacy_extensions = s;
} DCHPClientIdentifier;
typedef enum IPv6PrivacyExtensions {
- IPV6_PRIVACY_EXTENSIONS_DISABLE,
+ /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
+ IPV6_PRIVACY_EXTENSIONS_NO,
IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
- IPV6_PRIVACY_EXTENSIONS_PREFER_TEMPORARY,
+ IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
_IPV6_PRIVACY_EXTENSIONS_MAX,
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
} IPv6PrivacyExtensions;