]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: honor already specified family when parsing from= or to= in serialized rule
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 28 Aug 2020 03:58:49 +0000 (12:58 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 3 Sep 2020 23:48:08 +0000 (08:48 +0900)
src/network/networkd-routing-policy-rule.c
src/network/test-routing-policy-rule.c

index e7e89db97e983ff98ecb30417417eb4f1878f84f..d72246c20f237e19af42988c941133bea50ab048 100644 (file)
@@ -1175,17 +1175,25 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
 
         SET_FOREACH(rule, rules, i) {
                 _cleanup_free_ char *from_str = NULL, *to_str = NULL;
-                bool space = false;
                 const char *family_str;
+                bool space = false;
 
                 fputs("RULE=", f);
 
+                family_str = af_to_name(rule->family);
+                if (family_str) {
+                        fprintf(f, "family=%s",
+                                family_str);
+                        space = true;
+                }
+
                 if (!in_addr_is_null(rule->family, &rule->from)) {
                         r = in_addr_to_string(rule->family, &rule->from, &from_str);
                         if (r < 0)
                                 return r;
 
-                        fprintf(f, "from=%s/%hhu",
+                        fprintf(f, "%sfrom=%s/%hhu",
+                                space ? " " : "",
                                 from_str, rule->from_prefixlen);
                         space = true;
                 }
@@ -1201,14 +1209,6 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
                         space = true;
                 }
 
-                family_str = af_to_name(rule->family);
-                if (family_str) {
-                        fprintf(f, "%sfamily=%s",
-                                space ? " " : "",
-                                family_str);
-                        space = true;
-                }
-
                 if (rule->tos != 0) {
                         fprintf(f, "%stos=%hhu",
                                 space ? " " : "",
@@ -1356,7 +1356,18 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
                         }
                         *b++ = '\0';
 
-                        if (STR_IN_SET(a, "from", "to")) {
+                        if (streq(a, "family")) {
+                                r = af_from_name(b);
+                                if (r < 0) {
+                                        log_warning_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b);
+                                        continue;
+                                }
+                                if (rule->family != AF_UNSPEC && rule->family != r) {
+                                        log_warning("RPDB rule family is already specified, ignoring assignment: %s", b);
+                                        continue;
+                                }
+                                rule->family = r;
+                        } if (STR_IN_SET(a, "from", "to")) {
                                 union in_addr_union *buffer;
                                 uint8_t *prefixlen;
 
@@ -1368,19 +1379,14 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
                                         prefixlen = &rule->from_prefixlen;
                                 }
 
-                                r = in_addr_prefix_from_string_auto(b, &rule->family, buffer, prefixlen);
+                                if (rule->family == AF_UNSPEC)
+                                        r = in_addr_prefix_from_string_auto(b, &rule->family, buffer, prefixlen);
+                                else
+                                        r = in_addr_prefix_from_string(b, rule->family, buffer, prefixlen);
                                 if (r < 0) {
                                         log_warning_errno(r, "RPDB rule prefix is invalid, ignoring assignment: %s", b);
                                         continue;
                                 }
-
-                        } else if (streq(a, "family")) {
-                                r = af_from_name(b);
-                                if (r < 0) {
-                                        log_warning_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b);
-                                        continue;
-                                }
-                                rule->family = r;
                         } else if (streq(a, "tos")) {
                                 r = safe_atou8(b, &rule->tos);
                                 if (r < 0) {
index 0a0434aaabafdb5c541f43e938485304424a08da..85924bc0c9ede108ace6c2f751d0312597fd5957 100644 (file)
@@ -62,30 +62,34 @@ int main(int argc, char **argv) {
         test_setup_logging(LOG_DEBUG);
 
         test_rule_serialization("basic parsing",
-                                "RULE=from=1.2.3.4/32 to=2.3.4.5/32 family=AF_INET tos=5 priority=10 fwmark=1/2 invert_rule=yes table=10", NULL);
+                                "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 priority=10 fwmark=1/2 invert_rule=yes table=10", NULL);
 
         test_rule_serialization("ignored values",
                                 "RULE=something=to=ignore from=1.2.3.4/32 from=1.2.3.4/32"
                                 "   \t  to=2.3.4.5/24 to=2.3.4.5/32 tos=5 fwmark=2 fwmark=1 table=10 table=20",
-                                "RULE=from=1.2.3.4/32 to=2.3.4.5/32 family=AF_INET tos=5 fwmark=1/0 invert_rule=no table=20");
+                                "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 fwmark=1/0 invert_rule=no table=20");
 
         test_rule_serialization("ipv6",
-                                "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 invert_rule=yes table=6", NULL);
+                                "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=yes table=6", NULL);
 
-        assert_se(asprintf(&p, "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 invert_rule=no table=%d", RT_TABLE_MAIN) >= 0);
+        assert_se(asprintf(&p, "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=no table=%d", RT_TABLE_MAIN) >= 0);
         test_rule_serialization("default table",
                                 "RULE=from=1::2/64 to=2::3/64", p);
 
         test_rule_serialization("incoming interface",
                                 "RULE=from=1::2/64 to=2::3/64 table=1 iif=lo",
-                                "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 iif=lo invert_rule=no table=1");
+                                "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 iif=lo invert_rule=no table=1");
 
         test_rule_serialization("outgoing interface",
-                                "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 oif=eth0 invert_rule=no table=1", NULL);
+                                "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 oif=eth0 invert_rule=no table=1", NULL);
 
         test_rule_serialization("freeing interface names",
                                 "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 iif=e0 iif=e1 oif=e0 oif=e1 table=1",
-                                "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 iif=e1 oif=e1 invert_rule=no table=1");
+                                "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 iif=e1 oif=e1 invert_rule=no table=1");
+
+        test_rule_serialization("ignoring invalid family",
+                                "RULE=from=1::2/64 to=2::3/64 family=AF_UNSEPC family=AF_INET table=1",
+                                "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=no table=1");
 
         return 0;
 }