Merge nwfilter createRuleInstance driver into applyNewRules

The current nwfilter tech driver API has a 'createRuleInstance' method
which populates virNWFilterRuleInstPtr with a command line string
containing variable placeholders. The 'applyNewRules' method then
expands the variables and executes the commands. This split of
responsibility won't work when switching to the virFirewallPtr
APIs, since we can't just build up command line strings. This patch
this merges the functionality of 'createRuleInstance' into the
applyNewRules method.

The virNWFilterRuleInstPtr struct is changed from holding an array
of opaque pointers, into holding generic metadata about the rules
to be processed. In essence this is the result of taking a linked
set of virNWFilterDefPtr's and flattening the tree to get a list
of virNWFilterRuleDefPtr's. At the same time we must keep track of
any nested virNWFilterObjPtr instances, so that the locks are held
for the duration of the 'applyNewRules' method.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2014-03-25 13:44:50 +00:00
parent 4dd7eaa36f
commit 3f74b2eb2c
3 changed files with 389 additions and 400 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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;