network: fix handling of routing policy rule fwmask

The firewall mask should be applied even if the mark is 0, to allow defining a
value of e.g. 0/255.

Fixes #36973
This commit is contained in:
Beniamino Galvani
2025-04-15 22:13:11 +02:00
committed by Yu Watanabe
parent 49ff90c70d
commit ec65c29e51
4 changed files with 41 additions and 11 deletions

View File

@@ -1738,8 +1738,10 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
<term><varname>FirewallMark=</varname></term>
<listitem>
<para>Specifies the iptables firewall mark value to match (a number in the range
1…4294967295). Optionally, the firewall mask (also a number between 1…4294967295) can be
suffixed with a slash (<literal>/</literal>), e.g., <literal>7/255</literal>.</para>
0…4294967295). Optionally, the firewall mask (also a number between 0…4294967295) can be
suffixed with a slash (<literal>/</literal>), e.g., <literal>7/255</literal>. When the
mark value is non-zero and no mask is explicitly specified, all bits of the mark are
compared. </para>
<xi:include href="version-info.xml" xpointer="v235"/>
</listitem>

View File

@@ -615,7 +615,7 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
if (r < 0)
return r;
if (rule->fwmark > 0) {
if (rule->fwmark > 0 || rule->fwmask > 0) {
r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark);
if (r < 0)
return r;
@@ -1315,14 +1315,12 @@ static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *re
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;
}
if (slash) {
r = safe_atou32(slash + 1, &fwmask);
if (r < 0)
return r;
} else if (fwmark > 0)
fwmask = UINT32_MAX;
*ret_fwmark = fwmark;
*ret_fwmask = fwmask;

View File

@@ -48,6 +48,24 @@ From=10.1.0.0/16
Priority=104
Table=12
[RoutingPolicyRule]
IncomingInterface=test1
FirewallMark=0/1
Priority=200
Table=20
[RoutingPolicyRule]
IncomingInterface=test1
FirewallMark=7/255
Priority=201
Table=21
[RoutingPolicyRule]
IncomingInterface=test1
FirewallMark=9999
Priority=202
Table=22
# The four routing policy rules below intentionally have the same config
# excepts for their To= addresses. See issue #35874.
[RoutingPolicyRule]

View File

@@ -3890,6 +3890,18 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
print(output)
self.assertIn('104: from 10.1.0.0/16 iif test1 lookup 12 nop', output)
output = check_output('ip rule list iif test1 priority 200')
print(output)
self.assertIn('200: from all fwmark 0/0x1 iif test1 lookup 20', output)
output = check_output('ip rule list iif test1 priority 201')
print(output)
self.assertIn('201: from all fwmark 0x7/0xff iif test1 lookup 21', output)
output = check_output('ip rule list iif test1 priority 202')
print(output)
self.assertIn('202: from all fwmark 0x270f iif test1 lookup 22', output)
output = check_output('ip rule list to 192.0.2.0/26')
print(output)
self.assertIn('to 192.0.2.0/26 lookup 1001', output)