From 16c89e649d248b0fc7c1dc7ad9f3323be4eac0f4 Mon Sep 17 00:00:00 2001 From: Devon Pringle Date: Mon, 14 Dec 2020 16:23:17 +1000 Subject: [PATCH] networkd: add RouteDenyList Allow configuration for IPv6 discovered routes to be ignored instead of adding them as a route. This can be used to block unwanted routes, for example, you may wish to not receive some set of routes on an interface if they are causing issues. --- man/systemd.network.xml | 11 +++++- src/network/networkd-ndisc.c | 38 +++++++++++++------ src/network/networkd-network-gperf.gperf | 5 ++- src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + .../fuzz-network-parser/directives.network | 1 + 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index e46f506f0f..7a330c12fa 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2095,7 +2095,16 @@ IPv6Token=prefixstable:2002:da8:1:: DenyList= - A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router advertisements in the list are ignored. + A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router + advertisements in the list are ignored. + + + + + RouteDenyList= + + A whitespace-separated list of IPv6 route prefixes. IPv6 route prefixes supplied via + router advertisements in the list are ignored. diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 0d21089d5c..61d3c98795 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -839,6 +839,16 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); + if (set_contains(link->network->ndisc_deny_listed_route_prefix, &gateway.in6)) { + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf = NULL; + + (void) in_addr_to_string(AF_INET6, &gateway, &buf); + log_link_debug(link, "Route Prefix '%s' is deny-listed, ignoring", strnull(buf)); + } + return 0; + } + if (link_has_ipv6_address(link, &gateway.in6) == 0) { if (DEBUG_LOGGING) { _cleanup_free_ char *buf = NULL; @@ -1378,8 +1388,8 @@ int config_parse_ndisc_deny_listed_prefix( void *data, void *userdata) { - Network *network = data; - const char *p; + Set **list = data; + bool is_route; int r; assert(filename); @@ -1388,11 +1398,13 @@ int config_parse_ndisc_deny_listed_prefix( assert(data); if (isempty(rvalue)) { - network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix); + *list = set_free_free(*list); return 0; } - for (p = rvalue;;) { + is_route = streq_ptr(lvalue, "RouteDenyList"); + + for (const char *p = rvalue;;) { _cleanup_free_ char *n = NULL; _cleanup_free_ struct in6_addr *a = NULL; union in_addr_union ip; @@ -1402,8 +1414,8 @@ int config_parse_ndisc_deny_listed_prefix( return log_oom(); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s", - rvalue); + "Failed to parse NDisc deny-listed %sprefix, ignoring assignment: %s", + is_route ? "route " : "", rvalue); return 0; } if (r == 0) @@ -1412,20 +1424,24 @@ int config_parse_ndisc_deny_listed_prefix( r = in_addr_from_string(AF_INET6, n, &ip); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n); + "NDisc deny-listed %sprefix is invalid, ignoring assignment: %s", + is_route ? "route " : "", n); continue; } - if (set_contains(network->ndisc_deny_listed_prefix, &ip.in6)) - continue; - a = newdup(struct in6_addr, &ip.in6, 1); if (!a) return log_oom(); - r = set_ensure_consume(&network->ndisc_deny_listed_prefix, &in6_addr_hash_ops, TAKE_PTR(a)); + r = set_ensure_consume(list, &in6_addr_hash_ops, TAKE_PTR(a)); if (r < 0) return log_oom(); + if (r == 0) + log_syntax(unit, LOG_WARNING, filename, line, 0, + "NDisc deny-listed %sprefix entry %s is duplicated, ignoring assignment.", + is_route ? "route " : "", n); + if (r > 0) + TAKE_PTR(a); } } diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index ccf7867d4f..b082ffe6e8 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -237,8 +237,9 @@ IPv6AcceptRA.UseDNS, config_parse_bool, IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client) IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0 -IPv6AcceptRA.DenyList, config_parse_ndisc_deny_listed_prefix, 0, 0 -IPv6AcceptRA.BlackList, config_parse_ndisc_deny_listed_prefix, 0, 0 +IPv6AcceptRA.DenyList, config_parse_ndisc_deny_listed_prefix, 0, offsetof(Network, ndisc_deny_listed_prefix) +IPv6AcceptRA.BlackList, config_parse_ndisc_deny_listed_prefix, 0, offsetof(Network, ndisc_deny_listed_prefix) +IPv6AcceptRA.RouteDenyList, config_parse_ndisc_deny_listed_prefix, 0, offsetof(Network, ndisc_deny_listed_route_prefix) DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_DNS].emit) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index a5440a83c7..c037904cdd 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -607,6 +607,7 @@ static Network *network_free(Network *network) { ordered_set_free(network->router_search_domains); free(network->router_dns); set_free_free(network->ndisc_deny_listed_prefix); + set_free_free(network->ndisc_deny_listed_route_prefix); free(network->bridge_name); free(network->bond_name); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index a23de93126..feda19bbc1 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -257,6 +257,7 @@ struct Network { IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client; uint32_t ipv6_accept_ra_route_table; Set *ndisc_deny_listed_prefix; + Set *ndisc_deny_listed_route_prefix; OrderedSet *ipv6_tokens; /* LLDP support */ diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index a4da64bd00..6b7cbb3559 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -312,6 +312,7 @@ UseAutonomousPrefix= UseOnLinkPrefix= DenyList= BlackList= +RouteDenyList= [DHCPServer] EmitNTP= PoolSize=