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>
---
src/conf/nwfilter_conf.h | 4 +-
src/nwfilter/nwfilter_ebiptables_driver.c | 93 +++++++++++++++++++++--------
src/nwfilter/nwfilter_gentech_driver.c | 32 +++++++++-
3 files changed, 100 insertions(+), 29 deletions(-)
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 17e954e..4348378 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -525,7 +525,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 e6a4880..918625c 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1136,6 +1136,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
*
@@ -1154,7 +1155,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];
@@ -1181,6 +1183,13 @@ _iptablesCreateRuleInstance(int directionIn,
PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+ if (dummy) {
+ virBufferAsprintf(&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:
@@ -1521,6 +1530,8 @@ _iptablesCreateRuleInstance(int directionIn,
return -1;
}
+prskip:
+
if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) ||
skipRule) {
virBufferFreeAndReset(&buf);
@@ -1636,7 +1647,9 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0;
@@ -1668,7 +1681,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,
@@ -1680,7 +1693,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
if (rc)
@@ -1700,7 +1714,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,
@@ -1712,7 +1727,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
@@ -1736,7 +1752,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,
@@ -1747,7 +1764,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
}
@@ -1761,7 +1779,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0;
@@ -1777,7 +1797,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
}
if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
@@ -1800,7 +1822,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,
@@ -1811,7 +1833,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1822,7 +1845,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,
@@ -1833,7 +1856,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1844,7 +1868,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,
@@ -1855,7 +1879,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
return rc;
}
@@ -1886,7 +1911,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],
@@ -1909,6 +1935,11 @@ ebtablesCreateRuleInstance(char chainPrefix,
PRINT_CHAIN(chain, chainPrefix, ifname,
virNWFilterChainSuffixTypeToString(nwfilter->chainsuffix));
+ if (dummy) {
+ virBufferAsprintf(&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:
@@ -2317,6 +2348,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
return -1;
}
+prskip:
+
switch (rule->action) {
case VIR_NWFILTER_RULE_ACTION_REJECT:
/* REJECT not supported */
@@ -2374,11 +2407,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:
@@ -2389,26 +2426,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;
@@ -2427,7 +2468,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -2444,7 +2487,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 7891983..79350ac 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -284,7 +284,9 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
virNWFilterDefPtr filter,
virNWFilterRuleDefPtr rule,
const char *ifname,
- virNWFilterHashTablePtr vars)
+ virNWFilterHashTablePtr vars,
+ bool usetemp,
+ bool dummy)
{
int rc;
int i;
@@ -297,8 +299,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++)
@@ -354,6 +356,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
@@ -377,6 +381,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,
@@ -387,18 +393,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;
@@ -456,6 +478,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
next_filter,
ifname,
tmpvars,
+ matchvar, notmatch,
nEntries, insts,
useNewFilter,
foundNewFilter,
@@ -684,6 +707,7 @@ virNWFilterInstantiate(virConnectPtr conn,
filter,
ifname,
vars,
+ 0, 0,
&nEntries, &insts,
useNewFilter, foundNewFilter,
driver);
--
1.7.6.4