From c7a31e70791439fe89dea413bd54a08d8424b7e2 Mon Sep 17 00:00:00 2001 From: Wen Liang Date: Thu, 12 Oct 2023 08:13:58 -0400 Subject: [PATCH] fix: Allow address 0.0.0.0/0 or ::/0 for 'from'/'to' in routing rule validation `from 0.0.0.0/0` means from all IPv4 addresses, `from ::/0` means from all IPv6 addresses. In NM, if `from` property is not specified in a routing rule, NM still appends `from 0.0.0.0/0` or `from ::/0` to the rule. NM also allows to specify `to 0.0.0.0/0` or `to ::/0` in a routing rule, but the connection profiles will only show the `from` setting for the rule. Signed-off-by: Wen Liang --- library/network_connections.py | 8 ++++++-- module_utils/network_lsr/argument_validator.py | 18 +++++++++++++++--- tests/playbooks/tests_routing_rules.yml | 12 ++++++++++++ tests/unit/test_network_connections.py | 8 ++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/library/network_connections.py b/library/network_connections.py index 2ee151c..5267e82 100644 --- a/library/network_connections.py +++ b/library/network_connections.py @@ -1243,7 +1243,9 @@ class NMUtil: routing_rule["dport"][0], routing_rule["dport"][1], ) - if routing_rule["from"]: + # In NM, when user specifies `from 0.0.0.0/0`` or `from ::/0` in a + # routing rule, NM treats it as if the `from` setting is not specified. + if routing_rule["from"] and routing_rule["from"]["prefix"]: NM.IPRoutingRule.set_from( nm_routing_rule, routing_rule["from"]["address"], @@ -1274,7 +1276,9 @@ class NMUtil: ) if routing_rule["table"]: NM.IPRoutingRule.set_table(nm_routing_rule, routing_rule["table"]) - if routing_rule["to"]: + # In NM, when user specifies `to 0.0.0.0/0`` or `to ::/0` in a + # routing rule, NM treats it as if the `to` setting is not specified. + if routing_rule["to"] and routing_rule["to"]["prefix"]: NM.IPRoutingRule.set_to( nm_routing_rule, routing_rule["to"]["address"], diff --git a/module_utils/network_lsr/argument_validator.py b/module_utils/network_lsr/argument_validator.py index 5c58ffb..9ccaeb6 100644 --- a/module_utils/network_lsr/argument_validator.py +++ b/module_utils/network_lsr/argument_validator.py @@ -779,15 +779,27 @@ class ArgValidatorIPRoutingRule(ArgValidatorDict): name, "missing 'table' for the routing rule", ) - - if result["from"] is not None: + # `from 0.0.0.0/0` means from all IPv4 addresses + # `from ::/0` means from all IPv6 addresses + # In NM, if `from` property is not specified in a routing rule, NM + # still appends `from 0.0.0.0/0` or `from ::/0` to the rule + if result["from"] is not None and result["from"]["address"] not in [ + "0.0.0.0", + "::", + ]: if result["from"]["prefix"] == 0: raise ValidationError( name, "the prefix length for 'from' cannot be zero", ) - if result["to"] is not None: + # NM also allows to specify `to 0.0.0.0/0` or `to ::/0` in a routing + # rule, but the connection profiles will only show the `from` setting + # for the rule + if result["to"] is not None and result["to"]["address"] not in [ + "0.0.0.0", + "::", + ]: if result["to"]["prefix"] == 0: raise ValidationError( name, diff --git a/tests/playbooks/tests_routing_rules.yml b/tests/playbooks/tests_routing_rules.yml index 5d248f7..9c7c4dc 100644 --- a/tests/playbooks/tests_routing_rules.yml +++ b/tests/playbooks/tests_routing_rules.yml @@ -92,6 +92,10 @@ family: ipv4 oif: oiftest table: 30400 + - priority: 30403 + from: 0.0.0.0/0 + to: 0.0.0.0/0 + table: 30400 - priority: 30600 to: 2001:db8::4/32 table: 30600 @@ -100,6 +104,10 @@ dport: 128 - 256 invert: true table: 30600 + - priority: 30602 + from: ::/0 + to: ::/0 + table: 30600 - priority: 200 from: 198.51.100.56/26 table: custom @@ -220,6 +228,8 @@ 0.0.0.0/0 iif iiftest table 30400") - connection_route_rule.stdout is search("priority 30402 from 0.0.0.0/0 oif oiftest table 30400") + - connection_route_rule.stdout is search("priority 30403 from + 0.0.0.0/0 table 30400") - connection_route_rule.stdout is search("priority 200 from 198.51.100.56/26 table 200") msg: "the specified IPv4 routing rule was not configured in the @@ -235,6 +245,8 @@ ::/0 dport 128-256 table 30600") or connection_route_rule6.stdout is search("not priority 30601 from ::/0 dport 128-256 table 30600") + - connection_route_rule6.stdout is search("priority 30602 from + ::/0 table 30600") msg: "the specified IPv6 routing rule was not configured in the connection '{{ interface }}'" diff --git a/tests/unit/test_network_connections.py b/tests/unit/test_network_connections.py index 63a81dd..1abff1f 100644 --- a/tests/unit/test_network_connections.py +++ b/tests/unit/test_network_connections.py @@ -5050,6 +5050,14 @@ class TestValidatorRoutingRules(Python26CompatTestCase): self.validator.validate, self.test_connections, ) + self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "::/0" + self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "::/0" + self.validator.validate(self.test_connections) + + self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4" + self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "0.0.0.0/0" + self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "0.0.0.0/0" + self.validator.validate(self.test_connections) def test_routing_rule_missing_table(self): """