]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/dhcp-pd: allow to customize route type for delegated prefix
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 4 Aug 2024 09:18:51 +0000 (18:18 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 5 Aug 2024 20:24:16 +0000 (05:24 +0900)
Closes #33929.

man/systemd.network.xml
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp-prefix-delegation.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h

index b4d438823db9077d32768de8772effbb205c5ff4..ebcb6d048164eda17c4695b134357ee7378d3343 100644 (file)
@@ -2762,6 +2762,23 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>UnassignedSubnetPolicy=</varname></term>
+        <listitem>
+          <para>Takes <literal>none</literal>, or one of the reject types: <literal>unreachable</literal>,
+          <literal>prohibit</literal>, <literal>blackhole</literal>, or <literal>throw</literal>. If a reject
+          type is specified, the reject route corresponding to the acquired 6RD prefix will be configured.
+          For example, when <literal>unreachable</literal>,
+          <programlisting>unreachable 2001:db8::/56 dev lo proto dhcp metric 1024 pref medium</programlisting>
+          will be configured. See <ulink url="https://datatracker.ietf.org/doc/html/rfc7084">RFC 7084</ulink>.
+          If <literal>none</literal> is specified, such route will not be configured. This may be useful when
+          custom firewall rules that handle packets for unassigned subnets will be configured.
+          Defaults to <literal>unreachable</literal>.</para>
+
+          <xi:include href="version-info.xml" xpointer="v257"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>IPv6OnlyMode=</varname></term>
         <listitem>
@@ -3002,6 +3019,23 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>UnassignedSubnetPolicy=</varname></term>
+        <listitem>
+          <para>Takes <literal>none</literal> or one of the reject types: <literal>unreachable</literal>,
+          <literal>prohibit</literal>, <literal>blackhole</literal>, or <literal>throw</literal>. If a reject
+          type is specified, the reject route corresponding to the delegated prefix will be configured.
+          For example, when <literal>unreachable</literal>,
+          <programlisting>unreachable 2001:db8::/56 dev lo proto dhcp metric 1024 pref medium</programlisting>
+          will be configured. See <ulink url="https://datatracker.ietf.org/doc/html/rfc7084">RFC 7084</ulink>.
+          If <literal>none</literal> is specified, such route will not be configured. This may be useful when
+          custom firewall rules that handle packets for unassigned subnets will be configured.
+          Defaults to <literal>unreachable</literal>.</para>
+
+          <xi:include href="version-info.xml" xpointer="v257"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>RapidCommit=</varname></term>
         <listitem>
index 2e660b77631a5efacc36df7911425eb556c95534..1ffb4888dd0a3648b3950a516d54045089784118 100644 (file)
@@ -13,6 +13,7 @@
 #include "networkd-manager.h"
 #include "networkd-queue.h"
 #include "networkd-radv.h"
+#include "networkd-route-util.h"
 #include "networkd-route.h"
 #include "networkd-setlink.h"
 #include "parse-util.h"
@@ -697,6 +698,7 @@ static int dhcp_request_unreachable_route(
                 usec_t lifetime_usec,
                 NetworkConfigSource source,
                 const union in_addr_union *server_address,
+                uint8_t type, /* RTN_* */
                 unsigned *counter,
                 route_netlink_handler_t callback,
                 bool *configured) {
@@ -710,10 +712,14 @@ static int dhcp_request_unreachable_route(
         assert(addr);
         assert(IN_SET(source, NETWORK_CONFIG_SOURCE_DHCP4, NETWORK_CONFIG_SOURCE_DHCP6));
         assert(server_address);
+        assert(type == RTN_UNSPEC || route_type_is_reject(type));
         assert(counter);
         assert(callback);
         assert(configured);
 
+        if (type == RTN_UNSPEC)
+                return 0; /* Disabled. */
+
         if (prefixlen >= 64) {
                 log_link_debug(link, "Not adding a blocking route for DHCP delegated prefix %s since the prefix has length >= 64.",
                                IN6_ADDR_PREFIX_TO_STRING(addr, prefixlen));
@@ -729,7 +735,7 @@ static int dhcp_request_unreachable_route(
         route->family = AF_INET6;
         route->dst.in6 = *addr;
         route->dst_prefixlen = prefixlen;
-        route->type = RTN_UNREACHABLE;
+        route->type = type;
         route->protocol = RTPROT_DHCP;
         route->priority = IP6_RT_PRIO_USER;
         route->lifetime_usec = lifetime_usec;
@@ -758,8 +764,12 @@ static int dhcp4_request_unreachable_route(
                 usec_t lifetime_usec,
                 const union in_addr_union *server_address) {
 
+        assert(link);
+        assert(link->network);
+
         return dhcp_request_unreachable_route(link, addr, prefixlen, lifetime_usec,
                                               NETWORK_CONFIG_SOURCE_DHCP4, server_address,
+                                              link->network->dhcp_6rd_prefix_route_type,
                                               &link->dhcp4_messages, dhcp4_unreachable_route_handler,
                                               &link->dhcp4_configured);
 }
@@ -771,8 +781,12 @@ static int dhcp6_request_unreachable_route(
                 usec_t lifetime_usec,
                 const union in_addr_union *server_address) {
 
+        assert(link);
+        assert(link->network);
+
         return dhcp_request_unreachable_route(link, addr, prefixlen, lifetime_usec,
                                               NETWORK_CONFIG_SOURCE_DHCP6, server_address,
+                                              link->network->dhcp6_pd_prefix_route_type,
                                               &link->dhcp6_messages, dhcp6_unreachable_route_handler,
                                               &link->dhcp6_configured);
 }
@@ -1297,3 +1311,51 @@ int config_parse_dhcp_pd_subnet_id(
 
         return 0;
 }
+
+int config_parse_dhcp_pd_prefix_route_type(
+                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) {
+
+        uint8_t *p = ASSERT_PTR(data);
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *p = RTN_UNREACHABLE; /* Defaults to unreachable. */
+                return 0;
+        }
+
+        if (streq(rvalue, "none")) {
+                *p = RTN_UNSPEC; /* Indicate that the route is disabled. */
+                return 0;
+        }
+
+        r = route_type_from_string(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse %s=, ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        if (!route_type_is_reject(r)) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "Invalid route type is specified to %s=, ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        *p = r;
+        return 0;
+}
index 4a8cca92b6dfccd745a3688bacaef7ce38b46f31..0d68a51d0f62a5e7cdca34ed23a00234c0401947 100644 (file)
@@ -23,3 +23,4 @@ void dhcp4_pd_prefix_lost(Link *uplink);
 int dhcp_pd_reconfigure_address(Address *address, Link *link);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_pd_subnet_id);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_pd_prefix_route_type);
index 23e25ffc1fb284c4c6b0e6d0a92d8e72aaef96ff..aa849fe5353d3a42f7667f1cf1c4cab97597ea1f 100644 (file)
@@ -269,6 +269,7 @@ DHCPv4.InitialCongestionWindow,              config_parse_tcp_window,
 DHCPv4.InitialAdvertisedReceiveWindow,       config_parse_tcp_window,                                  0,                             offsetof(Network, dhcp_advertised_receive_window)
 DHCPv4.FallbackLeaseLifetimeSec,             config_parse_dhcp_fallback_lease_lifetime,                0,                             0
 DHCPv4.Use6RD,                               config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_6rd)
+DHCPv4.UnassignedSubnetPolicy,               config_parse_dhcp_pd_prefix_route_type,                   0,                             offsetof(Network, dhcp_6rd_prefix_route_type)
 DHCPv4.IPv6OnlyMode,                         config_parse_tristate,                                    0,                             offsetof(Network, dhcp_ipv6_only_mode)
 DHCPv4.NetLabel,                             config_parse_string,                                      CONFIG_PARSE_STRING_SAFE,      offsetof(Network, dhcp_netlabel)
 DHCPv4.NFTSet,                               config_parse_nft_set,                                     NFT_SET_PARSE_NETWORK,         offsetof(Network, dhcp_nft_set_context)
@@ -288,6 +289,7 @@ DHCPv6.UserClass,                            config_parse_dhcp_user_or_vendor_cl
 DHCPv6.VendorClass,                          config_parse_dhcp_user_or_vendor_class,                   AF_INET6,                      offsetof(Network, dhcp6_vendor_class)
 DHCPv6.SendVendorOption,                     config_parse_dhcp_send_option,                            AF_INET6,                      offsetof(Network, dhcp6_client_send_vendor_options)
 DHCPv6.PrefixDelegationHint,                 config_parse_dhcp6_pd_prefix_hint,                        0,                             0
+DHCPv6.UnassignedSubnetPolicy,               config_parse_dhcp_pd_prefix_route_type,                   0,                             offsetof(Network, dhcp6_pd_prefix_route_type)
 DHCPv6.WithoutRA,                            config_parse_dhcp6_client_start_mode,                     0,                             offsetof(Network, dhcp6_client_start_mode)
 DHCPv6.SendOption,                           config_parse_dhcp_send_option,                            AF_INET6,                      offsetof(Network, dhcp6_client_send_options)
 DHCPv6.IAID,                                 config_parse_iaid,                                        AF_INET6,                      0
index 8232db06c934c3bec84c50cf45bdf37eb9f4cd56..4e4e5eb2a8d3ac122652fc5987b9dd11c19a0cc7 100644 (file)
@@ -402,6 +402,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .dhcp_ip_service_type = -1,
                 .dhcp_broadcast = -1,
                 .dhcp_ipv6_only_mode = -1,
+                .dhcp_6rd_prefix_route_type = RTN_UNREACHABLE,
 
                 .dhcp6_use_address = true,
                 .dhcp6_use_pd_prefix = true,
@@ -415,6 +416,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .dhcp6_duid.type = _DUID_TYPE_INVALID,
                 .dhcp6_client_start_mode = _DHCP6_CLIENT_START_MODE_INVALID,
                 .dhcp6_send_release = true,
+                .dhcp6_pd_prefix_route_type = RTN_UNREACHABLE,
 
                 .dhcp_pd = -1,
                 .dhcp_pd_announce = true,
index 92d367eccf8eab983484dc6028f5367196a6f36b..66a8328e2934cfaf8ccc9a41f25a22fe705ab79b 100644 (file)
@@ -167,6 +167,7 @@ struct Network {
         bool dhcp_use_timezone;
         bool dhcp_use_hostname;
         bool dhcp_use_6rd;
+        uint8_t dhcp_6rd_prefix_route_type;
         bool dhcp_send_release;
         bool dhcp_send_decline;
         UseDomains dhcp_use_domains;
@@ -195,6 +196,7 @@ struct Network {
         DUID dhcp6_duid;
         uint8_t dhcp6_pd_prefix_length;
         struct in6_addr dhcp6_pd_prefix_hint;
+        uint8_t dhcp6_pd_prefix_route_type;
         char *dhcp6_hostname;
         char *dhcp6_mudurl;
         char **dhcp6_user_class;