From 1a3a6309a73b6a67c7de712011b69b907c2f80a6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 14:44:04 +0900 Subject: [PATCH 1/9] network: rename gateway_from_dhcp -> gateway_from_dhcp_or_ra As for IPv6 case gateway is given by RA. --- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-ndisc.c | 2 +- src/network/networkd-route.c | 14 +++++++------- src/network/networkd-route.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 2920e615f3c..fe8d667c038 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -388,7 +388,7 @@ static int link_set_dhcp_routes(Link *link) { return log_link_error_errno(link, r, "Could not set router: %m"); HASHMAP_FOREACH(rt, link->network->routes_by_section) { - if (!rt->gateway_from_dhcp) + if (!rt->gateway_from_dhcp_or_ra) continue; if (rt->family != AF_INET) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index c67dd7d88ed..00adbecb891 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -524,7 +524,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { Route *route_gw; HASHMAP_FOREACH(route_gw, link->network->routes_by_section) { - if (!route_gw->gateway_from_dhcp) + if (!route_gw->gateway_from_dhcp_or_ra) continue; if (route_gw->family != AF_INET6) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 1ed82d9adce..86404b9dc64 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1192,7 +1192,7 @@ int link_set_routes(Link *link) { /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ for (phase = 0; phase < _PHASE_MAX; phase++) HASHMAP_FOREACH(rt, link->network->routes_by_section) { - if (rt->gateway_from_dhcp) + if (rt->gateway_from_dhcp_or_ra) continue; if ((in_addr_is_null(rt->gw_family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY)) @@ -1723,7 +1723,7 @@ int config_parse_gateway( } if (isempty(rvalue)) { - n->gateway_from_dhcp = false; + n->gateway_from_dhcp_or_ra = false; n->gw_family = AF_UNSPEC; n->gw = IN_ADDR_NULL; TAKE_PTR(n); @@ -1731,21 +1731,21 @@ int config_parse_gateway( } if (streq(rvalue, "_dhcp")) { - n->gateway_from_dhcp = true; + n->gateway_from_dhcp_or_ra = true; TAKE_PTR(n); return 0; } if (streq(rvalue, "_dhcp4")) { n->gw_family = AF_INET; - n->gateway_from_dhcp = true; + n->gateway_from_dhcp_or_ra = true; TAKE_PTR(n); return 0; } if (streq(rvalue, "_dhcp6")) { n->gw_family = AF_INET6; - n->gateway_from_dhcp = true; + n->gateway_from_dhcp_or_ra = true; TAKE_PTR(n); return 0; } @@ -1758,7 +1758,7 @@ int config_parse_gateway( return 0; } - n->gateway_from_dhcp = false; + n->gateway_from_dhcp_or_ra = false; TAKE_PTR(n); return 0; } @@ -2386,7 +2386,7 @@ static int route_section_verify(Route *route, Network *network) { if (route->family == AF_UNSPEC) { assert(route->section); - if (route->gateway_from_dhcp) { + if (route->gateway_from_dhcp_or_ra) { log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. " "Please use \"_dhcp4\" or \"_dhcp6\" instead. Assuming \"_dhcp4\".", route->section->filename, route->section->line); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 8207b67a2df..71ca8760243 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -45,7 +45,7 @@ typedef struct Route { unsigned char pref; unsigned flags; int gateway_onlink; - bool gateway_from_dhcp; + bool gateway_from_dhcp_or_ra; union in_addr_union gw; union in_addr_union dst; From b8caa4ef34d701c44dabd80a6d259da783fa0edb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 14:52:11 +0900 Subject: [PATCH 2/9] network: rename Gateway=_dhcp6 -> Gateway=_ipv6ra --- man/systemd.network.xml | 5 ++--- src/network/networkd-route.c | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 512d657138f..5307a508d3f 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1283,9 +1283,8 @@ IPv6Token=prefixstable:2002:da8:1:: Gateway= Takes the gateway address or the special values _dhcp4 and - _dhcp6. If _dhcp4 or _dhcp6 is - set, then the gateway address provided by DHCP (or in the IPv6 case, provided by IPv6 RA) - is used. + _ipv6ra. If _dhcp4 or _ipv6ra is + set, then the gateway address provided by DHCPv4 or IPv6 RA is used. diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 86404b9dc64..da8a12dc713 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1743,7 +1743,7 @@ int config_parse_gateway( return 0; } - if (streq(rvalue, "_dhcp6")) { + if (streq(rvalue, "_ipv6ra")) { n->gw_family = AF_INET6; n->gateway_from_dhcp_or_ra = true; TAKE_PTR(n); @@ -2388,7 +2388,7 @@ static int route_section_verify(Route *route, Network *network) { if (route->gateway_from_dhcp_or_ra) { log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. " - "Please use \"_dhcp4\" or \"_dhcp6\" instead. Assuming \"_dhcp4\".", + "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".", route->section->filename, route->section->line); route->family = AF_INET; From c3d679c43f3e754dd77796c2f5796be42ca2b99e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 15:07:49 +0900 Subject: [PATCH 3/9] network: when Gateway=_dhcp, assume gateway family based on other settings --- src/network/networkd-route.c | 43 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index da8a12dc713..30d9fb2ba46 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2380,25 +2380,42 @@ static int route_section_verify(Route *route, Network *network) { if (section_is_invalid(route->section)) return -EINVAL; + if (route->gateway_from_dhcp_or_ra) + if (route->gw_family == AF_UNSPEC) { + /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */ + switch (route->family) { + case AF_UNSPEC: + log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. " + "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".", + route->section->filename, route->section->line); + route->family = AF_INET; + break; + case AF_INET: + case AF_INET6: + log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. " + "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.", + route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra"); + break; + default: + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid route family. Ignoring [Route] section from line %u.", + route->section->filename, route->section->line); + } + route->gw_family = route->family; + } + + /* When only Gateway= is specified, assume the route family based on the Gateway address. */ if (route->family == AF_UNSPEC) route->family = route->gw_family; if (route->family == AF_UNSPEC) { assert(route->section); - if (route->gateway_from_dhcp_or_ra) { - log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. " - "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".", - route->section->filename, route->section->line); - - route->family = AF_INET; - route->gw_family = AF_INET; - } else - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: Route section without Gateway=, Destination=, Source=, " - "or PreferredSource= field configured. " - "Ignoring [Route] section from line %u.", - route->section->filename, route->section->line); + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Route section without Gateway=, Destination=, Source=, " + "or PreferredSource= field configured. " + "Ignoring [Route] section from line %u.", + route->section->filename, route->section->line); } if (route->family == AF_INET6 && route->gw_family == AF_INET) From 5bb80a46030902e636c72d850ff9aa97c8632f3f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 15:12:55 +0900 Subject: [PATCH 4/9] network: determine a [Route] section will be used or not by gateway family instead of route family By this commit, user can configure dynamic IPv6 Gateway with IPv4 destination. --- src/network/networkd-dhcp4.c | 3 +-- src/network/networkd-ndisc.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index fe8d667c038..29404e34ee5 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -391,10 +391,9 @@ static int link_set_dhcp_routes(Link *link) { if (!rt->gateway_from_dhcp_or_ra) continue; - if (rt->family != AF_INET) + if (rt->gw_family != AF_INET) continue; - rt->gw_family = AF_INET; rt->gw.in = router[0]; r = dhcp_route_configure(rt, link); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 00adbecb891..06c21a2e33a 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -527,11 +527,10 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { if (!route_gw->gateway_from_dhcp_or_ra) continue; - if (route_gw->family != AF_INET6) + if (route_gw->gw_family != AF_INET6) continue; route_gw->gw = gateway; - route_gw->gw_family = AF_INET6; r = ndisc_route_configure(route_gw, link, rt); if (r < 0) From c27abcf4fbd9d18f3a3b94453d6983ee10af1e4f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 15:52:02 +0900 Subject: [PATCH 5/9] network: when Gateway=_dhcp4, set several properties based on lease if they are not explicitly specified Before this commit, event when Gateway=_dhcp4 or _ra is set, the route was configured with 'protocol static', and other properties specified by RouteTable=, RouteMTU=, or etc, were ignored. This commit makes set the route protocol based on the protocol the gateway address is obtained, and apply other settings if it is not explicitly specified in the [Route] section. --- src/network/networkd-dhcp4.c | 8 ++++++++ src/network/networkd-ndisc.c | 17 +++++++++++++++-- src/network/networkd-route.c | 2 ++ src/network/networkd-route.h | 10 +++++++--- test/test-network/systemd-networkd-tests.py | 2 +- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 29404e34ee5..1396829bdd4 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -395,6 +395,14 @@ static int link_set_dhcp_routes(Link *link) { continue; rt->gw.in = router[0]; + if (!rt->protocol_set) + rt->protocol = RTPROT_DHCP; + if (!rt->priority_set) + rt->priority = link->network->dhcp_route_metric; + if (!rt->table_set) + rt->table = table; + if (rt->mtu == 0) + rt->mtu = link->network->dhcp_route_mtu; r = dhcp_route_configure(rt, link); if (r < 0) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 06c21a2e33a..ca27c4ad715 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -461,7 +461,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { union in_addr_union gateway; uint16_t lifetime; unsigned preference; - uint32_t mtu; + uint32_t table, mtu; usec_t time_now; int r; @@ -504,12 +504,14 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { else if (r < 0) return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m"); + table = link_get_ipv6_accept_ra_route_table(link); + r = route_new(&route); if (r < 0) return log_oom(); route->family = AF_INET6; - route->table = link_get_ipv6_accept_ra_route_table(link); + route->table = table; route->priority = link->network->dhcp6_route_metric; route->protocol = RTPROT_RA; route->pref = preference; @@ -531,6 +533,17 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { continue; route_gw->gw = gateway; + if (!route_gw->table_set) + route_gw->table = table; + if (!route_gw->priority_set) + route_gw->priority = link->network->dhcp6_route_metric; + if (!route_gw->protocol_set) + route_gw->protocol = RTPROT_RA; + if (!route_gw->pref_set) + route->pref = preference; + route_gw->lifetime = time_now + lifetime * USEC_PER_SEC; + if (route_gw->mtu == 0) + route_gw->mtu = mtu; r = ndisc_route_configure(route_gw, link, rt); if (r < 0) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 30d9fb2ba46..83a3b35e2c0 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1902,6 +1902,7 @@ int config_parse_route_priority( return 0; } + n->priority_set = true; TAKE_PTR(n); return 0; } @@ -2086,6 +2087,7 @@ int config_parse_ipv6_route_preference( return 0; } + n->pref_set = true; TAKE_PTR(n); return 0; } diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 71ca8760243..e896719e13b 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -32,20 +32,24 @@ typedef struct Route { unsigned char dst_prefixlen; unsigned char src_prefixlen; unsigned char scope; - bool scope_set; unsigned char protocol; /* RTPROT_* */ unsigned char type; /* RTN_* */ unsigned char tos; uint32_t priority; /* note that ip(8) calls this 'metric' */ uint32_t table; - bool table_set; uint32_t mtu; uint32_t initcwnd; uint32_t initrwnd; unsigned char pref; unsigned flags; int gateway_onlink; - bool gateway_from_dhcp_or_ra; + + bool scope_set:1; + bool table_set:1; + bool priority_set:1; + bool protocol_set:1; + bool pref_set:1; + bool gateway_from_dhcp_or_ra:1; union in_addr_union gw; union in_addr_union dst; diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 3189302655a..752b2fee435 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3899,7 +3899,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip route list dev veth99 10.0.0.0/8') print(output) - self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static') + self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto dhcp') def test_dhcp_client_gateway_ipv6(self): copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', From 3773eb5485b027599f176f8ce42c3eb28863d567 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 16:36:54 +0900 Subject: [PATCH 6/9] network: introduce network_adjust_ipv6_accept_ra() --- src/network/networkd-ndisc.c | 29 ++++++++++++++++------------- src/network/networkd-ndisc.h | 2 ++ src/network/networkd-network.c | 17 +++-------------- src/network/networkd-sysctl.c | 2 +- src/network/networkd-sysctl.h | 1 - 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index ca27c4ad715..6fde8fe2392 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -14,7 +14,6 @@ #include "networkd-dhcp6.h" #include "networkd-manager.h" #include "networkd-ndisc.h" -#include "networkd-sysctl.h" #include "string-table.h" #include "string-util.h" #include "strv.h" @@ -52,19 +51,23 @@ bool link_ipv6_accept_ra_enabled(Link *link) { if (!link_ipv6ll_enabled(link)) return false; - /* If unset use system default (enabled if local forwarding is disabled. - * disabled if local forwarding is enabled). - * If set, ignore or enforce RA independent of local forwarding state. - */ - if (link->network->ipv6_accept_ra < 0) + assert(link->network->ipv6_accept_ra >= 0); + return link->network->ipv6_accept_ra; +} + +void network_adjust_ipv6_accept_ra(Network *network) { + assert(network); + + if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) { + if (network->ipv6_accept_ra > 0) + log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. " + "Disabling IPv6AcceptRA=.", network->filename); + network->ipv6_accept_ra = false; + } + + if (network->ipv6_accept_ra < 0) /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ - return !link_ip_forward_enabled(link, AF_INET6); - else if (link->network->ipv6_accept_ra > 0) - /* accept RA even if ip_forward is enabled */ - return true; - else - /* ignore RA */ - return false; + network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6); } static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force); diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index fd7bb0e97fc..4e9a704995f 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -71,6 +71,8 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) { bool link_ipv6_accept_ra_enabled(Link *link); +void network_adjust_ipv6_accept_ra(Network *network); + int ndisc_configure(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 9707c97653b..a9ad8054ff8 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -19,6 +19,7 @@ #include "networkd-fdb.h" #include "networkd-manager.h" #include "networkd-mdb.h" +#include "networkd-ndisc.h" #include "networkd-neighbor.h" #include "networkd-network.h" #include "networkd-nexthop.h" @@ -188,11 +189,6 @@ int network_verify(Network *network) { if (network->bond) { /* Bonding slave does not support addressing. */ - if (network->ipv6_accept_ra > 0) { - log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.", - network->filename); - network->ipv6_accept_ra = 0; - } if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) { log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.", network->filename); @@ -223,12 +219,6 @@ int network_verify(Network *network) { network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6; if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) { - if (network->ipv6_accept_ra > 0) { - log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. " - "Disabling IPv6AcceptRA=.", network->filename); - network->ipv6_accept_ra = false; - } - if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) { log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. " "Disabling DHCPv6 client.", network->filename); @@ -249,13 +239,12 @@ int network_verify(Network *network) { SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false); } - if (network->ipv6_accept_ra < 0 && network->bridge) - network->ipv6_accept_ra = false; - /* IPMasquerade=yes implies IPForward=yes */ if (network->ip_masquerade) network->ip_forward |= ADDRESS_FAMILY_IPV4; + network_adjust_ipv6_accept_ra(network); + if (network->mtu > 0 && network->dhcp_use_mtu) { log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. " "Disabling UseMTU=.", network->filename); diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index c8facbf8316..de4ed95981e 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -38,7 +38,7 @@ static int link_set_proxy_arp(Link *link) { return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0); } -bool link_ip_forward_enabled(Link *link, int family) { +static bool link_ip_forward_enabled(Link *link, int family) { assert(link); assert(IN_SET(family, AF_INET, AF_INET6)); diff --git a/src/network/networkd-sysctl.h b/src/network/networkd-sysctl.h index a409d8f54f2..552b55226ac 100644 --- a/src/network/networkd-sysctl.h +++ b/src/network/networkd-sysctl.h @@ -16,7 +16,6 @@ typedef enum IPv6PrivacyExtensions { _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, } IPv6PrivacyExtensions; -bool link_ip_forward_enabled(Link *link, int family); int link_set_sysctl(Link *link); int link_set_ipv6_mtu(Link *link); From 22d37e5df6e8bc5bb3ab6f7eaa47aac13fd3a50d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 16:52:33 +0900 Subject: [PATCH 7/9] network: introduce network_adjust_dhcp() --- src/network/networkd-dhcp-common.c | 32 ++++++++++++++++++++++++------ src/network/networkd-dhcp-common.h | 3 +++ src/network/networkd-network.c | 13 ++---------- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 46d27f8f544..a41bd348dc4 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -26,18 +26,38 @@ bool link_dhcp_enabled(Link *link, int family) { if (link->flags & IFF_LOOPBACK) return false; - if (!link->network) - return false; - - if (link->network->bond) - return false; - if (link->iftype == ARPHRD_CAN) return false; + if (!link->network) + return false; + return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); } +void network_adjust_dhcp(Network *network) { + assert(network); + assert(network->dhcp >= 0); + + if (network->dhcp == ADDRESS_FAMILY_NO) + return; + + /* Bonding slave does not support addressing. */ + if (network->bond) { + log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.", + network->filename); + network->dhcp = ADDRESS_FAMILY_NO; + return; + } + + if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6) && + FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) { + log_warning("%s: DHCPv6 client is enabled but IPv6 link local addressing is disabled. " + "Disabling DHCPv6 client.", network->filename); + SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false); + } +} + DUID* link_get_duid(Link *link) { if (link->network->duid.type != _DUID_TYPE_INVALID) return &link->network->duid; diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index e3982a7ef16..fc84450e5eb 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -9,6 +9,7 @@ typedef struct Link Link; typedef struct Manager Manager; +typedef struct Network Network; typedef enum DHCPUseDomains { DHCP_USE_DOMAINS_NO, @@ -46,6 +47,8 @@ static inline bool link_dhcp6_enabled(Link *link) { return link_dhcp_enabled(link, AF_INET6); } +void network_adjust_dhcp(Network *network); + DUID* link_get_duid(Link *link); int link_configure_duid(Link *link); int manager_request_product_uuid(Manager *m, Link *link); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index a9ad8054ff8..6bfc4cb9ebe 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -16,6 +16,7 @@ #include "network-internal.h" #include "networkd-address-label.h" #include "networkd-address.h" +#include "networkd-dhcp-common.h" #include "networkd-fdb.h" #include "networkd-manager.h" #include "networkd-mdb.h" @@ -194,11 +195,6 @@ int network_verify(Network *network) { network->filename); network->link_local = ADDRESS_FAMILY_NO; } - if (network->dhcp != ADDRESS_FAMILY_NO) { - log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.", - network->filename); - network->dhcp = ADDRESS_FAMILY_NO; - } if (network->dhcp_server) { log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.", network->filename); @@ -219,12 +215,6 @@ int network_verify(Network *network) { network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6; if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) { - if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) { - log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. " - "Disabling DHCPv6 client.", network->filename); - SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false); - } - if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) { log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. " "Disabling IPv6PrefixDelegation=.", network->filename); @@ -244,6 +234,7 @@ int network_verify(Network *network) { network->ip_forward |= ADDRESS_FAMILY_IPV4; network_adjust_ipv6_accept_ra(network); + network_adjust_dhcp(network); if (network->mtu > 0 && network->dhcp_use_mtu) { log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. " From 956dbf361b69b8ec818147e29a6b4e5f9f4927cc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 17:04:04 +0900 Subject: [PATCH 8/9] network: warn if dynamic gateway is specified but corresponding protocol is disabled --- src/network/networkd-route.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 83a3b35e2c0..707660df3c0 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2382,7 +2382,7 @@ static int route_section_verify(Route *route, Network *network) { if (section_is_invalid(route->section)) return -EINVAL; - if (route->gateway_from_dhcp_or_ra) + if (route->gateway_from_dhcp_or_ra) { if (route->gw_family == AF_UNSPEC) { /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */ switch (route->family) { @@ -2406,6 +2406,19 @@ static int route_section_verify(Route *route, Network *network) { route->gw_family = route->family; } + if (route->gw_family == AF_INET && !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. " + "Ignoring [Route] section from line %u.", + route->section->filename, route->section->line); + + if (route->gw_family == AF_INET6 && !network->ipv6_accept_ra) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. " + "Ignoring [Route] section from line %u.", + route->section->filename, route->section->line); + } + /* When only Gateway= is specified, assume the route family based on the Gateway address. */ if (route->family == AF_UNSPEC) route->family = route->gw_family; From 9087e3d609b21fc9b45cb3fd8611b8b065427dfe Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Oct 2020 17:06:35 +0900 Subject: [PATCH 9/9] test-network: do not use deprecated value --- test/test-network/conf/dhcp-client-gateway-ipv4.network | 2 +- test/test-network/conf/dhcp-client-gateway-ipv6.network | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-network/conf/dhcp-client-gateway-ipv4.network b/test/test-network/conf/dhcp-client-gateway-ipv4.network index 7e6f6b33e01..de43c16d118 100644 --- a/test/test-network/conf/dhcp-client-gateway-ipv4.network +++ b/test/test-network/conf/dhcp-client-gateway-ipv4.network @@ -6,5 +6,5 @@ DHCP=ipv4 IPv6AcceptRA=no [Route] -Gateway=_dhcp +Gateway=_dhcp4 Destination=10.0.0.0/8 diff --git a/test/test-network/conf/dhcp-client-gateway-ipv6.network b/test/test-network/conf/dhcp-client-gateway-ipv6.network index ce708e7da9a..604a953b581 100644 --- a/test/test-network/conf/dhcp-client-gateway-ipv6.network +++ b/test/test-network/conf/dhcp-client-gateway-ipv6.network @@ -5,5 +5,5 @@ Name=veth99 DHCP=ipv6 [Route] -Gateway=_dhcp +Gateway=_ipv6ra Destination=2001:1234:5:9fff:ff:ff:ff:ff/128