mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-22 22:03:43 +03:00
Merge pull request #16986 from yuwata/network-fix-routing-policy-rule-issue-16784
network: fix routing policy rule issue
This commit is contained in:
commit
3a17308c2a
@ -691,7 +691,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
switch (type) {
|
||||
case RTM_NEWNEIGH:
|
||||
if (neighbor)
|
||||
log_link_debug(link, "Remembering neighbor: %s->%s",
|
||||
log_link_debug(link, "Received remembered neighbor: %s->%s",
|
||||
strnull(addr_str), strnull(lladdr_str));
|
||||
else {
|
||||
/* A neighbor appeared that we did not request */
|
||||
@ -1082,9 +1082,6 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
|
||||
assert_not_reached("Received rule message with unsupported address family");
|
||||
}
|
||||
|
||||
if (tmp->from_prefixlen == 0 && tmp->to_prefixlen == 0)
|
||||
return 0;
|
||||
|
||||
r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m");
|
||||
@ -1181,9 +1178,12 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWRULE:
|
||||
if (!rule) {
|
||||
log_debug("Remembering foreign routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u",
|
||||
from, tmp->from_prefixlen, to, tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
||||
if (rule)
|
||||
log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
||||
else {
|
||||
log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
||||
r = routing_policy_rule_add_foreign(m, tmp, &rule);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
|
||||
@ -1192,10 +1192,13 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
|
||||
}
|
||||
break;
|
||||
case RTM_DELRULE:
|
||||
log_debug("Forgetting routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u",
|
||||
from, tmp->from_prefixlen, to, tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
||||
routing_policy_rule_free(rule);
|
||||
|
||||
if (rule) {
|
||||
log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
||||
routing_policy_rule_free(rule);
|
||||
} else
|
||||
log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.",
|
||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1298,19 +1301,24 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWNEXTHOP:
|
||||
if (!nexthop) {
|
||||
log_debug("Remembering foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id);
|
||||
if (nexthop)
|
||||
log_link_debug(link, "Received remembered nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id);
|
||||
else {
|
||||
log_link_debug(link, "Remembering foreign nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id);
|
||||
r = nexthop_add_foreign(link, tmp, &nexthop);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not remember foreign nexthop, ignoring: %m");
|
||||
log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RTM_DELNEXTHOP:
|
||||
log_debug("Forgetting foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id);
|
||||
nexthop_free(nexthop);
|
||||
|
||||
if (nexthop) {
|
||||
log_link_debug(link, "Forgetting nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id);
|
||||
nexthop_free(nexthop);
|
||||
} else
|
||||
log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, oif: %d, id: %d, ignoring.",
|
||||
strna(gateway), tmp->oif, tmp->id);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -333,37 +333,48 @@ static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_messa
|
||||
return 1;
|
||||
}
|
||||
|
||||
int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback) {
|
||||
int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(routing_policy_rule);
|
||||
assert(rule);
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
assert(IN_SET(routing_policy_rule->family, AF_INET, AF_INET6));
|
||||
assert(IN_SET(rule->family, AF_INET, AF_INET6));
|
||||
|
||||
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, routing_policy_rule->family);
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *from = NULL, *to = NULL;
|
||||
|
||||
(void) in_addr_to_string(rule->family, &rule->from, &from);
|
||||
(void) in_addr_to_string(rule->family, &rule->to, &to);
|
||||
|
||||
log_link_debug(link,
|
||||
"Removing routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
||||
rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table);
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, rule->family);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate RTM_DELRULE message: %m");
|
||||
|
||||
if (in_addr_is_null(routing_policy_rule->family, &routing_policy_rule->from) == 0) {
|
||||
r = netlink_message_append_in_addr_union(m, FRA_SRC, routing_policy_rule->family, &routing_policy_rule->from);
|
||||
if (in_addr_is_null(rule->family, &rule->from) == 0) {
|
||||
r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m");
|
||||
|
||||
r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, routing_policy_rule->from_prefixlen);
|
||||
r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set source prefix length: %m");
|
||||
}
|
||||
|
||||
if (in_addr_is_null(routing_policy_rule->family, &routing_policy_rule->to) == 0) {
|
||||
r = netlink_message_append_in_addr_union(m, FRA_DST, routing_policy_rule->family, &routing_policy_rule->to);
|
||||
if (in_addr_is_null(rule->family, &rule->to) == 0) {
|
||||
r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m");
|
||||
|
||||
r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, routing_policy_rule->to_prefixlen);
|
||||
r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
|
||||
}
|
||||
@ -473,8 +484,8 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
|
||||
(void) in_addr_to_string(rule->family, &rule->to, &to);
|
||||
|
||||
log_link_debug(link,
|
||||
"Configuring routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u",
|
||||
from, rule->from_prefixlen, to, rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table);
|
||||
"Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
||||
rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table);
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family);
|
||||
@ -529,18 +540,16 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
|
||||
r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append FRA_FWMARK attribute: %m");
|
||||
}
|
||||
|
||||
if (rule->fwmask > 0) {
|
||||
r = sd_netlink_message_append_u32(m, FRA_FWMASK, rule->fwmask);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append FRA_FWMASK attribute: %m");
|
||||
}
|
||||
|
||||
if (rule->iif) {
|
||||
r = sd_netlink_message_append_string(m, FRA_IFNAME, rule->iif);
|
||||
r = sd_netlink_message_append_string(m, FRA_IIFNAME, rule->iif);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append FRA_IFNAME attribute: %m");
|
||||
return log_link_error_errno(link, r, "Could not append FRA_IIFNAME attribute: %m");
|
||||
}
|
||||
|
||||
if (rule->oif) {
|
||||
@ -644,31 +653,39 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_fwmark_fwmask(const char *s, uint32_t *fwmark, uint32_t *fwmask) {
|
||||
_cleanup_free_ char *f = NULL;
|
||||
char *p;
|
||||
static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *ret_fwmask) {
|
||||
_cleanup_free_ char *fwmark_str = NULL;
|
||||
uint32_t fwmark, fwmask = 0;
|
||||
const char *slash;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(ret_fwmark);
|
||||
assert(ret_fwmask);
|
||||
|
||||
f = strdup(s);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
p = strchr(f, '/');
|
||||
if (p)
|
||||
*p++ = '\0';
|
||||
|
||||
r = safe_atou32(f, fwmark);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse RPDB rule firewall mark, ignoring: %s", f);
|
||||
|
||||
if (p) {
|
||||
r = safe_atou32(p, fwmask);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse RPDB rule mask, ignoring: %s", f);
|
||||
slash = strchr(s, '/');
|
||||
if (slash) {
|
||||
fwmark_str = strndup(s, slash - s);
|
||||
if (!fwmark_str)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = safe_atou32(fwmark_str ?: s, &fwmark);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (fwmark > 0) {
|
||||
if (slash) {
|
||||
r = safe_atou32(slash + 1, &fwmask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else
|
||||
fwmask = UINT32_MAX;
|
||||
}
|
||||
|
||||
*ret_fwmark = fwmark;
|
||||
*ret_fwmask = fwmask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1223,9 +1240,11 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
|
||||
}
|
||||
|
||||
if (rule->fwmark != 0) {
|
||||
fprintf(f, "%sfwmark=%"PRIu32"/%"PRIu32,
|
||||
fprintf(f, "%sfwmark=%"PRIu32,
|
||||
space ? " " : "",
|
||||
rule->fwmark, rule->fwmask);
|
||||
rule->fwmark);
|
||||
if (rule->fwmask != UINT32_MAX)
|
||||
fprintf(f, "/%"PRIu32, rule->fwmask);
|
||||
space = true;
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ void routing_policy_rule_free(RoutingPolicyRule *rule);
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
|
||||
int routing_policy_rule_section_verify(RoutingPolicyRule *rule);
|
||||
|
||||
int routing_policy_rule_configure(RoutingPolicyRule *address, Link *link, link_netlink_message_handler_t callback);
|
||||
int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback);
|
||||
int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback);
|
||||
int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback);
|
||||
|
||||
int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret);
|
||||
int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret);
|
||||
|
@ -67,7 +67,7 @@ int main(int argc, char **argv) {
|
||||
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/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 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);
|
||||
|
@ -0,0 +1,33 @@
|
||||
[Match]
|
||||
Name=test1
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
|
||||
# fwmark
|
||||
[RoutingPolicyRule]
|
||||
Table=1011
|
||||
Family=ipv4
|
||||
Priority=10111
|
||||
FirewallMark=1011
|
||||
|
||||
# oif
|
||||
[RoutingPolicyRule]
|
||||
Table=1011
|
||||
Family=ipv4
|
||||
Priority=10112
|
||||
OutgoingInterface=test1
|
||||
|
||||
# iif
|
||||
[RoutingPolicyRule]
|
||||
Table=1011
|
||||
Family=ipv4
|
||||
Priority=10113
|
||||
IncomingInterface=test1
|
||||
|
||||
# source
|
||||
[RoutingPolicyRule]
|
||||
Table=1011
|
||||
Family=ipv4
|
||||
Priority=10114
|
||||
From=192.168.8.254
|
@ -1735,9 +1735,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
'25-vrf.network',
|
||||
'26-link-local-addressing-ipv6.network',
|
||||
'routing-policy-rule-dummy98.network',
|
||||
'routing-policy-rule-test1.network']
|
||||
'routing-policy-rule-test1.network',
|
||||
'routing-policy-rule-reconfigure.network',
|
||||
]
|
||||
|
||||
routing_policy_rule_tables = ['7', '8', '9']
|
||||
routing_policy_rule_tables = ['7', '8', '9', '1011']
|
||||
routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
|
||||
|
||||
def setUp(self):
|
||||
@ -1970,32 +1972,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, 'iif test1')
|
||||
self.assertRegex(output, 'lookup 8')
|
||||
|
||||
output = check_output('ip -6 rule list iif test1 priority 101')
|
||||
print(output)
|
||||
self.assertRegex(output, '101:')
|
||||
self.assertRegex(output, 'from all')
|
||||
self.assertRegex(output, 'iif test1')
|
||||
self.assertRegex(output, 'lookup 9')
|
||||
|
||||
run('ip rule delete iif test1 priority 111')
|
||||
|
||||
output = check_output('ip rule list iif test1 priority 111')
|
||||
print(output)
|
||||
self.assertEqual(output, '')
|
||||
|
||||
run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
|
||||
|
||||
self.wait_online(['test1:degraded'])
|
||||
|
||||
output = check_output('ip rule list iif test1 priority 111')
|
||||
print(output)
|
||||
self.assertRegex(output, '111:')
|
||||
self.assertRegex(output, 'from 192.168.100.18')
|
||||
self.assertRegex(output, r'tos (0x08|throughput)\s')
|
||||
self.assertRegex(output, 'iif test1')
|
||||
self.assertRegex(output, 'oif test1')
|
||||
self.assertRegex(output, 'lookup 7')
|
||||
|
||||
def test_routing_policy_rule_issue_11280(self):
|
||||
copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
|
||||
'routing-policy-rule-dummy98.network', '12-dummy.netdev')
|
||||
@ -2016,6 +1992,39 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
|
||||
stop_networkd(remove_state_files=False)
|
||||
|
||||
def test_routing_policy_rule_reconfigure(self):
|
||||
copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure.network', '11-dummy.netdev')
|
||||
start_networkd()
|
||||
self.wait_online(['test1:degraded'])
|
||||
|
||||
output = check_output('ip rule list table 1011')
|
||||
print(output)
|
||||
self.assertRegex(output, '10111: from all fwmark 0x3f3 lookup 1011')
|
||||
self.assertRegex(output, '10112: from all oif test1 lookup 1011')
|
||||
self.assertRegex(output, '10113: from all iif test1 lookup 1011')
|
||||
self.assertRegex(output, '10114: from 192.168.8.254 lookup 1011')
|
||||
|
||||
run('ip rule delete priority 10111')
|
||||
run('ip rule delete priority 10112')
|
||||
run('ip rule delete priority 10113')
|
||||
run('ip rule delete priority 10114')
|
||||
run('ip rule delete priority 10115')
|
||||
|
||||
output = check_output('ip rule list table 1011')
|
||||
print(output)
|
||||
self.assertEqual(output, '')
|
||||
|
||||
run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
|
||||
|
||||
self.wait_online(['test1:degraded'])
|
||||
|
||||
output = check_output('ip rule list table 1011')
|
||||
print(output)
|
||||
self.assertRegex(output, '10111: from all fwmark 0x3f3 lookup 1011')
|
||||
self.assertRegex(output, '10112: from all oif test1 lookup 1011')
|
||||
self.assertRegex(output, '10113: from all iif test1 lookup 1011')
|
||||
self.assertRegex(output, '10114: from 192.168.8.254 lookup 1011')
|
||||
|
||||
@expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
|
||||
def test_routing_policy_rule_port_range(self):
|
||||
copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
|
||||
|
Loading…
x
Reference in New Issue
Block a user