Blob Blame History Raw
From 2871abfceceba37c6ba38aa0ef25e23a059294ec Mon Sep 17 00:00:00 2001
From: Vrinda Punj <vpunj@redhat.com>
Date: Wed, 18 Nov 2020 13:14:44 -0500
Subject: [PATCH 67/68] fix(zone): add source with mac address

nftables supports matching the destination MAC, but iptables does not.
As such, lift the restriction from nftables. For iptables, gracefully
ignore the scenarios in which we attempt to match destination MAC.

Fixes: #703
Fixes: df4aefcbe7b7 ("improvement(ipXtables): add utility function match sources")
Fixes: 1582c5dd736a ("feat: nftables: convert to libnftables JSON interface")

Co-authored-by: Eric Garver <eric@garver.life>
(cherry picked from commit 20151fbb5c5104e3d4dbc4ea938b9a68bdbcf225)
(cherry picked from commit 79bb113a2a108ce1c69dc7bc7af60297b8ec2ad0)
---
 src/firewall/core/ipXtables.py     |  4 ++++
 src/firewall/core/nftables.py      |  2 --
 src/tests/regression/gh703.at      | 23 +++++++++++++++++++++++
 src/tests/regression/regression.at |  1 +
 4 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 src/tests/regression/gh703.at

diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
index 450e427c08b5..b28146edd060 100644
--- a/src/firewall/core/ipXtables.py
+++ b/src/firewall/core/ipXtables.py
@@ -814,6 +814,10 @@ class ip4tables(object):
         else:
             zone_dispatch_chain = "%s_ZONES" % (chain)
 
+        # iptables can not match destination MAC
+        if check_mac(address) and chain in ["POSTROUTING", "FORWARD_OUT", "OUTPUT"]:
+            return []
+
         target = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS[chain], zone=zone)
         action = "-g"
 
diff --git a/src/firewall/core/nftables.py b/src/firewall/core/nftables.py
index 0a73c2c2669d..a0a899dd3eef 100644
--- a/src/firewall/core/nftables.py
+++ b/src/firewall/core/nftables.py
@@ -1067,8 +1067,6 @@ class nftables(object):
             return self._set_match_fragment(address[len("ipset:"):], True if "daddr" == addr_field else False, invert)
         else:
             if check_mac(address):
-                if addr_field == "daddr":
-                    raise FirewallError(INVALID_RULE, "%s._rule_addr_fragment()", (self.__class__))
                 family = "ether"
             elif check_single_address("ipv4", address):
                 family = "ip"
diff --git a/src/tests/regression/gh703.at b/src/tests/regression/gh703.at
new file mode 100644
index 000000000000..af724a7713a7
--- /dev/null
+++ b/src/tests/regression/gh703.at
@@ -0,0 +1,23 @@
+FWD_START_TEST([add source with mac address])
+AT_KEYWORDS(gh703)
+
+FWD_CHECK([--zone=home --add-source=34:7e:5c:3a:4c:32], 0, [ignore])
+
+NFT_LIST_RULES([ip], [nat_POSTROUTING_ZONES_SOURCE], 0, [dnl
+    table ip firewalld {
+        chain nat_POSTROUTING_ZONES_SOURCE {
+            ether daddr 34:7e:5c:3a:4c:32 goto nat_POST_home
+        }          
+    }          
+])
+NFT_LIST_RULES([ip6], [nat_POSTROUTING_ZONES_SOURCE], 0, [dnl
+    table ip6 firewalld {
+        chain nat_POSTROUTING_ZONES_SOURCE {
+            ether daddr 34:7e:5c:3a:4c:32 goto nat_POST_home
+        }          
+    }          
+])
+
+dnl NOTE: iptables does _not_ support matching mac destination.
+
+FWD_END_TEST
diff --git a/src/tests/regression/regression.at b/src/tests/regression/regression.at
index c1e8620ee700..7597a458076c 100644
--- a/src/tests/regression/regression.at
+++ b/src/tests/regression/regression.at
@@ -36,3 +36,4 @@ m4_include([regression/rhbz1541077.at])
 m4_include([regression/rhbz1855140.at])
 m4_include([regression/rhbz1871298.at])
 m4_include([regression/rhbz1596304.at])
+m4_include([regression/gh703.at])
-- 
2.27.0