1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-20 18:27:16 +01:00

Support for NAT branching for iptables; see #84

This commit is contained in:
Vadim Kurland 2009-10-20 19:31:55 +00:00
parent 0dc0a989f0
commit 7d672c2169
25 changed files with 1469 additions and 741 deletions

View File

@ -1 +1 @@
#define BUILD_NUM 1620
#define BUILD_NUM 1621

View File

@ -1,3 +1,27 @@
2009-10-20 vadim <vadim@vk.crocodile.org>
* Support for branch rules in NAT rule sets. Currently only
supported on iptables and PF. NAT rules get column "Action" for
these platforms, with possible acctions "Translate" and "Branch".
Action parameters dialog for the Branch action provides drop well
where another NAT ruleset object can be dropped (just like with
Branch action in the Policy rules). Action "Translate" performs
translation as defined in the rule. Objects in the "Translated
source/destination/service" are ignored in NAT rules with action
"Branch" and a warning is issued at compile time.
* NATCompiler_ipt.cpp (splitNATBranchRule::processNext): Support
for branching NAT rules for iptables. Rules in the branch rule set
are processed first and their targets and corresponding chains are
recorded. These rules are placed in the user-defined chains with
the name composed of the rule set name and the
chain ("POSTROUTING" or "PREROUTING") that corresponds to the
chosen target. Then top NAT rule set is processed. Branching rules
found in it pass control to the chains used for the rules from the
branching rule set. IF branching rule set uses a mix of SNAT and
DNAT rules, the branching rule in the top rule set is split and
placed in both PREROUTING and POSTROUTING chains as appropriate.
2009-10-14 vadim <vadim@vk.crocodile.org>
* src/res/configlets/linux24/conntrack: Implemented support for

View File

@ -548,11 +548,10 @@ void CompilerDriver::findImportedRuleSets(Firewall *fw,
{
for (list<FWObject*>::iterator r=(*i)->begin(); r!=(*i)->end(); ++r)
{
PolicyRule *rule = PolicyRule::cast(*r);
RuleSet *ruleset = NULL;
if (rule->getAction() == PolicyRule::Branch &&
(ruleset = rule->getBranch())!=NULL &&
!ruleset->isChildOf(fw))
Rule *rule = Rule::cast(*r);
RuleSet *ruleset = rule->getBranch();
if (ruleset!=NULL && !ruleset->isChildOf(fw))
{
ruleset->setTop(false);
imported_policies.push_back(ruleset);

View File

@ -67,8 +67,8 @@ ActionsDialog::ActionsDialog(QWidget *parent) : BaseObjectDialog(parent)
m_dialog->setupUi(this);
m_dialog->iptBranchDropArea->addAcceptedTypes("Policy");
m_dialog->iptBranchDropArea->addAcceptedTypes("NAT");
m_dialog->iptBranchDropArea->addAcceptedTypes("Routing");
//m_dialog->iptBranchDropArea->addAcceptedTypes("NAT");
//m_dialog->iptBranchDropArea->addAcceptedTypes("Routing");
m_dialog->iptBranchDropArea->setHelperText("Drop rule set object here");
connect (m_dialog->iptBranchDropArea,
SIGNAL(objectDeleted()),this,SLOT(changed()));
@ -76,14 +76,21 @@ ActionsDialog::ActionsDialog(QWidget *parent) : BaseObjectDialog(parent)
SIGNAL(objectInserted()),this,SLOT(changed()));
m_dialog->pfBranchDropArea->addAcceptedTypes("Policy");
m_dialog->pfBranchDropArea->addAcceptedTypes("NAT");
m_dialog->pfBranchDropArea->addAcceptedTypes("Routing");
//m_dialog->pfBranchDropArea->addAcceptedTypes("NAT");
//m_dialog->pfBranchDropArea->addAcceptedTypes("Routing");
m_dialog->pfBranchDropArea->setHelperText("Drop rule set object here");
connect (m_dialog->pfBranchDropArea,
SIGNAL(objectDeleted()),this,SLOT(changed()));
connect (m_dialog->pfBranchDropArea,
SIGNAL(objectInserted()),this,SLOT(changed()));
m_dialog->natBranchDropArea->addAcceptedTypes("NAT");
m_dialog->natBranchDropArea->setHelperText("Drop NAT rule set object here");
connect (m_dialog->natBranchDropArea,
SIGNAL(objectDeleted()),this,SLOT(changed()));
connect (m_dialog->natBranchDropArea,
SIGNAL(objectInserted()),this,SLOT(changed()));
m_dialog->pfTagDropArea->addAcceptedTypes("TagService");
connect (m_dialog->pfTagDropArea,
SIGNAL(objectDeleted()),this,SLOT(changed()));
@ -199,6 +206,13 @@ void ActionsDialog::applyChanges()
rule->setBranch(ruleset);
}
if (editor=="NATBranch")
{
RuleSet *ruleset = RuleSet::cast(m_dialog->natBranchDropArea->getObject());
// if ruleset==NULL, setBranch clears setting in the rule
rule->setBranch(ruleset);
}
if (m_dialog->useDummyNetPipe->isChecked())
ropt->setInt("ipfw_classify_method",DUMMYNETPIPE);
else
@ -249,7 +263,11 @@ void ActionsDialog::setRule(Rule *r)
string act;
if (policy_rule) act = policy_rule->getActionAsString();
if (nat_rule) act = nat_rule->getActionAsString();
if (nat_rule)
{
act = nat_rule->getActionAsString();
if (act == "Branch") act = "NATBranch";
}
help_name = string(platform + "_" + act).c_str();
@ -398,6 +416,12 @@ void ActionsDialog::setRule(Rule *r)
RuleSet *ruleset = r->getBranch();
m_dialog->iptBranchDropArea->setObject(ruleset);
}
else if (editor=="NATBranch")
{
w = m_dialog->NATBranchPage;
RuleSet *ruleset = r->getBranch();
m_dialog->natBranchDropArea->setObject(ruleset);
}
else if (editor=="RouteIPT")
{
w=m_dialog->RouteIPTPage;

View File

@ -37,7 +37,7 @@
<enum>QFrame::Plain</enum>
</property>
<property name="currentIndex" >
<number>12</number>
<number>14</number>
</property>
<widget class="QWidget" name="TagStrPage" >
<layout class="QGridLayout" >
@ -1042,6 +1042,65 @@ object properties dialog.</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="NATBranchPage" >
<layout class="QGridLayout" name="gridLayout_2" >
<item row="0" column="0" colspan="2" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>NAT Rule set object:</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="FWObjectDropArea" native="1" name="natBranchDropArea" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>100</width>
<height>80</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>100</width>
<height>80</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1" >
<spacer name="horizontalSpacer" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>663</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1" >
<spacer name="verticalSpacer" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>33</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -1057,7 +1116,6 @@ object properties dialog.</string>
<container>1</container>
</customwidget>
</customwidgets>
<includes/>
<resources>
<include location="MainRes.qrc" />
</resources>

View File

@ -24,39 +24,22 @@
*/
#include "../../config.h"
#include "../../build_num"
#include <fstream>
#include <iostream>
#include <algorithm>
#include <functional>
#include <stdexcept>
#include <assert.h>
#include <cstring>
#include <iomanip>
#include <memory>
#include "Configlet.h"
#include "CompilerDriver_ipt.h"
#include "PolicyCompiler_ipt.h"
#include "PolicyCompiler_secuwall.h"
#include "MangleTableCompiler_ipt.h"
#include "OSConfigurator_linux24.h"
#include "OSConfigurator_ipcop.h"
#include "OSConfigurator_secuwall.h"
#include "fwcompiler/Preprocessor.h"
#include "fwbuilder/Resources.h"
#include "fwbuilder/FWObjectDatabase.h"
#include "fwbuilder/FWException.h"
#include "fwbuilder/Cluster.h"
#include "fwbuilder/ClusterGroup.h"
#include "fwbuilder/Firewall.h"
#include "fwbuilder/Interface.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/Rule.h"
#include "fwbuilder/RuleSet.h"
#include <QStringList>
#include <fstream>
#include <iostream>
#include <assert.h>
using namespace std;
@ -191,232 +174,4 @@ string CompilerDriver_ipt::dumpScript(Firewall *fw,
return res.str();
}
bool CompilerDriver_ipt::processPolicyRuleSet(
Firewall *fw,
FWObject *ruleset,
const string &single_rule_id,
ostringstream &filter_table_stream,
ostringstream &mangle_table_stream,
ostringstream &automatic_rules_stream,
OSConfigurator_linux24 *oscnf,
int policy_af,
std::map<const std::string, bool> &minus_n_commands_filter,
std::map<const std::string, bool> &minus_n_commands_mangle)
{
int policy_rules_count = 0;
int mangle_rules_count = 0;
bool have_connmark = false;
bool have_connmark_in_output = false;
bool empty_output = true;
string prolog_place = fw->getOptionsObject()->getStr("prolog_place");
string platform = fw->getStr("platform");
string host_os = fw->getStr("host_OS");
bool flush_and_set_default_policy = Resources::getTargetOptionBool(
host_os, "default/flush_and_set_default_policy");
string platform_family = Resources::platform_res[platform]->
getResourceStr("/FWBuilderResources/Target/family");
string os_family = Resources::os_res[host_os]->
getResourceStr("/FWBuilderResources/Target/family");
Policy *policy = Policy::cast(ruleset);
assignRuleSetChain(policy);
string branch_name = policy->getName();
if (!policy->matchingAddressFamily(policy_af)) return true;
bool ipv6_policy = (policy_af == AF_INET6);
std::auto_ptr<MangleTableCompiler_ipt> mangle_compiler(
new MangleTableCompiler_ipt(objdb , fw,
ipv6_policy , oscnf,
&minus_n_commands_mangle ));
if (!policy->isTop())
mangle_compiler->registerRuleSetChain(branch_name);
mangle_compiler->setSourceRuleSet( policy );
mangle_compiler->setRuleSetName(branch_name);
mangle_compiler->setSingleRuleCompileMode(single_rule_id);
mangle_compiler->setDebugLevel( dl );
if (rule_debug_on) mangle_compiler->setDebugRule( drp );
mangle_compiler->setVerbose( (bool)(verbose) );
mangle_compiler->setHaveDynamicInterfaces(have_dynamic_interfaces);
if (inTestMode()) mangle_compiler->setTestMode();
if (inEmbeddedMode()) mangle_compiler->setEmbeddedMode();
if ( (mangle_rules_count = mangle_compiler->prolog()) > 0 )
{
mangle_compiler->compile();
mangle_compiler->epilog();
// We need to generate automatic rules in mangle
// table (-j CONNMARK --restore-mark) if CONNMARK
// target is present in any ruleset, not only in
// the top-level ruleset. So we keep global
// boolean flags for this condition which will
// become true if any ruleset has such
// rules. We'll call
// MangleTableCompiler_ipt::flushAndSetDefaultPolicy
// later if either of these flags is true after
// all rulesets have been processed.
have_connmark |= mangle_compiler->haveConnMarkRules();
have_connmark_in_output |= mangle_compiler->haveConnMarkRulesInOutput();
long m_str_pos = mangle_table_stream.tellp();
if (policy->isTop())
{
ostringstream tmp;
if (flush_and_set_default_policy)
tmp << mangle_compiler->flushAndSetDefaultPolicy();
tmp << mangle_compiler->printAutomaticRules();
if (tmp.tellp() > 0)
{
if (!single_rule_compile_on)
{
mangle_table_stream << "# ================ Table 'mangle', ";
mangle_table_stream << "automatic rules";
mangle_table_stream << "\n";
}
mangle_table_stream << tmp.str();
}
}
if (mangle_compiler->getCompiledScriptLength() > 0)
{
ostringstream tmp;
if (mangle_compiler->haveErrorsAndWarnings())
{
all_errors.push_back(mangle_compiler->getErrors("").c_str());
// tmp << "# Policy compiler errors and warnings:" << "\n";
// tmp << mangle_compiler->getErrors("# ");
}
tmp << mangle_compiler->getCompiledScript();
if (tmp.tellp() > 0)
{
if (!single_rule_compile_on)
{
mangle_table_stream << "# ================ Table 'mangle', ";
mangle_table_stream << "rule set " << branch_name << "\n";
}
mangle_table_stream << tmp.str();
}
}
if (m_str_pos!=mangle_table_stream.tellp())
{
mangle_table_stream << "\n";
empty_output = false;
}
}
std::auto_ptr<PolicyCompiler_ipt> policy_compiler;
if (fw->getStr("host_OS") == "secuwall") {
policy_compiler = std::auto_ptr<PolicyCompiler_ipt>(
new PolicyCompiler_secuwall(objdb,fw, ipv6_policy, oscnf,
&minus_n_commands_filter));
} else {
policy_compiler = std::auto_ptr<PolicyCompiler_ipt>(
new PolicyCompiler_ipt(objdb,fw, ipv6_policy, oscnf,
&minus_n_commands_filter));
}
if (policy_compiler.get()==NULL)
throw FWException("Unrecognized firewall platform " +
fw->getStr("platform") +
" (family " + platform_family+")");
if (!policy->isTop())
policy_compiler->registerRuleSetChain(branch_name);
policy_compiler->setSourceRuleSet( policy );
policy_compiler->setRuleSetName(branch_name);
policy_compiler->setSingleRuleCompileMode(single_rule_id);
policy_compiler->setDebugLevel( dl );
if (rule_debug_on) policy_compiler->setDebugRule( drp );
policy_compiler->setVerbose( (bool)(verbose) );
policy_compiler->setHaveDynamicInterfaces(have_dynamic_interfaces);
if (inTestMode()) policy_compiler->setTestMode();
if (inEmbeddedMode()) policy_compiler->setEmbeddedMode();
if ( (policy_rules_count=policy_compiler->prolog()) > 0 )
{
policy_compiler->compile();
policy_compiler->epilog();
if (policy_compiler->getCompiledScriptLength() > 0)
{
ostringstream tmp;
if (policy_compiler->haveErrorsAndWarnings())
{
all_errors.push_back(policy_compiler->getErrors("").c_str());
// tmp << "# Policy compiler errors and warnings:" << "\n";
// tmp << policy_compiler->getErrors("# ");
}
tmp << policy_compiler->getCompiledScript();
if (tmp.tellp() > 0)
{
empty_output = false;
if (!single_rule_compile_on)
{
filter_table_stream << "# ================ Table 'filter', ";
filter_table_stream << "rule set " << branch_name << "\n";
}
filter_table_stream << tmp.str();
}
}
}
/* bug #2550074: "Automatic rules for filter table included twice
* in iptables". If user had two policy ruleset objects marked as
* "top" rule set, then automaitc rules were added twice. Since we
* add rules to automatic_rules_stream only in this one place, it
* is sufficient to check if the stream is empty to avoid
* duplication. Note that on windows tellp() seems to return -1
* if no data has ever been written to the stream.
*/
long auto_rules_stream_position = automatic_rules_stream.tellp();
if (policy->isTop() && auto_rules_stream_position <= 0)
{
ostringstream tmp;
if (flush_and_set_default_policy)
tmp << policy_compiler->flushAndSetDefaultPolicy();
if (!prolog_done && prolog_place == "after_flush" &&
!fw->getOptionsObject()->getBool("use_iptables_restore"))
{
tmp << "prolog_commands" << endl;
prolog_done = true;
}
tmp << policy_compiler->printAutomaticRules();
if (tmp.tellp() > 0)
{
empty_output = false;
if (!single_rule_compile_on)
{
automatic_rules_stream
<< "# ================ Table 'filter', automatic rules"
<< "\n";
}
automatic_rules_stream << tmp.str();
}
}
return empty_output;
}

View File

@ -32,6 +32,8 @@
#include <string>
#include <sstream>
#include <map>
#include <list>
#include <QString>
#include <QMap>
@ -50,6 +52,19 @@ namespace fwcompiler {
class CompilerDriver_ipt : public CompilerDriver {
// commands that pass control to branch chains should go into
// POSTROUTING or PREROUTING chains depending on the targets used
// inside the branch. Branches that use mixed rules (both SNAT
// and DNAT) will be split so that two separate chains are created, one
// for all SNAT rules and another for all DNAT rules. Rules in
// the top NAT ruleset that pass control to them will be placed into
// PREROUTING or POSTROUTING chain depending on the target in the branch.
// The following maps targets used in the branch to the ruleset name.
// By convention, the chain created for the branch rules will be named
// using combination of the ruleset name and word "PREROUTING"
// or "POSTROUTING"
std::map<std::string, std::list<std::string> > branch_ruleset_to_chain_mapping;
public:
CompilerDriver_ipt(libfwbuilder::FWObjectDatabase *db);
@ -84,6 +99,16 @@ public:
std::map<const std::string, bool> &minus_n_commands_filter,
std::map<const std::string, bool> &minus_n_commands_mangle);
bool processNatRuleSet(
libfwbuilder::Firewall *fw,
libfwbuilder::FWObject *ruleset,
const std::string &single_rule_id,
std::ostringstream &nat_stream,
fwcompiler::OSConfigurator_linux24 *oscnf,
int policy_af,
std::map<const std::string, bool> &minus_n_commands_nat);
virtual void processStateSyncGroups(libfwbuilder::Cluster *cluster,
libfwbuilder::Firewall *member_fw);

View File

@ -0,0 +1,130 @@
/*
Firewall Builder
Copyright (C) 2009 NetCitadel, LLC
Author: Vadim Kurland vadim@vk.crocodile.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that license as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../../config.h"
#include "CompilerDriver_ipt.h"
#include "NATCompiler_ipt.h"
#include "OSConfigurator_linux24.h"
#include "fwbuilder/FWObjectDatabase.h"
#include "fwbuilder/FWException.h"
#include "fwbuilder/Firewall.h"
#include "fwbuilder/NAT.h"
#include "fwbuilder/Resources.h"
#include <fstream>
#include <iostream>
#include <memory>
using namespace std;
using namespace libfwbuilder;
using namespace fwcompiler;
bool CompilerDriver_ipt::processNatRuleSet(
Firewall *fw,
FWObject *ruleset,
const std::string &single_rule_id,
std::ostringstream &nat_rules_stream,
fwcompiler::OSConfigurator_linux24 *oscnf,
int policy_af,
std::map<const std::string, bool> &minus_n_commands_nat)
{
int nat_rules_count = 0;
string host_os = fw->getStr("host_OS");
bool flush_and_set_default_policy = Resources::getTargetOptionBool(
host_os, "default/flush_and_set_default_policy");
bool empty_output = true;
NAT *nat = NAT::cast(ruleset);
assignRuleSetChain(nat);
string branch_name = nat->getName();
if (!nat->matchingAddressFamily(policy_af)) return true;
bool ipv6_policy = (policy_af == AF_INET6);
// compile NAT rules before policy rules because policy
// compiler needs to know the number of virtual addresses
// being created for NAT
std::auto_ptr<NATCompiler_ipt> nat_compiler(
new NATCompiler_ipt(objdb, fw, ipv6_policy,
oscnf, &minus_n_commands_nat));
if (!nat->isTop())
nat_compiler->registerRuleSetChain(branch_name);
nat_compiler->setSourceRuleSet( nat );
nat_compiler->setRuleSetName(branch_name);
nat_compiler->setSingleRuleCompileMode(single_rule_id);
nat_compiler->setDebugLevel( dl );
if (rule_debug_on) nat_compiler->setDebugRule( drn );
nat_compiler->setVerbose( (bool)(verbose) );
nat_compiler->setHaveDynamicInterfaces(have_dynamic_interfaces);
if (inTestMode()) nat_compiler->setTestMode();
if (inEmbeddedMode()) nat_compiler->setEmbeddedMode();
nat_compiler->setRulesetToChainMapping(&branch_ruleset_to_chain_mapping);
if ( (nat_rules_count=nat_compiler->prolog()) > 0 )
{
nat_compiler->compile();
nat_compiler->epilog();
}
have_nat = (have_nat || (nat_rules_count > 0));
if (nat_compiler->getCompiledScriptLength() > 0)
{
if (!single_rule_compile_on)
nat_rules_stream << "# ================ Table 'nat', "
<< " rule set "
<< branch_name << "\n";
if (nat_compiler->haveErrorsAndWarnings())
{
all_errors.push_back(nat_compiler->getErrors("").c_str());
}
if (nat->isTop())
{
if (flush_and_set_default_policy)
nat_rules_stream << nat_compiler->flushAndSetDefaultPolicy();
nat_rules_stream << nat_compiler->printAutomaticRules();
}
nat_rules_stream << nat_compiler->getCompiledScript();
nat_rules_stream << "\n";
empty_output = false;
branch_ruleset_to_chain_mapping[branch_name] = nat_compiler->getUsedChains();
}
return empty_output;
}

View File

@ -0,0 +1,280 @@
/*
Firewall Builder
Copyright (C) 2009 NetCitadel, LLC
Author: Vadim Kurland vadim@vk.crocodile.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that license as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../../config.h"
#include "CompilerDriver_ipt.h"
#include "MangleTableCompiler_ipt.h"
#include "PolicyCompiler_ipt.h"
#include "PolicyCompiler_secuwall.h"
#include "OSConfigurator_linux24.h"
#include "Configlet.h"
#include "fwbuilder/FWObjectDatabase.h"
#include "fwbuilder/FWException.h"
#include "fwbuilder/Firewall.h"
#include "fwbuilder/Interface.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/Resources.h"
#include <fstream>
#include <iostream>
#include <memory>
using namespace std;
using namespace libfwbuilder;
using namespace fwcompiler;
bool CompilerDriver_ipt::processPolicyRuleSet(
Firewall *fw,
FWObject *ruleset,
const string &single_rule_id,
ostringstream &filter_table_stream,
ostringstream &mangle_table_stream,
ostringstream &automatic_rules_stream,
OSConfigurator_linux24 *oscnf,
int policy_af,
std::map<const std::string, bool> &minus_n_commands_filter,
std::map<const std::string, bool> &minus_n_commands_mangle)
{
int policy_rules_count = 0;
int mangle_rules_count = 0;
bool have_connmark = false;
bool have_connmark_in_output = false;
bool empty_output = true;
string prolog_place = fw->getOptionsObject()->getStr("prolog_place");
string platform = fw->getStr("platform");
string host_os = fw->getStr("host_OS");
bool flush_and_set_default_policy = Resources::getTargetOptionBool(
host_os, "default/flush_and_set_default_policy");
string platform_family = Resources::platform_res[platform]->
getResourceStr("/FWBuilderResources/Target/family");
string os_family = Resources::os_res[host_os]->
getResourceStr("/FWBuilderResources/Target/family");
Policy *policy = Policy::cast(ruleset);
assignRuleSetChain(policy);
string branch_name = policy->getName();
if (!policy->matchingAddressFamily(policy_af)) return true;
bool ipv6_policy = (policy_af == AF_INET6);
std::auto_ptr<MangleTableCompiler_ipt> mangle_compiler(
new MangleTableCompiler_ipt(objdb , fw,
ipv6_policy , oscnf,
&minus_n_commands_mangle ));
if (!policy->isTop())
mangle_compiler->registerRuleSetChain(branch_name);
mangle_compiler->setSourceRuleSet( policy );
mangle_compiler->setRuleSetName(branch_name);
mangle_compiler->setSingleRuleCompileMode(single_rule_id);
mangle_compiler->setDebugLevel( dl );
if (rule_debug_on) mangle_compiler->setDebugRule( drp );
mangle_compiler->setVerbose( (bool)(verbose) );
mangle_compiler->setHaveDynamicInterfaces(have_dynamic_interfaces);
if (inTestMode()) mangle_compiler->setTestMode();
if (inEmbeddedMode()) mangle_compiler->setEmbeddedMode();
if ( (mangle_rules_count = mangle_compiler->prolog()) > 0 )
{
mangle_compiler->compile();
mangle_compiler->epilog();
// We need to generate automatic rules in mangle
// table (-j CONNMARK --restore-mark) if CONNMARK
// target is present in any ruleset, not only in
// the top-level ruleset. So we keep global
// boolean flags for this condition which will
// become true if any ruleset has such
// rules. We'll call
// MangleTableCompiler_ipt::flushAndSetDefaultPolicy
// later if either of these flags is true after
// all rulesets have been processed.
have_connmark |= mangle_compiler->haveConnMarkRules();
have_connmark_in_output |= mangle_compiler->haveConnMarkRulesInOutput();
long m_str_pos = mangle_table_stream.tellp();
if (policy->isTop())
{
ostringstream tmp;
if (flush_and_set_default_policy)
tmp << mangle_compiler->flushAndSetDefaultPolicy();
tmp << mangle_compiler->printAutomaticRules();
if (tmp.tellp() > 0)
{
if (!single_rule_compile_on)
{
mangle_table_stream << "# ================ Table 'mangle', ";
mangle_table_stream << "automatic rules";
mangle_table_stream << "\n";
}
mangle_table_stream << tmp.str();
}
}
if (mangle_compiler->getCompiledScriptLength() > 0)
{
ostringstream tmp;
if (mangle_compiler->haveErrorsAndWarnings())
{
all_errors.push_back(mangle_compiler->getErrors("").c_str());
// tmp << "# Policy compiler errors and warnings:" << "\n";
// tmp << mangle_compiler->getErrors("# ");
}
tmp << mangle_compiler->getCompiledScript();
if (tmp.tellp() > 0)
{
if (!single_rule_compile_on)
{
mangle_table_stream << "# ================ Table 'mangle', ";
mangle_table_stream << "rule set " << branch_name << "\n";
}
mangle_table_stream << tmp.str();
}
}
if (m_str_pos!=mangle_table_stream.tellp())
{
mangle_table_stream << "\n";
empty_output = false;
}
}
std::auto_ptr<PolicyCompiler_ipt> policy_compiler;
if (fw->getStr("host_OS") == "secuwall") {
policy_compiler = std::auto_ptr<PolicyCompiler_ipt>(
new PolicyCompiler_secuwall(objdb,fw, ipv6_policy, oscnf,
&minus_n_commands_filter));
} else {
policy_compiler = std::auto_ptr<PolicyCompiler_ipt>(
new PolicyCompiler_ipt(objdb,fw, ipv6_policy, oscnf,
&minus_n_commands_filter));
}
if (policy_compiler.get()==NULL)
throw FWException("Unrecognized firewall platform " +
fw->getStr("platform") +
" (family " + platform_family+")");
if (!policy->isTop())
policy_compiler->registerRuleSetChain(branch_name);
policy_compiler->setSourceRuleSet( policy );
policy_compiler->setRuleSetName(branch_name);
policy_compiler->setSingleRuleCompileMode(single_rule_id);
policy_compiler->setDebugLevel( dl );
if (rule_debug_on) policy_compiler->setDebugRule( drp );
policy_compiler->setVerbose( (bool)(verbose) );
policy_compiler->setHaveDynamicInterfaces(have_dynamic_interfaces);
if (inTestMode()) policy_compiler->setTestMode();
if (inEmbeddedMode()) policy_compiler->setEmbeddedMode();
if ( (policy_rules_count=policy_compiler->prolog()) > 0 )
{
policy_compiler->compile();
policy_compiler->epilog();
if (policy_compiler->getCompiledScriptLength() > 0)
{
ostringstream tmp;
if (policy_compiler->haveErrorsAndWarnings())
{
all_errors.push_back(policy_compiler->getErrors("").c_str());
// tmp << "# Policy compiler errors and warnings:" << "\n";
// tmp << policy_compiler->getErrors("# ");
}
tmp << policy_compiler->getCompiledScript();
if (tmp.tellp() > 0)
{
empty_output = false;
if (!single_rule_compile_on)
{
filter_table_stream << "# ================ Table 'filter', ";
filter_table_stream << "rule set " << branch_name << "\n";
}
filter_table_stream << tmp.str();
}
}
}
/* bug #2550074: "Automatic rules for filter table included twice
* in iptables". If user had two policy ruleset objects marked as
* "top" rule set, then automaitc rules were added twice. Since we
* add rules to automatic_rules_stream only in this one place, it
* is sufficient to check if the stream is empty to avoid
* duplication. Note that on windows tellp() seems to return -1
* if no data has ever been written to the stream.
*/
long auto_rules_stream_position = automatic_rules_stream.tellp();
if (policy->isTop() && auto_rules_stream_position <= 0)
{
ostringstream tmp;
if (flush_and_set_default_policy)
tmp << policy_compiler->flushAndSetDefaultPolicy();
if (!prolog_done && prolog_place == "after_flush" &&
!fw->getOptionsObject()->getBool("use_iptables_restore"))
{
tmp << "prolog_commands" << endl;
prolog_done = true;
}
tmp << policy_compiler->printAutomaticRules();
if (tmp.tellp() > 0)
{
empty_output = false;
if (!single_rule_compile_on)
{
automatic_rules_stream
<< "# ================ Table 'filter', automatic rules"
<< "\n";
}
automatic_rules_stream << tmp.str();
}
}
return empty_output;
}

View File

@ -163,9 +163,6 @@ string CompilerDriver_ipt::run(const std::string &cluster_id,
string os_variant = DISTRO;
bool flush_and_set_default_policy = Resources::getTargetOptionBool(
platform, "default/flush_and_set_default_policy");
/* minimal sanity checking */
if (os_family == "ipcop")
{
@ -203,7 +200,6 @@ string CompilerDriver_ipt::run(const std::string &cluster_id,
list<FWObject*> all_policies = fw->getByType(Policy::TYPENAME);
list<FWObject*> all_nat = fw->getByType(NAT::TYPENAME);
int nat_rules_count = 0;
int routing_rules_count = 0;
bool have_nat = false;
bool have_ipv6 = false;
@ -223,6 +219,7 @@ string CompilerDriver_ipt::run(const std::string &cluster_id,
findImportedRuleSets(fw, all_policies);
findBranchesInMangleTable(fw, all_policies);
findImportedRuleSets(fw, all_nat);
// command line options -4 and -6 control address family for which
// script will be generated. If "-4" is used, only ipv4 part will
@ -297,78 +294,52 @@ string CompilerDriver_ipt::run(const std::string &cluster_id,
ostringstream nat_rules_stream;
bool empty_output = true;
//MangleTableCompiler_ipt *top_level_mangle_compiler = NULL;
// First, process branch NAT rulesets, then top NAT ruleset
NAT *top_nat = NULL;
for (list<FWObject*>::iterator p=all_nat.begin();
p!=all_nat.end(); ++p )
p!=all_nat.end(); ++p)
{
NAT *nat = NAT::cast(*p);
assignRuleSetChain(nat);
string branch_name = nat->getName();
if (!nat->matchingAddressFamily(policy_af)) continue;
// compile NAT rules before policy rules because policy
// compiler needs to know the number of virtual addresses
// being created for NAT
std::auto_ptr<NATCompiler_ipt> nat_compiler(
new NATCompiler_ipt(objdb, fw, ipv6_policy,
oscnf.get(), &minus_n_commands_nat));
nat_compiler->setSourceRuleSet( nat );
nat_compiler->setRuleSetName(branch_name);
nat_compiler->setSingleRuleCompileMode(single_rule_id);
nat_compiler->setDebugLevel( dl );
if (rule_debug_on) nat_compiler->setDebugRule( drn );
nat_compiler->setVerbose( (bool)(verbose) );
nat_compiler->setHaveDynamicInterfaces(have_dynamic_interfaces);
if (inTestMode()) nat_compiler->setTestMode();
if (inEmbeddedMode()) nat_compiler->setEmbeddedMode();
if ( (nat_rules_count=nat_compiler->prolog()) > 0 )
if (nat->isTop())
{
nat_compiler->compile();
nat_compiler->epilog();
}
have_nat = (have_nat || (nat_rules_count > 0));
if (nat_compiler->getCompiledScriptLength() > 0)
{
if (!single_rule_compile_on)
nat_rules_stream << "# ================ Table 'nat', "
<< " rule set "
<< branch_name << "\n";
if (nat_compiler->haveErrorsAndWarnings())
{
all_errors.push_back(nat_compiler->getErrors("").c_str());
// nat_rules_stream << "# NAT compiler errors and "
// << "warnings:\n";
// nat_rules_stream << nat_compiler->getErrors("# ");
}
if (nat->isTop())
{
if (flush_and_set_default_policy)
nat_rules_stream << nat_compiler->flushAndSetDefaultPolicy();
nat_rules_stream << nat_compiler->printAutomaticRules();
}
nat_rules_stream << nat_compiler->getCompiledScript();
nat_rules_stream << "\n";
empty_output = false;
top_nat = nat;
continue;
}
if (! processNatRuleSet(
fw,
nat,
single_rule_id,
nat_rules_stream,
oscnf.get(),
policy_af,
minus_n_commands_nat)) empty_output = false;
}
if (top_nat &&
! processNatRuleSet(
fw,
top_nat,
single_rule_id,
nat_rules_stream,
oscnf.get(),
policy_af,
minus_n_commands_nat)) empty_output = false;
Policy *top_policy = NULL;
for (list<FWObject*>::iterator p=all_policies.begin();
p!=all_policies.end(); ++p )
{
Policy *policy = Policy::cast(*p);
if (!policy->matchingAddressFamily(policy_af)) continue;
if (policy->isTop())
{
top_policy = policy;
continue;
}
if (! processPolicyRuleSet(
fw,
@ -383,6 +354,21 @@ string CompilerDriver_ipt::run(const std::string &cluster_id,
minus_n_commands_mangle)) empty_output = false;
}
if (top_policy &&
! processPolicyRuleSet(
fw,
top_policy,
single_rule_id,
filter_rules_stream,
mangle_rules_stream,
automaitc_rules_stream,
oscnf.get(),
policy_af,
minus_n_commands_filter,
minus_n_commands_mangle)) empty_output = false;
if (!empty_output && !single_rule_compile_on)
{
if (ipv6_policy)

View File

@ -213,7 +213,8 @@ string NATCompiler_ipt::PrintRule::_printChainDirectionAndInterface(NATRule *rul
ostr << rule->getStr("ipt_chain") << " ";
switch (rule->getRuleType()) {
switch (rule->getRuleType())
{
case NATRule::SNAT:
if (!iface_name.empty()) ostr << "-o " << iface_name;
break;
@ -598,7 +599,9 @@ bool NATCompiler_ipt::PrintRule::processNext()
string chain = rule->getStr("ipt_chain");
if (ipt_comp->chain_usage_counter[chain] == 0)
{
return true;
}
tmp_queue.push_back(rule);
@ -679,7 +682,8 @@ bool NATCompiler_ipt::PrintRule::processNext()
cmdout << "-j " << rule->getStr("ipt_target") << " ";
switch (rule->getRuleType()) {
switch (rule->getRuleType())
{
case NATRule::SNAT:
if (rule->getStr("ipt_target")=="SNAT")
{
@ -732,6 +736,10 @@ bool NATCompiler_ipt::PrintRule::processNext()
if (!ports.empty()) cmdout << "--to-ports " << ports;
}
break;
case NATRule::NATBranch:
break;
default: break;
}
cmdout << " ";

View File

@ -157,12 +157,11 @@ string NATCompiler_ipt::debugPrintRule(Rule *r)
return NATCompiler::debugPrintRule(rule)+
" " + FWObjectDatabase::getStringId(rule->getInterfaceId()) +
" " + rule->getStr("ipt_chain") +
" " + rule->getStr("ipt_target") +
" c=" + rule->getStr("ipt_chain") +
" t=" + rule->getStr("ipt_target") +
" (type="+rule->getRuleTypeAsString()+")";
}
void NATCompiler_ipt::verifyPlatform()
{
string family = Resources::platform_res[fw->getStr("platform")]->
@ -480,7 +479,6 @@ bool NATCompiler_ipt::splitSDNATRule::processNext()
return true;
}
bool NATCompiler_ipt::VerifyRules::processNext()
{
NATRule *rule=getNext(); if (rule==NULL) return false;
@ -526,6 +524,19 @@ bool NATCompiler_ipt::VerifyRules::processNext()
rule,
"Load balancing rules are not supported.");
if (rule->getRuleType()==NATRule::NATBranch )
{
RuleSet *branch = rule->getBranch();
if (branch == NULL)
compiler->abort(
rule,
"Action 'Branch' needs NAT rule set to point to");
if (!NAT::isA(branch))
compiler->abort(
rule,
"Action 'Branch' must point to a NAT rule set "
"(points to " + branch->getTypeName() + ")");
}
if (rule->getRuleType()==NATRule::SNAT )
{
@ -536,7 +547,6 @@ bool NATCompiler_ipt::VerifyRules::processNext()
"Can not use network object in translated source.");
}
if (rule->getRuleType()==NATRule::SNetnat && !tsrc->isAny() )
{
Network *a1=Network::cast(compiler->getFirstOSrc(rule));
@ -559,9 +569,6 @@ bool NATCompiler_ipt::VerifyRules::processNext()
"Original and translated destination should both be networks of the same size .");
}
// Service *osrv_obj = compiler->getFirstOSrv(rule);
// Service *tsrv_obj = compiler->getFirstTSrv(rule);
return true;
}
@ -1788,6 +1795,96 @@ bool NATCompiler_ipt::splitNONATRule::processNext()
return true;
}
/**
* Branch rule in NAT rule sets should go into PREROUTING or
* POSTROUTING chain depending on the target of the rules in the
* branch. Iptables verifies this when a command that passes control
* (the one with "-j <branch_ruleset_name>") is entered. If branch
* ruleset has -j SNAT, the command that sends control to the branch
* should be in POSTROUTING. Attempt to place it in PREROUTING ends
* with an error "iptables: Invalid argument".
*
* Note that if branch rule set contains a mix of rules that use both
* SNAT and DNAT targets, the branching rule (that should pass control
* to the branch) can not be added to PREROUTING and POSTROUTING
* chains, it just gives an error "iptables: Invalid argument" for both.
* Tested with iptables 1.4.1.1 10/20/2009
*/
bool NATCompiler_ipt::splitNATBranchRule::processNext()
{
NATCompiler_ipt *ipt_comp = dynamic_cast<NATCompiler_ipt*>(compiler);
NATRule *rule=getNext(); if (rule==NULL) return false;
if ( rule->getRuleType()==NATRule::NATBranch)
{
RuleSet *branch = rule->getBranch();
if (branch)
{
string branch_name = branch->getName();
if (ipt_comp->branch_ruleset_to_chain_mapping)
{
map<string, list<string> >::const_iterator lit =
ipt_comp->branch_ruleset_to_chain_mapping->find(branch_name);
if (lit!=ipt_comp->branch_ruleset_to_chain_mapping->end())
{
list<string> chains = lit->second;
list<string>::iterator it;
for (it=chains.begin(); it!=chains.end(); ++it)
{
string branch_chain = *it;
// If chain in the branch rule set does not
// start with its own name plus "_", skip it
// because it is one of the standard chains
if (branch_chain.find(branch_name + "_") == 0)
{
// branch chain is <branch_ruleset_name> + "_" + <chain>
string my_chain = branch_chain.substr(branch_name.length()+1);
NATRule *r = compiler->dbcopy->createNATRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setStr("ipt_chain", my_chain);
r->setStr("ipt_target", *it);
tmp_queue.push_back(r);
}
}
}
} else
{
compiler->warning(rule,
"NAT branching rule does not have information"
" about targets used in the branch ruleset"
" to choose proper chain in the nat table."
" Will split the rule and place it in both"
" PREROUTNING and POSTROUTING");
NATRule *r = compiler->dbcopy->createNATRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setStr("ipt_chain", "POSTROUTING");
r->setStr("ipt_target", branch_name);
tmp_queue.push_back(r);
r = compiler->dbcopy->createNATRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setStr("ipt_chain", "PREROUTING");
r->setStr("ipt_target", branch_name);
tmp_queue.push_back(r);
}
}
else
{
compiler->abort(rule,
"NAT branching rule misses branch rule set.");
// in case we are in the test mode and abort() does not really abort
rule->setStr("ipt_target", "UNDEFINED");
}
} else
tmp_queue.push_back(rule);
return true;
}
bool NATCompiler_ipt::localNATRule::processNext()
{
NATRule *rule=getNext(); if (rule==NULL) return false;
@ -1894,24 +1991,45 @@ bool NATCompiler_ipt::DNATforFW::processNext()
bool NATCompiler_ipt::decideOnChain::processNext()
{
NATCompiler_ipt *ipt_comp = dynamic_cast<NATCompiler_ipt*>(compiler);
NATRule *rule=getNext(); if (rule==NULL) return false;
tmp_queue.push_back(rule);
if ( ! rule->getStr("ipt_chain").empty() ) return true; // already defined
switch (rule->getRuleType()) {
case NATRule::SNAT: rule->setStr("ipt_chain","POSTROUTING"); break;
case NATRule::SNetnat: rule->setStr("ipt_chain","POSTROUTING"); break;
case NATRule::Masq: rule->setStr("ipt_chain","POSTROUTING"); break;
case NATRule::DNAT: rule->setStr("ipt_chain","PREROUTING"); break;
case NATRule::DNetnat: rule->setStr("ipt_chain","PREROUTING"); break;
case NATRule::Redirect: rule->setStr("ipt_chain","PREROUTING"); break;
string chain;
switch (rule->getRuleType())
{
case NATRule::SNAT: chain = "POSTROUTING"; break;
case NATRule::SNetnat: chain = "POSTROUTING"; break;
case NATRule::Masq: chain = "POSTROUTING"; break;
case NATRule::DNAT: chain = "PREROUTING"; break;
case NATRule::DNetnat: chain = "PREROUTING"; break;
case NATRule::Redirect: chain = "PREROUTING"; break;
case NATRule::NONAT:
// processor splitNONATRule took care of NONAT rule
break;
case NATRule::NATBranch:
// processor splitNATBranchRule took care of NATBranch rule
break;
default: ;
}
if (!rule->getStr("ipt_chain").empty())
{
if (!compiler->getSourceRuleSet()->isTop() &&
ipt_comp->getRuleSetName() == rule->getStr("ipt_chain"))
{
// this is a NAT branch. Need to rename the chain to add
// information about the chain that would have been used
// if this was top ruleset
string new_chain = compiler->getRuleSetName() + "_" + chain;
ipt_comp->registerRuleSetChain(new_chain);
rule->setStr("ipt_chain", new_chain);
}
return true; // already defined
}
if (!chain.empty()) rule->setStr("ipt_chain", chain);
return true;
}
@ -1924,7 +2042,8 @@ bool NATCompiler_ipt::decideOnTarget::processNext()
if ( ! rule->getStr("ipt_target").empty() ) return true; // already defined
switch (rule->getRuleType()) {
switch (rule->getRuleType())
{
case NATRule::NONAT: rule->setStr("ipt_target","ACCEPT"); break;
case NATRule::SNAT: rule->setStr("ipt_target","SNAT"); break;
case NATRule::SNetnat: rule->setStr("ipt_target","NETMAP"); break;
@ -1933,6 +2052,9 @@ bool NATCompiler_ipt::decideOnTarget::processNext()
case NATRule::Masq: rule->setStr("ipt_target","MASQUERADE"); break;
case NATRule::Redirect: rule->setStr("ipt_target","REDIRECT"); break;
case NATRule::Return: rule->setStr("ipt_target","RETURN"); break;
case NATRule::NATBranch:
// this case has been taken care for in splitNATBranchRule()
break;
default: ;
}
return true;
@ -2210,18 +2332,20 @@ bool NATCompiler_ipt::countChainUsage::processNext()
return true;
}
void NATCompiler_ipt::registerRuleSetChain(const std::string &chain_name)
{
chain_usage_counter[chain_name] = 1;
}
void NATCompiler_ipt::compile()
{
// FWOptions* options=fw->getOptionsObject();
string banner = " Compiling rules for 'nat' table";
string banner = " Compiling ruleset " + getRuleSetName() +
" for 'nat' table";
if (ipv6) banner += ", IPv6";
info(banner);
try {
try
{
Compiler::compile();
add( new NATCompiler::Begin());
@ -2322,6 +2446,7 @@ void NATCompiler_ipt::compile()
}
add( new splitNONATRule("NAT rules that request no translation"));
add( new splitNATBranchRule("Split Branch rules to use all chains"));
add( new localNATRule("process local NAT rules"));
// add( new DNATforFW("process DNAT rules for packets originated on the firewall"));
add( new decideOnChain( "decide on chain" ) );
@ -2448,4 +2573,12 @@ string NATCompiler_ipt::commit()
return res;
}
list<string> NATCompiler_ipt::getUsedChains()
{
list<string> res;
for (map<string, int>::iterator it=chain_usage_counter.begin();
it!=chain_usage_counter.end(); ++it)
res.push_back(it->first);
return res;
}

View File

@ -65,7 +65,10 @@ namespace fwcompiler {
// new chains across different compiler runs (used to process
// rules in different policy or nat objects)
std::map<const std::string, bool> *minus_n_commands;
// This map is located in CompilerDriver_ipt
const std::map<std::string, std::list<std::string> > *branch_ruleset_to_chain_mapping;
static const std::list<std::string>& getStandardChains();
std::string getInterfaceVarName(libfwbuilder::FWObject *iface,
bool v6=false);
@ -98,6 +101,12 @@ namespace fwcompiler {
*/
DECLARE_NAT_RULE_PROCESSOR(splitSDNATRule);
/**
* this processor spits NAT rule with action Branch to
* generate iptables commands in all chains that it needs
*/
DECLARE_NAT_RULE_PROCESSOR(splitNATBranchRule);
/**
* verifies correctness of the NAT rules
*/
@ -583,8 +592,17 @@ namespace fwcompiler {
have_dynamic_interfaces=false;
printRule=NULL;
minus_n_commands = m_n_commands_map;
branch_ruleset_to_chain_mapping = NULL;
}
/**
* this method registers chain used for the ruleset (most
* often branch rule set). Since rules in the same ruleset do
* not use this chain as target, rule processor
* countChainUsage considers it unused. Registering it makes
* sure its usage counter is > 0.
*/
void registerRuleSetChain(const std::string &chain_name);
virtual void verifyPlatform();
virtual int prolog();
@ -597,8 +615,13 @@ namespace fwcompiler {
virtual std::string printAutomaticRules();
std::string commit();
std::list<std::string> getUsedChains();
static std::string getNewTmpChainName(libfwbuilder::NATRule *rule);
void setRulesetToChainMapping(const std::map<std::string, std::list<std::string> > *m)
{ branch_ruleset_to_chain_mapping = m; }
};

View File

@ -4908,4 +4908,13 @@ PolicyRule* PolicyCompiler_ipt::addMgmtRule(Address* src,
return rule;
}
list<string> PolicyCompiler_ipt::getUsedChains()
{
list<string> res;
for (map<string, int>::iterator it=chain_usage_counter.begin();
it!=chain_usage_counter.end(); ++it)
res.push_back(it->first);
return res;
}

View File

@ -1073,6 +1073,9 @@ namespace fwcompiler
bool haveConnMarkRulesInOutput() { return have_connmark_in_output; }
bool isMangleOnlyRuleSet(const std::string &rule_set_name);
std::list<std::string> getUsedChains();
};

View File

@ -8,6 +8,8 @@ TEMPLATE = lib
SOURCES = CompilerDriver_ipt.cpp \
CompilerDriver_ipt_cluster.cpp \
CompilerDriver_ipt_run.cpp \
CompilerDriver_ipt_policy.cpp \
CompilerDriver_ipt_nat.cpp \
MangleTableCompiler_ipt.cpp \
NATCompiler_PrintRule.cpp \
NATCompiler_PrintRuleIptRst.cpp \

View File

@ -179,6 +179,10 @@ nameif %in %il security%sl
<supported>True</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>False</supported>
<parameter>None</parameter>
</NATBranch>
</actions>
</capabilities>

View File

@ -102,6 +102,10 @@ interface %in
<supported>False</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>False</supported>
<parameter>None</parameter>
</NATBranch>
</actions>
</capabilities>

View File

@ -83,6 +83,10 @@
<supported>True</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>False</supported>
<parameter>None</parameter>
</NATBranch>
</actions>
</capabilities>
</Target>

View File

@ -81,6 +81,10 @@
<supported>False</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>False</supported>
<parameter>None</parameter>
</NATBranch>
</actions>
</capabilities>
</Target>

View File

@ -96,6 +96,10 @@
<supported>True</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>True</supported>
<parameter>NATBranch</parameter>
</NATBranch>
</actions>
</capabilities>
</Target>

View File

@ -86,6 +86,10 @@
<supported>True</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>True</supported>
<parameter>NATBranch</parameter>
</NATBranch>
</actions>
</capabilities>
</Target>

View File

@ -450,6 +450,10 @@ exit
<supported>True</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>False</supported>
<parameter>None</parameter>
</NATBranch>
</actions>
</capabilities>
</Target>

View File

@ -73,6 +73,10 @@
<supported>False</supported>
<parameter>None</parameter>
</Translate>
<NATBranch>
<supported>False</supported>
<parameter>None</parameter>
</NATBranch>
</actions>
</capabilities>

File diff suppressed because it is too large Load Diff