From nobody Thu Sep 19 01:06:16 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) 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 171596896221750.16462555070564; Fri, 17 May 2024 11:02:42 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 27BB867; Fri, 17 May 2024 14:02:41 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 001B21E21; Fri, 17 May 2024 13:32:01 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id AE0E51C80; Fri, 17 May 2024 13:30:23 -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 E6C5B1A06 for ; Fri, 17 May 2024 13:30:12 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-470-WANmF78nOwOwHhQZrvGnYA-1; Fri, 17 May 2024 13:30:10 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 99647101A551 for ; Fri, 17 May 2024 17:30:10 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.16.223]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8011840C6EB7 for ; Fri, 17 May 2024 17:30:10 +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.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, 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 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1715967012; h=from:from: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; bh=mAY18Xlqen8/5VaD6pIeZq/Cf6LkOpsELZlCJbL7Syk=; b=d4KlMY2XMyrbU+82zMT3qshducR7B1jAWb/FAEnBXsL0GDaZuoDwSAFUk6TK30n/6KgZ1S uUhm2d8npNJFGzSdz+lDiQq1Yd4nsUk6BjfrXU/7Rt2BJfVuVBUjmyJFoU06R5VeoYj4JS l7Douatgi76N5FO0mdFVsR6q+m6z8pc= X-MC-Unique: WANmF78nOwOwHhQZrvGnYA-1 From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v5 19/30] util: new functions virFirewallParseXML() and virFirewallFormat() Date: Fri, 17 May 2024 13:29:56 -0400 Message-ID: <20240517173007.8125-20-laine@redhat.com> In-Reply-To: <20240517173007.8125-1-laine@redhat.com> References: <20240517173007.8125-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: QY6O2KDFNFCCFTJEQTBD53C4BLXESH7F X-Message-ID-Hash: QY6O2KDFNFCCFTJEQTBD53C4BLXESH7F 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: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1715968963919100001 Content-Type: text/plain; charset="utf-8"; x-default="true" These functions convert a virFirewall object to/from XML so that it can be serialized to disk (in a virNetworkObj's status file) and restored later (e.g. after libvirtd/virtnetworkd is restarted). Signed-off-by: Laine Stump Reviewed-by: Daniel P. Berrang=C3=A9 --- src/libvirt_private.syms | 2 + src/util/virfirewall.c | 219 +++++++++++++++++++++++++++++++++++++++ src/util/virfirewall.h | 9 ++ 3 files changed, 230 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4e6a113ba1..eb328ca04f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2415,11 +2415,13 @@ virFirewallCmdAddArgList; virFirewallCmdAddArgSet; virFirewallCmdGetArgCount; virFirewallCmdToString; +virFirewallFormat; virFirewallFree; virFirewallGetBackend; virFirewallGetName; virFirewallNew; virFirewallNewFromRollback; +virFirewallParseXML; virFirewallRemoveCmd; virFirewallSetName; virFirewallStartRollback; diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c index 2f4f128cd1..649b2289c0 100644 --- a/src/util/virfirewall.c +++ b/src/util/virfirewall.c @@ -39,6 +39,14 @@ VIR_ENUM_IMPL(virFirewallBackend, VIR_FIREWALL_BACKEND_LAST, "iptables"); =20 +VIR_ENUM_DECL(virFirewallLayer); +VIR_ENUM_IMPL(virFirewallLayer, + VIR_FIREWALL_LAYER_LAST, + "ethernet", + "ipv4", + "ipv6", +); + typedef struct _virFirewallGroup virFirewallGroup; =20 VIR_ENUM_DECL(virFirewallLayerCommand); @@ -827,3 +835,214 @@ virFirewallNewFromRollback(virFirewall *original, =20 return 0; } + + +/* virFirewallGetFlagsFromNode: + * @node: the xmlNode to check for an ignoreErrors attribute + * + * A short helper to get the setting of the ignorErrors attribute from + * an xmlNode. Returns -1 on error (with error reported), or the + * VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS bit set/reset according to + * the value of the attribute. + */ +static int +virFirewallGetFlagsFromNode(xmlNodePtr node) +{ + virTristateBool ignoreErrors; + + if (virXMLPropTristateBool(node, "ignoreErrors", VIR_XML_PROP_NONE, &i= gnoreErrors) < 0) + return -1; + + if (ignoreErrors =3D=3D VIR_TRISTATE_BOOL_YES) + return VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS; + return 0; +} + + +/** + * virFirewallParseXML: + * @firewall: pointer to virFirewall* to fill in with new virFirewall obje= ct + * + * Construct a new virFirewall object according to the XML in + * xmlNodePtr. Return 0 (and new object) on success, or -1 (with + * error reported) on error. + * + * Example of element XML: + * + * + * + * + * + * arg1 + * arg2 + * ... + * + * + * + * ... + + * ... + * + * ... + * + */ +int +virFirewallParseXML(virFirewall **firewall, + xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + g_autoptr(virFirewall) newfw =3D NULL; + virFirewallBackend backend; + g_autofree xmlNodePtr *groupNodes =3D NULL; + ssize_t ngroups; + size_t g; + VIR_XPATH_NODE_AUTORESTORE(ctxt); + + ctxt->node =3D node; + + if (virXMLPropEnum(node, "backend", virFirewallBackendTypeFromString, + VIR_XML_PROP_REQUIRED, &backend) < 0) { + return -1; + } + + newfw =3D virFirewallNew(backend); + + newfw->name =3D virXMLPropString(node, "name"); + + ngroups =3D virXPathNodeSet("./group", ctxt, &groupNodes); + if (ngroups < 0) + return -1; + + for (g =3D 0; g < ngroups; g++) { + int flags =3D 0; + g_autofree xmlNodePtr *actionNodes =3D NULL; + ssize_t nactions; + size_t a; + + ctxt->node =3D groupNodes[g]; + nactions =3D virXPathNodeSet("./action", ctxt, &actionNodes); + if (nactions < 0) + return -1; + if (nactions =3D=3D 0) + continue; + + if ((flags =3D virFirewallGetFlagsFromNode(groupNodes[g])) < 0) + return -1; + + virFirewallStartTransaction(newfw, flags); + + for (a =3D 0; a < nactions; a++) { + g_autofree xmlNodePtr *argsNodes =3D NULL; + ssize_t nargs; + size_t i; + virFirewallLayer layer; + virFirewallCmd *action; + bool ignoreErrors; + + ctxt->node =3D actionNodes[a]; + + if (!(ctxt->node =3D virXPathNode("./args", ctxt))) + continue; + + if ((flags =3D virFirewallGetFlagsFromNode(actionNodes[a])) < = 0) + return -1; + + ignoreErrors =3D flags & VIR_FIREWALL_TRANSACTION_IGNORE_ERROR= S; + + if (virXMLPropEnum(actionNodes[a], "layer", + virFirewallLayerTypeFromString, + VIR_XML_PROP_REQUIRED, &layer) < 0) { + return -1; + } + + nargs =3D virXPathNodeSet("./item", ctxt, &argsNodes); + if (nargs < 0) + return -1; + if (nargs =3D=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid firewall command has 0 arguments= ")); + return -1; + } + + action =3D virFirewallAddCmdFull(newfw, layer, ignoreErrors, + NULL, NULL, NULL); + for (i =3D 0; i < nargs; i++) { + + char *arg =3D virXMLNodeContentString(argsNodes[i]); + if (!arg) + return -1; + + virFirewallCmdAddArg(newfw, action, arg); + } + } + } + + *firewall =3D g_steal_pointer(&newfw); + return 0; +} + + +/** + * virFirewallFormat: + * @buf: output buffer + * @firewall: the virFirewall object to format as XML + * + * Format virFirewall object @firewall into @buf as XML. + * Returns 0 on success, -1 on failure. + * + */ +int +virFirewallFormat(virBuffer *buf, + virFirewall *firewall) +{ + size_t g; + g_auto(virBuffer) attrBuf =3D VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBuf =3D VIR_BUFFER_INIT_CHILD(buf); + + virBufferEscapeString(&attrBuf, " name=3D'%s'", firewall->name); + virBufferAsprintf(&attrBuf, " backend=3D'%s'", + virFirewallBackendTypeToString(virFirewallGetBackend= (firewall))); + + for (g =3D 0; g < firewall->ngroups; g++) { + virFirewallGroup *group =3D firewall->groups[g]; + bool groupIgnoreErrors =3D (group->actionFlags & + VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + size_t a; + + virBufferAddLit(&childBuf, "\n"); + virBufferAdjustIndent(&childBuf, 2); + + for (a =3D 0; a < group->naction; a++) { + virFirewallCmd *action =3D group->action[a]; + size_t i; + + virBufferAsprintf(&childBuf, "layer)); + /* if the entire group has ignoreErrors=3D'yes', then it's + * redundant to have it for an action of the group + */ + if (action->ignoreErrors && !groupIgnoreErrors) + virBufferAddLit(&childBuf, " ignoreErrors=3D'yes'"); + virBufferAddLit(&childBuf, ">\n"); + + virBufferAdjustIndent(&childBuf, 2); + virBufferAddLit(&childBuf, "\n"); + virBufferAdjustIndent(&childBuf, 2); + for (i =3D 0; i < virFirewallCmdGetArgCount(action); i++) + virBufferEscapeString(&childBuf, "%s\n", acti= on->args[i]); + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "\n"); + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "\n"); + } + + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "\n"); + } + + virXMLFormatElement(buf, "firewall", &attrBuf, &childBuf); + return 0; +} diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h index 931dfb04cf..917745c315 100644 --- a/src/util/virfirewall.h +++ b/src/util/virfirewall.h @@ -22,6 +22,8 @@ =20 #include "internal.h" #include "virenum.h" +#include "virbuffer.h" +#include "virxml.h" =20 typedef struct _virFirewall virFirewall; =20 @@ -131,4 +133,11 @@ void virFirewallStartRollback(virFirewall *firewall, =20 int virFirewallApply(virFirewall *firewall); =20 +int virFirewallParseXML(virFirewall **firewall, + xmlNodePtr node, + xmlXPathContextPtr ctxt); + +int virFirewallFormat(virBuffer *buf, + virFirewall *firewall); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virFirewall, virFirewallFree); --=20 2.45.0