]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: add support for prefix allow-list and route allow-list
authorSusant Sahani <ssahani@vmware.com>
Fri, 18 Dec 2020 19:28:38 +0000 (20:28 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 24 Dec 2020 08:16:13 +0000 (17:16 +0900)
man/systemd.network.xml
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/fuzz/fuzz-network-parser/directives.network

index 020dcfd56e68aaf03a67720550915b897296bd01..903ffd88de556b338c537b80e780fc9073cf724b 100644 (file)
@@ -2100,6 +2100,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           </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>
@@ -2108,6 +2117,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           </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>
index a4ac0d20237f16df6379ac9e6494e3887f4c8979..59ab8a7843430c13fbf5db3ccc52e3b4e3819930 100644 (file)
@@ -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);
         }
 }
 
index 1562411224895d0b72f82e1a5b8a614745290a2a..e2cb82b346f8d2d10bc6067bb30fbe5b4f06cf5e 100644 (file)
@@ -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);
 
index 82a4f10b048b51abfd89f1f6245de16e69775eb6..6c999e43636d68b5678aba0cd6315b1353de7844 100644 (file)
@@ -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
index c037904cdd1c1f025be8c20e69761e56ff844cda..89a1f8acba18cb144b241823e918485e211c54ad 100644 (file)
@@ -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);
index feda19bbc1fe257bb267a618afa279222968326d..835e7299ead40ae6b9711969247ed01d83421bc4 100644 (file)
@@ -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 */
index 66e19d865f886f6eb003bb79441c5bc7aaee14d4..f1f7ad0cb87188809b98624aa38cb3b438ea8071 100644 (file)
@@ -310,7 +310,9 @@ UseDNS=
 DHCPv6Client=
 UseAutonomousPrefix=
 UseOnLinkPrefix=
+PrefixAllowList=
 PrefixDenyList=
+RouteAllowList=
 RouteDenyList=
 DenyList=
 BlackList=