firewalld/SOURCES/0033-v2.4.0-chore-icmp-convert-type-code-map-to-tuple.patch
2026-05-26 12:16:34 -04:00

266 lines
10 KiB
Diff

From 3c9a81ac67bf2a25190233e3fd20c07e7d33ba97 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Wed, 29 Oct 2025 11:32:35 -0400
Subject: [PATCH 33/37] v2.4.0: chore(icmp): convert type/code map to tuple
This will make it easier to use/query.
(cherry picked from commit 6c33bbcdb60e257ec1102baaff128f5b345c67f8)
---
src/firewall/core/icmp.py | 158 +++++++++++++++++-----------------
src/firewall/core/io/ipset.py | 26 ++++--
2 files changed, 100 insertions(+), 84 deletions(-)
diff --git a/src/firewall/core/icmp.py b/src/firewall/core/icmp.py
index 87f87ab1c49e..db0398eee6fd 100644
--- a/src/firewall/core/icmp.py
+++ b/src/firewall/core/icmp.py
@@ -20,89 +20,91 @@
#
__all__ = [ "ICMP_TYPES", "ICMPV6_TYPES",
- "check_icmp_type", "check_icmpv6_type" ]
+ "check_icmp_type_code", "check_icmpv6_type_code" ]
ICMP_TYPES = {
- "echo-reply": "0/0",
- "pong": "0/0",
- "destination-unreachable": "3/0",
- "network-unreachable": "3/0",
- "tos-network-unreachable": "3/0",
- "host-unreachable": "3/1",
- "tos-host-unreachable": "3/1",
- "protocol-unreachable": "3/2",
- "port-unreachable": "3/3",
- "fragmentation-needed": "3/4",
- "source-route-failed": "3/5",
+ # "type": (type, code, backend omit code)
+ "echo-reply": (0, 0, True),
+ "pong": (0, 0, True),
+ "destination-unreachable": (3, 0, True),
+ "network-unreachable": (3, 0, False),
+ "tos-network-unreachable": (3, 0, False),
+ "host-unreachable": (3, 1, False),
+ "tos-host-unreachable": (3, 1, False),
+ "protocol-unreachable": (3, 2, False),
+ "port-unreachable": (3, 3, False),
+ "fragmentation-needed": (3, 4, False),
+ "source-route-failed": (3, 5, False),
# RFC-1112 Section 3.2.2.1 defines type 3, code 6-12
- "network-unknown": "3/6",
- "host-unknown": "3/7",
- "network-prohibited": "3/9",
- "host-prohibited": "3/10",
- "TOS-network-unreachable": "3/11",
- "TOS-host-unreachable": "3/12",
+ "network-unknown": (3, 6, False),
+ "host-unknown": (3, 7, False),
+ "network-prohibited": (3, 9, False),
+ "host-prohibited": (3, 10, False),
+ "TOS-network-unreachable": (3, 11, False),
+ "TOS-host-unreachable": (3, 12, False),
# RFC-1812 Section 5.2.7.1 defines type 3, code 13-15
- "communication-prohibited": "3/13",
- "host-precedence-violation": "3/14",
- "precedence-cutoff": "3/15",
- "source-quench": "4/0",
- "network-redirect": "5/0",
- "redirect": "5/0",
- "host-redirect": "5/1",
- "tos-host-redirect": "5/1",
- "TOS-network-redirect": "5/2",
- "tos-network-redirect": "5/2",
- "TOS-host-redirect": "5/3",
- "echo-request": "8/0",
- "ping": "8/0",
- "router-advertisement": "9/0",
- "router-solicitation": "10/0",
- "time-exceeded": "11/0",
- "ttl-zero-during-transit": "11/0",
- "ttl-zero-during-reassembly": "11/1",
- "parameter-problem": "12/0",
- "ip-header-bad": "12/0",
- "required-option-missing": "12/1",
- "timestamp-request": "13/0",
- "timestamp-reply": "14/0",
- "address-mask-request": "17/0",
- "address-mask-reply": "18/0",
+ "communication-prohibited": (3, 13, False),
+ "host-precedence-violation": (3, 14, False),
+ "precedence-cutoff": (3, 15, False),
+ "source-quench": (4, 0, True),
+ "network-redirect": (5, 0, False),
+ "redirect": (5, 0, True),
+ "host-redirect": (5, 1, False),
+ "tos-host-redirect": (5, 1, False),
+ "TOS-network-redirect": (5, 2, False),
+ "tos-network-redirect": (5, 2, False),
+ "TOS-host-redirect": (5, 3, False),
+ "echo-request": (8, 0, True),
+ "ping": (8, 0, True),
+ "router-advertisement": (9, 0, True),
+ "router-solicitation": (10, 0, True),
+ "time-exceeded": (11, 0, True),
+ "ttl-zero-during-transit": (11, 0, False),
+ "ttl-zero-during-reassembly": (11, 1, False),
+ "parameter-problem": (12, 0, True),
+ "ip-header-bad": (12, 0, False),
+ "required-option-missing": (12, 1, False),
+ "timestamp-request": (13, 0, True),
+ "timestamp-reply": (14, 0, True),
+ "address-mask-request": (17, 0, False),
+ "address-mask-reply": (18, 0, False),
}
ICMPV6_TYPES = {
- "destination-unreachable": "1/0",
- "no-route": "1/0",
- "communication-prohibited": "1/1",
- "beyond-scope": "1/2",
- "address-unreachable": "1/3",
- "port-unreachable": "1/4",
- "failed-policy": "1/5",
- "reject-route": "1/6",
- "packet-too-big": "2/0",
- "time-exceeded": "3/0",
- "ttl-zero-during-transit": "3/0",
- "ttl-zero-during-reassembly": "3/1",
- "parameter-problem": "4/0",
- "bad-header": "4/0",
- "unknown-header-type": "4/1",
- "unknown-option": "4/2",
- "echo-request": "128/0",
- "ping": "128/0",
- "echo-reply": "129/0",
- "pong": "129/0",
- "router-solicitation": "133/0",
- "router-advertisement": "134/0",
- "neighbour-solicitation": "135/0",
- "neigbour-solicitation": "135/0",
- "neighbour-advertisement": "136/0",
- "neigbour-advertisement": "136/0",
- "redirect": "137/0",
+ # "type": (type, code, backend omit code)
+ "destination-unreachable": (1, 0, True),
+ "no-route": (1, 0, False),
+ "communication-prohibited": (1, 1, False),
+ "beyond-scope": (1, 2, False),
+ "address-unreachable": (1, 3, False),
+ "port-unreachable": (1, 4, False),
+ "failed-policy": (1, 5, False),
+ "reject-route": (1, 6, False),
+ "packet-too-big": (2, 0, True),
+ "time-exceeded": (3, 0, True),
+ "ttl-zero-during-transit": (3, 0, False),
+ "ttl-zero-during-reassembly": (3, 1, False),
+ "parameter-problem": (4, 0, True),
+ "bad-header": (4, 0, False),
+ "unknown-header-type": (4, 1, False),
+ "unknown-option": (4, 2, False),
+ "echo-request": (128, 0, True),
+ "ping": (128, 0, True),
+ "echo-reply": (129, 0, True),
+ "pong": (129, 0, True),
+ "router-solicitation": (133, 0, True),
+ "router-advertisement": (134, 0, True),
+ "neighbour-solicitation": (135, 0, True),
+ "neigbour-solicitation": (135, 0, True),
+ "neighbour-advertisement": (136, 0, True),
+ "neigbour-advertisement": (136, 0, True),
+ "redirect": (137, 0, True),
# MLD is RFC-2710
- "mld-listener-query": "130/0",
- "mld-listener-report": "131/0",
- "mld-listener-done": "132/0",
+ "mld-listener-query": (130, 0, True),
+ "mld-listener-report": (131, 0, True),
+ "mld-listener-done": (132, 0, True),
# MLDv2 is RFC-9777
- "mld2-listener-report": "143/0",
+ "mld2-listener-report": (143, 0, True),
}
def check_icmp_name(_name):
@@ -110,8 +112,8 @@ def check_icmp_name(_name):
return True
return False
-def check_icmp_type(_type):
- if _type in ICMP_TYPES.values():
+def check_icmp_type_code(_type, _code):
+ if (_type, _code) in ICMP_TYPES.values():
return True
return False
@@ -120,7 +122,7 @@ def check_icmpv6_name(_name):
return True
return False
-def check_icmpv6_type(_type):
- if _type in ICMPV6_TYPES.values():
+def check_icmpv6_type_code(_type, _code):
+ if (_type, _code) in ICMPV6_TYPES.values():
return True
return False
diff --git a/src/firewall/core/io/ipset.py b/src/firewall/core/io/ipset.py
index 1222c588a345..edb19cc784b3 100644
--- a/src/firewall/core/io/ipset.py
+++ b/src/firewall/core/io/ipset.py
@@ -35,8 +35,8 @@ from firewall.functions import checkIP, checkIP6, checkIPnMask, \
from firewall.core.io.io_object import PY2, IO_Object, \
IO_Object_ContentHandler, IO_Object_XMLGenerator
from firewall.core.ipset import IPSET_TYPES, IPSET_CREATE_OPTIONS
-from firewall.core.icmp import check_icmp_name, check_icmp_type, \
- check_icmpv6_name, check_icmpv6_type
+from firewall.core.icmp import check_icmp_name, check_icmp_type_code, \
+ check_icmpv6_name, check_icmpv6_type_code
from firewall.core.logger import log
from firewall import errors
from firewall.errors import FirewallError
@@ -216,24 +216,38 @@ class IPSet(IO_Object):
errors.INVALID_ENTRY,
"invalid protocol for family '%s' in '%s'" % \
(family, entry))
- if not check_icmp_name(splits[1]) and not \
- check_icmp_type(splits[1]):
+ if not check_icmp_name(splits[1]) and "/" not in splits[1]:
raise FirewallError(
errors.INVALID_ENTRY,
"invalid icmp type '%s' in '%s'" % \
(splits[1], entry))
+ else:
+ (_type, _code) = splits[1].split("/")
+ if not check_icmp_type_code(_type, _code):
+ raise FirewallError(
+ errors.INVALID_ENTRY,
+ "invalid icmp type '%s' in '%s'"
+ % (splits[1], entry),
+ )
elif splits[0] in [ "icmpv6", "ipv6-icmp" ]:
if family != "ipv6":
raise FirewallError(
errors.INVALID_ENTRY,
"invalid protocol for family '%s' in '%s'" % \
(family, entry))
- if not check_icmpv6_name(splits[1]) and not \
- check_icmpv6_type(splits[1]):
+ if not check_icmpv6_name(splits[1]) and "/" not in splits[1]:
raise FirewallError(
errors.INVALID_ENTRY,
"invalid icmpv6 type '%s' in '%s'" % \
(splits[1], entry))
+ else:
+ (_type, _code) = splits[1].split("/")
+ if not check_icmpv6_type_code(_type, _code):
+ raise FirewallError(
+ errors.INVALID_ENTRY,
+ "invalid icmpv6 type '%s' in '%s'"
+ % (splits[1], entry),
+ )
elif splits[0] not in [ "tcp", "sctp", "udp", "udplite" ] \
and not checkProtocol(splits[0]):
raise FirewallError(
--
2.52.0