On Sun, Apr 21, 2024 at 10:53:26PM -0400, Laine Stump wrote: > 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 <laine@xxxxxxxxxx> > --- > src/libvirt_private.syms | 2 + > src/util/virfirewall.c | 217 +++++++++++++++++++++++++++++++++++++++ > src/util/virfirewall.h | 9 ++ > 3 files changed, 228 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index e3dcb353b7..aa253a238b 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -2413,10 +2413,12 @@ virFirewallCmdAddArgList; > virFirewallCmdAddArgSet; > virFirewallCmdGetArgCount; > virFirewallCmdToString; > +virFirewallFormat; > virFirewallFree; > virFirewallGetBackend; > virFirewallNew; > virFirewallNewFromRollback; > +virFirewallParseXML; > virFirewallRemoveCmd; > virFirewallStartRollback; > virFirewallStartTransaction; > diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c > index 57d45abc17..684569c760 100644 > --- a/src/util/virfirewall.c > +++ b/src/util/virfirewall.c > @@ -40,6 +40,14 @@ VIR_ENUM_IMPL(virFirewallBackend, > "UNSET", /* not yet set */ > "iptables"); > > +VIR_ENUM_DECL(virFirewallLayer); > +VIR_ENUM_IMPL(virFirewallLayer, > + VIR_FIREWALL_LAYER_LAST, > + "ethernet", > + "ipv4", > + "ipv6", > +); > + > typedef struct _virFirewallGroup virFirewallGroup; > > VIR_ENUM_DECL(virFirewallLayerCommand); > @@ -810,3 +818,212 @@ virFirewallNewFromRollback(virFirewall *original, > > 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, &ignoreErrors) < 0) > + return -1; > + > + if (ignoreErrors == VIR_TRISTATE_BOOL_YES) > + return VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS; > + return 0; > +} > + > + > +/** > + * virFirewallParseXML: > + * @firewall: pointer to virFirewall* to fill in with new virFirewall object > + * > + * 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 <firewall> element XML: > + * > + * <firewall backend='iptables|nftables'> > + * <group ignoreErrors='yes|no'> > + * <action layer='ethernet|ipv4|ipv6' ignoreErrors='yes|no'> > + * <args> > + * <item>arg1</item> > + * <item>arg2</item> > + * ... > + * </args> > + * </action> > + * <action ...> > + * ... > + </action> > + * ... > + * </group> > + * ... > + * </firewall> > + */ > +int > +virFirewallParseXML(virFirewall **firewall, > + xmlNodePtr node, > + xmlXPathContextPtr ctxt) > +{ > + g_autoptr(virFirewall) newfw = NULL; > + virFirewallBackend backend; > + g_autofree xmlNodePtr *groupNodes = NULL; > + ssize_t ngroups; > + size_t g; > + VIR_XPATH_NODE_AUTORESTORE(ctxt); > + > + ctxt->node = node; > + > + ngroups = virXPathNodeSet("./group", ctxt, &groupNodes); > + if (ngroups < 0) > + return -1; > + if (ngroups == 0) > + return 0; > + > + if (virXMLPropEnum(node, "backend", virFirewallBackendTypeFromString, > + VIR_XML_PROP_REQUIRED, &backend) < 0) { > + return -1; > + } > + > + newfw = virFirewallNew(backend); > + > + for (g = 0; g < ngroups; g++) { > + int flags = 0; > + g_autofree xmlNodePtr *actionNodes = NULL; > + ssize_t nactions; > + size_t a; > + > + ctxt->node = groupNodes[g]; > + nactions = virXPathNodeSet("./action", ctxt, &actionNodes); > + if (nactions < 0) > + return -1; > + if (nactions == 0) > + continue; > + > + if ((flags = virFirewallGetFlagsFromNode(groupNodes[g])) < 0) > + return -1; > + > + virFirewallStartTransaction(newfw, flags); > + > + for (a = 0; a < nactions; a++) { > + g_autofree xmlNodePtr *argsNodes = NULL; > + ssize_t nargs; > + size_t i; > + virFirewallLayer layer; > + virFirewallCmd *action; > + bool ignoreErrors; > + > + ctxt->node = actionNodes[a]; > + > + if (!(ctxt->node = virXPathNode("./args", ctxt))) > + continue; > + > + if ((flags = virFirewallGetFlagsFromNode(actionNodes[a])) < 0) > + return -1; > + > + ignoreErrors = flags & VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS; > + > + if (virXMLPropEnum(actionNodes[a], "layer", > + virFirewallLayerTypeFromString, > + VIR_XML_PROP_REQUIRED, &layer) < 0) { > + return -1; > + } > + > + nargs = virXPathNodeSet("./item", ctxt, &argsNodes); > + if (nargs < 0) > + return -1; > + if (nargs == 0) > + continue; In an earlier patch you indicated that nargs == 0 was an error condition we should check and report. How about reporting it here too, rather than delaying it ? > + > + action = virFirewallAddCmdFull(newfw, layer, ignoreErrors, > + NULL, NULL, NULL); > + for (i = 0; i < nargs; i++) { > + > + char *arg = virXMLNodeContentString(argsNodes[i]); > + if (!arg) > + return -1; > + > + virFirewallCmdAddArg(newfw, action, arg); > + } > + } > + } > + > + *firewall = g_steal_pointer(&newfw); > + return 0; > +} With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :| _______________________________________________ Devel mailing list -- devel@xxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx