From a536ec3872b929e0036f894052d2f0a73c590a9c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 06:38:46 +0900 Subject: [PATCH 1/4] network: dhcp6pd: gracefully handle delegated prefix whose prefixlen is larger than 64 --- src/network/networkd-dhcp-prefix-delegation.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 0bc922d400..b388a9f882 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -667,17 +667,17 @@ static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen, usec_t lifetime_usec) { _cleanup_(route_freep) Route *route = NULL; - _cleanup_free_ char *buf = NULL; Route *existing; int r; assert(link); assert(addr); - (void) in6_addr_prefix_to_string(addr, prefixlen, &buf); + if (prefixlen >= 64) { + _cleanup_free_ char *buf = NULL; - if (prefixlen == 64) { - log_link_debug(link, "Not adding a blocking route for DHCPv6 delegated subnet %s since distributed prefix is 64", + (void) in6_addr_prefix_to_string(addr, prefixlen, &buf); + log_link_debug(link, "Not adding a blocking route for DHCPv6 delegated prefix %s since the prefix has length >= 64.", strna(buf)); return 0; } @@ -703,9 +703,13 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad r = link_request_route(link, TAKE_PTR(route), true, &link->dhcp6_messages, dhcp6_route_handler, NULL); - if (r < 0) + if (r < 0) { + _cleanup_free_ char *buf = NULL; + + (void) in6_addr_prefix_to_string(addr, prefixlen, &buf); return log_link_error_errno(link, r, "Failed to request unreachable route for DHCPv6 delegated subnet %s: %m", strna(buf)); + } return 0; } @@ -743,7 +747,7 @@ static int dhcp6_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_ if (r < 0) return log_link_error_errno(link, r, "Failed to store DHCPv6 PD prefix %s: %m", strna(buf)); - return prefixlen <= 64; + return 0; } static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { @@ -826,8 +830,6 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len); if (r < 0) return r; - if (r == 0) - continue; r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec); if (r < 0) From 5ed10a194a5e577baadd49d10928550ee8b89142 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 04:36:48 +0900 Subject: [PATCH 2/4] network: dhcp6pd: set server address for unreachable route This is just for json output. --- src/network/networkd-dhcp-prefix-delegation.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index b388a9f882..46e75e77c1 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -665,13 +665,20 @@ static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li return 1; } -static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen, usec_t lifetime_usec) { +static int dhcp6_request_unreachable_route( + Link *link, + const struct in6_addr *addr, + uint8_t prefixlen, + usec_t lifetime_usec, + const union in_addr_union *server_address) { + _cleanup_(route_freep) Route *route = NULL; Route *existing; int r; assert(link); assert(addr); + assert(server_address); if (prefixlen >= 64) { _cleanup_free_ char *buf = NULL; @@ -687,6 +694,7 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad return log_oom(); route->source = NETWORK_CONFIG_SOURCE_DHCP6; + route->provider = *server_address; route->family = AF_INET6; route->dst.in6 = *addr; route->dst_prefixlen = prefixlen; @@ -797,6 +805,7 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { } int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { + union in_addr_union server_address; usec_t timestamp_usec; Link *link; int r; @@ -804,6 +813,10 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { assert(dhcp6_link); assert(dhcp6_link->dhcp6_lease); + r = sd_dhcp6_lease_get_server_address(dhcp6_link->dhcp6_lease, &server_address.in6); + if (r < 0) + return log_link_warning_errno(dhcp6_link, r, "Failed to get server address of DHCPv6 lease: %m"); + r = sd_dhcp6_lease_get_timestamp(dhcp6_link->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_warning_errno(dhcp6_link, r, "Failed to get timestamp of DHCPv6 lease: %m"); @@ -831,7 +844,7 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { if (r < 0) return r; - r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec); + r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec, &server_address); if (r < 0) return r; } From 2d00239cbe0ed8944bd47aa4cc6b60778b806e17 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 06:54:03 +0900 Subject: [PATCH 3/4] network: dhcp6pd: always use main route table for unreachable route This mostly reverts e47bcb7d0b2cb07c5c594e374baeb061bb7f88ba. --- man/systemd.network.xml | 1 - src/network/networkd-dhcp-common.c | 38 ++----------------- src/network/networkd-dhcp-common.h | 1 - src/network/networkd-dhcp-prefix-delegation.c | 1 - src/network/networkd-network-gperf.gperf | 7 ++-- src/network/networkd-network.h | 4 -- .../fuzz-network-parser/directives.network | 1 - 7 files changed, 7 insertions(+), 46 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 0714ebcd77..68d91390cc 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2085,7 +2085,6 @@ Table=1234 - RouteMetric= UseDNS= UseNTP= UseHostname= diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index c1de646a17..66d4153c84 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -39,15 +39,6 @@ uint32_t link_get_dhcp4_route_table(Link *link) { return link_get_vrf_table(link); } -uint32_t link_get_dhcp6_route_table(Link *link) { - assert(link); - assert(link->network); - - if (link->network->dhcp6_route_table_set) - return link->network->dhcp6_route_table; - return link_get_vrf_table(link); -} - uint32_t link_get_ipv6_accept_ra_route_table(Link *link) { assert(link); assert(link->network); @@ -533,13 +524,9 @@ int config_parse_dhcp_or_ra_route_table( assert(filename); assert(lvalue); - assert(IN_SET(ltype, - (RTPROT_DHCP<<16) | AF_UNSPEC, - (RTPROT_DHCP<<16) | AF_INET, - (RTPROT_DHCP<<16) | AF_INET6, - (RTPROT_RA<<16) | AF_INET6)); + assert(IN_SET(ltype, AF_INET, AF_INET6)); assert(rvalue); - assert(data); + assert(userdata); r = safe_atou32(rvalue, &rt); if (r < 0) { @@ -549,28 +536,11 @@ int config_parse_dhcp_or_ra_route_table( } switch(ltype) { - case (RTPROT_DHCP<<16) | AF_INET: + case AF_INET: network->dhcp_route_table = rt; network->dhcp_route_table_set = true; - network->dhcp_route_table_set_explicitly = true; break; - case (RTPROT_DHCP<<16) | AF_INET6: - network->dhcp6_route_table = rt; - network->dhcp6_route_table_set = true; - network->dhcp6_route_table_set_explicitly = true; - break; - case (RTPROT_DHCP<<16) | AF_UNSPEC: - /* For backward compatibility. */ - if (!network->dhcp_route_table_set_explicitly) { - network->dhcp_route_table = rt; - network->dhcp_route_table_set = true; - } - if (!network->dhcp6_route_table_set_explicitly) { - network->dhcp6_route_table = rt; - network->dhcp6_route_table_set = true; - } - break; - case (RTPROT_RA<<16) | AF_INET6: + case AF_INET6: network->ipv6_accept_ra_route_table = rt; network->ipv6_accept_ra_route_table_set = true; break; diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index d45b92e1a9..c19bc10407 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -51,7 +51,6 @@ typedef struct DUID { } DUID; uint32_t link_get_dhcp4_route_table(Link *link); -uint32_t link_get_dhcp6_route_table(Link *link); uint32_t link_get_ipv6_accept_ra_route_table(Link *link); bool link_dhcp_enabled(Link *link, int family); diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 46e75e77c1..3628423955 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -698,7 +698,6 @@ static int dhcp6_request_unreachable_route( route->family = AF_INET6; route->dst.in6 = *addr; route->dst_prefixlen = prefixlen; - route->table = link_get_dhcp6_route_table(link); route->type = RTN_UNREACHABLE; route->protocol = RTPROT_DHCP; route->priority = DHCP_ROUTE_METRIC; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3554e15c87..8de72911aa 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -228,7 +228,7 @@ DHCPv4.IAID, config_parse_iaid, DHCPv4.DUIDType, config_parse_network_duid_type, 0, 0 DHCPv4.DUIDRawData, config_parse_network_duid_rawdata, 0, 0 DHCPv4.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET, 0 -DHCPv4.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_INET, 0 +DHCPv4.RouteTable, config_parse_dhcp_or_ra_route_table, AF_INET, 0 DHCPv4.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release) @@ -257,7 +257,6 @@ DHCPv6.SendOption, config_parse_dhcp_send_option, DHCPv6.IAID, config_parse_iaid, AF_INET6, 0 DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Network, dhcp6_duid) DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, dhcp6_duid) -DHCPv6.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_INET6, 0 IPv6AcceptRA.UseGateway, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_gateway) IPv6AcceptRA.UseRoutePrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_route_prefix) IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix) @@ -266,7 +265,7 @@ IPv6AcceptRA.UseDNS, config_parse_bool, IPv6AcceptRA.UseDomains, config_parse_ipv6_accept_ra_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) IPv6AcceptRA.UseMTU, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_mtu) IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client) -IPv6AcceptRA.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_RA<<16) | AF_INET6, 0 +IPv6AcceptRA.RouteTable, config_parse_dhcp_or_ra_route_table, AF_INET6, 0 IPv6AcceptRA.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0 IPv6AcceptRA.RouterAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_router) IPv6AcceptRA.RouterDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_router) @@ -543,7 +542,7 @@ DHCP.IAID, config_parse_iaid, DHCP.DUIDType, config_parse_network_duid_type, 0, 0 DHCP.DUIDRawData, config_parse_network_duid_rawdata, 0, 0 DHCP.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_UNSPEC, 0 -DHCP.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_UNSPEC, 0 +DHCP.RouteTable, config_parse_dhcp_or_ra_route_table, AF_INET, 0 DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCP.RapidCommit, config_parse_warn_compat, DISABLED_LEGACY, 0 diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 9304ceaafb..295b2dbefa 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -133,7 +133,6 @@ struct Network { bool dhcp_route_metric_set; uint32_t dhcp_route_table; bool dhcp_route_table_set; - bool dhcp_route_table_set_explicitly; uint32_t dhcp_fallback_lease_lifetime; uint32_t dhcp_route_mtu; uint16_t dhcp_client_port; @@ -172,9 +171,6 @@ struct Network { bool dhcp6_use_hostname; bool dhcp6_use_ntp; bool dhcp6_use_ntp_set; - bool dhcp6_route_table; - bool dhcp6_route_table_set; - bool dhcp6_route_table_set_explicitly; DHCPUseDomains dhcp6_use_domains; bool dhcp6_use_domains_set; uint32_t dhcp6_iaid; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index c1c0026234..9889fbfad4 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -149,7 +149,6 @@ RouteMetric= IAID= DUIDType= DUIDRawData= -RouteTable= [DHCPv6PrefixDelegation] UplinkInterface= SubnetId= From 557e1b524922d7d534bc4e26d82655ea4d5ad07b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 06:57:41 +0900 Subject: [PATCH 4/4] network: dhcp6pd: use the kernel's default value for priority of unreachable route This should not change any behavior, as both values are equivalent. --- src/network/networkd-dhcp-prefix-delegation.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 3628423955..9922279fe2 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include + #include "sd-dhcp6-client.h" #include "hashmap.h" @@ -700,7 +702,7 @@ static int dhcp6_request_unreachable_route( route->dst_prefixlen = prefixlen; route->type = RTN_UNREACHABLE; route->protocol = RTPROT_DHCP; - route->priority = DHCP_ROUTE_METRIC; + route->priority = IP6_RT_PRIO_USER; route->lifetime_usec = lifetime_usec; if (route_get(link->manager, NULL, route, &existing) < 0)