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=