static int virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc, virNWFilterHashTablePtr vars, virNWFilterInstPtr inst) { virNWFilterHashTablePtr tmpvars = NULL; int ret = -1; char *xml; if (virAsprintf(&xml, "%s/nwfilterxml2firewalldata/%s.xml", abs_srcdir, inc->filterref) < 0) return -1; /* create a temporary hashmap for depth-first tree traversal */ if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params, vars))) goto cleanup; if (virNWFilterDefToInst(xml, tmpvars, inst) < 0) goto cleanup; ret = 0; cleanup: if (ret < 0) virNWFilterInstReset(inst); virNWFilterHashTableFree(tmpvars); VIR_FREE(xml); return ret; }
static void virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) { if (!inst) return; virNWFilterHashTableFree(inst->vars); VIR_FREE(inst); }
static void virNWFilterIPAddrLearnReqFree(virNWFilterIPAddrLearnReqPtr req) { if (!req) return; VIR_FREE(req->filtername); virNWFilterHashTableFree(req->filterparams); VIR_FREE(req); }
/** * virNWFilterCreateVarHashmap: * @macaddr: pointer to string containing formatted MAC address of interface * @ipaddr: pointer to string containing formatted IP address used by * VM on this interface; may be NULL * * Create a hashmap used for evaluating the firewall rules. Initializes * it with the standard variable 'MAC' and 'IP' if provided. * * Returns pointer to hashmap, NULL if an error occcurred. */ virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, const virNWFilterVarValuePtr ipaddr) { virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0); if (!table) return NULL; if (virNWFilterVarHashmapAddStdValues(table, macaddr, ipaddr) < 0) { virNWFilterHashTableFree(table); return NULL; } return table; }
/** * virNWFilterCreateVarHashmap: * @macaddr: pointer to string containing formatted MAC address of interface * @ipaddr: pointer to string containing formatted IP address used by * VM on this interface; may be NULL * * Create a hashmap used for evaluating the firewall rules. Initializes * it with the standard variable 'MAC' and 'IP' if provided. * * Returns pointer to hashmap, NULL if an error occcurred and error message * is attached to the virConnect object. */ virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, char *ipaddr) { virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0); if (!table) { virReportOOMError(); return NULL; } if (virNWFilterVarHashmapAddStdValues(table, macaddr, ipaddr)) { virNWFilterHashTableFree(table); return NULL; } return table; }
static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline) { char *actualargv = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virNWFilterHashTablePtr vars = virNWFilterHashTableCreate(0); virNWFilterInst inst; int ret = -1; memset(&inst, 0, sizeof(inst)); virCommandSetDryRun(&buf, NULL, NULL); if (!vars) goto cleanup; if (testSetDefaultParameters(vars) < 0) goto cleanup; if (virNWFilterDefToInst(xml, vars, &inst) < 0) goto cleanup; if (ebiptables_driver.applyNewRules("vnet0", inst.rules, inst.nrules) < 0) goto cleanup; if (virBufferError(&buf)) goto cleanup; actualargv = virBufferContentAndReset(&buf); virTestClearCommandPath(actualargv); virCommandSetDryRun(NULL, NULL, NULL); testRemoveCommonRules(actualargv); if (virTestCompareToFile(actualargv, cmdline) < 0) goto cleanup; ret = 0; cleanup: virBufferFreeAndReset(&buf); VIR_FREE(actualargv); virNWFilterInstReset(&inst); virNWFilterHashTableFree(vars); return ret; }
static virNWFilterHashTablePtr virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, virNWFilterHashTablePtr vars2) { virNWFilterHashTablePtr res = virNWFilterHashTableCreate(0); if (!res) return NULL; if (virNWFilterHashTablePutAll(vars1, res) < 0) goto err_exit; if (virNWFilterHashTablePutAll(vars2, res) < 0) goto err_exit; return res; err_exit: virNWFilterHashTableFree(res); return NULL; }
void virNWFilterIPAddrMapShutdown(void) { virNWFilterHashTableFree(ipAddressMap); ipAddressMap = NULL; }
/* * 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; }
/** * virNWFilterInstantiate: * @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. * @forceWithPendingReq: Ignore the check whether a pending learn request * is active; 'true' only when the rules are applied late * * Returns 0 on success, a value otherwise. * * Instantiate a filter by instantiating the filter itself 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. * * Call this function while holding the NWFilter filter update lock */ static int virNWFilterInstantiate(virConnectPtr conn, virNWFilterTechDriverPtr techdriver, enum virDomainNetType nettype, virNWFilterDefPtr filter, const char *ifname, int ifindex, const char *linkdev, virNWFilterHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, bool teardownOld, const unsigned char *macaddr, virNWFilterDriverStatePtr driver, bool forceWithPendingReq) { int rc; int j, nptrs; int nEntries = 0; virNWFilterRuleInstPtr *insts = NULL; void **ptrs = NULL; int instantiate = 1; virNWFilterHashTablePtr missing_vars = virNWFilterHashTableCreate(0); if (!missing_vars) { virReportOOMError(); rc = 1; goto err_exit; } rc = virNWFilterDetermineMissingVarsRec(conn, filter, vars, missing_vars, useNewFilter, driver); if (rc) goto err_exit; if (virHashSize(missing_vars->hashTable) == 1) { if (virHashLookup(missing_vars->hashTable, NWFILTER_STD_VAR_IP) != NULL) { if (virNWFilterLookupLearnReq(ifindex) == NULL) { rc = virNWFilterLearnIPAddress(techdriver, ifname, ifindex, linkdev, nettype, macaddr, filter->name, vars, driver, DETECT_DHCP|DETECT_STATIC); } goto err_exit; } rc = 1; goto err_exit; } else if (virHashSize(missing_vars->hashTable) > 1) { rc = 1; goto err_exit; } else if (!forceWithPendingReq && virNWFilterLookupLearnReq(ifindex) != NULL) { goto err_exit; } rc = _virNWFilterInstantiateRec(conn, techdriver, nettype, filter, ifname, vars, &nEntries, &insts, useNewFilter, foundNewFilter, driver); if (rc) goto err_exit; switch (useNewFilter) { case INSTANTIATE_FOLLOW_NEWFILTER: instantiate = *foundNewFilter; break; case INSTANTIATE_ALWAYS: instantiate = 1; break; } if (instantiate) { rc = virNWFilterRuleInstancesToArray(nEntries, insts, &ptrs, &nptrs); if (rc) goto err_exit; if (virNWFilterLockIface(ifname)) goto err_exit; rc = techdriver->applyNewRules(conn, ifname, nptrs, ptrs); if (teardownOld && rc == 0) techdriver->tearOldRules(conn, ifname); if (rc == 0 && ifaceCheck(false, ifname, NULL, ifindex)) { /* interface changed/disppeared */ techdriver->allTeardown(ifname); rc = 1; } virNWFilterUnlockIface(ifname); } err_exit: for (j = 0; j < nEntries; j++) virNWFilterRuleInstFree(insts[j]); VIR_FREE(insts); VIR_FREE(ptrs); virNWFilterHashTableFree(missing_vars); 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; }