From nobody Fri Dec 19 19:16:03 2025 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1714500005251575.4726893276602; Tue, 30 Apr 2024 11:00:05 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id CCBA753D; Tue, 30 Apr 2024 13:59:48 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 09DF42421; Tue, 30 Apr 2024 13:45:12 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 8CDB91E72; Tue, 30 Apr 2024 13:44:29 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 690761E72 for ; Tue, 30 Apr 2024 13:44:24 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-390-CnKmtVZNNsOWo47qi2_gVA-1; Tue, 30 Apr 2024 13:44:22 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6977E1C4C3E7 for ; Tue, 30 Apr 2024 17:44:22 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.16.229]) by smtp.corp.redhat.com (Postfix) with ESMTP id 516C2581C8 for ; Tue, 30 Apr 2024 17:44:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: CnKmtVZNNsOWo47qi2_gVA-1 From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v4 14/30] util: new functions to support adding individual firewall rollback commands Date: Tue, 30 Apr 2024 13:44:03 -0400 Message-ID: <20240430174420.371179-15-laine@redhat.com> In-Reply-To: <20240430174420.371179-1-laine@redhat.com> References: <20240430174420.371179-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: 4RW7ZJWY374A26I3MGNJZJC47EZECQGR X-Message-ID-Hash: 4RW7ZJWY374A26I3MGNJZJC47EZECQGR X-MailFrom: laine@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8"; x-default="true" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1714500007357100001 In the past virFirewall required all rollback commands for a group (those commands necessary to "undo" any rules that had been added in that group in case of a later failure) to be manually added by switching into the virFirewall object into "rollback mode" and then re-calling the inverse of the exact virFirewallAddCmd*() APIs that had been called to add the original rules (ie. for each "iptables --insert" command, for rollback we would need to add a command with all arguments identical except that "--insert" would be replaced by "--delete"). Because nftables can't search for rules to remove by comparing all the arguments (it instead expects *only* a handle that is provided via stdout when the rule was originally added), we won't be able to follow the iptables method and manually construct the command to undo any given nft command by just duplicating all the args of the command (except the action). Instead we will need to be able to automatically create a rollback command at the time the rule-adding command is executed (e.g. an "nft delete rule" command that would include the rule handle returned in stdout by an "nft add rule" command). In order to make this happen, we need to be able to 1) learn whether the user of the virFirewall API desires this behavior (handled by a new transaction flag called VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK that can be retrieved with the new virFirewallTransactionGetFlags() API), and 2) add a new command to the current group's rollback command list (with the new virFirewallAddRollbackCmd()). We will actually use this capability in an upcoming patch. Signed-off-by: Laine Stump Reviewed-by: Daniel P. Berrang=C3=A9 --- src/libvirt_private.syms | 1 + src/util/virfirewall.c | 55 +++++++++++++++++++++++++++++++++++----- src/util/virfirewall.h | 7 +++++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 457b51e289..b3cbe1a833 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2404,6 +2404,7 @@ virFileCacheSetPriv; =20 # util/virfirewall.h virFirewallAddCmdFull; +virFirewallAddRollbackCmd; virFirewallApply; virFirewallBackendTypeFromString; virFirewallBackendTypeToString; diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c index 77de34533d..9def8999d5 100644 --- a/src/util/virfirewall.c +++ b/src/util/virfirewall.c @@ -198,10 +198,12 @@ void virFirewallFree(virFirewall *firewall) fwCmd->args[fwCmd->argsLen++] =3D g_strdup(str); \ } while (0) =20 + static virFirewallCmd * virFirewallAddCmdFullV(virFirewall *firewall, virFirewallLayer layer, bool ignoreErrors, + bool isRollback, virFirewallQueryCallback cb, void *opaque, va_list args) @@ -218,18 +220,16 @@ virFirewallAddCmdFullV(virFirewall *firewall, } group =3D firewall->groups[firewall->currentGroup]; =20 - fwCmd =3D g_new0(virFirewallCmd, 1); - fwCmd->layer =3D layer; - fwCmd->queryCB =3D cb; - fwCmd->queryOpaque =3D opaque; =20 while ((str =3D va_arg(args, char *)) !=3D NULL) ADD_ARG(fwCmd, str); =20 - if (group->addingRollback) { + if (isRollback || group->addingRollback) { fwCmd->ignoreErrors =3D true; /* always ignore errors when rolling= back */ + fwCmd->queryCB =3D NULL; /* rollback commands can't have a callbac= k */ + fwCmd->queryOpaque =3D NULL; VIR_APPEND_ELEMENT_COPY(group->rollback, group->nrollback, fwCmd); } else { /* when not rolling back, ignore errors if this group (transaction) @@ -237,6 +237,8 @@ virFirewallAddCmdFullV(virFirewall *firewall, * if this specific rule was created with ignoreErrors =3D=3D true */ fwCmd->ignoreErrors =3D ignoreErrors || (group->actionFlags & VIR_= FIREWALL_TRANSACTION_IGNORE_ERRORS); + fwCmd->queryCB =3D cb; + fwCmd->queryOpaque =3D opaque; VIR_APPEND_ELEMENT_COPY(group->action, group->naction, fwCmd); } =20 @@ -277,7 +279,33 @@ virFirewallCmd *virFirewallAddCmdFull(virFirewall *fir= ewall, virFirewallCmd *fwCmd; va_list args; va_start(args, opaque); - fwCmd =3D virFirewallAddCmdFullV(firewall, layer, ignoreErrors, cb, op= aque, args); + fwCmd =3D virFirewallAddCmdFullV(firewall, layer, ignoreErrors, false,= cb, opaque, args); + va_end(args); + return fwCmd; +} + + +/** + * virFirewallAddRollbackCmd: + * @firewall: firewall commands to add to + * @layer: the firewall layer to change + * @...: NULL terminated list of strings for the command + * + * Add a command to the current firewall command group "rollback". + * Rollback commands always ignore errors and don't support any + * callbacks. + * + * Returns the new Command + */ +virFirewallCmd * +virFirewallAddRollbackCmd(virFirewall *firewall, + virFirewallLayer layer, + ...) +{ + virFirewallCmd *fwCmd; + va_list args; + va_start(args, layer); + fwCmd =3D virFirewallAddCmdFullV(firewall, layer, true, true, NULL, NU= LL, args); va_end(args); return fwCmd; } @@ -434,6 +462,21 @@ void virFirewallStartTransaction(virFirewall *firewall, firewall->currentGroup =3D firewall->ngroups - 1; } =20 + +/** + * virFirewallTransactionGetFlags: + * @firewall: the firewall to look at + * + * Returns the virFirewallTransactionFlags for the currently active + * group (transaction) in @firewall. + */ +static virFirewallTransactionFlags G_GNUC_UNUSED +virFirewallTransactionGetFlags(virFirewall *firewall) +{ + return firewall->groups[firewall->currentGroup]->actionFlags; +} + + /** * virFirewallBeginRollback: * @firewall: the firewall ruleset diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h index 1ca1cce10a..e6aac365f1 100644 --- a/src/util/virfirewall.h +++ b/src/util/virfirewall.h @@ -73,6 +73,11 @@ virFirewallCmd *virFirewallAddCmdFull(virFirewall *firew= all, ...) G_GNUC_NULL_TERMINATED; =20 +virFirewallCmd *virFirewallAddRollbackCmd(virFirewall *firewall, + virFirewallLayer layer, + ...) + G_GNUC_NULL_TERMINATED; + void virFirewallRemoveCmd(virFirewall *firewall, virFirewallCmd *rule); =20 @@ -105,6 +110,8 @@ typedef enum { /* Ignore all errors when applying rules, so no * rollback block will be required */ VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS =3D (1 << 0), + /* Set to auto-add a rollback rule for each rule that is applied */ + VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK =3D (1 << 1), } virFirewallTransactionFlags; =20 void virFirewallStartTransaction(virFirewall *firewall, --=20 2.44.0 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org