From c995fa02b1e23ea73cd1b7f62cb4dd23e951def7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 23 Aug 2021 01:36:21 +0900 Subject: [PATCH 1/2] network: dhcp4,ndisc: make addresses in Allow/DenyList= optionally take prefix length Closes #20505. --- man/systemd.network.xml | 40 +++++--- src/network/networkd-dhcp-common.c | 90 +++++++++++++++++ src/network/networkd-dhcp-common.h | 11 +++ src/network/networkd-dhcp4.c | 119 +++-------------------- src/network/networkd-dhcp4.h | 1 - src/network/networkd-ndisc.c | 93 +++--------------- src/network/networkd-ndisc.h | 1 - src/network/networkd-network-gperf.gperf | 22 ++--- src/network/networkd-network.c | 12 +-- 9 files changed, 172 insertions(+), 217 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 573ba959eb..7de3f688f3 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1965,7 +1965,8 @@ IPv6Token=prefixstable:2002:da8:1:: DenyList= - A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are + A whitespace-separated list of IPv4 addresses. Each address can optionally take a + prefix length after /. DHCP offers from servers in the list are rejected. Note that if AllowList= is configured then DenyList= is ignored. @@ -1974,7 +1975,8 @@ IPv6Token=prefixstable:2002:da8:1:: AllowList= - A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are + A whitespace-separated list of IPv4 addresses. Each address can optionally take a + prefix length after /. DHCP offers from servers in the list are accepted. @@ -2292,50 +2294,56 @@ IPv6Token=prefixstable:2002:da8:1:: RouterDenyList= - A whitespace-separated list of IPv6 router addresses. Any information advertised by - the listed router is ignored. + A whitespace-separated list of IPv6 router addresses. Each address can optionally + take a prefix length after /. 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. + A whitespace-separated list of IPv6 router addresses. Each address can optionally + take a prefix length after /. Only information advertised by the listed + router is accepted. Note that if RouterAllowList= is configured then + RouterDenyList= is ignored. PrefixDenyList= - 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. Each prefix can optionally take its + prefix length after /. IPv6 prefixes supplied via router advertisements + in the list are ignored. 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. + A whitespace-separated list of IPv6 prefixes. Each prefix can optionally take its + prefix length after /. IPv6 prefixes supplied via router advertisements + in the list are allowed. Note that if PrefixAllowList= is configured + then PrefixDenyList= is ignored. RouteDenyList= - A whitespace-separated list of IPv6 route prefixes. IPv6 route prefixes supplied via - router advertisements in the list are ignored. + A whitespace-separated list of IPv6 route prefixes. Each prefix can optionally take + its prefix length after /. IPv6 route prefixes supplied via router + advertisements in the list are ignored. 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 + A whitespace-separated list of IPv6 route prefixes. Each prefix can optionally take + its prefix length after /. IPv6 route prefixes supplied via router + advertisements in the list are allowed. Note that if RouteAllowList= is configured then RouteDenyList= is ignored. diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 19c888287c..25725f4f28 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -203,6 +203,30 @@ int dhcp_configure_duid(Link *link, const DUID *duid) { return 0; } +bool address_is_filtered(int family, const union in_addr_union *address, uint8_t prefixlen, Set *allow_list, Set *deny_list) { + struct in_addr_prefix *p; + + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(address); + + if (allow_list) { + SET_FOREACH(p, allow_list) + if (p->family == family && + p->prefixlen <= prefixlen && + in_addr_prefix_covers(family, &p->address, p->prefixlen, address) > 0) + return false; + + return true; + } + + SET_FOREACH(p, deny_list) + if (p->family == family && + in_addr_prefix_intersect(family, &p->address, p->prefixlen, address, prefixlen) > 0) + return true; + + return false; +} + int config_parse_dhcp( const char* unit, const char *filename, @@ -1144,3 +1168,69 @@ int config_parse_network_duid_rawdata( /* For backward compatibility, also set DHCPv6 DUID if not specified explicitly. */ return config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &network->dhcp6_duid, network); } + +int config_parse_address_filter( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Set **list = data; + int r; + + assert(filename); + assert(lvalue); + assert(IN_SET(ltype, AF_INET, AF_INET6)); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *list = set_free(*list); + return 0; + } + + for (const char *p = rvalue;;) { + _cleanup_free_ char *n = NULL; + _cleanup_free_ struct in_addr_prefix *a = NULL; + struct in_addr_prefix prefix; + + r = extract_first_word(&p, &n, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse NDisc %s=, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_prefix_from_string(n, ltype, &prefix.address, &prefix.prefixlen); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "NDisc %s= entry is invalid, ignoring assignment: %s", + lvalue, n); + continue; + } + + prefix.family = ltype; + a = newdup(struct in_addr_prefix, &prefix, 1); + if (!a) + return log_oom(); + + r = set_ensure_consume(list, &in_addr_prefix_hash_ops_free, TAKE_PTR(a)); + if (r < 0) + return log_oom(); + if (r == 0) + log_syntax(unit, LOG_WARNING, filename, line, 0, + "%s %s= entry is duplicated, ignoring assignment: %s", + section, lvalue, n); + } +} diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 316f5cf10b..236640e9e0 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -5,6 +5,8 @@ #include "conf-parser.h" #include "dhcp-identifier.h" +#include "in-addr-util.h" +#include "set.h" #include "time-util.h" #define DHCP_ROUTE_METRIC 1024 @@ -63,6 +65,14 @@ static inline const DUID *link_get_dhcp6_duid(Link *link) { int dhcp_configure_duid(Link *link, const DUID *duid); int manager_request_product_uuid(Manager *m); +bool address_is_filtered(int family, const union in_addr_union *address, uint8_t prefixlen, Set *allow_list, Set *deny_list); +static inline bool in4_address_is_filtered(const struct in_addr *address, Set *allow_list, Set *deny_list) { + return address_is_filtered(AF_INET, &(union in_addr_union) { .in = *address }, 32, allow_list, deny_list); +} +static inline bool in6_prefix_is_filtered(const struct in6_addr *prefix, uint8_t prefixlen, Set *allow_list, Set *deny_list) { + return address_is_filtered(AF_INET6, &(union in_addr_union) { .in6 = *prefix }, prefixlen, allow_list, deny_list); +} + const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; @@ -85,3 +95,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_type); CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata); CONFIG_PARSER_PROTOTYPE(config_parse_manager_duid_rawdata); CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_rawdata); +CONFIG_PARSER_PROTOTYPE(config_parse_address_filter); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 6b4f6aaabd..dcc16e0a5d 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1125,7 +1125,7 @@ static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) { return r; } -static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) { +static int dhcp_server_is_filtered(Link *link, sd_dhcp_client *client) { sd_dhcp_lease *lease; struct in_addr addr; int r; @@ -1142,39 +1142,16 @@ static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) { if (r < 0) return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m"); - if (set_contains(link->network->dhcp_deny_listed_ip, UINT32_TO_PTR(addr.s_addr))) { - log_struct(LOG_DEBUG, - LOG_LINK_INTERFACE(link), - LOG_LINK_MESSAGE(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in deny-list, ignoring offer", - IPV4_ADDRESS_FMT_VAL(addr))); - return true; - } + if (in4_address_is_filtered(&addr, link->network->dhcp_allow_listed_ip, link->network->dhcp_deny_listed_ip)) { + if (DEBUG_LOGGING) { + if (link->network->dhcp_allow_listed_ip) + log_link_debug(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" not found in allow-list, ignoring offer.", + IPV4_ADDRESS_FMT_VAL(addr)); + else + log_link_debug(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in deny-list, ignoring offer.", + IPV4_ADDRESS_FMT_VAL(addr)); + } - return false; -} - -static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) { - sd_dhcp_lease *lease; - struct in_addr addr; - int r; - - assert(link); - assert(link->network); - assert(client); - - r = sd_dhcp_client_get_lease(client, &lease); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get DHCP lease: %m"); - - r = sd_dhcp_lease_get_server_identifier(lease, &addr); - if (r < 0) - return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m"); - - if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) { - log_struct(LOG_DEBUG, - LOG_LINK_INTERFACE(link), - LOG_LINK_MESSAGE(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in allow-list, accepting offer", - IPV4_ADDRESS_FMT_VAL(addr))); return true; } @@ -1267,19 +1244,13 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) { } break; case SD_DHCP_CLIENT_EVENT_SELECTING: - if (!set_isempty(link->network->dhcp_allow_listed_ip)) { - r = dhcp_server_is_allow_listed(link, client); - if (r < 0) - return r; - if (r == 0) - return -ENOMSG; - } else { - r = dhcp_server_is_deny_listed(link, client); - if (r < 0) - return r; - if (r != 0) - return -ENOMSG; + r = dhcp_server_is_filtered(link, client); + if (r < 0) { + link_enter_failed(link); + return r; } + if (r > 0) + return -ENOMSG; break; case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE: @@ -1759,64 +1730,6 @@ int config_parse_dhcp_max_attempts( return 0; } -int config_parse_dhcp_acl_ip_address( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Network *network = data; - Set **acl; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - acl = STR_IN_SET(lvalue, "DenyList", "BlackList") ? &network->dhcp_deny_listed_ip : &network->dhcp_allow_listed_ip; - - if (isempty(rvalue)) { - *acl = set_free(*acl); - return 0; - } - - for (const char *p = rvalue;;) { - _cleanup_free_ char *n = NULL; - union in_addr_union ip; - - r = extract_first_word(&p, &n, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse DHCP '%s=' IP address, ignoring assignment: %s", - lvalue, rvalue); - return 0; - } - if (r == 0) - return 0; - - r = in_addr_from_string(AF_INET, n, &ip); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "DHCP '%s=' IP address is invalid, ignoring assignment: %s", lvalue, n); - continue; - } - - r = set_ensure_put(acl, NULL, UINT32_TO_PTR(ip.in.s_addr)); - if (r < 0) - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to store DHCP '%s=' IP address '%s', ignoring assignment: %m", lvalue, n); - } -} - int config_parse_dhcp_ip_service_type( const char *unit, const char *filename, diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 541fd62aa2..339372963d 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -28,7 +28,6 @@ int request_process_dhcp4_client(Request *req); int link_request_dhcp4_client(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index fe1f1e0333..1c796486a1 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -917,13 +917,15 @@ 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 destination address: %m"); - if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) && - !set_contains(link->network->ndisc_allow_listed_route_prefix, &dst)) || - set_contains(link->network->ndisc_deny_listed_route_prefix, &dst)) { + r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get route prefix length: %m"); + + if (in6_prefix_is_filtered(&dst, prefixlen, link->network->ndisc_allow_listed_route_prefix, link->network->ndisc_deny_listed_route_prefix)) { if (DEBUG_LOGGING) { _cleanup_free_ char *buf = NULL; - (void) in6_addr_to_string(&dst, &buf); + (void) in6_addr_prefix_to_string(&dst, prefixlen, &buf); if (!set_isempty(link->network->ndisc_allow_listed_route_prefix)) log_link_debug(link, "Route prefix '%s' is not in allow list, ignoring", strna(buf)); else @@ -946,10 +948,6 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { return 0; } - r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get route prefix length: %m"); - r = sd_ndisc_router_route_get_preference(rt, &preference); if (r < 0) return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m"); @@ -1184,6 +1182,7 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { switch (type) { case SD_NDISC_OPTION_PREFIX_INFORMATION: { + unsigned prefixlen; struct in6_addr a; uint8_t flags; @@ -1191,13 +1190,15 @@ 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_isempty(link->network->ndisc_allow_listed_prefix) && - !set_contains(link->network->ndisc_allow_listed_prefix, &a)) || - set_contains(link->network->ndisc_deny_listed_prefix, &a)) { + r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + + if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) { if (DEBUG_LOGGING) { _cleanup_free_ char *b = NULL; - (void) in6_addr_to_string(&a, &b); + (void) in6_addr_prefix_to_string(&a, prefixlen, &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 @@ -1267,9 +1268,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { 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)) || - set_contains(link->network->ndisc_deny_listed_router, &router)) { + if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) { if (DEBUG_LOGGING) { _cleanup_free_ char *buf = NULL; @@ -1486,70 +1485,6 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( ipv6_token_compare_func, free); -int config_parse_ndisc_address_filter( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Set **list = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - *list = set_free_free(*list); - return 0; - } - - for (const char *p = rvalue;;) { - _cleanup_free_ char *n = NULL; - _cleanup_free_ struct in6_addr *a = NULL; - union in_addr_union ip; - - r = extract_first_word(&p, &n, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse NDisc %s=, ignoring assignment: %s", - lvalue, rvalue); - return 0; - } - if (r == 0) - return 0; - - r = in_addr_from_string(AF_INET6, n, &ip); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "NDisc %s= entry is invalid, ignoring assignment: %s", - lvalue, n); - continue; - } - - a = newdup(struct in6_addr, &ip.in6, 1); - if (!a) - return log_oom(); - - 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 %s= entry is duplicated, ignoring assignment: %s", - lvalue, n); - } -} - int config_parse_address_generation_type( const char *unit, const char *filename, diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 2660794b5c..bb32a68690 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -58,7 +58,6 @@ int ndisc_start(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link); -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); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_use_domains); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 846e54aed7..405ddccc8b 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -227,8 +227,8 @@ DHCPv4.UseTimezone, config_parse_bool, DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release) DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline) -DHCPv4.DenyList, config_parse_dhcp_acl_ip_address, 0, 0 -DHCPv4.AllowList, config_parse_dhcp_acl_ip_address, 0, 0 +DHCPv4.DenyList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_deny_listed_ip) +DHCPv4.AllowList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_allow_listed_ip) DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type) DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options) DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options) @@ -260,12 +260,12 @@ IPv6AcceptRA.UseMTU, config_parse_bool, 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.RouteMetric, config_parse_dhcp_route_metric, 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) -IPv6AcceptRA.RouteDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_route_prefix) +IPv6AcceptRA.RouterAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_router) +IPv6AcceptRA.RouterDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_router) +IPv6AcceptRA.PrefixAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_prefix) +IPv6AcceptRA.PrefixDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) +IPv6AcceptRA.RouteAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_route_prefix) +IPv6AcceptRA.RouteDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_route_prefix) DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0 DHCPServer.UplinkInterface, config_parse_uplink, 0, 0 DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target) @@ -498,7 +498,7 @@ IPv6PrefixDelegation.DNS, config_parse_radv_dns, IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0 IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) -DHCPv4.BlackList, config_parse_dhcp_acl_ip_address, 0, 0 +DHCPv4.BlackList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_deny_listed_ip) DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0 DHCP.UseNTP, config_parse_dhcp_use_ntp, 0, 0 @@ -526,8 +526,8 @@ DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, 0 DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) DHCPv6.RouteMetric, config_parse_dhcp_route_metric, 0, 0 -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) +IPv6AcceptRA.DenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) +IPv6AcceptRA.BlackList, config_parse_address_filter, AF_INET6, 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 1928db537e..526ed39b58 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -601,12 +601,12 @@ 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); - set_free_free(network->ndisc_allow_listed_route_prefix); + set_free(network->ndisc_deny_listed_router); + set_free(network->ndisc_allow_listed_router); + set_free(network->ndisc_deny_listed_prefix); + set_free(network->ndisc_allow_listed_prefix); + set_free(network->ndisc_deny_listed_route_prefix); + set_free(network->ndisc_allow_listed_route_prefix); free(network->batadv_name); free(network->bridge_name); From ab47f96041e29be514d0a286f51dd9fd7b3a6b39 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 23 Aug 2021 20:37:36 +0900 Subject: [PATCH 2/2] test-network: add more testcases for *Allow/DenyList= --- .../conf/dhcp-client-allow-list.network | 11 +++++++++++ .../conf/ipv6ra-prefix-client.network | 9 ++++----- test/test-network/conf/ipv6ra-prefix.network | 7 +++++++ test/test-network/systemd-networkd-tests.py | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 test/test-network/conf/dhcp-client-allow-list.network diff --git a/test/test-network/conf/dhcp-client-allow-list.network b/test/test-network/conf/dhcp-client-allow-list.network new file mode 100644 index 0000000000..8228369887 --- /dev/null +++ b/test/test-network/conf/dhcp-client-allow-list.network @@ -0,0 +1,11 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCPv4] +# DenyList= will be ignored +AllowList=192.168.5.0/24 192.168.6.0/24 +DenyList=192.168.5.0/24 diff --git a/test/test-network/conf/ipv6ra-prefix-client.network b/test/test-network/conf/ipv6ra-prefix-client.network index e18ecaf290..b046d9f992 100644 --- a/test/test-network/conf/ipv6ra-prefix-client.network +++ b/test/test-network/conf/ipv6ra-prefix-client.network @@ -6,9 +6,8 @@ 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:: +# PrefixDenyList= will be ignored. +PrefixAllowList=2001:db8:0:1:: 2001:db8:0:1:: 2001:db8:0:1::/64 +PrefixDenyList=2001:db8:0:1::/64 2001:db8:0:1:: 2001:db8:0:3::/64 +RouteDenyList=2001:db1:fff::/64 2001:db1:fff:: 2001:db2:fff::/64 UseDomains=yes diff --git a/test/test-network/conf/ipv6ra-prefix.network b/test/test-network/conf/ipv6ra-prefix.network index 72ad808b71..ae74c6e2c6 100644 --- a/test/test-network/conf/ipv6ra-prefix.network +++ b/test/test-network/conf/ipv6ra-prefix.network @@ -15,6 +15,9 @@ Prefix=2001:db8:0:1::/64 Prefix=2001:db8:0:2::/64 Assign=yes +[IPv6Prefix] +Prefix=2001:db8:0:3::/64 + [IPv6RoutePrefix] Route=2001:db0:fff::/64 LifetimeSec=1000 @@ -22,3 +25,7 @@ LifetimeSec=1000 [IPv6RoutePrefix] Route=2001:db1:fff::/64 LifetimeSec=1000 + +[IPv6RoutePrefix] +Route=2001:db2:fff::/64 +LifetimeSec=1000 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index e5610bf1b2..bb27744d35 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3931,6 +3931,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): '25-veth.netdev', '25-vrf.netdev', '25-vrf.network', + 'dhcp-client-allow-list.network', 'dhcp-client-anonymize.network', 'dhcp-client-decline.network', 'dhcp-client-gateway-ipv4.network', @@ -4764,6 +4765,16 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') + def test_dhcp_client_allow_list(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-allow-list.network') + + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip -4 address show dev veth99 scope global dynamic') + print(output) + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') + class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): links = [ 'dummy98', @@ -4800,18 +4811,22 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): print(output) self.assertIn('inet6 2001:db8:0:1:', output) self.assertNotIn('inet6 2001:db8:0:2:', output) + self.assertNotIn('inet6 2001:db8:0:3:', 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.assertNotIn('2001:db8:0:3::/64 proto ra', output) self.assertIn('2001:db0:fff::/64 via ', output) self.assertNotIn('2001:db1:fff::/64 via ', output) + self.assertNotIn('2001:db2: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) + self.assertNotIn('inet6 2001:db8:0:3:', output) output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env) print(output)