From fb83f0f12e3ce0a972943b2e087375986983e959 Mon Sep 17 00:00:00 2001 From: Eric Garver Date: Thu, 18 Oct 2018 16:26:54 -0400 Subject: [PATCH 19/34] rich: add support for rule priorities (cherry picked from commit aeac75088ef2263a7a91c52956c914e69bee8a4b) --- src/firewall/core/io/zone.py | 9 +++++++-- src/firewall/core/rich.py | 19 +++++++++++++++++-- src/firewall/errors.py | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/firewall/core/io/zone.py b/src/firewall/core/io/zone.py index 05368e9c73eb..68b2a7c9567c 100644 --- a/src/firewall/core/io/zone.py +++ b/src/firewall/core/io/zone.py @@ -88,7 +88,7 @@ class Zone(IO_Object): "zone": [ "name", "immutable", "target", "version" ], "masquerade": [ "enabled" ], "forward-port": [ "to-port", "to-addr" ], - "rule": [ "family" ], + "rule": [ "family", "priority" ], "source": [ "address", "mac", "invert", "family", "ipset" ], "destination": [ "invert" ], "log": [ "prefix", "level" ], @@ -627,6 +627,7 @@ class zone_ContentHandler(IO_Object_ContentHandler): elif name == "rule": family = None + priority = 0 if "family" in attrs: family = attrs["family"] if family not in [ "ipv4", "ipv6" ]: @@ -634,7 +635,9 @@ class zone_ContentHandler(IO_Object_ContentHandler): attrs["family"]) self._rule_error = True return - self._rule = rich.Rich_Rule(family) + if "priority" in attrs: + priority = int(attrs["priority"]) + self._rule = rich.Rich_Rule(family=family, priority=priority) elif name == "limit": if not self._limit_ok: @@ -834,6 +837,8 @@ def zone_writer(zone, path=None): attrs = { } if rule.family: attrs["family"] = rule.family + if rule.priority != 0: + attrs["priority"] = str(rule.priority) handler.ignorableWhitespace(" ") handler.startElement("rule", attrs) handler.ignorableWhitespace("\n") diff --git a/src/firewall/core/rich.py b/src/firewall/core/rich.py index 04791da612a2..c415bf39212f 100644 --- a/src/firewall/core/rich.py +++ b/src/firewall/core/rich.py @@ -266,12 +266,16 @@ class Rich_Limit(object): return '' class Rich_Rule(object): - def __init__(self, family=None, rule_str=None): + priority_min = -32768 + priority_max = 32767 + + def __init__(self, family=None, rule_str=None, priority=0): if family is not None: self.family = str(family) else: self.family = None + self.priority = priority self.source = None self.destination = None self.element = None @@ -303,6 +307,7 @@ class Rich_Rule(object): if not rule_str: raise FirewallError(errors.INVALID_RULE, 'empty rule') + self.priority = 0 self.family = None self.source = None self.destination = None @@ -325,7 +330,7 @@ class Rich_Rule(object): #print ("in_elements: ", in_elements) #print ("index: %s, element: %s, attribute: %s=%s" % (index, element, attr_name, attr_value)) if attr_name: # attribute - if attr_name not in ['family', 'address', 'mac', 'ipset', + if attr_name not in ['priority', 'family', 'address', 'mac', 'ipset', 'invert', 'value', 'port', 'protocol', 'to-port', 'to-addr', 'name', 'prefix', 'level', 'type', @@ -360,6 +365,8 @@ class Rich_Rule(object): if not element and attr_name: if attr_name == 'family': raise FirewallError(errors.INVALID_RULE, "'family' outside of rule. Use 'rule family=...'.") + elif attr_name == 'priority': + raise FirewallError(errors.INVALID_RULE, "'priority' outside of rule. Use 'rule priority=...'.") else: raise FirewallError(errors.INVALID_RULE, "'%s' outside of any element. Use 'rule %s= ...'." % (attr_name, attr_name)) elif 'rule' not in element: @@ -371,6 +378,8 @@ class Rich_Rule(object): if attr_value not in ['ipv4', 'ipv6']: raise FirewallError(errors.INVALID_RULE, "'family' attribute cannot have '%s' value. Use 'ipv4' or 'ipv6' instead." % attr_value) self.family = attr_value + elif attr_name == 'priority': + self.priority = int(attr_value) elif attr_name: if attr_name == 'protocol': err_msg = "wrong 'protocol' usage. Use either 'rule protocol value=...' or 'rule [forward-]port protocol=...'." @@ -528,6 +537,10 @@ class Rich_Rule(object): if type(self.element) == Rich_ForwardPort: raise FirewallError(errors.MISSING_FAMILY) + if self.priority < self.priority_min or self.priority > self.priority_max: + raise FirewallError(errors.INVALID_PRIORITY, "'priority' attribute must be between %d and %d." \ + % (self.priority_min, self.priority_max)) + if self.element is None: if self.action is None: raise FirewallError(errors.INVALID_RULE, "no element, no action") @@ -679,6 +692,8 @@ class Rich_Rule(object): def __str__(self): ret = 'rule' + if self.priority: + ret += ' priority="%d"' % self.priority if self.family: ret += ' family="%s"' % self.family if self.source: diff --git a/src/firewall/errors.py b/src/firewall/errors.py index a48038028f25..4589f60848b9 100644 --- a/src/firewall/errors.py +++ b/src/firewall/errors.py @@ -87,6 +87,7 @@ INVALID_IPSET = 135 INVALID_ENTRY = 136 INVALID_OPTION = 137 INVALID_HELPER = 138 +INVALID_PRIORITY = 139 MISSING_TABLE = 200 MISSING_CHAIN = 201 -- 2.18.0