Skip to content

Commit

Permalink
network: Allow to configure unreachable/blackhole RoutingPolicyRule
Browse files Browse the repository at this point in the history
  • Loading branch information
ssahani committed Dec 16, 2020
1 parent 2210191 commit ed52b54
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 2 deletions.
8 changes: 8 additions & 0 deletions man/systemd.network.xml
Expand Up @@ -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>. When unset, the kernel's default will be used.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

Expand Down
1 change: 1 addition & 0 deletions src/network/networkd-network-gperf.gperf
Expand Up @@ -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
Expand Down
80 changes: 80 additions & 0 deletions src/network/networkd-routing-policy-rule.c
Expand Up @@ -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 <= UCHAR_MAX);
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type, int);

RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
if (!rule)
return NULL;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -475,6 +492,10 @@ 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");
}

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;
}

Expand Down Expand Up @@ -805,6 +826,12 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
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 ip rule type, ignoring: %m");
return 0;
}

r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
Expand Down Expand Up @@ -1415,6 +1442,46 @@ 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 RPDB rule FRA type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}

n->type = (unsigned char) t;

n = NULL;

return 0;
}

static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
if (section_is_invalid(rule->section))
return -EINVAL;
Expand Down Expand Up @@ -1494,6 +1561,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 ? " " : "",
Expand Down Expand Up @@ -1670,6 +1744,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) {
Expand Down
6 changes: 4 additions & 2 deletions src/network/networkd-routing-policy-rule.h
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
1 change: 1 addition & 0 deletions test/fuzz/fuzz-network-parser/directives.network
Expand Up @@ -275,6 +275,7 @@ InvertRule=
Family=
SuppressPrefixLength=
User=
Type=
[IPv6SendRA]
RouterPreference=
DNSLifetimeSec=
Expand Down

0 comments on commit ed52b54

Please sign in to comment.