/* * virnwfilterbindingobj.c: network filter binding object processing * * Copyright (C) 2018 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include #include #include "viralloc.h" #include "virerror.h" #include "virstring.h" #include "nwfilter_params.h" #include "virnwfilterbindingobj.h" #include "viruuid.h" #include "virfile.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER struct _virNWFilterBindingObj { virObjectLockable parent; bool removing; virNWFilterBindingDef *def; }; static virClass *virNWFilterBindingObjClass; static void virNWFilterBindingObjDispose(void *obj); static int virNWFilterBindingObjOnceInit(void) { if (!VIR_CLASS_NEW(virNWFilterBindingObj, virClassForObjectLockable())) return -1; return 0; } VIR_ONCE_GLOBAL_INIT(virNWFilterBindingObj); virNWFilterBindingObj * virNWFilterBindingObjNew(void) { virNWFilterBindingObj *ret; if (virNWFilterBindingObjInitialize() < 0) return NULL; if (!(ret = virObjectLockableNew(virNWFilterBindingObjClass))) return NULL; virObjectLock(ret); return ret; } static void virNWFilterBindingObjDispose(void *obj) { virNWFilterBindingObj *bobj = obj; virNWFilterBindingDefFree(bobj->def); } virNWFilterBindingDef * virNWFilterBindingObjGetDef(virNWFilterBindingObj *obj) { return obj->def; } void virNWFilterBindingObjSetDef(virNWFilterBindingObj *obj, virNWFilterBindingDef *def) { virNWFilterBindingDefFree(obj->def); obj->def = def; } virNWFilterBindingDef * virNWFilterBindingObjStealDef(virNWFilterBindingObj *obj) { return g_steal_pointer(&obj->def); } bool virNWFilterBindingObjGetRemoving(virNWFilterBindingObj *obj) { return obj->removing; } void virNWFilterBindingObjSetRemoving(virNWFilterBindingObj *obj, bool removing) { obj->removing = removing; } /** * virNWFilterBindingObjEndAPI: * @obj: binding object * * Finish working with a binding object in an API. This function * clears whatever was left of a domain that was gathered using * virNWFilterBindingObjListFindByPortDev(). Currently that means * only unlocking and decrementing the reference counter of that * object. And in order to make sure the caller does not access * the object, the pointer is cleared. */ void virNWFilterBindingObjEndAPI(virNWFilterBindingObj **obj) { if (!*obj) return; virObjectUnlock(*obj); g_clear_pointer(obj, virObjectUnref); } char * virNWFilterBindingObjConfigFile(const char *dir, const char *name) { return g_strdup_printf("%s/%s.xml", dir, name); } int virNWFilterBindingObjSave(const virNWFilterBindingObj *obj, const char *statusDir) { char *filename; char *xml = NULL; int ret = -1; if (!(filename = virNWFilterBindingObjConfigFile(statusDir, obj->def->portdevname))) return -1; if (!(xml = virNWFilterBindingObjFormat(obj))) goto cleanup; if (g_mkdir_with_parents(statusDir, 0777) < 0) { virReportSystemError(errno, _("cannot create config directory '%s'"), statusDir); goto cleanup; } ret = virXMLSaveFile(filename, obj->def->portdevname, "nwfilter-binding-create", xml); cleanup: VIR_FREE(xml); VIR_FREE(filename); return ret; } int virNWFilterBindingObjDelete(const virNWFilterBindingObj *obj, const char *statusDir) { char *filename; int ret = -1; if (!(filename = virNWFilterBindingObjConfigFile(statusDir, obj->def->portdevname))) return -1; if (unlink(filename) < 0 && errno != ENOENT) { virReportSystemError(errno, _("Unable to remove status '%s' for nwfilter binding %s'"), filename, obj->def->portdevname); goto cleanup; } ret = 0; cleanup: VIR_FREE(filename); return ret; } static virNWFilterBindingObj * virNWFilterBindingObjParseXML(xmlDocPtr doc, xmlXPathContextPtr ctxt) { virNWFilterBindingObj *ret; xmlNodePtr node; if (!(ret = virNWFilterBindingObjNew())) return NULL; if (!(node = virXPathNode("./filterbinding", ctxt))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("filter binding status missing content")); goto cleanup; } if (!(ret->def = virNWFilterBindingDefParseNode(doc, node))) goto cleanup; return ret; cleanup: virObjectUnref(ret); return NULL; } static virNWFilterBindingObj * virNWFilterBindingObjParseNode(xmlDocPtr doc, xmlNodePtr root) { g_autoptr(xmlXPathContext) ctxt = NULL; if (STRNEQ((const char *)root->name, "filterbindingstatus")) { virReportError(VIR_ERR_XML_ERROR, _("unknown root element '%s' for filter binding"), root->name); return NULL; } if (!(ctxt = virXMLXPathContextNew(doc))) return NULL; ctxt->node = root; return virNWFilterBindingObjParseXML(doc, ctxt); } static virNWFilterBindingObj * virNWFilterBindingObjParse(const char *xmlStr, const char *filename) { virNWFilterBindingObj *obj = NULL; g_autoptr(xmlDoc) xml = NULL; if ((xml = virXMLParse(filename, xmlStr, _("(nwfilterbinding_status)"), NULL, false))) { obj = virNWFilterBindingObjParseNode(xml, xmlDocGetRootElement(xml)); } return obj; } virNWFilterBindingObj * virNWFilterBindingObjParseFile(const char *filename) { return virNWFilterBindingObjParse(NULL, filename); } char * virNWFilterBindingObjFormat(const virNWFilterBindingObj *obj) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "\n"); virBufferAdjustIndent(&buf, 2); if (virNWFilterBindingDefFormatBuf(&buf, obj->def) < 0) return NULL; virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "\n"); return virBufferContentAndReset(&buf); }