This is an automated email from the ASF dual-hosted git repository.

DaanHoogland pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.22 by this push:
     new de4ca48dfb3 Routed network ACL: match protocol-number rules with ip 
protocol, not ip nexthdr (#14352)
de4ca48dfb3 is described below

commit de4ca48dfb37ef0fefef6dc816b31777be01fd83
Author: Brad House - Nexthop <[email protected]>
AuthorDate: Thu Oct 22 08:43:03 2026 -0400

    Routed network ACL: match protocol-number rules with ip protocol, not ip 
nexthdr (#14352)
    
    Signed-off-by: Brad House <[email protected]>
---
 systemvm/debian/opt/cloud/bin/configure.py |  2 +-
 systemvm/test/TestCsAclRouting.py          | 67 ++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/systemvm/debian/opt/cloud/bin/configure.py 
b/systemvm/debian/opt/cloud/bin/configure.py
index 0575433ad00..95cb7360846 100755
--- a/systemvm/debian/opt/cloud/bin/configure.py
+++ b/systemvm/debian/opt/cloud/bin/configure.py
@@ -450,7 +450,7 @@ class CsAcl(CsDataBag):
                 if protocol != "all":
                     icmp_type = ""
                     if protocol == "protocol":
-                        protocol = "ip nexthdr %d" % rule['protocol']
+                        protocol = "ip protocol %d" % rule['protocol']
                     proto = protocol
                     if proto == "icmp":
                         proto = proto_str = "icmp"
diff --git a/systemvm/test/TestCsAclRouting.py 
b/systemvm/test/TestCsAclRouting.py
new file mode 100644
index 00000000000..7d67d711fb9
--- /dev/null
+++ b/systemvm/test/TestCsAclRouting.py
@@ -0,0 +1,67 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import unittest
+from configure import CsAcl
+
+
+class FakeConfig:
+
+    def __init__(self):
+        self.fw = []
+        self.ipv6_acl = []
+        self.nft_ipv4_acl = []
+
+    def get_fw(self):
+        return self.fw
+
+    def get_ipv6_acl(self):
+        return self.ipv6_acl
+
+    def get_nft_ipv4_acl(self):
+        return self.nft_ipv4_acl
+
+    def is_vpc(self):
+        return True
+
+    def is_routed(self):
+        return True
+
+
+class TestCsAclRouting(unittest.TestCase):
+
+    def test_protocol_number_rule(self):
+        config = FakeConfig()
+        obj = {"device": "eth3", "nic_ip": "10.1.1.1", "nic_netmask": "24", 
"nic_ip6_cidr": "fd00:1::/64",
+               "ingress_rules": [{"type": "protocol", "protocol": 47, "cidr": 
"1.2.3.4/32,2001:db8::/64", "allowed": True}],
+               "egress_rules": [{"type": "protocol", "protocol": 47, "cidr": 
"5.6.7.8/32", "allowed": False}]}
+        acl = CsAcl.AclDevice(obj, config)
+        acl.create()
+
+        # nexthdr is an IPv6 header field, nft rejects it in an ip rule
+        ip4 = [r['rule'] for r in config.nft_ipv4_acl if r.get('chain') == 
"eth3_ingress_policy" and 'rule' in r]
+        self.assertIn("ip saddr 1.2.3.4/32 ip protocol 47 accept", ip4)
+        ip6 = [r['rule'] for r in config.ipv6_acl if r.get('chain') == 
"eth3_ingress_policy" and 'rule' in r]
+        # the IPv4 match must not leak into the IPv6 rule
+        self.assertTrue(any(r.startswith("ip6 saddr 2001:db8::/64 ") and 
r.endswith(" 47 accept") for r in ip6))
+        self.assertFalse(any("ip protocol" in r for r in ip6))
+        ip4 = [r['rule'] for r in config.nft_ipv4_acl if r.get('chain') == 
"eth3_egress_policy" and 'rule' in r]
+        self.assertIn("ip daddr 5.6.7.8/32 ip protocol 47 drop", ip4)
+
+
+if __name__ == '__main__':
+    unittest.main()

Reply via email to