]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: add RoutingPolicyRule.Family= setting
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 31 Jul 2019 22:41:36 +0000 (07:41 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 16 Aug 2019 13:02:17 +0000 (22:02 +0900)
Closes #13233.

man/systemd.network.xml
src/network/networkd-network-gperf.gperf
src/network/networkd-routing-policy-rule.c
src/network/networkd-routing-policy-rule.h
src/network/networkd-util.c
src/network/networkd-util.h
test/fuzz/fuzz-network-parser/directives.network

index accc824e4d77428cd18f8fb37f429f48a4d67615..95c56b0ae3cabaceef1925fd2904fca34e23e52c 100644 (file)
             <para>A boolean. Specifies whether the rule to be inverted. Defaults to false.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>Family=</varname></term>
+          <listitem>
+            <para>Takes a special value <literal>ipv4</literal>, <literal>ipv6</literal>, or
+            <literal>both</literal>. By default, the address family is determined by the address
+            specified in <varname>To=</varname> or <varname>From=</varname>. If neither
+            <varname>To=</varname> nor <varname>From=</varname> are specified, then defaults to
+            <literal>ipv4</literal>.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
   </refsect1>
 
index 8c7e5db4bbfd514adc722cdfd1212ce8872eae58..d4d108ad25dbeaecc0855ef9d3d00f5271c5d9f0 100644 (file)
@@ -122,6 +122,7 @@ RoutingPolicyRule.IPProtocol,           config_parse_routing_policy_rule_ip_prot
 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
+RoutingPolicyRule.Family,               config_parse_routing_policy_rule_family,         0,                             0
 Route.Gateway,                          config_parse_gateway,                            0,                             0
 Route.Destination,                      config_parse_destination,                        0,                             0
 Route.Source,                           config_parse_destination,                        0,                             0
index 1494727ead9b5c4784cfbb1e03f9438c5efce82d..5edc2444a70fd4345f33fefbcfc640532e0c2d12 100644 (file)
@@ -11,6 +11,7 @@
 #include "networkd-routing-policy-rule.h"
 #include "netlink-util.h"
 #include "networkd-manager.h"
+#include "networkd-util.h"
 #include "parse-util.h"
 #include "socket-util.h"
 #include "string-util.h"
@@ -569,11 +570,45 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
 }
 
 int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
+        int r;
+
         if (section_is_invalid(rule->section))
                 return -EINVAL;
 
-        if (rule->family == AF_UNSPEC)
+        if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) ||
+            (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                "%s: address family specified by Family= conflicts with the address "
+                                "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
+                                rule->section->filename, rule->section->line);
+
+        if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) {
+                _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL;
+
+                assert(rule->family == AF_UNSPEC);
+
+                /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */
+
+                r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6);
+                if (r < 0)
+                        return r;
+
+                r = routing_policy_rule_copy(rule6, rule);
+                if (r < 0)
+                        return r;
+
                 rule->family = AF_INET;
+                rule6->family = AF_INET6;
+
+                TAKE_PTR(rule6);
+        }
+
+        if (rule->family == AF_UNSPEC) {
+                if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6))
+                        rule->family = AF_INET6;
+                else
+                        rule->family = AF_INET;
+        }
 
         return 0;
 }
@@ -973,6 +1008,46 @@ int config_parse_routing_policy_rule_invert(
         return 0;
 }
 
+int config_parse_routing_policy_rule_family(
+                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_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
+        Network *network = userdata;
+        AddressFamily a;
+        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;
+
+        a = routing_policy_rule_address_family_from_string(rvalue);
+        if (a < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "Invalid address family '%s', ignoring.", rvalue);
+                return 0;
+        }
+
+        n->address_family = a;
+        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;
index 8ddb85307c4058082b26c3c3698abdc216ca4aa8..6b8e3102275e48611f154224a66a872cf977e2c8 100644 (file)
@@ -36,7 +36,8 @@ struct RoutingPolicyRule {
         uint32_t fwmask;
         uint32_t priority;
 
-        int family;
+        AddressFamily address_family; /* Specified by Family= */
+        int family; /* Automatically determined by From= or To= */
         unsigned char to_prefixlen;
         unsigned char from_prefixlen;
 
@@ -77,3 +78,4 @@ 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);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_family);
index 2f56b4c7f11d93a23ffefc9a49cc486ec205b5a9..3fd26836c6ac9841ef3078410a995a78620d8976 100644 (file)
@@ -24,8 +24,15 @@ static const char * const link_local_address_family_table[_ADDRESS_FAMILY_MAX] =
         [ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback",
 };
 
+static const char * const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = {
+        [ADDRESS_FAMILY_YES]           = "both",
+        [ADDRESS_FAMILY_IPV4]          = "ipv4",
+        [ADDRESS_FAMILY_IPV6]          = "ipv6",
+};
+
 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family, AddressFamily, ADDRESS_FAMILY_YES);
+DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
                          AddressFamily, "Failed to parse option");
 
index c96c2fd9fa2208015b377835911f2bb4e1189c84..3a57819f398bb86d6f2f68485a389700cba445ed 100644 (file)
@@ -32,6 +32,9 @@ AddressFamily address_family_from_string(const char *s) _pure_;
 const char *link_local_address_family_to_string(AddressFamily b) _const_;
 AddressFamily link_local_address_family_from_string(const char *s) _pure_;
 
+const char *routing_policy_rule_address_family_to_string(AddressFamily b) _const_;
+AddressFamily routing_policy_rule_address_family_from_string(const char *s) _pure_;
+
 int kernel_route_expiration_supported(void);
 
 int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
index 7be38b0f34bb1925e6b12ac642385040e23a8d2e..848d4bd187c9a8e1d0da9f3a32e45ce77414de9d 100644 (file)
@@ -208,6 +208,7 @@ SourcePort=
 DestinationPort=
 IPProtocol=
 InvertRule=
+Family=
 [IPv6PrefixDelegation]
 RouterPreference=
 DNSLifetimeSec=