</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>PrefixAllowList=</varname></term>
+ <listitem>
+ <para>A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router
+ advertisements in the list are allowed. Note that if <varname>PrefixAllowList=</varname> is
+ configured then <varname>PrefixDenyList=</varname> is ignored.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>RouteDenyList=</varname></term>
<listitem>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>RouteAllowList=</varname></term>
+ <listitem>
+ <para>A whitespace-separated list of IPv6 route prefixes. IPv6 route prefixes supplied via
+ router advertisements in the list are allowed. Note that if <varname>RouteAllowList=</varname> is
+ configured then <varname>RouteDenyList=</varname> is ignored.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>DHCPv6Client=</varname></term>
<listitem>
if (network->ipv6_accept_ra < 0)
/* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
+
+ /* When PrefixAllowList= or RouteAllowList= are specified, then PrefixDenyList= or RouteDenyList= are ignored. */
+ if (!set_isempty(network->ndisc_allow_listed_prefix))
+ network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
+ if (!set_isempty(network->ndisc_allow_listed_route_prefix))
+ network->ndisc_deny_listed_route_prefix = set_free_free(network->ndisc_deny_listed_route_prefix);
}
static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get route address: %m");
- if (set_contains(link->network->ndisc_deny_listed_route_prefix, &dst.in6)) {
+ if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) &&
+ !set_contains(link->network->ndisc_allow_listed_route_prefix, &dst.in6)) ||
+ set_contains(link->network->ndisc_deny_listed_route_prefix, &dst.in6)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL;
(void) in_addr_to_string(AF_INET6, &dst, &buf);
- log_link_debug(link, "Route Prefix '%s' is deny-listed, ignoring", strnull(buf));
+ if (!set_isempty(link->network->ndisc_allow_listed_route_prefix))
+ log_link_debug(link, "Route prefix '%s' is not in allow list, ignoring", strnull(buf));
+ else
+ log_link_debug(link, "Route prefix '%s' is in deny list, ignoring", strnull(buf));
}
return 0;
}
if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m");
- if (set_contains(link->network->ndisc_deny_listed_prefix, &a.in6)) {
+ if ((!set_isempty(link->network->ndisc_allow_listed_prefix) &&
+ !set_contains(link->network->ndisc_allow_listed_prefix, &a.in6)) ||
+ set_contains(link->network->ndisc_deny_listed_prefix, &a.in6)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *b = NULL;
(void) in_addr_to_string(AF_INET6, &a, &b);
- log_link_debug(link, "Prefix '%s' is deny-listed, ignoring", strna(b));
+ if (!set_isempty(link->network->ndisc_allow_listed_prefix))
+ log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b));
+ else
+ log_link_debug(link, "Prefix '%s' is in deny list, ignoring", strna(b));
}
break;
}
ipv6_token_compare_func,
free);
-int config_parse_ndisc_deny_listed_prefix(
+int config_parse_ndisc_address_filter(
const char *unit,
const char *filename,
unsigned line,
void *userdata) {
Set **list = data;
- bool is_route;
int r;
assert(filename);
return 0;
}
- is_route = streq_ptr(lvalue, "RouteDenyList");
-
for (const char *p = rvalue;;) {
_cleanup_free_ char *n = NULL;
_cleanup_free_ struct in6_addr *a = NULL;
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse NDisc deny-listed %sprefix, ignoring assignment: %s",
- is_route ? "route " : "", rvalue);
+ "Failed to parse NDisc %s=, ignoring assignment: %s",
+ lvalue, rvalue);
return 0;
}
if (r == 0)
r = in_addr_from_string(AF_INET6, n, &ip);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "NDisc deny-listed %sprefix is invalid, ignoring assignment: %s",
- is_route ? "route " : "", n);
+ "NDisc %s= entry is invalid, ignoring assignment: %s",
+ lvalue, n);
continue;
}
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);
+ "NDisc %s= entry is duplicated, ignoring assignment: %s",
+ lvalue, n);
}
}
void ndisc_vacuum(Link *link);
void ndisc_flush(Link *link);
-CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_deny_listed_prefix);
+CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_address_filter);
CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
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.PrefixDenyList, 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)
+IPv6AcceptRA.PrefixAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_prefix)
+IPv6AcceptRA.PrefixDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_prefix)
+IPv6AcceptRA.RouteAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_route_prefix)
+IPv6AcceptRA.RouteDenyList, config_parse_ndisc_address_filter, 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)
DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
-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.DenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_prefix)
+IPv6AcceptRA.BlackList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_prefix)
TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_network_emulator_delay, 0, 0
TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_network_emulator_delay, 0, 0
ordered_set_free(network->router_search_domains);
free(network->router_dns);
set_free_free(network->ndisc_deny_listed_prefix);
+ set_free_free(network->ndisc_allow_listed_prefix);
set_free_free(network->ndisc_deny_listed_route_prefix);
+ set_free_free(network->ndisc_allow_listed_route_prefix);
free(network->bridge_name);
free(network->bond_name);
IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client;
uint32_t ipv6_accept_ra_route_table;
Set *ndisc_deny_listed_prefix;
+ Set *ndisc_allow_listed_prefix;
Set *ndisc_deny_listed_route_prefix;
+ Set *ndisc_allow_listed_route_prefix;
OrderedSet *ipv6_tokens;
/* LLDP support */
DHCPv6Client=
UseAutonomousPrefix=
UseOnLinkPrefix=
+PrefixAllowList=
PrefixDenyList=
+RouteAllowList=
RouteDenyList=
DenyList=
BlackList=