This patch adds the internal capability to add rules to existing chains
instead of using temporary chains and to generate placeholders for chains
that are referenced without generating a rule for them immediately. Finally,
it includes variable matching for filter instantiation (i.e., instantiate only
when a given variable is present in a filter, or only when it is not).
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 72bdade..25f7b60 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -517,7 +517,9 @@ typedef int (*virNWFilterRuleCreateInstance)(virConnectPtr conn,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
- virNWFilterRuleInstPtr res);
+ virNWFilterRuleInstPtr res,
+ bool usetemp,
+ bool dummy);
typedef int (*virNWFilterRuleApplyNewRules)(virConnectPtr conn,
const char *ifname,
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c
b/src/nwfilter/nwfilter_ebiptables_driver.c
index f16a143..f74f63b 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1134,6 +1134,7 @@ iptablesEnforceDirection(int directionIn,
* @isIPv6 : Whether this is an IPv6 rule
* @maySkipICMP : whether this rule may under certain circumstances skip
* the ICMP rule from being created
+ * @dummy : generate rule placeholder without installing
*
* Convert a single rule into its representation for later instantiation
*
@@ -1152,7 +1153,8 @@ _iptablesCreateRuleInstance(int directionIn,
const char *match, bool defMatch,
const char *accept_target,
bool isIPv6,
- bool maySkipICMP)
+ bool maySkipICMP,
+ bool dummy)
{
char chain[MAX_CHAINNAME_LENGTH];
char number[20];
@@ -1179,6 +1181,13 @@ _iptablesCreateRuleInstance(int directionIn,
PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+ if (dummy) {
+ virBufferVSprintf(&buf, CMD_DEF_PRE "%s -- %s -%%c %s %%s",
+ "echo", iptables_cmd, chain);
+ bufUsed = virBufferUse(&buf);
+ goto prskip;
+ }
+
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_TCP:
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -1510,6 +1519,8 @@ _iptablesCreateRuleInstance(int directionIn,
return -1;
}
+prskip:
+
if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) ||
skipRule) {
virBufferFreeAndReset(&buf);
@@ -1625,7 +1636,9 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0, directionOut = 0;
@@ -1658,7 +1671,7 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
return 1;
}
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
if (create) {
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
@@ -1670,7 +1683,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
if (rc)
@@ -1690,7 +1704,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
return 1;
}
- chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+ CHAINPREFIX_HOST_OUT;
if (create) {
rc = _iptablesCreateRuleInstance(!directionIn,
chainPrefix,
@@ -1702,7 +1717,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
@@ -1726,7 +1742,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
if (create) {
chainPrefix[0] = 'H';
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP :
+ CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1737,7 +1754,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
}
@@ -1751,7 +1769,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0;
@@ -1767,7 +1787,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
}
if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
@@ -1790,7 +1812,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
else
matchState = NULL;
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1801,7 +1823,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1812,7 +1835,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
else
matchState = NULL;
- chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP : CHAINPREFIX_HOST_OUT;
rc = _iptablesCreateRuleInstance(!directionIn,
chainPrefix,
nwfilter,
@@ -1823,7 +1846,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1834,7 +1858,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState = NULL;
chainPrefix[0] = 'H';
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1845,7 +1869,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
return rc;
}
@@ -1876,7 +1901,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool reverse)
+ bool reverse,
+ bool dummy)
{
char macaddr[VIR_MAC_STRING_BUFLEN],
ipaddr[INET_ADDRSTRLEN],
@@ -1899,6 +1925,11 @@ ebtablesCreateRuleInstance(char chainPrefix,
PRINT_CHAIN(chain, chainPrefix, ifname,
virNWFilterChainSuffixTypeToString(nwfilter->chainsuffix));
+ if (dummy) {
+ virBufferVSprintf(&buf, CMD_DEF_PRE "%s -- -t %s -%%c %s %%s",
+ "echo", EBTABLES_DEFAULT_TABLE, chain);
+ goto prskip;
+ }
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2300,6 +2331,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
return -1;
}
+prskip:
+
switch (rule->action) {
case VIR_NWFILTER_RULE_ACTION_REJECT:
/* REJECT not supported */
@@ -2357,11 +2390,15 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
- virNWFilterRuleInstPtr res)
+ virNWFilterRuleInstPtr res,
+ bool usetemp,
+ bool dummy)
{
int rc = 0;
bool isIPv6;
+ char chainPrefix;
+ chainPrefix = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_IP:
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2372,26 +2409,30 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT ||
rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
- rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP,
+ rc = ebtablesCreateRuleInstance(chainPrefix,
nwfilter,
rule,
ifname,
vars,
res,
- rule->tt ==
VIR_NWFILTER_RULE_DIRECTION_INOUT);
+ rule->tt ==
VIR_NWFILTER_RULE_DIRECTION_INOUT,
+ dummy);
if (rc)
return rc;
}
+ chainPrefix = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+ CHAINPREFIX_HOST_OUT;
if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN ||
rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
- rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP,
+ rc = ebtablesCreateRuleInstance(chainPrefix,
nwfilter,
rule,
ifname,
vars,
res,
- false);
+ false,
+ dummy);
}
break;
@@ -2417,7 +2458,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -2441,7 +2484,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_LAST:
diff --git a/src/nwfilter/nwfilter_gentech_driver.c
b/src/nwfilter/nwfilter_gentech_driver.c
index f89fb79..0bc3537 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -222,7 +222,9 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
virNWFilterDefPtr filter,
virNWFilterRuleDefPtr rule,
const char *ifname,
- virNWFilterHashTablePtr vars)
+ virNWFilterHashTablePtr vars,
+ bool usetemp,
+ bool dummy)
{
int rc;
int i;
@@ -235,8 +237,8 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
ret->techdriver = techdriver;
- rc = techdriver->createRuleInstance(conn, nettype, filter,
- rule, ifname, vars, ret);
+ rc = techdriver->createRuleInstance(conn, nettype, filter, rule, ifname,
+ vars, ret, usetemp, dummy);
if (rc) {
for (i = 0; i < ret->ndata; i++)
@@ -292,6 +294,8 @@ err_exit:
* @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.
+ * @matchvar: if non-null, variable name to match
+ * @notmatch: if matchvar set, match filters that do not reference matchvar
* @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
@@ -315,6 +319,8 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
virNWFilterDefPtr filter,
const char *ifname,
virNWFilterHashTablePtr vars,
+ const char *matchvar,
+ bool notmatch,
int *nEntries,
virNWFilterRuleInstPtr **insts,
enum instCase useNewFilter, bool *foundNewFilter,
@@ -325,18 +331,34 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
int i;
virNWFilterRuleInstPtr inst;
virNWFilterDefPtr next_filter;
+ bool usetemp, dummy;
for (i = 0; i < filter->nentries; i++) {
virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule;
virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include;
if (rule) {
+ usetemp = 1;
+ dummy = 0;
+ if (matchvar) {
+ int j;
+
+ for (j = 0; j < rule->nvars; ++j)
+ if (strcmp(rule->vars[j], matchvar) == 0)
+ break;
+ /* use temp chains only on base rule install */
+ usetemp = notmatch;
+ /* skip if not found; notmatch reverses the sense */
+ dummy = (j == rule->nvars) ^ notmatch;
+ }
inst = virNWFilterRuleInstantiate(conn,
techdriver,
nettype,
filter,
rule,
ifname,
- vars);
+ vars,
+ usetemp,
+ dummy);
if (!inst) {
rc = 1;
break;
@@ -394,6 +416,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
next_filter,
ifname,
tmpvars,
+ matchvar, notmatch,
nEntries, insts,
useNewFilter,
foundNewFilter,
@@ -623,6 +646,7 @@ virNWFilterInstantiate(virConnectPtr conn,
filter,
ifname,
vars,
+ 0, 0,
&nEntries, &insts,
useNewFilter, foundNewFilter,
driver);