#include "networkd-util.h"
#include "parse-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
+static const char *const fr_act_type_table[__FR_ACT_MAX] = {
+ [FR_ACT_BLACKHOLE] = "blackhole",
+ [FR_ACT_UNREACHABLE] = "unreachable",
+ [FR_ACT_PROHIBIT] = "prohibit",
+};
+
+assert_cc(__FR_ACT_MAX <= UINT8_MAX);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type, int);
+
RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
if (!rule)
return NULL;
.uid_range.start = UID_INVALID,
.uid_range.end = UID_INVALID,
.suppress_prefixlen = -1,
+ .type = FR_ACT_TO_TBL,
};
*ret = rule;
dest->to_prefixlen = src->to_prefixlen;
dest->invert_rule = src->invert_rule;
dest->tos = src->tos;
+ dest->type = src->type;
dest->fwmark = src->fwmark;
dest->fwmask = src->fwmask;
dest->priority = src->priority;
siphash24_compress_boolean(rule->invert_rule, state);
siphash24_compress(&rule->tos, sizeof(rule->tos), state);
+ siphash24_compress(&rule->type, sizeof(rule->type), state);
siphash24_compress(&rule->fwmark, sizeof(rule->fwmark), state);
siphash24_compress(&rule->fwmask, sizeof(rule->fwmask), state);
siphash24_compress(&rule->priority, sizeof(rule->priority), state);
if (r != 0)
return r;
+ r = CMP(a->type, b->type);
+ if (r != 0)
+ return r;
+
r = CMP(a->fwmark, b->fwmark);
if (r != 0)
return r;
return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
}
+ if (rule->type != FR_ACT_TO_TBL) {
+ r = sd_rtnl_message_routing_policy_rule_set_fib_type(m, rule->type);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FIB rule type attribute: %m");
+ }
+
return 0;
}
r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos);
if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m");
+ log_warning_errno(r, "rtnl: could not get FIB rule TOS, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_routing_policy_rule_get_fib_type(message, &tmp->type);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FIB rule type, ignoring: %m");
return 0;
}
return 0;
}
+int config_parse_routing_policy_rule_type(
+ 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;
+ int r, t;
+
+ 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 log_oom();
+
+ t = fr_act_type_from_string(rvalue);
+ if (t < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ n->type = (uint8_t) t;
+ n = NULL;
+
+ return 0;
+}
+
static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
if (section_is_invalid(rule->section))
return -EINVAL;
space = true;
}
+ if (rule->type != 0) {
+ fprintf(f, "%stype=%hhu",
+ space ? " " : "",
+ rule->type);
+ space = true;
+ }
+
if (rule->priority != 0) {
fprintf(f, "%spriority=%"PRIu32,
space ? " " : "",
log_warning_errno(r, "Failed to parse RPDB rule TOS, ignoring: %s", b);
continue;
}
+ } else if (streq(a, "type")) {
+ r = safe_atou8(b, &rule->type);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to parse RPDB rule type, ignoring: %s", b);
+ continue;
+ }
} else if (streq(a, "table")) {
r = safe_atou32(b, &rule->table);
if (r < 0) {
test_setup_logging(LOG_DEBUG);
test_rule_serialization("basic parsing",
- "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);
+ "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 type=1 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=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 fwmark=1 invert_rule=no table=20");
+ " \t to=2.3.4.5/24 to=2.3.4.5/32 tos=5 type=1 fwmark=2 fwmark=1 table=10 table=20",
+ "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 type=1 fwmark=1 invert_rule=no table=20");
test_rule_serialization("ipv6",
- "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=yes table=6", NULL);
+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 invert_rule=yes table=6", NULL);
- 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);
+ assert_se(asprintf(&p, "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 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=family=AF_INET6 from=1::2/64 to=2::3/64 iif=lo invert_rule=no table=1");
+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 iif=lo invert_rule=no table=1");
test_rule_serialization("outgoing interface",
- "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 oif=eth0 invert_rule=no table=1", NULL);
+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 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=family=AF_INET6 from=1::2/64 to=2::3/64 iif=e1 oif=e1 invert_rule=no table=1");
+ "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 type=1 iif=e0 iif=e1 oif=e0 oif=e1 table=1",
+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 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");
+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 invert_rule=no table=1");
return 0;
}