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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list