Compare commits

...

6 Commits

Author SHA1 Message Date
Yu Watanabe 2be7c6ab3b
Merge pull request #17477 from yuwata/network-drop-serialization-routing-policy-rule
network: do not serialize/deserialize routing policy rules
2020-12-30 00:18:24 +09:00
Yu Watanabe a9d240f4bf network: do not serialize/deserialize routing policy rules
We already handle foreign routing policy rules correctly by the previous
commit. So, the serialization/deserialization of rules are not necessary
anymore.
2020-12-29 16:13:54 +09:00
Yu Watanabe 0b81225e57 network: drop unnecessary routing policy rules
networkd already drop foreign address, routes, and nexthops on startup,
except those created by kernel. However, previously, routing policy
rules were not. The logic of serialization/deserialization of rules only
works for rules created by previous invocation of networkd, and does not
work for one created by other tools like `ip rule`.

This makes networkd drop foreign routing policy rules except created by
kernel on startup. Also, remove rules created by networkd when the
corresponding links are dropped or networkd is stopping.
2020-12-29 16:13:54 +09:00
Yu Watanabe e737dce544 network: treat rule which has l3mdev flag as created by kernel 2020-12-29 16:13:39 +09:00
Yu Watanabe 569eeb0c05 network: adjust protocol of rules sent from kernel when kernel does not support FRA_PROTOCOL
Otherwise, each configured rule is treated as foreign.
2020-12-29 16:03:26 +09:00
Yu Watanabe 1e5fd3216a network: set FRA_PROTOCOL to RTPROT_STATIC by default 2020-12-29 16:03:26 +09:00
8 changed files with 129 additions and 490 deletions

View File

@ -273,11 +273,6 @@ if conf.get('ENABLE_NETWORKD') == 1
[threads],
'', '', [], network_include_dir],
[['src/network/test-routing-policy-rule.c'],
[libnetworkd_core,
libsystemd_network],
[], '', '', [], network_include_dir],
[['src/network/test-network-tables.c',
test_tables_h],
[libnetworkd_core,

View File

@ -1973,37 +1973,51 @@ static int link_enter_join_netdev(Link *link) {
}
static int link_drop_foreign_config(Link *link) {
int r;
int k, r;
assert(link);
assert(link->manager);
r = link_drop_foreign_addresses(link);
if (r < 0)
return r;
r = link_drop_foreign_neighbors(link);
if (r < 0)
return r;
k = link_drop_foreign_neighbors(link);
if (k < 0 && r >= 0)
r = k;
return link_drop_foreign_routes(link);
k = link_drop_foreign_routes(link);
if (k < 0 && r >= 0)
r = k;
k = manager_drop_foreign_routing_policy_rules(link->manager);
if (k < 0 && r >= 0)
r = k;
return r;
}
static int link_drop_config(Link *link) {
int r;
int k, r;
assert(link);
assert(link->manager);
r = link_drop_addresses(link);
if (r < 0)
return r;
r = link_drop_neighbors(link);
if (r < 0)
return r;
k = link_drop_neighbors(link);
if (k < 0 && r >= 0)
r = k;
r = link_drop_routes(link);
if (r < 0)
return r;
k = link_drop_routes(link);
if (k < 0 && r >= 0)
r = k;
k = manager_drop_routing_policy_rules(link->manager, link);
if (k < 0 && r >= 0)
r = k;
ndisc_flush(link);
return 0;
return r;
}
int link_configure(Link *link) {

View File

@ -707,10 +707,6 @@ static int manager_save(Manager *m) {
ordered_set_print(f, "DOMAINS=", search_domains);
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
r = routing_policy_serialize_rules(m->rules, f);
if (r < 0)
goto fail;
r = fflush_and_check(f);
if (r < 0)
goto fail;
@ -851,8 +847,6 @@ int manager_new(Manager **ret) {
m->duid.type = DUID_TYPE_EN;
(void) routing_policy_load_rules(m->state_file, &m->rules_saved);
*ret = TAKE_PTR(m);
return 0;
@ -887,7 +881,6 @@ void manager_free(Manager *m) {
* So, it is necessary to set NULL after the sets are freed. */
m->rules = set_free(m->rules);
m->rules_foreign = set_free(m->rules_foreign);
set_free(m->rules_saved);
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);

View File

@ -60,7 +60,6 @@ struct Manager {
Set *rules;
Set *rules_foreign;
Set *rules_saved;
/* Manager stores routes without RTA_OIF attribute. */
Set *routes;

View File

@ -66,6 +66,7 @@ static int routing_policy_rule_new(RoutingPolicyRule **ret) {
.uid_range.start = UID_INVALID,
.uid_range.end = UID_INVALID,
.suppress_prefixlen = -1,
.protocol = RTPROT_UNSPEC,
.type = FR_ACT_TO_TBL,
};
@ -99,6 +100,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
rule->network = network;
rule->section = TAKE_PTR(n);
rule->protocol = RTPROT_STATIC;
r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops);
if (r < 0)
@ -144,6 +146,7 @@ static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *
dest->table = src->table;
dest->iif = TAKE_PTR(iif);
dest->oif = TAKE_PTR(oif);
dest->ipproto = src->ipproto;
dest->protocol = src->protocol;
dest->sport = src->sport;
dest->dport = src->dport;
@ -177,6 +180,7 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct
siphash24_compress(&rule->table, sizeof(rule->table), state);
siphash24_compress(&rule->suppress_prefixlen, sizeof(rule->suppress_prefixlen), state);
siphash24_compress(&rule->ipproto, sizeof(rule->ipproto), state);
siphash24_compress(&rule->protocol, sizeof(rule->protocol), state);
siphash24_compress(&rule->sport, sizeof(rule->sport), state);
siphash24_compress(&rule->dport, sizeof(rule->dport), state);
@ -250,6 +254,10 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro
if (r != 0)
return r;
r = CMP(a->ipproto, b->ipproto);
if (r != 0)
return r;
r = CMP(a->protocol, b->protocol);
if (r != 0)
return r;
@ -458,10 +466,14 @@ static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_n
return log_link_error_errno(link, r, "Could not append FRA_OIFNAME attribute: %m");
}
r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->protocol);
r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->ipproto);
if (r < 0)
return log_link_error_errno(link, r, "Could not append FRA_IP_PROTO attribute: %m");
r = sd_netlink_message_append_u8(m, FRA_PROTOCOL, rule->protocol);
if (r < 0)
return log_link_error_errno(link, r, "Could not append FRA_PROTOCOL attribute: %m");
if (rule->sport.start != 0 || rule->sport.end != 0) {
r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport));
if (r < 0)
@ -628,7 +640,7 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) {
return 0;
}
static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) {
static bool links_have_routing_policy_rule(const Manager *m, const RoutingPolicyRule *rule, const Link *except) {
Link *link;
assert(m);
@ -637,6 +649,9 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule
HASHMAP_FOREACH(link, m->links) {
RoutingPolicyRule *link_rule;
if (link == except)
continue;
if (!link->network)
continue;
@ -648,34 +663,29 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule
return false;
}
static void routing_policy_rule_purge(Manager *m) {
int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except) {
RoutingPolicyRule *rule;
int r;
int k, r = 0;
Set *rules;
assert(m);
SET_FOREACH(rule, m->rules_saved) {
RoutingPolicyRule *existing;
existing = set_get(m->rules_foreign, rule);
if (!existing)
continue; /* Saved rule does not exist anymore. */
if (manager_links_have_routing_policy_rule(m, existing))
continue; /* Existing links have the saved rule. */
/* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
* later when it is requested. */
r = routing_policy_rule_remove(existing, m);
if (r < 0) {
log_warning_errno(r, "Could not remove routing policy rules: %m");
rules = foreign ? m->rules_foreign : m->rules;
SET_FOREACH(rule, rules) {
/* Do not touch rules managed by kernel. */
if (rule->protocol == RTPROT_KERNEL)
continue;
}
assert_se(set_remove(m->rules_foreign, existing) == existing);
routing_policy_rule_free(existing);
/* The rule will be configured later, or already configured by a link. */
if (links_have_routing_policy_rule(m, rule, except))
continue;
k = routing_policy_rule_remove(rule, m);
if (k < 0 && r >= 0)
r = k;
}
return r;
}
int link_set_routing_policy_rules(Link *link) {
@ -712,7 +722,6 @@ int link_set_routing_policy_rules(Link *link) {
return log_link_warning_errno(link, r, "Could not set routing policy rule: %m");
}
routing_policy_rule_purge(link->manager);
if (link->routing_policy_rule_messages == 0)
link->routing_policy_rules_configured = true;
else {
@ -723,10 +732,34 @@ int link_set_routing_policy_rules(Link *link) {
return 0;
}
static const RoutingPolicyRule kernel_rules[] = {
{ .family = AF_INET, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
{ .family = AF_INET, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
{ .family = AF_INET, .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
{ .family = AF_INET6, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
{ .family = AF_INET6, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
};
static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) {
assert(rule);
if (rule->l3mdev > 0)
/* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
* is set, it is safe to treat the rule as created by kernel. */
return true;
for (size_t i = 0; i < ELEMENTSOF(kernel_rules); i++)
if (routing_policy_rule_equal(rule, &kernel_rules[i]))
return true;
return false;
}
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
RoutingPolicyRule *rule = NULL;
const char *iif = NULL, *oif = NULL;
bool adjust_protocol = false;
uint32_t suppress_prefixlen;
unsigned flags;
uint16_t type;
@ -852,12 +885,29 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
if (r < 0)
return log_oom();
r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol);
r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->ipproto);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
return 0;
}
r = sd_netlink_message_read_u8(message, FRA_PROTOCOL, &tmp->protocol);
if (r == -ENODATA)
/* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
* When the received message does not have FRA_PROTOCOL, then we need to adjust the
* protocol of the rule later. */
adjust_protocol = true;
else if (r < 0) {
log_warning_errno(r, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
return 0;
}
r = sd_netlink_message_read_u8(message, FRA_L3MDEV, &tmp->l3mdev);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
return 0;
}
r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
@ -884,6 +934,11 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
if (r >= 0)
tmp->suppress_prefixlen = (int) suppress_prefixlen;
if (adjust_protocol)
/* As .network files does not have setting to specify protocol, we can assume the
* protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
tmp->protocol = routing_policy_rule_is_created_by_kernel(tmp) ? RTPROT_KERNEL : RTPROT_STATIC;
(void) routing_policy_rule_get(m, tmp, &rule);
switch (type) {
@ -1271,7 +1326,7 @@ int config_parse_routing_policy_rule_ip_protocol(
return 0;
}
n->protocol = r;
n->ipproto = r;
n = NULL;
@ -1497,6 +1552,12 @@ static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
if (rule->family == AF_UNSPEC && rule->address_family == ADDRESS_FAMILY_NO)
rule->family = AF_INET;
/* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
* update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
* added in the future. */
if (rule->l3mdev > 0)
assert_not_reached("FRA_L3MDEV flag should not be configured.");
return 0;
}
@ -1509,342 +1570,3 @@ void network_drop_invalid_routing_policy_rules(Network *network) {
if (routing_policy_rule_section_verify(rule) < 0)
routing_policy_rule_free(rule);
}
int routing_policy_serialize_rules(Set *rules, FILE *f) {
RoutingPolicyRule *rule;
int r;
assert(f);
SET_FOREACH(rule, rules) {
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)) {
_cleanup_free_ char *str = NULL;
r = in_addr_to_string(rule->family, &rule->from, &str);
if (r < 0)
return r;
fprintf(f, "%sfrom=%s/%hhu",
space ? " " : "",
str, rule->from_prefixlen);
space = true;
}
if (!in_addr_is_null(rule->family, &rule->to)) {
_cleanup_free_ char *str = NULL;
r = in_addr_to_string(rule->family, &rule->to, &str);
if (r < 0)
return r;
fprintf(f, "%sto=%s/%hhu",
space ? " " : "",
str, rule->to_prefixlen);
space = true;
}
if (rule->tos != 0) {
fprintf(f, "%stos=%hhu",
space ? " " : "",
rule->tos);
space = true;
}
if (rule->type != 0) {
fprintf(f, "%stype=%hhu",
space ? " " : "",
rule->type);
space = true;
}
if (rule->priority != 0) {
fprintf(f, "%spriority=%"PRIu32,
space ? " " : "",
rule->priority);
space = true;
}
if (rule->fwmark != 0) {
fprintf(f, "%sfwmark=%"PRIu32,
space ? " " : "",
rule->fwmark);
if (rule->fwmask != UINT32_MAX)
fprintf(f, "/%"PRIu32, rule->fwmask);
space = true;
}
if (rule->iif) {
fprintf(f, "%siif=%s",
space ? " " : "",
rule->iif);
space = true;
}
if (rule->oif) {
fprintf(f, "%soif=%s",
space ? " " : "",
rule->oif);
space = true;
}
if (rule->protocol != 0) {
fprintf(f, "%sprotocol=%hhu",
space ? " " : "",
rule->protocol);
space = true;
}
if (rule->sport.start != 0 || rule->sport.end != 0) {
fprintf(f, "%ssourcesport=%"PRIu16"-%"PRIu16,
space ? " " : "",
rule->sport.start, rule->sport.end);
space = true;
}
if (rule->dport.start != 0 || rule->dport.end != 0) {
fprintf(f, "%sdestinationport=%"PRIu16"-%"PRIu16,
space ? " " : "",
rule->dport.start, rule->dport.end);
space = true;
}
if (rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID) {
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
fprintf(f, "%suidrange="UID_FMT"-"UID_FMT,
space ? " " : "",
rule->uid_range.start, rule->uid_range.end);
space = true;
}
if (rule->suppress_prefixlen >= 0) {
fprintf(f, "%ssuppress_prefixlen=%d",
space ? " " : "",
rule->suppress_prefixlen);
space = true;
}
fprintf(f, "%sinvert_rule=%s table=%"PRIu32"\n",
space ? " " : "",
yes_no(rule->invert_rule),
rule->table);
}
return 0;
}
static int routing_policy_rule_read_full_file(const char *state_file, char ***ret) {
_cleanup_strv_free_ char **lines = NULL;
_cleanup_free_ char *s = NULL;
int r;
assert(state_file);
r = read_full_file(state_file, &s, NULL);
if (r == -ENOENT) {
*ret = NULL;
return 0;
}
if (r < 0)
return r;
lines = strv_split_newlines(s);
if (!lines)
return -ENOMEM;
*ret = TAKE_PTR(lines);
return 0;
}
int routing_policy_load_rules(const char *state_file, Set **rules) {
_cleanup_strv_free_ char **data = NULL;
char **i;
int r;
assert(state_file);
assert(rules);
r = routing_policy_rule_read_full_file(state_file, &data);
if (r < 0)
return log_warning_errno(r, "Failed to read %s, ignoring: %m", state_file);
STRV_FOREACH(i, data) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
const char *p;
p = startswith(*i, "RULE=");
if (!p)
continue;
r = routing_policy_rule_new(&rule);
if (r < 0)
return log_oom();
for (;;) {
_cleanup_free_ char *a = NULL;
char *b;
r = extract_first_word(&p, &a, NULL, 0);
if (r < 0)
return log_oom();
if (r == 0)
break;
b = strchr(a, '=');
if (!b) {
log_warning_errno(r, "Failed to parse RPDB rule, ignoring: %s", a);
continue;
}
*b++ = '\0';
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;
} else if (STR_IN_SET(a, "from", "to")) {
union in_addr_union *buffer;
uint8_t *prefixlen;
if (streq(a, "to")) {
buffer = &rule->to;
prefixlen = &rule->to_prefixlen;
} else {
buffer = &rule->from;
prefixlen = &rule->from_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, "tos")) {
r = safe_atou8(b, &rule->tos);
if (r < 0) {
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) {
log_warning_errno(r, "Failed to parse RPDB rule table, ignoring: %s", b);
continue;
}
} else if (streq(a, "priority")) {
r = safe_atou32(b, &rule->priority);
if (r < 0) {
log_warning_errno(r, "Failed to parse RPDB rule priority, ignoring: %s", b);
continue;
}
} else if (streq(a, "fwmark")) {
r = parse_fwmark_fwmask(b, &rule->fwmark, &rule->fwmask);
if (r < 0) {
log_warning_errno(r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a);
continue;
}
} else if (streq(a, "iif")) {
if (free_and_strdup(&rule->iif, b) < 0)
return log_oom();
} else if (streq(a, "oif")) {
if (free_and_strdup(&rule->oif, b) < 0)
return log_oom();
} else if (streq(a, "protocol")) {
r = safe_atou8(b, &rule->protocol);
if (r < 0) {
log_warning_errno(r, "Failed to parse RPDB rule protocol, ignoring: %s", b);
continue;
}
} else if (streq(a, "sourceport")) {
uint16_t low, high;
r = parse_ip_port_range(b, &low, &high);
if (r < 0) {
log_warning_errno(r, "Invalid routing policy rule source port range, ignoring assignment: '%s'", b);
continue;
}
rule->sport.start = low;
rule->sport.end = high;
} else if (streq(a, "destinationport")) {
uint16_t low, high;
r = parse_ip_port_range(b, &low, &high);
if (r < 0) {
log_warning_errno(r, "Invalid routing policy rule destination port range, ignoring assignment: '%s'", b);
continue;
}
rule->dport.start = low;
rule->dport.end = high;
} else if (streq(a, "uidrange")) {
uid_t lower, upper;
r = parse_uid_range(b, &lower, &upper);
if (r < 0) {
log_warning_errno(r, "Invalid routing policy rule uid range, ignoring assignment: '%s'", b);
continue;
}
rule->uid_range.start = lower;
rule->uid_range.end = upper;
} else if (streq(a, "suppress_prefixlen")) {
r = parse_ip_prefix_length(b, &rule->suppress_prefixlen);
if (r == -ERANGE) {
log_warning_errno(r, "Prefix length outside of valid range 0-128, ignoring: %s", b);
continue;
}
if (r < 0) {
log_warning_errno(r, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", b);
continue;
}
} else if (streq(a, "invert_rule")) {
r = parse_boolean(b);
if (r < 0) {
log_warning_errno(r, "Failed to parse RPDB rule invert_rule, ignoring: %s", b);
continue;
}
rule->invert_rule = r;
} else
log_warning("Unknown RPDB rule, ignoring: %s", a);
}
r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule);
if (r < 0) {
log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", *i);
continue;
}
if (r > 0)
rule = NULL;
}
return 0;
}

View File

@ -24,9 +24,11 @@ typedef struct RoutingPolicyRule {
uint8_t tos;
uint8_t type;
uint8_t protocol;
uint8_t ipproto; /* FRA_IP_PROTO */
uint8_t protocol; /* FRA_PROTOCOL */
uint8_t to_prefixlen;
uint8_t from_prefixlen;
uint8_t l3mdev; /* FRA_L3MDEV */
uint32_t table;
uint32_t fwmark;
@ -56,9 +58,13 @@ void network_drop_invalid_routing_policy_rules(Network *network);
int link_set_routing_policy_rules(Link *link);
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
int routing_policy_serialize_rules(Set *rules, FILE *f);
int routing_policy_load_rules(const char *state_file, Set **rules);
int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except);
static inline int manager_drop_foreign_routing_policy_rules(Manager *m) {
return manager_drop_routing_policy_rules_internal(m, true, NULL);
}
static inline int manager_drop_routing_policy_rules(Manager *m, const Link *except) {
return manager_drop_routing_policy_rules_internal(m, false, except);
}
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table);

View File

@ -1,90 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "fd-util.h"
#include "fileio.h"
#include "networkd-routing-policy-rule.h"
#include "string-util.h"
#include "tests.h"
#include "tmpfile-util.h"
static void test_rule_serialization(const char *title, const char *ruleset, const char *expected) {
char pattern[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX",
pattern2[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX",
pattern3[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX";
const char *cmd;
int fd, fd2, fd3;
_cleanup_fclose_ FILE *f = NULL, *f2 = NULL, *f3 = NULL;
Set *rules = NULL;
_cleanup_free_ char *buf = NULL;
size_t buf_size;
log_info("========== %s ==========", title);
log_info("put:\n%s\n", ruleset);
fd = mkostemp_safe(pattern);
assert_se(fd >= 0);
assert_se(f = fdopen(fd, "a+"));
assert_se(write_string_stream(f, ruleset, 0) == 0);
assert_se(routing_policy_load_rules(pattern, &rules) == 0);
fd2 = mkostemp_safe(pattern2);
assert_se(fd2 >= 0);
assert_se(f2 = fdopen(fd2, "a+"));
assert_se(routing_policy_serialize_rules(rules, f2) == 0);
assert_se(fflush_and_check(f2) == 0);
assert_se(read_full_file(pattern2, &buf, &buf_size) == 0);
log_info("got:\n%s", buf);
fd3 = mkostemp_safe(pattern3);
assert_se(fd3 >= 0);
assert_se(f3 = fdopen(fd3, "w"));
assert_se(write_string_stream(f3, expected ?: ruleset, 0) == 0);
cmd = strjoina("diff -u ", pattern3, " ", pattern2);
log_info("$ %s", cmd);
assert_se(system(cmd) == 0);
set_free(rules);
}
int main(int argc, char **argv) {
_cleanup_free_ char *p = NULL;
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 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 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 type=1 invert_rule=yes table=6", NULL);
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 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 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 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 type=1 invert_rule=no table=1");
return 0;
}

View File

@ -3326,7 +3326,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
output = check_output('ip rule list table 100')
print(output)
self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
self.assertIn('0: from all to 8.8.8.8 lookup 100', output)
class NetworkdLLDPTests(unittest.TestCase, Utilities):
links = ['veth99']