From d0d6a4cd70477970812bff0a37e70f66208d7c14 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Sun, 8 Feb 2015 22:27:15 +0100 Subject: [PATCH] networkd: generalize IPv4LL to LinkLocal This allows both IPv4 and IPv6 link-local addresses to be enabled or disabled. By default we still enable IPv6LL and disable IPv4LL. The old config option is kept for backwards compatibility, but removed from the documentation. --- man/systemd.network.xml | 8 ++-- network/80-container-host0.network | 2 +- network/80-container-ve.network | 2 +- src/network/networkd-ipv4ll.c | 2 +- src/network/networkd-link.c | 48 ++++++++++++++++++++++-- src/network/networkd-link.h | 1 + src/network/networkd-network-gperf.gperf | 3 +- src/network/networkd-network.c | 33 ++++++++++++++++ src/network/networkd.h | 8 +++- 9 files changed, 96 insertions(+), 11 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index b8facdc0a..6c137e16e 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -236,10 +236,12 @@ - IPv4LL= + LinkLocal= - A boolean. When true, enables IPv4 link-local support. - + Enables link-local address autoconfiguration. Accepts + yes, no, + ipv4, or ipv6. Defaults to + ipv6. diff --git a/network/80-container-host0.network b/network/80-container-host0.network index 8d9293f23..4e68c3d54 100644 --- a/network/80-container-host0.network +++ b/network/80-container-host0.network @@ -11,4 +11,4 @@ Name=host0 [Network] DHCP=yes -IPv4LL=yes +LinkLocal=yes diff --git a/network/80-container-ve.network b/network/80-container-ve.network index 7bde1d493..cac436d81 100644 --- a/network/80-container-ve.network +++ b/network/80-container-ve.network @@ -12,6 +12,6 @@ Driver=veth [Network] # Default to using a /28 prefix, giving up to 13 addresses per container. Address=0.0.0.0/28 -IPv4LL=yes +LinkLocal=yes DHCPServer=yes IPMasquerade=yes diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 339bf4d19..8050801e1 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -209,7 +209,7 @@ int ipv4ll_configure(Link *link) { assert(link); assert(link->network); - assert(link->network->ipv4ll); + assert(IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES)); r = sd_ipv4ll_new(&link->ipv4ll); if (r < 0) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index eff1ce94b..3b9881d71 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -72,7 +72,17 @@ bool link_ipv4ll_enabled(Link *link) { if (!link->network) return false; - return link->network->ipv4ll; + return IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); +} + +bool link_ipv6ll_enabled(Link *link) { + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + return IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); } bool link_lldp_enabled(Link *link) { @@ -1087,6 +1097,38 @@ static int link_up(Link *link) { } } + if (!link_ipv6ll_enabled(link)) { + r = sd_rtnl_message_open_container(req, IFLA_AF_SPEC); + if (r < 0) { + log_link_error(link, "Could not open IFLA_AF_SPEC container: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_open_container(req, AF_INET6); + if (r < 0) { + log_link_error(link, "Could not open AF_INET6 container: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, IN6_ADDR_GEN_MODE_NONE); + if (r < 0) { + log_link_error(link, "Could not append IFLA_INET6_ADDR_GEN_MODE: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_close_container(req); + if (r < 0) { + log_link_error(link, "Could not close AF_INET6 contaire: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_close_container(req); + if (r < 0) { + log_link_error(link, "Could not close IFLA_AF_SPEC contaire: %s", strerror(-r)); + return r; + } + } + r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); if (r < 0) { @@ -1391,8 +1433,8 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, return r; if (link->flags & IFF_LOOPBACK) { - if (network->ipv4ll) - log_link_debug(link, "ignoring IPv4LL for loopback link"); + if (network->link_local != ADDRESS_FAMILY_NO) + log_link_debug(link, "ignoring link-local autoconfiguration for loopback link"); if (network->dhcp != ADDRESS_FAMILY_NO) log_link_debug(link, "ignoring DHCP clients for loopback link"); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index ce83f24da..449dbc884 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -116,6 +116,7 @@ int icmp6_configure(Link *link); bool link_lldp_enabled(Link *link); bool link_ipv4ll_enabled(Link *link); +bool link_ipv6ll_enabled(Link *link); bool link_dhcp4_server_enabled(Link *link); bool link_dhcp4_enabled(Link *link); bool link_dhcp6_enabled(Link *link); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 26fce97b6..525f2ba79 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -36,7 +36,7 @@ Network.VXLAN, config_parse_netdev, 0, Network.Tunnel, config_parse_tunnel, 0, 0 Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp) Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server) -Network.IPv4LL, config_parse_bool, 0, offsetof(Network, ipv4ll) +Network.LinkLocal, config_parse_address_family_boolean,0, offsetof(Network, link_local) Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp) Network.Address, config_parse_address, 0, 0 @@ -69,6 +69,7 @@ Bridge.Cost, config_parse_unsigned, 0, BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 /* backwards compatibility: do not add new entries to this section */ +Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 504419cdb..c39ba6dfa 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -107,6 +107,8 @@ static int network_load_one(Manager *manager, const char *filename) { network->llmnr = LLMNR_SUPPORT_YES; + network->link_local = ADDRESS_FAMILY_IPV6; + r = config_parse(NULL, filename, file, "Match\0" "Link\0" @@ -520,6 +522,37 @@ int config_parse_tunnel(const char *unit, return 0; } +int config_parse_ipv4ll( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + AddressFamilyBoolean *link_local = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Note that this is mostly like + * config_parse_address_family_boolean(), except that it + * applies only to IPv4 */ + + if (parse_boolean(rvalue)) + *link_local |= ADDRESS_FAMILY_IPV4; + else + *link_local &= ~ADDRESS_FAMILY_IPV4; + + return 0; +} + int config_parse_dhcp( const char* unit, const char *filename, diff --git a/src/network/networkd.h b/src/network/networkd.h index 147b21acd..4f3bcf36f 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -126,7 +126,7 @@ struct Network { bool dhcp_critical; bool dhcp_routes; unsigned dhcp_route_metric; - bool ipv4ll; + AddressFamilyBoolean link_local; bool ipv4ll_route; bool dhcp_server; @@ -399,6 +399,12 @@ int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +/* IPv4LL support (legacy) */ + +int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, + const char *section, unsigned section_line, const char *lvalue, + int ltype, const char *rvalue, void *data, void *userdata); + /* LLMNR support */ const char* llmnr_support_to_string(LLMNRSupport i) _const_; -- 2.30.2