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;
}
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 ? " " : "",
}
*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;
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) {
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;
}