aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.network.xml6
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c26
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-routing-policy-rule.c45
-rw-r--r--src/network/networkd-routing-policy-rule.h3
-rw-r--r--src/systemd/sd-netlink.h2
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network1
-rw-r--r--test/fuzz/fuzz-unit-file/directives.service1
8 files changed, 85 insertions, 0 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 229449c5a..ceb0788d7 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1015,6 +1015,12 @@
Defaults to unset.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>InvertRule=</varname></term>
+ <listitem>
+ <para>A boolean. Specifies wheather the rule to be inverted. Defaults to false.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index 4416e1720..2d4d00e0e 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -852,6 +852,32 @@ int sd_rtnl_message_routing_policy_rule_get_table(sd_netlink_message *m, unsigne
return 0;
}
+int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags) {
+ struct rtmsg *routing_policy_rule;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
+
+ routing_policy_rule = NLMSG_DATA(m->hdr);
+ routing_policy_rule->rtm_flags |= flags;
+
+ return 0;
+}
+
+int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags) {
+ struct rtmsg *routing_policy_rule;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
+
+ routing_policy_rule = NLMSG_DATA(m->hdr);
+ *flags = routing_policy_rule->rtm_flags;
+
+ return 0;
+}
+
int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type) {
struct rtmsg *routing_policy_rule;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index ed15d2217..61c2e55fe 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -104,6 +104,7 @@ RoutingPolicyRule.OutgoingInterface, config_parse_routing_policy_rule_device,
RoutingPolicyRule.IPProtocol, config_parse_routing_policy_rule_ip_protocol, 0, 0
RoutingPolicyRule.SourcePort, config_parse_routing_policy_rule_port_range, 0, 0
RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_port_range, 0, 0
+RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_invert, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c
index 96013e702..2dc78622c 100644
--- a/src/network/networkd-routing-policy-rule.c
+++ b/src/network/networkd-routing-policy-rule.c
@@ -588,6 +588,12 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
return log_error_errno(r, "Could not append FRA_DPORT_RANGE attribute: %m");
}
+ if (rule->invert_rule) {
+ r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT);
+ if (r < 0)
+ return log_error_errno(r, "Could not append FIB_RULE_INVERT attribute: %m");
+ }
+
rule->link = link;
r = netlink_call_async(link->manager->rtnl, NULL, m,
@@ -959,6 +965,45 @@ int config_parse_routing_policy_rule_ip_protocol(
return 0;
}
+int config_parse_routing_policy_rule_invert(
+ 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) {
+
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
+ Network *network = userdata;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = routing_policy_rule_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule invert, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ n->invert_rule = r;
+
+ n = NULL;
+
+ return 0;
+}
+
static int routing_policy_rule_read_full_file(const char *state_file, char **ret) {
_cleanup_free_ char *s = NULL;
size_t size;
diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h
index 0e4215bff..b35126e2c 100644
--- a/src/network/networkd-routing-policy-rule.h
+++ b/src/network/networkd-routing-policy-rule.h
@@ -25,6 +25,8 @@ struct RoutingPolicyRule {
Link *link;
NetworkConfigSection *section;
+ bool invert_rule;
+
uint8_t tos;
uint8_t protocol;
@@ -79,3 +81,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_ip_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert);
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index 20bff2838..30be5b113 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -179,6 +179,8 @@ int sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(sd_netlink_message
int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char *len);
int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type);
int sd_rtnl_message_routing_policy_rule_get_rtm_type(sd_netlink_message *m, unsigned char *type);
+int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags);
+int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags);
/* genl */
int sd_genl_socket_open(sd_netlink **nl);
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 8ea809a7e..d8f556a6e 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -153,6 +153,7 @@ FirewallMark=
SourcePort=
DestinationPort=
IPProtocol=
+InvertRule=
[IPv6PrefixDelegation]
RouterPreference=
DNSLifetimeSec=
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
index f454fd313..f5560ea2c 100644
--- a/test/fuzz/fuzz-unit-file/directives.service
+++ b/test/fuzz/fuzz-unit-file/directives.service
@@ -442,6 +442,7 @@ Independent=
InitialAdvertisedReceiveWindow=
InitialCongestionWindow=
InputKey=
+InvertRule=
KernelCommandLine=
KernelVersion=
Key=