mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-02 09:47:03 +03:00
network: Allow to configure unreachable/blackhole RoutingPolicyRule (#17984)
This commit is contained in:
parent
5cd35a171c
commit
d7d1d18fd2
@ -1261,6 +1261,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Type=</varname></term>
|
||||
<listitem>
|
||||
<para>Specifies Routing Policy Database (RPDB) rule type. Takes one of <literal>blackhole</literal>,
|
||||
<literal>unreachable</literal> or <literal>prohibit</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -161,6 +161,7 @@ RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_in
|
||||
RoutingPolicyRule.Family, config_parse_routing_policy_rule_family, 0, 0
|
||||
RoutingPolicyRule.User, config_parse_routing_policy_rule_uid_range, 0, 0
|
||||
RoutingPolicyRule.SuppressPrefixLength, config_parse_routing_policy_rule_suppress_prefixlen, 0, 0
|
||||
RoutingPolicyRule.Type, config_parse_routing_policy_rule_type, 0, 0
|
||||
Route.Gateway, config_parse_gateway, 0, 0
|
||||
Route.Destination, config_parse_destination, 0, 0
|
||||
Route.Source, config_parse_destination, 0, 0
|
||||
|
@ -15,10 +15,20 @@
|
||||
#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;
|
||||
@ -56,6 +66,7 @@ static int routing_policy_rule_new(RoutingPolicyRule **ret) {
|
||||
.uid_range.start = UID_INVALID,
|
||||
.uid_range.end = UID_INVALID,
|
||||
.suppress_prefixlen = -1,
|
||||
.type = FR_ACT_TO_TBL,
|
||||
};
|
||||
|
||||
*ret = rule;
|
||||
@ -126,6 +137,7 @@ static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *
|
||||
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;
|
||||
@ -158,6 +170,7 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct
|
||||
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);
|
||||
@ -213,6 +226,10 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro
|
||||
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;
|
||||
@ -475,6 +492,12 @@ static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_n
|
||||
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;
|
||||
}
|
||||
|
||||
@ -801,7 +824,13 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1415,6 +1444,45 @@ int config_parse_routing_policy_rule_suppress_prefixlen(
|
||||
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;
|
||||
@ -1494,6 +1562,13 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (rule->type != 0) {
|
||||
fprintf(f, "%stype=%hhu",
|
||||
space ? " " : "",
|
||||
rule->type);
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (rule->priority != 0) {
|
||||
fprintf(f, "%spriority=%"PRIu32,
|
||||
space ? " " : "",
|
||||
@ -1670,6 +1745,12 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
|
||||
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) {
|
||||
|
@ -23,7 +23,10 @@ typedef struct RoutingPolicyRule {
|
||||
bool invert_rule;
|
||||
|
||||
uint8_t tos;
|
||||
uint8_t type;
|
||||
uint8_t protocol;
|
||||
uint8_t to_prefixlen;
|
||||
uint8_t from_prefixlen;
|
||||
|
||||
uint32_t table;
|
||||
uint32_t fwmark;
|
||||
@ -32,8 +35,6 @@ typedef struct RoutingPolicyRule {
|
||||
|
||||
AddressFamily address_family; /* Specified by Family= */
|
||||
int family; /* Automatically determined by From= or To= */
|
||||
unsigned char to_prefixlen;
|
||||
unsigned char from_prefixlen;
|
||||
|
||||
char *iif;
|
||||
char *oif;
|
||||
@ -71,3 +72,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_family);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_uid_range);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_suppress_prefixlen);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_type);
|
||||
|
@ -57,34 +57,34 @@ int main(int argc, char **argv) {
|
||||
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;
|
||||
}
|
||||
|
@ -275,6 +275,7 @@ InvertRule=
|
||||
Family=
|
||||
SuppressPrefixLength=
|
||||
User=
|
||||
Type=
|
||||
[IPv6SendRA]
|
||||
RouterPreference=
|
||||
DNSLifetimeSec=
|
||||
|
Loading…
x
Reference in New Issue
Block a user