diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 5c876cc10e..0659f4c367 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -477,46 +477,6 @@ printCommentVar(virBufferPtr dest, const char *buf) } -static void -ebiptablesRuleInstFree(ebiptablesRuleInstPtr inst) -{ - if (!inst) - return; - - VIR_FREE(inst->commandTemplate); - VIR_FREE(inst); -} - - -static int -ebiptablesAddRuleInst(virNWFilterRuleInstPtr res, - char *commandTemplate, - const char *neededChain, - virNWFilterChainPriority chainPriority, - char chainprefix, - virNWFilterRulePriority priority, - enum RuleType ruleType) -{ - ebiptablesRuleInstPtr inst; - - if (VIR_ALLOC(inst) < 0) - return -1; - - inst->commandTemplate = commandTemplate; - inst->neededProtocolChain = neededChain; - inst->chainPriority = chainPriority; - inst->chainprefix = chainprefix; - inst->priority = priority; - inst->ruleType = ruleType; - - if (VIR_APPEND_ELEMENT(res->data, res->ndata, inst) < 0) { - VIR_FREE(inst); - return -1; - } - return 0; -} - - static int ebtablesHandleEthHdr(virBufferPtr buf, virNWFilterVarCombIterPtr vars, @@ -2648,13 +2608,18 @@ ebtablesCreateRuleInstance(char chainPrefix, * pointed to by res, -1 otherwise */ static int -ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, - const char *chainSuffix, +ebiptablesCreateRuleInstance(const char *chainSuffix, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - virNWFilterRuleInstPtr res) + char ***templates, + size_t *ntemplates) { + size_t i; + + *templates = NULL; + *ntemplates = 0; + if (virNWFilterRuleIsProtocolEthernet(rule)) { if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { @@ -2666,17 +2631,11 @@ ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, vars, rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT, &template) < 0) - return -1; + goto error; - if (ebiptablesAddRuleInst(res, - template, - chainSuffix, - chainPriority, - CHAINPREFIX_HOST_IN_TEMP, - rule->priority, - RT_EBTABLES) < 0) { + if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { VIR_FREE(template); - return -1; + goto error; } } @@ -2690,24 +2649,15 @@ ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, vars, false, &template) < 0) - return -1; + goto error; - if (ebiptablesAddRuleInst(res, - template, - chainSuffix, - chainPriority, - CHAINPREFIX_HOST_OUT_TEMP, - rule->priority, - RT_EBTABLES) < 0) { + if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { VIR_FREE(template); - return -1; + goto error; } } } else { bool isIPv6; - char **templates = NULL; - size_t ntemplates = 0; - size_t i, j; if (virNWFilterRuleIsProtocolIPv6(rule)) { isIPv6 = true; } else if (virNWFilterRuleIsProtocolIPv4(rule)) { @@ -2715,76 +2665,27 @@ ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, } else { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("unexpected protocol type")); - return -1; + goto error; } if (iptablesCreateRuleInstance(rule, ifname, vars, isIPv6, - &templates, - &ntemplates) < 0) - return -1; - - for (i = 0; i < ntemplates; i++) { - if (ebiptablesAddRuleInst(res, - templates[i], - chainSuffix, - chainPriority, - '\0', - rule->priority, - (isIPv6) ? RT_IP6TABLES : RT_IPTABLES) < 0) { - for (j = i; j < ntemplates; j++) - VIR_FREE(templates[j]); - return -1; - } - } + templates, + ntemplates) < 0) + goto error; } return 0; -} -static int -ebiptablesCreateRuleInstanceIterate(virNWFilterDefPtr nwfilter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars, - virNWFilterRuleInstPtr res) -{ - int rc = 0; - virNWFilterVarCombIterPtr vciter, tmp; - - /* rule->vars holds all the variables names that this rule will access. - * iterate over all combinations of the variables' values and instantiate - * the filtering rule with each combination. - */ - tmp = vciter = virNWFilterVarCombIterCreate(vars, - rule->varAccess, rule->nVarAccess); - if (!vciter) - return -1; - - do { - rc = ebiptablesCreateRuleInstance(nwfilter->chainPriority, - nwfilter->chainsuffix, - rule, - ifname, - tmp, - res); - if (rc < 0) - break; - tmp = virNWFilterVarCombIterNext(tmp); - } while (tmp != NULL); - - virNWFilterVarCombIterFree(vciter); - - return rc; -} - -static int -ebiptablesFreeRuleInstance(void *_inst) -{ - ebiptablesRuleInstFree((ebiptablesRuleInstPtr)_inst); - return 0; + error: + for (i = 0; i < *ntemplates; i++) + VIR_FREE((*templates)[i]); + VIR_FREE(*templates); + *templates = NULL; + *ntemplates = 0; + return -1; } @@ -3562,12 +3463,40 @@ ebiptablesRuleOrderSort(const void *a, const void *b) return insta->priority - instb->priority; } + static int -ebiptablesRuleOrderSortPtr(const void *a, const void *b) +virNWFilterRuleInstSort(const void *a, const void *b) { - ebiptablesRuleInst * const *insta = a; - ebiptablesRuleInst * const *instb = b; - return ebiptablesRuleOrderSort(*insta, *instb); + const virNWFilterRuleInst *insta = a; + const virNWFilterRuleInst *instb = b; + const char *root = virNWFilterChainSuffixTypeToString( + VIR_NWFILTER_CHAINSUFFIX_ROOT); + bool root_a = STREQ(insta->chainSuffix, root); + bool root_b = STREQ(instb->chainSuffix, root); + + /* ensure root chain commands appear before all others since + we will need them to create the child chains */ + if (root_a) { + if (root_b) { + goto normal; + } + return -1; /* a before b */ + } + if (root_b) { + return 1; /* b before a */ + } + normal: + /* priorities are limited to range [-1000, 1000] */ + return insta->priority - instb->priority; +} + + +static int +virNWFilterRuleInstSortPtr(const void *a, const void *b) +{ + virNWFilterRuleInst * const *insta = a; + virNWFilterRuleInst * const *instb = b; + return virNWFilterRuleInstSort(*insta, *instb); } static int @@ -3673,13 +3602,106 @@ ebtablesCreateTmpRootAndSubChains(virBufferPtr buf, return rc; } + +static int +iptablesRuleInstCommand(virBufferPtr buf, + const char *ifname, + virNWFilterRuleInstPtr rule, + char cmd, int pos) +{ + virNWFilterVarCombIterPtr vciter, tmp; + char **templates = NULL; + size_t ntemplates = 0; + size_t i; + int ret = -1; + + /* rule->vars holds all the variables names that this rule will access. + * iterate over all combinations of the variables' values and instantiate + * the filtering rule with each combination. + */ + tmp = vciter = virNWFilterVarCombIterCreate(rule->vars, + rule->def->varAccess, + rule->def->nVarAccess); + if (!vciter) + return -1; + + do { + if (ebiptablesCreateRuleInstance(rule->chainSuffix, + rule->def, + ifname, + tmp, + &templates, + &ntemplates) < 0) + goto cleanup; + tmp = virNWFilterVarCombIterNext(tmp); + } while (tmp != NULL); + + for (i = 0; i < ntemplates; i++) + iptablesInstCommand(buf, templates[i], cmd, pos); + + ret = 0; + cleanup: + for (i = 0; i < ntemplates; i++) + VIR_FREE(templates[i]); + VIR_FREE(templates); + virNWFilterVarCombIterFree(vciter); + return ret; +} + + +static int +ebtablesRuleInstCommand(virBufferPtr buf, + const char *ifname, + virNWFilterRuleInstPtr rule, + char cmd, int pos, + bool stopOnError) +{ + virNWFilterVarCombIterPtr vciter, tmp; + char **templates = NULL; + size_t ntemplates = 0; + size_t i; + int ret = -1; + + /* rule->vars holds all the variables names that this rule will access. + * iterate over all combinations of the variables' values and instantiate + * the filtering rule with each combination. + */ + tmp = vciter = virNWFilterVarCombIterCreate(rule->vars, + rule->def->varAccess, + rule->def->nVarAccess); + if (!vciter) + return -1; + + do { + if (ebiptablesCreateRuleInstance(rule->chainSuffix, + rule->def, + ifname, + tmp, + &templates, + &ntemplates) < 0) + goto cleanup; + tmp = virNWFilterVarCombIterNext(tmp); + } while (tmp != NULL); + + for (i = 0; i < ntemplates; i++) + ebiptablesInstCommand(buf, templates[i], cmd, pos, stopOnError); + + ret = 0; + cleanup: + for (i = 0; i < ntemplates; i++) + VIR_FREE(templates[i]); + VIR_FREE(templates); + virNWFilterVarCombIterFree(vciter); + return ret; +} + + static int ebiptablesApplyNewRules(const char *ifname, - int nruleInstances, - void **_inst) + virNWFilterRuleInstPtr *rules, + size_t nrules) { size_t i, j; - ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst; virBuffer buf = VIR_BUFFER_INITIALIZER; virHashTablePtr chains_in_set = virHashCreate(10, NULL); virHashTablePtr chains_out_set = virHashCreate(10, NULL); @@ -3689,28 +3711,27 @@ ebiptablesApplyNewRules(const char *ifname, int nEbtChains = 0; char *errmsg = NULL; - if (inst == NULL) - nruleInstances = 0; - if (!chains_in_set || !chains_out_set) goto exit_free_sets; - if (nruleInstances > 1 && inst) - qsort(inst, nruleInstances, sizeof(inst[0]), - ebiptablesRuleOrderSortPtr); + if (nrules) + qsort(rules, nrules, sizeof(rules[0]), + virNWFilterRuleInstSortPtr); /* scan the rules to see which chains need to be created */ - for (i = 0; i < nruleInstances; i++) { - sa_assert(inst); - if (inst[i]->ruleType == RT_EBTABLES) { - const char *name = inst[i]->neededProtocolChain; - if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP) { + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { + const char *name = rules[i]->chainSuffix; + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { if (virHashUpdateEntry(chains_in_set, name, - &inst[i]->chainPriority) < 0) + &rules[i]->chainPriority) < 0) goto exit_free_sets; - } else { + } + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_IN || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { if (virHashUpdateEntry(chains_out_set, name, - &inst[i]->chainPriority) < 0) + &rules[i]->chainPriority) < 0) goto exit_free_sets; } } @@ -3759,37 +3780,34 @@ ebiptablesApplyNewRules(const char *ifname, * priority -500 and the chain with priority -500 will * then be created before it. */ - for (i = 0; i < nruleInstances; i++) { - if (inst[i]->chainPriority > inst[i]->priority && - !strstr("root", inst[i]->neededProtocolChain)) { + for (i = 0; i < nrules; i++) { + if (rules[i]->chainPriority > rules[i]->priority && + !strstr("root", rules[i]->chainSuffix)) { - inst[i]->priority = inst[i]->chainPriority; + rules[i]->priority = rules[i]->chainPriority; } } /* process ebtables commands; interleave commands from filters with commands for creating and connecting ebtables chains */ j = 0; - for (i = 0; i < nruleInstances; i++) { - sa_assert(inst); - switch (inst[i]->ruleType) { - case RT_EBTABLES: + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { while (j < nEbtChains && - ebtChains[j].priority <= inst[i]->priority) { + ebtChains[j].priority <= rules[i]->priority) { ebiptablesInstCommand(&buf, ebtChains[j++].commandTemplate, 'A', -1, true); } - ebiptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1, true); - break; - case RT_IPTABLES: - haveIptables = true; - break; - case RT_IP6TABLES: - haveIp6tables = true; - break; + ebtablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1, true); + } else { + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + haveIptables = true; + else if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) + haveIp6tables = true; } } @@ -3828,12 +3846,12 @@ ebiptablesApplyNewRules(const char *ifname, NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - for (i = 0; i < nruleInstances; i++) { - sa_assert(inst); - if (inst[i]->ruleType == RT_IPTABLES) - iptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1); + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + iptablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1); } if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) @@ -3869,11 +3887,12 @@ ebiptablesApplyNewRules(const char *ifname, NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - for (i = 0; i < nruleInstances; i++) { - if (inst[i]->ruleType == RT_IP6TABLES) - iptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1); + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) + iptablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1); } if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) @@ -4095,12 +4114,10 @@ virNWFilterTechDriver ebiptables_driver = { .init = ebiptablesDriverInit, .shutdown = ebiptablesDriverShutdown, - .createRuleInstance = ebiptablesCreateRuleInstanceIterate, .applyNewRules = ebiptablesApplyNewRules, .tearNewRules = ebiptablesTearNewRules, .tearOldRules = ebiptablesTearOldRules, .allTeardown = ebiptablesAllTeardown, - .freeRuleInstance = ebiptablesFreeRuleInstance, .canApplyBasicRules = ebiptablesCanApplyBasicRules, .applyBasicRules = ebtablesApplyBasicRules, diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index d482f43347..5bed106dc2 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -119,14 +119,10 @@ virNWFilterTechDriverForName(const char *name) static void virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) { - size_t i; if (!inst) return; - for (i = 0; i < inst->ndata; i++) - inst->techdriver->freeRuleInstance(inst->data[i]); - - VIR_FREE(inst->data); + virNWFilterHashTableFree(inst->vars); VIR_FREE(inst); } @@ -272,51 +268,6 @@ virNWFilterPrintVars(virHashTablePtr vars, } -/** - * virNWFilterRuleInstantiate: - * @techdriver: the driver to use for instantiation - * @filter: The filter the rule is part of - * @rule : The rule that is to be instantiated - * @ifname: The name of the interface - * @vars: map containing variable names and value used for instantiation - * - * Returns virNWFilterRuleInst object on success, NULL on error with - * error reported. - * - * Instantiate a single rule. Return a pointer to virNWFilterRuleInst - * object that will hold an array of driver-specific data resulting - * from the instantiation. Returns NULL on error with error reported. - */ -static virNWFilterRuleInstPtr -virNWFilterRuleInstantiate(virNWFilterTechDriverPtr techdriver, - virNWFilterDefPtr filter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars) -{ - int rc; - size_t i; - virNWFilterRuleInstPtr ret; - - if (VIR_ALLOC(ret) < 0) - return NULL; - - ret->techdriver = techdriver; - - rc = techdriver->createRuleInstance(filter, - rule, ifname, vars, ret); - - if (rc) { - for (i = 0; i < ret->ndata; i++) - techdriver->freeRuleInstance(ret->data[i]); - VIR_FREE(ret); - ret = NULL; - } - - return ret; -} - - /** * virNWFilterCreateVarsFrom: * @vars1: pointer to hash table @@ -350,125 +301,198 @@ virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, } +typedef struct _virNWFilterInst virNWFilterInst; +typedef virNWFilterInst *virNWFilterInstPtr; +struct _virNWFilterInst { + virNWFilterObjPtr *filters; + size_t nfilters; + virNWFilterRuleInstPtr *rules; + size_t nrules; +}; + + +static void +virNWFilterInstReset(virNWFilterInstPtr inst) +{ + size_t i; + + for (i = 0; i < inst->nfilters; i++) + virNWFilterObjUnlock(inst->filters[i]); + VIR_FREE(inst->filters); + inst->nfilters = 0; + + for (i = 0; i < inst->nrules; i++) + virNWFilterRuleInstFree(inst->rules[i]); + VIR_FREE(inst->rules); +} + + + +static int +virNWFilterDefToInst(virNWFilterDriverStatePtr driver, + virNWFilterDefPtr def, + virNWFilterHashTablePtr vars, + enum instCase useNewFilter, + bool *foundNewFilter, + virNWFilterInstPtr inst); + +static int +virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, + virNWFilterRuleDefPtr rule, + virNWFilterHashTablePtr vars, + virNWFilterInstPtr inst) +{ + virNWFilterRuleInstPtr ruleinst; + int ret = -1; + + if (VIR_ALLOC(ruleinst) < 0) + goto cleanup; + + ruleinst->chainSuffix = def->chainsuffix; + ruleinst->chainPriority = def->chainPriority; + ruleinst->def = rule; + ruleinst->priority = rule->priority; + if (!(ruleinst->vars = virNWFilterHashTableCreate(0))) + goto cleanup; + if (virNWFilterHashTablePutAll(vars, ruleinst->vars) < 0) + goto cleanup; + + if (VIR_APPEND_ELEMENT(inst->rules, + inst->nrules, + ruleinst) < 0) + goto cleanup; + inst = NULL; + + ret = 0; + cleanup: + virNWFilterRuleInstFree(ruleinst); + return ret; +} + + +static int +virNWFilterIncludeDefToRuleInst(virNWFilterDriverStatePtr driver, + virNWFilterIncludeDefPtr inc, + virNWFilterHashTablePtr vars, + enum instCase useNewFilter, + bool *foundNewFilter, + virNWFilterInstPtr inst) +{ + virNWFilterObjPtr obj; + virNWFilterHashTablePtr tmpvars = NULL; + virNWFilterDefPtr childdef; + int ret = -1; + + VIR_DEBUG("Instantiating filter %s", inc->filterref); + obj = virNWFilterObjFindByName(&driver->nwfilters, + inc->filterref); + if (!obj) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("referenced filter '%s' is missing"), + inc->filterref); + goto cleanup; + } + if (obj->wantRemoved) { + virReportError(VIR_ERR_NO_NWFILTER, + _("Filter '%s' is in use."), + inc->filterref); + goto cleanup; + } + + /* create a temporary hashmap for depth-first tree traversal */ + if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params, + vars))) + goto cleanup; + + childdef = obj->def; + + switch (useNewFilter) { + case INSTANTIATE_FOLLOW_NEWFILTER: + if (obj->newDef) { + childdef = obj->newDef; + *foundNewFilter = true; + } + break; + case INSTANTIATE_ALWAYS: + break; + } + + if (VIR_APPEND_ELEMENT(inst->filters, + inst->nfilters, + obj) < 0) + goto cleanup; + obj = NULL; + + if (virNWFilterDefToInst(driver, + childdef, + tmpvars, + useNewFilter, + foundNewFilter, + inst) < 0) + goto cleanup; + + ret = 0; + cleanup: + if (ret < 0) + virNWFilterInstReset(inst); + virNWFilterHashTableFree(tmpvars); + if (obj) + virNWFilterObjUnlock(obj); + return ret; +} + + /** - * _virNWFilterInstantiateRec: - * @techdriver: The driver to use for instantiation - * @filter: The filter to instantiate - * @ifname: The name of the interface to apply the rules to + * virNWFilterDefToInst: + * @driver: the driver state pointer + * @def: The filter to instantiate * @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 + * @rulesout: array to be filled with rule instance + * @nrulesout: counter to be filled with number of rule instances * - * Returns 0 on success, a value otherwise. + * Recursively expand a nested filter into a flat list of rule instances, + * in a depth-first traversal of the tree. * - * 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. + * Returns 0 on success, -1 on error */ static int -_virNWFilterInstantiateRec(virNWFilterTechDriverPtr techdriver, - virNWFilterDefPtr filter, - const char *ifname, - virNWFilterHashTablePtr vars, - size_t *nEntries, - virNWFilterRuleInstPtr **insts, - enum instCase useNewFilter, bool *foundNewFilter, - virNWFilterDriverStatePtr driver) +virNWFilterDefToInst(virNWFilterDriverStatePtr driver, + virNWFilterDefPtr def, + virNWFilterHashTablePtr vars, + enum instCase useNewFilter, + bool *foundNewFilter, + virNWFilterInstPtr inst) { - virNWFilterObjPtr obj; - int rc = 0; size_t i; - virNWFilterRuleInstPtr inst; - virNWFilterDefPtr next_filter; + int ret = -1; - for (i = 0; i < filter->nentries; i++) { - virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule; - virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include; - if (rule) { - inst = virNWFilterRuleInstantiate(techdriver, - filter, - rule, - ifname, - vars); - if (!inst) { - rc = -1; - break; - } - - if (VIR_APPEND_ELEMENT_COPY(*insts, *nEntries, inst) < 0) { - rc = -1; - break; - } - - } else if (inc) { - VIR_DEBUG("Instantiating filter %s", inc->filterref); - obj = virNWFilterObjFindByName(&driver->nwfilters, inc->filterref); - if (obj) { - - if (obj->wantRemoved) { - virReportError(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) { - 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(techdriver, - next_filter, - ifname, - tmpvars, - nEntries, insts, - useNewFilter, - foundNewFilter, - driver); - - virNWFilterHashTableFree(tmpvars); - - virNWFilterObjUnlock(obj); - if (rc < 0) - break; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("referenced filter '%s' is missing"), - inc->filterref); - rc = -1; - break; - } + for (i = 0; i < def->nentries; i++) { + if (def->filterEntries[i]->rule) { + if (virNWFilterRuleDefToRuleInst(def, + def->filterEntries[i]->rule, + vars, + inst) < 0) + goto cleanup; + } else if (def->filterEntries[i]->include) { + if (virNWFilterIncludeDefToRuleInst(driver, + def->filterEntries[i]->include, + vars, + useNewFilter, foundNewFilter, + inst) < 0) + goto cleanup; } } - return rc; + + ret = 0; + cleanup: + if (ret < 0) + virNWFilterInstReset(inst); + return ret; } @@ -578,35 +602,6 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, } -static int -virNWFilterRuleInstancesToArray(int nEntries, - virNWFilterRuleInstPtr *insts, - void ***ptrs, - int *nptrs) -{ - size_t i, j; - - *nptrs = 0; - - for (j = 0; j < nEntries; j++) - (*nptrs) += insts[j]->ndata; - - if ((*nptrs) == 0) - return 0; - - if (VIR_ALLOC_N((*ptrs), (*nptrs)) < 0) - return -1; - - (*nptrs) = 0; - - for (j = 0; j < nEntries; j++) - for (i = 0; i < insts[j]->ndata; i++) - (*ptrs)[(*nptrs)++] = insts[j]->data[i]; - - return 0; -} - - /** * virNWFilterInstantiate: * @vmuuid: The UUID of the VM @@ -642,11 +637,7 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, bool forceWithPendingReq) { int rc; - size_t j; - int nptrs; - size_t nEntries = 0; - virNWFilterRuleInstPtr *insts = NULL; - void **ptrs = NULL; + virNWFilterInst inst; bool instantiate = true; char *buf; virNWFilterVarValuePtr lv; @@ -654,6 +645,9 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, bool reportIP = false; virNWFilterHashTablePtr missing_vars = virNWFilterHashTableCreate(0); + + memset(&inst, 0, sizeof(inst)); + if (!missing_vars) { rc = -1; goto err_exit; @@ -717,13 +711,11 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, goto err_exit; } - rc = _virNWFilterInstantiateRec(techdriver, - filter, - ifname, - vars, - &nEntries, &insts, - useNewFilter, foundNewFilter, - driver); + rc = virNWFilterDefToInst(driver, + filter, + vars, + useNewFilter, foundNewFilter, + &inst); if (rc < 0) goto err_exit; @@ -738,16 +730,10 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, } if (instantiate) { - - rc = virNWFilterRuleInstancesToArray(nEntries, insts, - &ptrs, &nptrs); - if (rc < 0) - goto err_exit; - if (virNWFilterLockIface(ifname) < 0) goto err_exit; - rc = techdriver->applyNewRules(ifname, nptrs, ptrs); + rc = techdriver->applyNewRules(ifname, inst.rules, inst.nrules); if (teardownOld && rc == 0) techdriver->tearOldRules(ifname); @@ -763,13 +749,7 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, } err_exit: - - for (j = 0; j < nEntries; j++) - virNWFilterRuleInstFree(insts[j]); - - VIR_FREE(insts); - VIR_FREE(ptrs); - + virNWFilterInstReset(&inst); virNWFilterHashTableFree(missing_vars); return rc; diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h index ed09a67914..7b6f56fd6a 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -35,24 +35,20 @@ typedef virNWFilterTechDriver *virNWFilterTechDriverPtr; typedef struct _virNWFilterRuleInst virNWFilterRuleInst; typedef virNWFilterRuleInst *virNWFilterRuleInstPtr; struct _virNWFilterRuleInst { - size_t ndata; - void **data; - virNWFilterTechDriverPtr techdriver; + const char *chainSuffix; + virNWFilterChainPriority chainPriority; + virNWFilterRuleDefPtr def; + virNWFilterRulePriority priority; + virNWFilterHashTablePtr vars; }; typedef int (*virNWFilterTechDrvInit)(bool privileged); typedef void (*virNWFilterTechDrvShutdown)(void); -typedef int (*virNWFilterRuleCreateInstance)(virNWFilterDefPtr filter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars, - virNWFilterRuleInstPtr res); - typedef int (*virNWFilterRuleApplyNewRules)(const char *ifname, - int nruleInstances, - void **_inst); + virNWFilterRuleInstPtr *rules, + size_t nrules); typedef int (*virNWFilterRuleTeardownNewRules)(const char *ifname); @@ -60,8 +56,6 @@ typedef int (*virNWFilterRuleTeardownOldRules)(const char *ifname); typedef int (*virNWFilterRuleAllTeardown)(const char *ifname); -typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst); - typedef int (*virNWFilterCanApplyBasicRules)(void); typedef int (*virNWFilterApplyBasicRules)(const char *ifname, @@ -87,12 +81,10 @@ struct _virNWFilterTechDriver { virNWFilterTechDrvInit init; virNWFilterTechDrvShutdown shutdown; - virNWFilterRuleCreateInstance createRuleInstance; virNWFilterRuleApplyNewRules applyNewRules; virNWFilterRuleTeardownNewRules tearNewRules; virNWFilterRuleTeardownOldRules tearOldRules; virNWFilterRuleAllTeardown allTeardown; - virNWFilterRuleFreeInstanceData freeRuleInstance; virNWFilterCanApplyBasicRules canApplyBasicRules; virNWFilterApplyBasicRules applyBasicRules;