From nobody Mon Sep 16 20:06:10 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1682911270; cv=none; d=zohomail.com; s=zohoarc; b=jcKVWaySEdHfj+MVPQOSuNEI3gAaHgi05tqEKLx5Koe1XO0c2p9CkIuYCnIRcWr+UQsbWwV/avWYm92MJFWHmESxGtpjJicLnabjxUGIU9aFmbmnxgU5gdq++MA9u7rnw9QLJCH8ZAx/8PxWZn0EMDsvXH/bTBX2143luVV+TJk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1682911270; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=dUElZeRLHVfKBO2+GgTYqwJ+jOXTjusoxbjhrLLp8ds=; b=eCjwtDLlMwEGASQnmO2SoQ/N7gOsqFMrZSISwApNNHehGSbWJHD4rQZdzEldw+7968kfFAd0DWNHiJxCYXzqA2/G2zPXuoesMzvKy/JX/v/N3k5gQc4Z+jk+qJV8W5EnemDpKr9eYkdFH7IxZMONdlxSQLFRZAkMSbMB7FsjaYQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1682911270894875.7092323427397; Sun, 30 Apr 2023 20:21:10 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-226-WVfqtbudPiOSEmltqM70TA-1; Sun, 30 Apr 2023 23:20:12 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3FF2E1818E50; Mon, 1 May 2023 03:20:09 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 298B4112131E; Mon, 1 May 2023 03:20:09 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id C46E61946A54; Mon, 1 May 2023 03:20:06 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id CAD8519465B3 for ; Mon, 1 May 2023 03:20:05 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 7B9FD4750C1; Mon, 1 May 2023 03:19:45 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.8.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5F4AD4750C0 for ; Mon, 1 May 2023 03:19:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1682911269; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=dUElZeRLHVfKBO2+GgTYqwJ+jOXTjusoxbjhrLLp8ds=; b=JsOr0Nmlv7u9bjJZ0rzD7pwMIJIQHR7C3OGGzjNXPnPIfdU/ktBmaTHg3WqxqetG/oiFzr vgSLIFljGgR20sp1GxEOgsuERL8VUm5IrDXJRHW4nxtNEmNY6oNXsgpZezs3yuLw0jW3mb AzaVjwof1OEhPIpofsvS7XBnQNsAp14= X-MC-Unique: WVfqtbudPiOSEmltqM70TA-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Laine Stump To: libvir-list@redhat.com Subject: [libvirt PATCH 09/28] util/network: reintroduce virFirewallBackend, but different Date: Sun, 30 Apr 2023 23:19:24 -0400 Message-Id: <20230501031943.288145-10-laine@redhat.com> In-Reply-To: <20230501031943.288145-1-laine@redhat.com> References: <20230501031943.288145-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1682911271582100001 Content-Type: text/plain; charset="utf-8"; x-default="true" In the past, virFirewallBackend was a private static in virfirewall.c that was set at daemon init time, and used to globally (i.e. for all drivers in the daemon) determine whether to directly execute iptables commands, or to run them indirectly via the firewalld passthrough API. This was removed in commit d566cc55, since we decided that using the firewalld passthrough API is never appropriate. Now the virFirewallBackend enum is being reintroduced, with a slightly different meaning and usage pattern. It will be used to pick between using nftables commands or iptables commands (in either case directly handled by libvirt, *not* via firewalld). Additionally, rather than being a static known only within virfirewall.c and applying to all firewall commands for all drivers, each virFirewall object will have its own backend setting, which will be set during virFirewallNew() by the driver who wants to add a firewall rule. This will allow the nwfilter and network drivers to each have their own backend setting, even when they coexist in a single unified daemon. At least as important as that, it will also allow an instance of the network driver to remove iptables rules that had been added by a previous instance, and then add nftables rules for the new instance (in the case that an admin, or possibly an update, switches the driver backend from iptables to nftable) Initially, the enum will only have one usable value - VIR_FIREWALL_BACKEND_IPTABLES, and that will be hardcoded into all calls to virFirewallNew(). The other enum value (along with a method of setting it for each driver) will be added later, when it can be used (when the nftables backend is in the code). Signed-off-by: Laine Stump --- src/libvirt_private.syms | 3 +++ src/network/bridge_driver_linux.c | 4 ++-- src/nwfilter/nwfilter_ebiptables_driver.c | 16 ++++++++-------- src/util/virebtables.c | 4 ++-- src/util/virfirewall.c | 16 +++++++++++++++- src/util/virfirewall.h | 12 +++++++++++- src/util/viriptables.c | 2 +- tests/virfirewalltest.c | 20 ++++++++++---------- 8 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cf68e4c942..a09e5ae871 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2373,7 +2373,10 @@ virFileCacheSetPriv; # util/virfirewall.h virFirewallAddRuleFull; virFirewallApply; +virFirewallBackendTypeFromString; +virFirewallBackendTypeToString; virFirewallFree; +virFirewallGetBackend; virFirewallNew; virFirewallRemoveRule; virFirewallRuleAddArg; diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_= linux.c index e03c17b259..c6aab9b236 100644 --- a/src/network/bridge_driver_linux.c +++ b/src/network/bridge_driver_linux.c @@ -806,7 +806,7 @@ int networkAddFirewallRules(virNetworkDef *def) { size_t i; virNetworkIPDef *ipdef; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 if (virOnce(&createdOnce, networkSetupPrivateChains) < 0) return -1; @@ -932,7 +932,7 @@ void networkRemoveFirewallRules(virNetworkDef *def) { size_t i; virNetworkIPDef *ipdef; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS= ); networkRemoveChecksumFirewallRules(fw, def); diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfil= ter_ebiptables_driver.c index 99a74a60e5..9ed23c27a3 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2815,7 +2815,7 @@ static int ebtablesApplyBasicRules(const char *ifname, const virMacAddr *macaddr) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); char chain[MAX_CHAINNAME_LENGTH]; char chainPrefix =3D CHAINPREFIX_HOST_IN_TEMP; char macaddr_str[VIR_MAC_STRING_BUFLEN]; @@ -2888,7 +2888,7 @@ ebtablesApplyDHCPOnlyRules(const char *ifname, char macaddr_str[VIR_MAC_STRING_BUFLEN]; unsigned int idx =3D 0; unsigned int num_dhcpsrvrs; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virMacAddrFormat(macaddr, macaddr_str); =20 @@ -2990,7 +2990,7 @@ ebtablesApplyDropAllRules(const char *ifname) { char chain_in [MAX_CHAINNAME_LENGTH], chain_out[MAX_CHAINNAME_LENGTH]; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 if (ebiptablesAllTeardown(ifname) < 0) return -1; @@ -3037,7 +3037,7 @@ ebtablesRemoveBasicRules(const char *ifname) static int ebtablesCleanAll(const char *ifname) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS= ); =20 @@ -3291,7 +3291,7 @@ ebiptablesApplyNewRules(const char *ifname, size_t nrules) { size_t i, j; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); g_autoptr(GHashTable) chains_in_set =3D virHashNew(NULL); g_autoptr(GHashTable) chains_out_set =3D virHashNew(NULL); bool haveEbtables =3D false; @@ -3513,7 +3513,7 @@ ebiptablesTearNewRulesFW(virFirewall *fw, const char = *ifname) static int ebiptablesTearNewRules(const char *ifname) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS= ); =20 @@ -3525,7 +3525,7 @@ ebiptablesTearNewRules(const char *ifname) static int ebiptablesTearOldRules(const char *ifname) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS= ); =20 @@ -3560,7 +3560,7 @@ ebiptablesTearOldRules(const char *ifname) static int ebiptablesAllTeardown(const char *ifname) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS= ); =20 diff --git a/src/util/virebtables.c b/src/util/virebtables.c index a1f5f7cf1e..f242186c52 100644 --- a/src/util/virebtables.c +++ b/src/util/virebtables.c @@ -78,7 +78,7 @@ ebtablesContextFree(ebtablesContext *ctx) int ebtablesAddForwardPolicyReject(ebtablesContext *ctx) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS= ); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, @@ -106,7 +106,7 @@ ebtablesForwardAllowIn(ebtablesContext *ctx, const char *macaddr, int action) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); =20 virFirewallStartTransaction(fw, 0); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c index 6603fd6341..e1fda162c4 100644 --- a/src/util/virfirewall.c +++ b/src/util/virfirewall.c @@ -36,6 +36,11 @@ =20 VIR_LOG_INIT("util.firewall"); =20 +VIR_ENUM_IMPL(virFirewallBackend, + VIR_FIREWALL_BACKEND_LAST, + "UNSET", /* not yet set */ + "iptables"); + typedef struct _virFirewallGroup virFirewallGroup; =20 struct _virFirewallRule { @@ -70,6 +75,7 @@ struct _virFirewall { size_t ngroups; virFirewallGroup **groups; size_t currentGroup; + virFirewallBackend backend; }; =20 static virMutex ruleLock =3D VIR_MUTEX_INITIALIZER; @@ -91,14 +97,22 @@ virFirewallGroupNew(void) * * Returns the new firewall ruleset */ -virFirewall *virFirewallNew(void) +virFirewall *virFirewallNew(virFirewallBackend backend) { virFirewall *firewall =3D g_new0(virFirewall, 1); =20 + firewall->backend =3D backend; return firewall; } =20 =20 +virFirewallBackend +virFirewallGetBackend(virFirewall *firewall) +{ + return firewall->backend; +} + + static void virFirewallRuleFree(virFirewallRule *rule) { diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h index ed0bc8b6f7..020dd2bedb 100644 --- a/src/util/virfirewall.h +++ b/src/util/virfirewall.h @@ -21,6 +21,7 @@ #pragma once =20 #include "internal.h" +#include "virenum.h" =20 typedef struct _virFirewall virFirewall; =20 @@ -42,9 +43,18 @@ typedef enum { VIR_FIREWALL_ACTION_LAST } virFirewallAction; =20 -virFirewall *virFirewallNew(void); +typedef enum { + VIR_FIREWALL_BACKEND_UNSET, + VIR_FIREWALL_BACKEND_IPTABLES, + + VIR_FIREWALL_BACKEND_LAST, +} virFirewallBackend; + +VIR_ENUM_DECL(virFirewallBackend); =20 +virFirewall *virFirewallNew(virFirewallBackend backend); void virFirewallFree(virFirewall *firewall); +virFirewallBackend virFirewallGetBackend(virFirewall *firewall); =20 /** * virFirewallAddRule: diff --git a/src/util/viriptables.c b/src/util/viriptables.c index 9c7f7790c4..96b69daf68 100644 --- a/src/util/viriptables.c +++ b/src/util/viriptables.c @@ -196,7 +196,7 @@ iptablesPrivateChainCreate(virFirewall *fw, int iptablesSetupPrivateChains(virFirewallLayer layer) { - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); iptablesGlobalChain filter_chains[] =3D { {"INPUT", VIR_NETFILTER_INPUT_CHAIN}, {"OUTPUT", VIR_NETFILTER_OUTPUT_CHAIN}, diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c index e676a434c8..48300bf242 100644 --- a/tests/virfirewalltest.c +++ b/tests/virfirewalltest.c @@ -62,7 +62,7 @@ static int testFirewallSingleGroup(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -102,7 +102,7 @@ static int testFirewallRemoveRule(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -148,7 +148,7 @@ static int testFirewallManyGroups(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -222,7 +222,7 @@ static int testFirewallIgnoreFailGroup(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -275,7 +275,7 @@ static int testFirewallIgnoreFailRule(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -327,7 +327,7 @@ static int testFirewallNoRollback(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -372,7 +372,7 @@ static int testFirewallSingleRollback(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -437,7 +437,7 @@ static int testFirewallManyRollback(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -505,7 +505,7 @@ static int testFirewallChainedRollback(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" @@ -682,7 +682,7 @@ static int testFirewallQuery(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) cmdbuf =3D VIR_BUFFER_INITIALIZER; - g_autoptr(virFirewall) fw =3D virFirewallNew(); + g_autoptr(virFirewall) fw =3D virFirewallNew(VIR_FIREWALL_BACKEND_IPTA= BLES); const char *actual =3D NULL; const char *expected =3D IPTABLES " -w -A INPUT --source 192.168.122.1 --jump ACCEPT\n" --=20 2.39.2