/** * virNWFilterVarHashmapAddStdValues: * @tables: pointer to hash tabel to add values to * @macaddr: The string of the MAC address to add to the hash table, * may be NULL * @ipaddr: The string of the IP address to add to the hash table; * may be NULL * * Returns 0 in case of success, 1 in case an error happened with * error having been reported. * * Adds a couple of standard keys (MAC, IP) to the hash table. */ static int virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table, char *macaddr, char *ipaddr) { if (macaddr) { if (virHashAddEntry(table->hashTable, NWFILTER_STD_VAR_MAC, macaddr) < 0) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'MAC' to hashmap")); return 1; } } if (ipaddr) { if (virHashAddEntry(table->hashTable, NWFILTER_STD_VAR_IP, ipaddr) < 0) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'IP' to hashmap")); return 1; } } return 0; }
int virNWFilterLockIface(const char *ifname) { virNWFilterIfaceLockPtr ifaceLock; virMutexLock(&ifaceMapLock); ifaceLock = virHashLookup(ifaceLockMap, ifname); if (!ifaceLock) { if (VIR_ALLOC(ifaceLock) < 0) { virReportOOMError(); goto err_exit; } if (virMutexInitRecursive(&ifaceLock->lock) < 0) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("mutex initialization failed")); VIR_FREE(ifaceLock); goto err_exit; } if (virStrcpyStatic(ifaceLock->ifname, ifname) == NULL) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("interface name %s does not fit into " "buffer "), ifaceLock->ifname); VIR_FREE(ifaceLock); goto err_exit; } while (virHashAddEntry(ifaceLockMap, ifname, ifaceLock)) { VIR_FREE(ifaceLock); goto err_exit; } ifaceLock->refctr = 0; } ifaceLock->refctr++; virMutexUnlock(&ifaceMapLock); virMutexLock(&ifaceLock->lock); return 0; err_exit: virMutexUnlock(&ifaceMapLock); return -1; }
static int _virNWFilterTeardownFilter(const char *ifname) { const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; techdriver = virNWFilterTechDriverForName(drvname); if (!techdriver) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get access to ACL tech " "driver '%s'"), drvname); return 1; } virNWFilterTerminateLearnReq(ifname); if (virNWFilterLockIface(ifname)) return 1; techdriver->allTeardown(ifname); virNWFilterDelIpAddrForIfname(ifname); virNWFilterUnlockIface(ifname); return 0; }
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; }
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; }
/** * virNWFilterVarHashmapAddStdValues: * @tables: pointer to hash tabel to add values to * @macaddr: The string of the MAC address to add to the hash table, * may be NULL * @ipaddr: The string of the IP address to add to the hash table; * may be NULL * * Returns 0 in case of success, -1 in case an error happened with * error having been reported. * * Adds a couple of standard keys (MAC, IP) to the hash table. */ static int virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table, char *macaddr, const virNWFilterVarValuePtr ipaddr) { virNWFilterVarValue *val; if (macaddr) { val = virNWFilterVarValueCreateSimple(macaddr); if (!val) return -1; if (virHashAddEntry(table->hashTable, NWFILTER_STD_VAR_MAC, val) < 0) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'MAC' to hashmap")); return -1; } } if (ipaddr) { val = virNWFilterVarValueCopy(ipaddr); if (!val) return -1; if (virHashAddEntry(table->hashTable, NWFILTER_STD_VAR_IP, val) < 0) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'IP' to hashmap")); return -1; } } return 0; }
int virNWFilterRollbackUpdateFilter(virConnectPtr conn, const virDomainNetDefPtr net) { const char *drvname = EBIPTABLES_DRIVER_ID; int ifindex; virNWFilterTechDriverPtr techdriver; techdriver = virNWFilterTechDriverForName(drvname); if (!techdriver) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get access to ACL tech " "driver '%s'"), drvname); return 1; } /* don't tear anything while the address is being learned */ if (ifaceGetIndex(true, net->ifname, &ifindex) == 0 && virNWFilterLookupLearnReq(ifindex) != NULL) return 0; return techdriver->tearNewRules(conn, net->ifname); }
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; }
/* * 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; }
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; }
/** * _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; }