}
-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,
* 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) {
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;
}
}
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)) {
} 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;
}
return insta->priority - instb->priority;
}
+
+static int
+virNWFilterRuleInstSort(const void *a, const void *b)
+{
+ 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
-ebiptablesRuleOrderSortPtr(const void *a, const void *b)
+virNWFilterRuleInstSortPtr(const void *a, const void *b)
{
- ebiptablesRuleInst * const *insta = a;
- ebiptablesRuleInst * const *instb = b;
- return ebiptablesRuleOrderSort(*insta, *instb);
+ virNWFilterRuleInst * const *insta = a;
+ virNWFilterRuleInst * const *instb = b;
+ return virNWFilterRuleInstSort(*insta, *instb);
}
static int
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);
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;
}
}
* 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;
}
}
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)
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)
.init = ebiptablesDriverInit,
.shutdown = ebiptablesDriverShutdown,
- .createRuleInstance = ebiptablesCreateRuleInstanceIterate,
.applyNewRules = ebiptablesApplyNewRules,
.tearNewRules = ebiptablesTearNewRules,
.tearOldRules = ebiptablesTearOldRules,
.allTeardown = ebiptablesAllTeardown,
- .freeRuleInstance = ebiptablesFreeRuleInstance,
.canApplyBasicRules = ebiptablesCanApplyBasicRules,
.applyBasicRules = ebtablesApplyBasicRules,
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);
}
}
-/**
- * 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
}
-/**
- * _virNWFilterInstantiateRec:
- * @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(virNWFilterTechDriverPtr techdriver,
- virNWFilterDefPtr filter,
- const char *ifname,
- virNWFilterHashTablePtr vars,
- size_t *nEntries,
- virNWFilterRuleInstPtr **insts,
- enum instCase useNewFilter, bool *foundNewFilter,
- virNWFilterDriverStatePtr driver)
+typedef struct _virNWFilterInst virNWFilterInst;
+typedef virNWFilterInst *virNWFilterInstPtr;
+struct _virNWFilterInst {
+ virNWFilterObjPtr *filters;
+ size_t nfilters;
+ virNWFilterRuleInstPtr *rules;
+ size_t nrules;
+};
+
+
+static void
+virNWFilterInstReset(virNWFilterInstPtr inst)
{
- virNWFilterObjPtr obj;
- int rc = 0;
size_t 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(techdriver,
- filter,
- rule,
- ifname,
- vars);
- if (!inst) {
- rc = -1;
- break;
- }
+ for (i = 0; i < inst->nfilters; i++)
+ virNWFilterObjUnlock(inst->filters[i]);
+ VIR_FREE(inst->filters);
+ inst->nfilters = 0;
- if (VIR_APPEND_ELEMENT_COPY(*insts, *nEntries, inst) < 0) {
- rc = -1;
- break;
- }
+ for (i = 0; i < inst->nrules; i++)
+ virNWFilterRuleInstFree(inst->rules[i]);
+ VIR_FREE(inst->rules);
+}
- } 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."),
+
+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);
- rc = -1;
- virNWFilterObjUnlock(obj);
- break;
- }
+ 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 */
- virNWFilterHashTablePtr tmpvars =
- virNWFilterCreateVarsFrom(inc->params,
- vars);
- if (!tmpvars) {
- rc = -1;
- virNWFilterObjUnlock(obj);
- break;
- }
+ /* create a temporary hashmap for depth-first tree traversal */
+ if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params,
+ vars)))
+ goto cleanup;
- next_filter = obj->def;
+ childdef = obj->def;
- switch (useNewFilter) {
- case INSTANTIATE_FOLLOW_NEWFILTER:
- if (obj->newDef) {
- next_filter = obj->newDef;
- *foundNewFilter = true;
- }
- break;
- case INSTANTIATE_ALWAYS:
- break;
- }
+ switch (useNewFilter) {
+ case INSTANTIATE_FOLLOW_NEWFILTER:
+ if (obj->newDef) {
+ childdef = obj->newDef;
+ *foundNewFilter = true;
+ }
+ break;
+ case INSTANTIATE_ALWAYS:
+ break;
+ }
- rc = _virNWFilterInstantiateRec(techdriver,
- next_filter,
- ifname,
- tmpvars,
- nEntries, insts,
- useNewFilter,
- foundNewFilter,
- driver);
+ 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;
- virNWFilterHashTableFree(tmpvars);
+ ret = 0;
+ cleanup:
+ if (ret < 0)
+ virNWFilterInstReset(inst);
+ virNWFilterHashTableFree(tmpvars);
+ if (obj)
+ virNWFilterObjUnlock(obj);
+ return ret;
+}
- virNWFilterObjUnlock(obj);
- if (rc < 0)
- break;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("referenced filter '%s' is missing"),
- inc->filterref);
- rc = -1;
- break;
- }
+
+/**
+ * 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.
+ * @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
+ *
+ * Recursively expand a nested filter into a flat list of rule instances,
+ * in a depth-first traversal of the tree.
+ *
+ * Returns 0 on success, -1 on error
+ */
+static int
+virNWFilterDefToInst(virNWFilterDriverStatePtr driver,
+ virNWFilterDefPtr def,
+ virNWFilterHashTablePtr vars,
+ enum instCase useNewFilter,
+ bool *foundNewFilter,
+ virNWFilterInstPtr inst)
+{
+ size_t i;
+ int ret = -1;
+
+ 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;
}
}
-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
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;
bool reportIP = false;
virNWFilterHashTablePtr missing_vars = virNWFilterHashTableCreate(0);
+
+ memset(&inst, 0, sizeof(inst));
+
if (!missing_vars) {
rc = -1;
goto err_exit;
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;
}
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);
}
err_exit:
-
- for (j = 0; j < nEntries; j++)
- virNWFilterRuleInstFree(insts[j]);
-
- VIR_FREE(insts);
- VIR_FREE(ptrs);
-
+ virNWFilterInstReset(&inst);
virNWFilterHashTableFree(missing_vars);
return rc;
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);
typedef int (*virNWFilterRuleAllTeardown)(const char *ifname);
-typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst);
-
typedef int (*virNWFilterCanApplyBasicRules)(void);
typedef int (*virNWFilterApplyBasicRules)(const char *ifname,
virNWFilterTechDrvInit init;
virNWFilterTechDrvShutdown shutdown;
- virNWFilterRuleCreateInstance createRuleInstance;
virNWFilterRuleApplyNewRules applyNewRules;
virNWFilterRuleTeardownNewRules tearNewRules;
virNWFilterRuleTeardownOldRules tearOldRules;
virNWFilterRuleAllTeardown allTeardown;
- virNWFilterRuleFreeInstanceData freeRuleInstance;
virNWFilterCanApplyBasicRules canApplyBasicRules;
virNWFilterApplyBasicRules applyBasicRules;