static int nwfilterListNWFilters(virConnectPtr conn, char **const names, int nnames) { virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData; int got = 0, i; nwfilterDriverLock(driver); for (i = 0 ; i < driver->nwfilters.count && got < nnames ; i++) { virNWFilterObjLock(driver->nwfilters.objs[i]); if (!(names[got] = strdup(driver->nwfilters.objs[i]->def->name))) { virNWFilterObjUnlock(driver->nwfilters.objs[i]); virReportOOMError(); goto cleanup; } got++; virNWFilterObjUnlock(driver->nwfilters.objs[i]); } nwfilterDriverUnlock(driver); return got; cleanup: nwfilterDriverUnlock(driver); for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); memset(names, 0, nnames * sizeof(*names)); return -1; }
int virNWFilterObjListGetNames(virNWFilterObjListPtr nwfilters, virConnectPtr conn, virNWFilterObjListFilter filter, char **const names, int maxnames) { int nnames = 0; size_t i; virNWFilterDefPtr def; for (i = 0; i < nwfilters->count && nnames < maxnames; i++) { virNWFilterObjPtr obj = nwfilters->objs[i]; virNWFilterObjLock(obj); def = obj->def; if (!filter || filter(conn, def)) { if (VIR_STRDUP(names[nnames], def->name) < 0) { virNWFilterObjUnlock(obj); goto failure; } nnames++; } virNWFilterObjUnlock(obj); } return nnames; failure: while (--nnames >= 0) VIR_FREE(names[nnames]); return -1; }
int virNWFilterObjListExport(virConnectPtr conn, virNWFilterObjListPtr nwfilters, virNWFilterPtr **filters, virNWFilterObjListFilter filter) { virNWFilterPtr *tmp_filters = NULL; int nfilters = 0; virNWFilterPtr nwfilter = NULL; virNWFilterObjPtr obj = NULL; virNWFilterDefPtr def; size_t i; int ret = -1; if (!filters) { ret = nwfilters->count; goto cleanup; } if (VIR_ALLOC_N(tmp_filters, nwfilters->count + 1) < 0) goto cleanup; for (i = 0; i < nwfilters->count; i++) { obj = nwfilters->objs[i]; virNWFilterObjLock(obj); def = obj->def; if (!filter || filter(conn, def)) { if (!(nwfilter = virGetNWFilter(conn, def->name, def->uuid))) { virNWFilterObjUnlock(obj); goto cleanup; } tmp_filters[nfilters++] = nwfilter; } virNWFilterObjUnlock(obj); } *filters = tmp_filters; tmp_filters = NULL; ret = nfilters; cleanup: if (tmp_filters) { for (i = 0; i < nfilters; i ++) virObjectUnref(tmp_filters[i]); } VIR_FREE(tmp_filters); return ret; }
static char * nwfilterGetXMLDesc(virNWFilterPtr obj, int flags) { virNWFilterDriverStatePtr driver = obj->conn->nwfilterPrivateData; virNWFilterObjPtr nwfilter; char *ret = NULL; virCheckFlags(0, NULL); nwfilterDriverLock(driver); nwfilter = virNWFilterObjFindByUUID(&driver->nwfilters, obj->uuid); nwfilterDriverUnlock(driver); if (!nwfilter) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, "%s", _("no nwfilter with matching uuid")); goto cleanup; } ret = virNWFilterDefFormat(nwfilter->def); cleanup: if (nwfilter) virNWFilterObjUnlock(nwfilter); return ret; }
int virNWFilterObjListLoadAllConfigs(virNWFilterObjListPtr nwfilters, const char *configDir) { DIR *dir; struct dirent *entry; int ret = -1; int rc; if ((rc = virDirOpenIfExists(&dir, configDir)) <= 0) return rc; while ((ret = virDirRead(dir, &entry, configDir)) > 0) { virNWFilterObjPtr obj; if (!virFileStripSuffix(entry->d_name, ".xml")) continue; obj = virNWFilterObjListLoadConfig(nwfilters, configDir, entry->d_name); if (obj) virNWFilterObjUnlock(obj); } VIR_DIR_CLOSE(dir); return ret; }
void virNWFilterObjListRemove(virNWFilterObjListPtr nwfilters, virNWFilterObjPtr obj) { size_t i; virNWFilterObjUnlock(obj); for (i = 0; i < nwfilters->count; i++) { virNWFilterObjLock(nwfilters->objs[i]); if (nwfilters->objs[i] == obj) { virNWFilterObjUnlock(nwfilters->objs[i]); virNWFilterObjFree(nwfilters->objs[i]); VIR_DELETE_ELEMENT(nwfilters->objs, i, nwfilters->count); break; } virNWFilterObjUnlock(nwfilters->objs[i]); } }
int virNWFilterObjListNumOfNWFilters(virNWFilterObjListPtr nwfilters, virConnectPtr conn, virNWFilterObjListFilter filter) { size_t i; int nfilters = 0; for (i = 0; i < nwfilters->count; i++) { virNWFilterObjPtr obj = nwfilters->objs[i]; virNWFilterObjLock(obj); if (!filter || filter(conn, obj->def)) nfilters++; virNWFilterObjUnlock(obj); } return nfilters; }
static int nwfilterUndefine(virNWFilterPtr obj) { virNWFilterDriverStatePtr driver = obj->conn->nwfilterPrivateData; virNWFilterObjPtr nwfilter; int ret = -1; nwfilterDriverLock(driver); virNWFilterCallbackDriversLock(); virNWFilterLockFilterUpdates(); nwfilter = virNWFilterObjFindByUUID(&driver->nwfilters, obj->uuid); if (!nwfilter) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, "%s", _("no nwfilter with matching uuid")); goto cleanup; } if (virNWFilterTestUnassignDef(obj->conn, nwfilter)) { virNWFilterReportError(VIR_ERR_OPERATION_INVALID, "%s", _("nwfilter is in use")); goto cleanup; } if (virNWFilterObjDeleteDef(nwfilter) < 0) goto cleanup; VIR_FREE(nwfilter->configFile); virNWFilterObjRemove(&driver->nwfilters, nwfilter); nwfilter = NULL; ret = 0; cleanup: if (nwfilter) virNWFilterObjUnlock(nwfilter); virNWFilterUnlockFilterUpdates(); virNWFilterCallbackDriversUnlock(); nwfilterDriverUnlock(driver); return ret; }
virNWFilterObjPtr virNWFilterObjListFindByUUID(virNWFilterObjListPtr nwfilters, const unsigned char *uuid) { size_t i; virNWFilterObjPtr obj; virNWFilterDefPtr def; for (i = 0; i < nwfilters->count; i++) { obj = nwfilters->objs[i]; virNWFilterObjLock(obj); def = obj->def; if (!memcmp(def->uuid, uuid, VIR_UUID_BUFLEN)) return obj; virNWFilterObjUnlock(obj); } return NULL; }
virNWFilterObjPtr virNWFilterObjListFindByName(virNWFilterObjListPtr nwfilters, const char *name) { size_t i; virNWFilterObjPtr obj; virNWFilterDefPtr def; for (i = 0; i < nwfilters->count; i++) { obj = nwfilters->objs[i]; virNWFilterObjLock(obj); def = obj->def; if (STREQ_NULLABLE(def->name, name)) return obj; virNWFilterObjUnlock(obj); } return NULL; }
virNWFilterObjPtr virNWFilterObjListFindInstantiateFilter(virNWFilterObjListPtr nwfilters, const char *filtername) { virNWFilterObjPtr obj; if (!(obj = virNWFilterObjListFindByName(nwfilters, filtername))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("referenced filter '%s' is missing"), filtername); return NULL; } if (virNWFilterObjWantRemoved(obj)) { virReportError(VIR_ERR_NO_NWFILTER, _("Filter '%s' is in use."), filtername); virNWFilterObjUnlock(obj); return NULL; } return obj; }
static virNWFilterPtr nwfilterLookupByName(virConnectPtr conn, const char *name) { virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData; virNWFilterObjPtr nwfilter; virNWFilterPtr ret = NULL; nwfilterDriverLock(driver); nwfilter = virNWFilterObjFindByName(&driver->nwfilters, name); nwfilterDriverUnlock(driver); if (!nwfilter) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, _("no nwfilter with matching name '%s'"), name); goto cleanup; } ret = virGetNWFilter(conn, nwfilter->def->name, nwfilter->def->uuid); cleanup: if (nwfilter) virNWFilterObjUnlock(nwfilter); return ret; }
static virNWFilterPtr nwfilterDefine(virConnectPtr conn, const char *xml) { virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData; virNWFilterDefPtr def; virNWFilterObjPtr nwfilter = NULL; virNWFilterPtr ret = NULL; nwfilterDriverLock(driver); virNWFilterCallbackDriversLock(); if (!(def = virNWFilterDefParseString(conn, xml))) goto cleanup; if (!(nwfilter = virNWFilterObjAssignDef(conn, &driver->nwfilters, def))) goto cleanup; if (virNWFilterObjSaveDef(driver, nwfilter, def) < 0) { virNWFilterObjRemove(&driver->nwfilters, nwfilter); def = NULL; goto cleanup; } def = NULL; ret = virGetNWFilter(conn, nwfilter->def->name, nwfilter->def->uuid); cleanup: virNWFilterDefFree(def); if (nwfilter) virNWFilterObjUnlock(nwfilter); virNWFilterCallbackDriversUnlock(); nwfilterDriverUnlock(driver); return ret; }
static int _virNWFilterObjListDefLoopDetect(virNWFilterObjListPtr nwfilters, virNWFilterDefPtr def, const char *filtername) { int rc = 0; size_t i; virNWFilterEntryPtr entry; virNWFilterObjPtr obj; if (!def) return 0; for (i = 0; i < def->nentries; i++) { entry = def->filterEntries[i]; if (entry->include) { if (STREQ(filtername, entry->include->filterref)) { rc = -1; break; } obj = virNWFilterObjListFindByName(nwfilters, entry->include->filterref); if (obj) { rc = _virNWFilterObjListDefLoopDetect(nwfilters, obj->def, filtername); virNWFilterObjUnlock(obj); if (rc < 0) break; } } } return rc; }
/** * _virNWFilterInstantiateRec: * @conn: pointer to virConnect object * @techdriver: The driver to use for instantiation * @filter: The filter to instantiate * @ifname: The name of the interface to apply the rules to * @vars: A map holding variable names and values used for instantiating * the filter and its subfilters. * @nEntries: number of virNWFilterInst objects collected * @insts: pointer to array for virNWFilterIns object pointers * @useNewFilter: instruct whether to use a newDef pointer rather than a * def ptr which is useful during a filter update * @foundNewFilter: pointer to int indivating whether a newDef pointer was * ever used; variable expected to be initialized to 0 by caller * * Returns 0 on success, a value otherwise. * * Recursively instantiate a filter by instantiating the given filter along * with all its subfilters in a depth-first traversal of the tree of * referenced filters. The name of the interface to which the rules belong * must be provided. Apply the values of variables as needed. Terminate with * error when a referenced filter is missing or a variable could not be * resolved -- among other reasons. */ static int _virNWFilterInstantiateRec(virConnectPtr conn, virNWFilterTechDriverPtr techdriver, enum virDomainNetType nettype, virNWFilterDefPtr filter, const char *ifname, virNWFilterHashTablePtr vars, int *nEntries, virNWFilterRuleInstPtr **insts, enum instCase useNewFilter, bool *foundNewFilter, virNWFilterDriverStatePtr driver) { virNWFilterObjPtr obj; int rc = 0; int i; virNWFilterRuleInstPtr inst; virNWFilterDefPtr next_filter; for (i = 0; i < filter->nentries; i++) { virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule; virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include; if (rule) { inst = virNWFilterRuleInstantiate(conn, techdriver, nettype, filter, rule, ifname, vars); if (!inst) { rc = 1; break; } if (VIR_REALLOC_N(*insts, (*nEntries)+1) < 0) { virReportOOMError(); rc = 1; break; } (*insts)[(*nEntries)++] = inst; } else if (inc) { VIR_DEBUG("Instantiating filter %s", inc->filterref); obj = virNWFilterObjFindByName(&driver->nwfilters, inc->filterref); if (obj) { if (obj->wantRemoved) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, _("Filter '%s' is in use."), inc->filterref); rc = 1; virNWFilterObjUnlock(obj); break; } /* create a temporary hashmap for depth-first tree traversal */ virNWFilterHashTablePtr tmpvars = virNWFilterCreateVarsFrom(inc->params, vars); if (!tmpvars) { virReportOOMError(); rc = 1; virNWFilterObjUnlock(obj); break; } next_filter = obj->def; switch (useNewFilter) { case INSTANTIATE_FOLLOW_NEWFILTER: if (obj->newDef) { next_filter = obj->newDef; *foundNewFilter = true; } break; case INSTANTIATE_ALWAYS: break; } rc = _virNWFilterInstantiateRec(conn, techdriver, nettype, next_filter, ifname, tmpvars, nEntries, insts, useNewFilter, foundNewFilter, driver); virNWFilterHashTableFree(tmpvars); virNWFilterObjUnlock(obj); if (rc) break; } else { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("referenced filter '%s' is missing"), inc->filterref); rc = 1; break; } } } return rc; }
static int virNWFilterDetermineMissingVarsRec(virConnectPtr conn, virNWFilterDefPtr filter, virNWFilterHashTablePtr vars, virNWFilterHashTablePtr missing_vars, int useNewFilter, virNWFilterDriverStatePtr driver) { virNWFilterObjPtr obj; int rc = 0; int i, j; virNWFilterDefPtr next_filter; for (i = 0; i < filter->nentries; i++) { virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule; virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include; if (rule) { /* check all variables of this rule */ for (j = 0; j < rule->nvars; j++) { if (!virHashLookup(vars->hashTable, rule->vars[j])) { virNWFilterHashTablePut(missing_vars, rule->vars[j], strdup("1"), 1); } } } else if (inc) { VIR_DEBUG("Following filter %s\n", inc->filterref); obj = virNWFilterObjFindByName(&driver->nwfilters, inc->filterref); if (obj) { if (obj->wantRemoved) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, _("Filter '%s' is in use."), inc->filterref); rc = 1; virNWFilterObjUnlock(obj); break; } /* create a temporary hashmap for depth-first tree traversal */ virNWFilterHashTablePtr tmpvars = virNWFilterCreateVarsFrom(inc->params, vars); if (!tmpvars) { virReportOOMError(); rc = 1; virNWFilterObjUnlock(obj); break; } next_filter = obj->def; switch (useNewFilter) { case INSTANTIATE_FOLLOW_NEWFILTER: if (obj->newDef) { next_filter = obj->newDef; } break; case INSTANTIATE_ALWAYS: break; } rc = virNWFilterDetermineMissingVarsRec(conn, next_filter, tmpvars, missing_vars, useNewFilter, driver); virNWFilterHashTableFree(tmpvars); virNWFilterObjUnlock(obj); if (rc) break; } else { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("referenced filter '%s' is missing"), inc->filterref); rc = 1; break; } } } return rc; }
virNWFilterObjPtr virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters, virNWFilterDefPtr def) { virNWFilterObjPtr obj; virNWFilterDefPtr objdef; if ((obj = virNWFilterObjListFindByUUID(nwfilters, def->uuid))) { objdef = obj->def; if (STRNEQ(def->name, objdef->name)) { virReportError(VIR_ERR_OPERATION_FAILED, _("filter with same UUID but different name " "('%s') already exists"), objdef->name); virNWFilterObjUnlock(obj); return NULL; } virNWFilterObjUnlock(obj); } else { if ((obj = virNWFilterObjListFindByName(nwfilters, def->name))) { char uuidstr[VIR_UUID_STRING_BUFLEN]; objdef = obj->def; virUUIDFormat(objdef->uuid, uuidstr); virReportError(VIR_ERR_OPERATION_FAILED, _("filter '%s' already exists with uuid %s"), def->name, uuidstr); virNWFilterObjUnlock(obj); return NULL; } } if (virNWFilterObjListDefLoopDetect(nwfilters, def) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("filter would introduce a loop")); return NULL; } if ((obj = virNWFilterObjListFindByName(nwfilters, def->name))) { objdef = obj->def; if (virNWFilterDefEqual(def, objdef, false)) { virNWFilterDefFree(objdef); obj->def = def; return obj; } obj->newDef = def; /* trigger the update on VMs referencing the filter */ if (virNWFilterTriggerVMFilterRebuild() < 0) { obj->newDef = NULL; virNWFilterObjUnlock(obj); return NULL; } virNWFilterDefFree(objdef); obj->def = def; obj->newDef = NULL; return obj; } if (!(obj = virNWFilterObjNew())) return NULL; if (VIR_APPEND_ELEMENT_COPY(nwfilters->objs, nwfilters->count, obj) < 0) { virNWFilterObjUnlock(obj); virNWFilterObjFree(obj); return NULL; } obj->def = def; return obj; }
/* * Call this function while holding the NWFilter filter update lock */ static int __virNWFilterInstantiateFilter(virConnectPtr conn, bool teardownOld, const char *ifname, int ifindex, const char *linkdev, enum virDomainNetType nettype, const unsigned char *macaddr, const char *filtername, virNWFilterHashTablePtr filterparams, enum instCase useNewFilter, virNWFilterDriverStatePtr driver, bool forceWithPendingReq, bool *foundNewFilter) { int rc; const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; virNWFilterObjPtr obj; virNWFilterHashTablePtr vars, vars1; virNWFilterDefPtr filter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; char *str_macaddr = NULL; const char *ipaddr; char *str_ipaddr = NULL; techdriver = virNWFilterTechDriverForName(drvname); if (!techdriver) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get access to ACL tech " "driver '%s'"), drvname); return 1; } VIR_DEBUG("filter name: %s", filtername); obj = virNWFilterObjFindByName(&driver->nwfilters, filtername); if (!obj) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, _("Could not find filter '%s'"), filtername); return 1; } if (obj->wantRemoved) { virNWFilterReportError(VIR_ERR_NO_NWFILTER, _("Filter '%s' is in use."), filtername); rc = 1; goto err_exit; } virFormatMacAddr(macaddr, vmmacaddr); str_macaddr = strdup(vmmacaddr); if (!str_macaddr) { virReportOOMError(); rc = 1; goto err_exit; } ipaddr = virNWFilterGetIpAddrForIfname(ifname); if (ipaddr) { str_ipaddr = strdup(ipaddr); if (!str_ipaddr) { virReportOOMError(); rc = 1; goto err_exit; } } vars1 = virNWFilterCreateVarHashmap(str_macaddr, str_ipaddr); if (!vars1) { rc = 1; goto err_exit; } str_macaddr = NULL; str_ipaddr = NULL; vars = virNWFilterCreateVarsFrom(vars1, filterparams); if (!vars) { rc = 1; goto err_exit_vars1; } filter = obj->def; switch (useNewFilter) { case INSTANTIATE_FOLLOW_NEWFILTER: if (obj->newDef) { filter = obj->newDef; *foundNewFilter = true; } break; case INSTANTIATE_ALWAYS: break; } rc = virNWFilterInstantiate(conn, techdriver, nettype, filter, ifname, ifindex, linkdev, vars, useNewFilter, foundNewFilter, teardownOld, macaddr, driver, forceWithPendingReq); virNWFilterHashTableFree(vars); err_exit_vars1: virNWFilterHashTableFree(vars1); err_exit: virNWFilterObjUnlock(obj); VIR_FREE(str_ipaddr); VIR_FREE(str_macaddr); return rc; }