From 8c86196b523ec04c0a0a61f338eef03aa4f67c39 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 09:13:47 +0900 Subject: [PATCH 1/8] network: drop redundant TAKE_PTR() Follow-up for 16c89e649d248b0fc7c1dc7ad9f3323be4eac0f4. --- src/network/networkd-ndisc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 61d3c98795..2027b73a56 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1440,8 +1440,6 @@ int config_parse_ndisc_deny_listed_prefix( 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); } } From 0afa4d569d3a661375ad1382f772f6f3968f3a1b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 12:48:21 +0900 Subject: [PATCH 2/8] sd-ndisc: fix indentation --- src/libsystemd-network/sd-ndisc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c index db7ada60a8..d02a2a9279 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -221,8 +221,7 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda if (!rt) return -ENOMEM; - r = icmp6_receive(fd, NDISC_ROUTER_RAW(rt), rt->raw_size, &rt->address, - &rt->timestamp); + r = icmp6_receive(fd, NDISC_ROUTER_RAW(rt), rt->raw_size, &rt->address, &rt->timestamp); if (r < 0) { switch (r) { case -EADDRNOTAVAIL: From 1cd5267e815a451ed9ee228d90b3c192a529dfcf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 13:07:30 +0900 Subject: [PATCH 3/8] network: fix condition for checking the provided gateway is assigned to link Fix bug introduced by 221019166f315252304b3459902ead613b905de5. --- src/network/networkd-ndisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 2027b73a56..7088cfa123 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -849,7 +849,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { return 0; } - if (link_has_ipv6_address(link, &gateway.in6) == 0) { + if (link_has_ipv6_address(link, &gateway.in6) > 0) { if (DEBUG_LOGGING) { _cleanup_free_ char *buf = NULL; From 19e334bd15a212de28a19a1da5091ffb9ee0fbe7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 13:12:40 +0900 Subject: [PATCH 4/8] network: make RouteDenyList= filter route prefix rather than gateway address DenyList= filters provided prefixes, not router address. So, RouteDenyLisy= should so for consistency. Fixes 16c89e649d248b0fc7c1dc7ad9f3323be4eac0f4. --- src/network/networkd-ndisc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 7088cfa123..a4ac0d2023 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -820,7 +820,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { _cleanup_(route_freep) Route *route = NULL; - union in_addr_union gateway; + union in_addr_union gateway, dst; uint32_t lifetime; unsigned preference, prefixlen; usec_t time_now; @@ -835,20 +835,24 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { if (lifetime == 0) return 0; - r = sd_ndisc_router_get_address(rt, &gateway.in6); + r = sd_ndisc_router_route_get_address(rt, &dst.in6); if (r < 0) - return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); + return log_link_error_errno(link, r, "Failed to get route address: %m"); - if (set_contains(link->network->ndisc_deny_listed_route_prefix, &gateway.in6)) { + if (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, &gateway, &buf); + (void) in_addr_to_string(AF_INET6, &dst, &buf); log_link_debug(link, "Route Prefix '%s' is deny-listed, ignoring", strnull(buf)); } return 0; } + r = sd_ndisc_router_get_address(rt, &gateway.in6); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); + if (link_has_ipv6_address(link, &gateway.in6) > 0) { if (DEBUG_LOGGING) { _cleanup_free_ char *buf = NULL; @@ -880,15 +884,12 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { route->priority = link->network->dhcp6_route_metric; route->protocol = RTPROT_RA; route->pref = preference; - route->gw.in6 = gateway.in6; + route->gw = gateway; route->gw_family = AF_INET6; + route->dst = dst; route->dst_prefixlen = prefixlen; route->lifetime = time_now + lifetime * USEC_PER_SEC; - r = sd_ndisc_router_route_get_address(rt, &route->dst.in6); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get route address: %m"); - r = ndisc_route_configure(route, link, rt); if (r < 0) return log_link_error_errno(link, r, "Could not set additional route: %m"); From 3f0af4a5f93b3b2bb8be860aed9bd348999ea590 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 14:00:24 +0900 Subject: [PATCH 5/8] network: rename DenyList= -> PrefixDenyList= --- man/systemd.network.xml | 2 +- src/network/networkd-network-gperf.gperf | 5 +++-- test/fuzz/fuzz-network-parser/directives.network | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 7a330c12fa..020dcfd56e 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2093,7 +2093,7 @@ IPv6Token=prefixstable:2002:da8:1:: - DenyList= + PrefixDenyList= A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router advertisements in the list are ignored. diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b082ffe6e8..82a4f10b04 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -237,8 +237,7 @@ 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, offsetof(Network, ndisc_deny_listed_prefix) -IPv6AcceptRA.BlackList, config_parse_ndisc_deny_listed_prefix, 0, offsetof(Network, ndisc_deny_listed_prefix) +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) 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) @@ -471,6 +470,8 @@ DHCP.RapidCommit, config_parse_bool, 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) 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 diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 6b7cbb3559..66e19d865f 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -310,9 +310,10 @@ UseDNS= DHCPv6Client= UseAutonomousPrefix= UseOnLinkPrefix= +PrefixDenyList= +RouteDenyList= DenyList= BlackList= -RouteDenyList= [DHCPServer] EmitNTP= PoolSize= From de6b6ff84c5078960b4891c24b20962671db4689 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Fri, 18 Dec 2020 20:28:38 +0100 Subject: [PATCH 6/8] networkd: add support for prefix allow-list and route allow-list --- man/systemd.network.xml | 18 ++++++++ src/network/networkd-ndisc.c | 41 ++++++++++++------- src/network/networkd-ndisc.h | 2 +- src/network/networkd-network-gperf.gperf | 10 +++-- src/network/networkd-network.c | 2 + src/network/networkd-network.h | 2 + .../fuzz-network-parser/directives.network | 2 + 7 files changed, 58 insertions(+), 19 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 020dcfd56e..903ffd88de 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2100,6 +2100,15 @@ IPv6Token=prefixstable:2002:da8:1:: + + PrefixAllowList= + + A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router + advertisements in the list are allowed. Note that if PrefixAllowList= is + configured then PrefixDenyList= is ignored. + + + RouteDenyList= @@ -2108,6 +2117,15 @@ IPv6Token=prefixstable:2002:da8:1:: + + RouteAllowList= + + A whitespace-separated list of IPv6 route prefixes. IPv6 route prefixes supplied via + router advertisements in the list are allowed. Note that if RouteAllowList= is + configured then RouteDenyList= is ignored. + + + DHCPv6Client= diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index a4ac0d2023..59ab8a7843 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -69,6 +69,12 @@ void network_adjust_ipv6_accept_ra(Network *network) { 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); @@ -839,12 +845,17 @@ 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 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; } @@ -1096,12 +1107,17 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { 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; } @@ -1377,7 +1393,7 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( 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, @@ -1390,7 +1406,6 @@ int config_parse_ndisc_deny_listed_prefix( void *userdata) { Set **list = data; - bool is_route; int r; assert(filename); @@ -1403,8 +1418,6 @@ int config_parse_ndisc_deny_listed_prefix( 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; @@ -1415,8 +1428,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 %sprefix, ignoring assignment: %s", - is_route ? "route " : "", rvalue); + "Failed to parse NDisc %s=, ignoring assignment: %s", + lvalue, rvalue); return 0; } if (r == 0) @@ -1425,8 +1438,8 @@ 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 %sprefix is invalid, ignoring assignment: %s", - is_route ? "route " : "", n); + "NDisc %s= entry is invalid, ignoring assignment: %s", + lvalue, n); continue; } @@ -1439,8 +1452,8 @@ int config_parse_ndisc_deny_listed_prefix( 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); } } diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 1562411224..e2cb82b346 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -77,7 +77,7 @@ int ndisc_configure(Link *link); 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); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 82a4f10b04..6c999e4363 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -237,8 +237,10 @@ 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.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) @@ -470,8 +472,8 @@ DHCP.RapidCommit, config_parse_bool, 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 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c037904cdd..89a1f8acba 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -607,7 +607,9 @@ 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_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); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index feda19bbc1..835e7299ea 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -257,7 +257,9 @@ struct Network { 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 */ diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 66e19d865f..f1f7ad0cb8 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -310,7 +310,9 @@ UseDNS= DHCPv6Client= UseAutonomousPrefix= UseOnLinkPrefix= +PrefixAllowList= PrefixDenyList= +RouteAllowList= RouteDenyList= DenyList= BlackList= From 75d26411900d3276edf536009dcc2bbd4766d43c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 14:27:25 +0900 Subject: [PATCH 7/8] network: introduce RouterAllowList= and RouterDenyList= in [IPv6AcceptRA] --- man/systemd.network.xml | 17 ++++++++++ src/network/networkd-ndisc.c | 34 ++++++++++++++----- src/network/networkd-network-gperf.gperf | 2 ++ src/network/networkd-network.c | 2 ++ src/network/networkd-network.h | 2 ++ .../fuzz-network-parser/directives.network | 2 ++ 6 files changed, 51 insertions(+), 8 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 903ffd88de..7baf1a9df0 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2092,6 +2092,23 @@ IPv6Token=prefixstable:2002:da8:1:: + + RouterDenyList= + + A whitespace-separated list of IPv6 router addresses. Any information advertised by + the listed router is ignored. + + + + + RouterAllowList= + + A whitespace-separated list of IPv6 router addresses. Only information advertised by + the listed router is accepted. Note that if RouterAllowList= is + configured then RouterDenyList= is ignored. + + + PrefixDenyList= diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 59ab8a7843..3f1837f591 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -70,7 +70,10 @@ void network_adjust_ipv6_accept_ra(Network *network) { /* 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. */ + /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then + * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */ + if (!set_isempty(network->ndisc_allow_listed_router)) + network->ndisc_deny_listed_router = set_free_free(network->ndisc_deny_listed_router); 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)) @@ -1168,7 +1171,7 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { } static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { - struct in6_addr router; + union in_addr_union router; uint64_t flags; NDiscAddress *na; NDiscRoute *nr; @@ -1179,21 +1182,36 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { assert(link->manager); assert(rt); + r = sd_ndisc_router_get_address(rt, &router.in6); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + + if ((!set_isempty(link->network->ndisc_allow_listed_router) && + !set_contains(link->network->ndisc_allow_listed_router, &router.in6)) || + set_contains(link->network->ndisc_deny_listed_router, &router.in6)) { + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf = NULL; + + (void) in_addr_to_string(AF_INET6, &router, &buf); + if (!set_isempty(link->network->ndisc_allow_listed_router)) + log_link_debug(link, "Router '%s' is not in allow list, ignoring", strna(buf)); + else + log_link_debug(link, "Router '%s' is in deny list, ignoring", strna(buf)); + } + return 0; + } + link->ndisc_addresses_configured = false; link->ndisc_routes_configured = false; link_dirty(link); - r = sd_ndisc_router_get_address(rt, &router); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); - SET_FOREACH(na, link->ndisc_addresses) - if (IN6_ARE_ADDR_EQUAL(&na->router, &router)) + if (IN6_ARE_ADDR_EQUAL(&na->router, &router.in6)) na->marked = true; SET_FOREACH(nr, link->ndisc_routes) - if (IN6_ARE_ADDR_EQUAL(&nr->router, &router)) + if (IN6_ARE_ADDR_EQUAL(&nr->router, &router.in6)) nr->marked = true; r = sd_ndisc_router_get_flags(rt, &flags); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 6c999e4363..2a6cb6deae 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -237,6 +237,8 @@ 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.RouterAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_router) +IPv6AcceptRA.RouterDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_router) 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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 89a1f8acba..daece28dbb 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -606,6 +606,8 @@ static Network *network_free(Network *network) { ordered_set_free(network->router_search_domains); free(network->router_dns); + set_free_free(network->ndisc_deny_listed_router); + set_free_free(network->ndisc_allow_listed_router); 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); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 835e7299ea..32f5ae8d72 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -256,6 +256,8 @@ struct Network { DHCPUseDomains ipv6_accept_ra_use_domains; IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client; uint32_t ipv6_accept_ra_route_table; + Set *ndisc_deny_listed_router; + Set *ndisc_allow_listed_router; Set *ndisc_deny_listed_prefix; Set *ndisc_allow_listed_prefix; Set *ndisc_deny_listed_route_prefix; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index f1f7ad0cb8..f57f0cd561 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -310,6 +310,8 @@ UseDNS= DHCPv6Client= UseAutonomousPrefix= UseOnLinkPrefix= +RouterAllowList= +RouterDenyList= PrefixAllowList= PrefixDenyList= RouteAllowList= From 635f2a6692ca447c72cb0941ddda0fef1fb5eb9f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 24 Dec 2020 13:50:48 +0900 Subject: [PATCH 8/8] test-network: add tests for [IPv6AcceptRA] PrefixDenyList= or friends --- .../ipv6ra-prefix-client-deny-list.network | 11 +++++ .../conf/ipv6ra-prefix-client.network | 7 ++++ test/test-network/conf/ipv6ra-prefix.network | 4 ++ test/test-network/systemd-networkd-tests.py | 40 +++++++++++++++++-- 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 test/test-network/conf/ipv6ra-prefix-client-deny-list.network diff --git a/test/test-network/conf/ipv6ra-prefix-client-deny-list.network b/test/test-network/conf/ipv6ra-prefix-client-deny-list.network new file mode 100644 index 0000000000..ce7a76f70c --- /dev/null +++ b/test/test-network/conf/ipv6ra-prefix-client-deny-list.network @@ -0,0 +1,11 @@ +[Match] +Name=veth-peer + +[Network] +DHCP=no +IPv6AcceptRA=yes + +[IPv6AcceptRA] +RouterDenyList=2001::1 +PrefixDenyList=2001:db8:0:2:: +RouteDenyList=2001:db1:fff:: diff --git a/test/test-network/conf/ipv6ra-prefix-client.network b/test/test-network/conf/ipv6ra-prefix-client.network index bc40b123c7..58883658f3 100644 --- a/test/test-network/conf/ipv6ra-prefix-client.network +++ b/test/test-network/conf/ipv6ra-prefix-client.network @@ -4,3 +4,10 @@ Name=veth-peer [Network] DHCP=no IPv6AcceptRA=yes + +[IPv6AcceptRA] +# PrefixDenyList= and RouteDenyList= will be ignored. +PrefixAllowList=2001:db8:0:1:: 2001:db8:0:1:: +PrefixDenyList=2001:db8:0:1:: 2001:db8:0:1:: +RouteAllowList=2001:db0:fff:: 2001:db0:fff:: +RouteDenyList=2001:db0:fff:: 2001:db0:fff:: diff --git a/test/test-network/conf/ipv6ra-prefix.network b/test/test-network/conf/ipv6ra-prefix.network index a0ac1e4537..cfb03f50c4 100644 --- a/test/test-network/conf/ipv6ra-prefix.network +++ b/test/test-network/conf/ipv6ra-prefix.network @@ -15,3 +15,7 @@ Assign=yes [IPv6RoutePrefix] Route=2001:db0:fff::/64 LifetimeSec=1000 + +[IPv6RoutePrefix] +Route=2001:db1:fff::/64 +LifetimeSec=1000 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 454e6ce66b..1c4046d4f2 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -4274,6 +4274,7 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): units = [ '25-veth.netdev', + 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network' ] @@ -4294,14 +4295,45 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): start_networkd() self.wait_online(['veth99:routable', 'veth-peer:routable']) + output = check_output('ip address show dev veth-peer') + print(output) + self.assertIn('inet6 2001:db8:0:1:', output) + self.assertNotIn('inet6 2001:db8:0:2:', output) + output = check_output('ip -6 route show dev veth-peer') print(output) - self.assertRegex(output, '2001:db8:0:1::/64 proto ra') + self.assertIn('2001:db8:0:1::/64 proto ra', output) + self.assertNotIn('2001:db8:0:2::/64 proto ra', output) + self.assertIn('2001:db0:fff::/64 via ', output) + self.assertNotIn('2001:db1:fff::/64 via ', output) - output = check_output('ip addr show dev veth99') + output = check_output('ip address show dev veth99') print(output) - self.assertNotRegex(output, '2001:db8:0:1') - self.assertRegex(output, '2001:db8:0:2') + self.assertNotIn('inet6 2001:db8:0:1:', output) + self.assertIn('inet6 2001:db8:0:2:', output) + + def test_ipv6_route_prefix_deny_list(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network') + + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth-peer') + print(output) + self.assertIn('inet6 2001:db8:0:1:', output) + self.assertNotIn('inet6 2001:db8:0:2:', output) + + output = check_output('ip -6 route show dev veth-peer') + print(output) + self.assertIn('2001:db8:0:1::/64 proto ra', output) + self.assertNotIn('2001:db8:0:2::/64 proto ra', output) + self.assertIn('2001:db0:fff::/64 via ', output) + self.assertNotIn('2001:db1:fff::/64 via ', output) + + output = check_output('ip address show dev veth99') + print(output) + self.assertNotIn('inet6 2001:db8:0:1:', output) + self.assertIn('inet6 2001:db8:0:2:', output) class NetworkdMTUTests(unittest.TestCase, Utilities): links = ['dummy98']