From 7f20a9e5b97108ca7a673acad099595247fdefca Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 19 Mar 2020 12:54:57 +0100 Subject: [PATCH 1/2] networkctl: Add a range to address genmode --- src/network/networkctl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 2761ba774c..c725baeedb 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -453,7 +453,11 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns, b r = sd_netlink_message_enter_container(m, AF_INET6); if (r >= 0) { r = sd_netlink_message_read_u8(m, IFLA_INET6_ADDR_GEN_MODE, &info->addr_gen_mode); - if (r >= 0) + if (r >= 0 && IN_SET(info->addr_gen_mode, + IN6_ADDR_GEN_MODE_EUI64, + IN6_ADDR_GEN_MODE_NONE, + IN6_ADDR_GEN_MODE_STABLE_PRIVACY, + IN6_ADDR_GEN_MODE_RANDOM)) info->has_ipv6_address_generation_mode = true; (void) sd_netlink_message_exit_container(m); From a6f1848a2328cf1493f363968d105cc23019af8a Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Sat, 18 Apr 2020 17:59:29 +0200 Subject: [PATCH 2/2] network: Allow to configure addr_gen_mode Defines how link-local and autoconf addresses are generated. 0: generate address based on EUI64 (default) 1: do no generate a link-local address, use EUI64 for addresses generated from autoconf 2: generate stable privacy addresses, using the secret from stable_secret (RFC7217) 3: generate stable privacy addresses, using a random secret if unset --- man/systemd.network.xml | 10 +++++++ src/network/networkd-link.c | 28 +++++++++++++++---- src/network/networkd-link.h | 14 ++++++++++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 2 +- src/network/networkd-network.h | 1 + .../fuzz-network-parser/directives.network | 1 + 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1aa9b132df..f9e8fa5c25 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -193,6 +193,16 @@ This happens when multicast routing is enabled. + + IPv6LinkLocalAddressGenerationMode= + + Specifies how IPv6 link local address is generated. Takes one of eui64, + none, stable-privacy and random. + When unset, the kernel's default will be used. Note that if LinkLocalAdressing= + not configured as ipv6 then IPv6LinkLocalAddressGenerationMode= + is ignored. + + Unmanaged= diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 32fe86045d..59e37baa6b 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1692,12 +1692,18 @@ static int link_configure_addrgen_mode(Link *link) { if (!link_ipv6ll_enabled(link)) ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE; - else if (sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL) < 0) - /* The file may not exist. And even if it exists, when stable_secret is unset, - * reading the file fails with EIO. */ - ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64; - else - ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; + else if (link->network->ipv6_address_gen_mode < 0) { + r = sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL); + if (r < 0) { + /* The file may not exist. And even if it exists, when stable_secret is unset, + * reading the file fails with EIO. */ + log_link_debug_errno(link, r, "Failed to read sysctl property stable_secret: %m"); + + ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64; + } else + ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; + } else + ipv6ll_mode = link->network->ipv6_address_gen_mode; r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode); if (r < 0) @@ -4434,6 +4440,16 @@ void link_clean(Link *link) { link_unref(set_remove(link->manager->dirty_links, link)); } +static const char* const link_ipv6_address_gen_mode_table[_LINK_IPV6_ADDRESS_GEN_MODE_MAX] = { + [LINK_IPV6_ADDRESSS_GEN_MODE_EUI64] = "eui64", + [LINK_IPV6_ADDRESSS_GEN_MODE_NONE] = "none", + [LINK_IPV6_ADDRESSS_GEN_MODE_STABLE_PRIVACY] = "stable-privacy", + [LINK_IPV6_ADDRESSS_GEN_MODE_RANDOM] = "random", +}; + +DEFINE_STRING_TABLE_LOOKUP(link_ipv6_address_gen_mode, LinkIPv6AddressGenMode); +DEFINE_CONFIG_PARSE_ENUM(config_parse_link_ipv6_address_gen_mode, link_ipv6_address_gen_mode, LinkIPv6AddressGenMode, "Failed to parse link IPv6 address generation mode"); + static const char* const link_state_table[_LINK_STATE_MAX] = { [LINK_STATE_PENDING] = "pending", [LINK_STATE_INITIALIZED] = "initialized", diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 3d07d882cd..e8d67e0d64 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -35,6 +35,15 @@ typedef enum LinkState { _LINK_STATE_INVALID = -1 } LinkState; +typedef enum LinkIPv6AddressGenMode { + LINK_IPV6_ADDRESSS_GEN_MODE_EUI64 = IN6_ADDR_GEN_MODE_EUI64, + LINK_IPV6_ADDRESSS_GEN_MODE_NONE = IN6_ADDR_GEN_MODE_NONE, + LINK_IPV6_ADDRESSS_GEN_MODE_STABLE_PRIVACY = IN6_ADDR_GEN_MODE_STABLE_PRIVACY, + LINK_IPV6_ADDRESSS_GEN_MODE_RANDOM = IN6_ADDR_GEN_MODE_RANDOM, + _LINK_IPV6_ADDRESS_GEN_MODE_MAX, + _LINK_IPV6_ADDRESS_GEN_MODE_INVALID = -1 +} LinkIPv6AddressGenMode; + typedef struct Manager Manager; typedef struct Network Network; typedef struct Address Address; @@ -209,6 +218,9 @@ int link_stop_clients(Link *link, bool may_keep_dhcp); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; +const char* link_ipv6_address_gen_mode_to_string(LinkIPv6AddressGenMode s) _const_; +LinkIPv6AddressGenMode link_ipv6_address_gen_mode_from_string(const char *s) _pure_; + uint32_t link_get_vrf_table(Link *link); uint32_t link_get_dhcp_route_table(Link *link); uint32_t link_get_ipv6_accept_ra_route_table(Link *link); @@ -217,6 +229,8 @@ int link_request_set_nexthop(Link *link); int link_reconfigure(Link *link, bool force); +CONFIG_PARSER_PROTOTYPE(config_parse_link_ipv6_address_gen_mode); + int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg); #define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg) #define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3749ff6b8d..a2dd5479b2 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -51,6 +51,7 @@ Link.ARP, config_parse_tristate, Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast) Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast) Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged) +Link.IPv6LinkLocalAddressGenerationMode, config_parse_link_ipv6_address_gen_mode, 0, offsetof(Network, ipv6_address_gen_mode) Link.RequiredForOnline, config_parse_required_for_online, 0, 0 Network.Description, config_parse_string, 0, offsetof(Network, description) Network.Bridge, config_parse_ifname, 0, offsetof(Network, bridge_name) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index cd57df6d3d..1b4083febf 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -461,7 +461,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .ipv6_accept_ra_start_dhcp6_client = true, .keep_configuration = _KEEP_CONFIGURATION_INVALID, - + .ipv6_address_gen_mode = _LINK_IPV6_ADDRESS_GEN_MODE_INVALID, .can_triple_sampling = -1, .can_termination = -1, .ip_service_type = -1, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 6811658fcc..362ef6508f 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -259,6 +259,7 @@ struct Network { bool configure_without_carrier; bool ignore_carrier_loss; KeepConfiguration keep_configuration; + LinkIPv6AddressGenMode ipv6_address_gen_mode; uint32_t iaid; DUID duid; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 625842a9ba..2b95192672 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -38,6 +38,7 @@ MTUBytes= Multicast= MACAddress= Group= +IPv6LinkLocalAddressGenerationMode= [BridgeFDB] VLANId= MACAddress=