]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: allow to configure routing policy rule even if requesting interface is not...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 4 Feb 2025 03:07:21 +0000 (12:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 4 Feb 2025 03:28:30 +0000 (12:28 +0900)
In the kernel, all routing policy rules are not assigned to any interface,
and we can configure them even if the relevant interface is down state.

Fixes a regression caused by 4f8b153d903fd4a6e8d7d3e49113582d70d1525a (v257).
Fixes #36244.

src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-routing-policy-rule.c

index 3f816d7fa25c451419dface2e004e6be86d0d047..67fc725f98092d453cc54af5601509b8581b66bc 100644 (file)
@@ -200,6 +200,17 @@ bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) {
         return check_ready_for_all_sr_iov_ports(link, allow_unmanaged, link_is_ready_to_configure_one);
 }
 
+bool link_is_ready_to_configure_by_name(Manager *manager, const char *name, bool allow_unmanaged) {
+        assert(manager);
+        assert(name);
+
+        Link *link;
+        if (link_get_by_name(manager, name, &link) < 0)
+                return false;
+
+        return link_is_ready_to_configure(link, allow_unmanaged);
+}
+
 void link_ntp_settings_clear(Link *link) {
         link->ntp = strv_free(link->ntp);
 }
index 113217cdb6ad8f5cfad00ed3a701c71d162a9953..c5806cea33217fc4094f102cbb599c124866583f 100644 (file)
@@ -225,6 +225,7 @@ typedef struct Link {
 typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*);
 
 bool link_is_ready_to_configure(Link *link, bool allow_unmanaged);
+bool link_is_ready_to_configure_by_name(Manager *manager, const char *name, bool allow_unmanaged);
 
 void link_ntp_settings_clear(Link *link);
 void link_dns_settings_clear(Link *link);
index 87dcaa4fc44b7896a9f67868c1718ef7d0ce9376..3b8d217757b71b6dcc9b8ec701aa962616b05d22 100644 (file)
@@ -872,6 +872,31 @@ int link_drop_routing_policy_rules(Link *link, bool only_static) {
         return r;
 }
 
+static int routing_policy_rule_is_ready_to_configure(const RoutingPolicyRule *rule, Link *link) {
+        assert(rule);
+        assert(link);
+        assert(link->manager);
+
+        /* For routing policy rules, it is not necessary to check operstate and friends of the interface.
+         * Hence, here we refuse to configure rules only when the interface is already removed, or in the
+         * failed state. */
+        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+                return false;
+
+        /* Strictly speaking checking existence of IIF and OIF below is not necessary. But, configuring
+         * routing policy rule with non-existent IIF or OIF is mostly meaningless, and 'ip rule' command
+         * shows [detached] for such rules, that may confuse users. Let's postpone to configure if one of
+         * IIF/OIF does not exist. */
+
+        if (rule->iif && !link_is_ready_to_configure_by_name(link->manager, rule->iif, /* allow_unmanaged = */ true))
+                return false;
+
+        if (rule->oif && !link_is_ready_to_configure_by_name(link->manager, rule->oif, /* allow_unmanaged = */ true))
+                return false;
+
+        return true;
+}
+
 static int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) {
         RoutingPolicyRule *existing;
         int r;
@@ -881,7 +906,7 @@ static int routing_policy_rule_process_request(Request *req, Link *link, Routing
         assert(link->manager);
         assert(rule);
 
-        if (!link_is_ready_to_configure(link, false))
+        if (!routing_policy_rule_is_ready_to_configure(rule, link))
                 return 0;
 
         r = routing_policy_rule_configure(rule, link, req);