mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-22 11:17:31 +01:00
612 lines
20 KiB
C++
612 lines
20 KiB
C++
/*
|
|
|
|
Firewall Builder
|
|
|
|
Copyright (C) 2002 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 "PolicyCompiler_ipf.h"
|
|
#include "fwcompiler/Compiler.h"
|
|
|
|
#include "fwbuilder/AddressTable.h"
|
|
#include "fwbuilder/FWObjectDatabase.h"
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/ICMPService.h"
|
|
#include "fwbuilder/IPService.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/Library.h"
|
|
#include "fwbuilder/Policy.h"
|
|
#include "fwbuilder/RuleElement.h"
|
|
#include "fwbuilder/TCPService.h"
|
|
#include "fwbuilder/UDPService.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <assert.h>
|
|
|
|
using namespace libfwbuilder;
|
|
using namespace fwcompiler;
|
|
using namespace std;
|
|
|
|
string PolicyCompiler_ipf::myPlatformName() { return "ipf"; }
|
|
|
|
int PolicyCompiler_ipf::prolog()
|
|
{
|
|
int n= PolicyCompiler_pf::prolog();
|
|
|
|
anytcp = dbcopy->createTCPService();
|
|
anytcp->setId(FWObjectDatabase::generateUniqueId()); //ANY_TCP_OBJ_ID);
|
|
persistent_objects->add(anytcp,false);
|
|
|
|
anyudp=dbcopy->createUDPService();
|
|
anyudp->setId(FWObjectDatabase::generateUniqueId()); //ANY_UDP_OBJ_ID);
|
|
persistent_objects->add(anyudp,false);
|
|
|
|
anyicmp=dbcopy->createICMPService();
|
|
anyicmp->setId(FWObjectDatabase::generateUniqueId()); //ANY_ICMP_OBJ_ID);
|
|
persistent_objects->add(anyicmp,false);
|
|
|
|
return n;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::expandAnyService::processNext()
|
|
{
|
|
PolicyCompiler_ipf *pcomp=dynamic_cast<PolicyCompiler_ipf*>(compiler);
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElementSrv *srv=rule->getSrv();
|
|
FWOptions *ruleopt =rule->getOptionsObject();
|
|
|
|
if (srv->isAny() && ! ruleopt->getBool("stateless") && rule->getAction()==PolicyRule::Accept) {
|
|
|
|
PolicyRule *r = compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
RuleElementSrv *nsrv=r->getSrv();
|
|
nsrv->clearChildren();
|
|
nsrv->addRef(pcomp->anyicmp); //compiler->dbcopy->findInIndex(ANY_ICMP_OBJ_ID));
|
|
tmp_queue.push_back(r);
|
|
|
|
r = compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
nsrv=r->getSrv();
|
|
nsrv->clearChildren();
|
|
nsrv->addRef(pcomp->anytcp); //compiler->dbcopy->findInIndex(ANY_TCP_OBJ_ID));
|
|
tmp_queue.push_back(r);
|
|
|
|
r = compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
nsrv=r->getSrv();
|
|
nsrv->clearChildren();
|
|
nsrv->addRef(pcomp->anyudp); //compiler->dbcopy->findInIndex(ANY_UDP_OBJ_ID));
|
|
tmp_queue.push_back(r);
|
|
|
|
r = compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
FWOptions *ruleopt =r->getOptionsObject();
|
|
ruleopt->setBool("stateless",true);
|
|
tmp_queue.push_back(r);
|
|
|
|
} else
|
|
tmp_queue.push_back(rule);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::doSrcNegation::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElementSrc *src=rule->getSrc();
|
|
|
|
if (src->getNeg()) {
|
|
RuleElementSrc *nsrc;
|
|
PolicyRule *r;
|
|
FWOptions *ruleopt;
|
|
|
|
r= compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
r->setAction(PolicyRule::Continue);
|
|
r->setLogging(false);
|
|
nsrc=r->getSrc();
|
|
nsrc->setNeg(false);
|
|
r->setBool("quick",false);
|
|
r->setBool("skip_check_for_duplicates",true);
|
|
ruleopt = r->getOptionsObject();
|
|
ruleopt->setBool("stateless", true);
|
|
tmp_queue.push_back(r);
|
|
|
|
r= compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
nsrc=r->getSrc();
|
|
nsrc->setNeg(false);
|
|
nsrc->clearChildren();
|
|
nsrc->setAnyElement();
|
|
r->setBool("quick",true);
|
|
r->setBool("skip_check_for_duplicates",true);
|
|
tmp_queue.push_back(r);
|
|
|
|
return true;
|
|
}
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::doDstNegation::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElementDst *dst=rule->getDst();
|
|
|
|
if (dst->getNeg()) {
|
|
RuleElementDst *ndst;
|
|
PolicyRule *r;
|
|
FWOptions *ruleopt;
|
|
|
|
r= compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
r->setAction(PolicyRule::Continue);
|
|
r->setLogging(false);
|
|
ndst=r->getDst();
|
|
ndst->setNeg(false);
|
|
r->setBool("quick",false);
|
|
r->setBool("skip_check_for_duplicates",true);
|
|
ruleopt = r->getOptionsObject();
|
|
ruleopt->setBool("stateless", true);
|
|
tmp_queue.push_back(r);
|
|
|
|
r= compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
ndst=r->getDst();
|
|
ndst->setNeg(false);
|
|
ndst->clearChildren();
|
|
ndst->setAnyElement();
|
|
r->setBool("quick",true);
|
|
r->setBool("skip_check_for_duplicates",true);
|
|
tmp_queue.push_back(r);
|
|
|
|
return true;
|
|
}
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::doSrvNegation::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElementSrv *srv=rule->getSrv();
|
|
|
|
if (srv->getNeg())
|
|
{
|
|
compiler->abort(rule, "Negation in Srv is not implemented");
|
|
return false;
|
|
}
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
void PolicyCompiler_ipf::specialCaseWithDynInterface::dropDynamicInterface(RuleElement *re)
|
|
{
|
|
list<FWObject*> cl;
|
|
for (list<FWObject*>::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
|
{
|
|
FWObject *o = *i1;
|
|
FWObject *obj = o;
|
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
|
Interface *ifs =Interface::cast( obj );
|
|
|
|
if (ifs!=NULL && !ifs->isRegular()) continue;
|
|
cl.push_back(obj);
|
|
}
|
|
if (!cl.empty())
|
|
{
|
|
re->clearChildren();
|
|
for (list<FWObject*>::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
|
re->addRef( (*i1) );
|
|
}
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::specialCaseWithDynInterface::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
dropDynamicInterface( rule->getDst() );
|
|
dropDynamicInterface( rule->getSrc() );
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
|
|
PolicyCompiler_ipf::calculateSkip::calculateSkip(const std::string &n) : PolicyRuleProcessor(n)
|
|
{
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::calculateSkip::processNext()
|
|
{
|
|
// PolicyRule *rule;
|
|
|
|
slurp();
|
|
if (tmp_queue.size()==0) return false;
|
|
|
|
/*
|
|
* first, we scan all rules and build a hash that maps attribute
|
|
* "skip_label" to rule number. Attribute "skip_label" is set in
|
|
* optimize1, after which we could have split some rules, so this
|
|
* attrbiute may not be unique. We want to skip to the first rule
|
|
* marked with the same skip label if there are few with the same
|
|
* label. The simplest way to find the first one with the same label
|
|
* is to scan rules in reverse order, that is from the bottom up.
|
|
*/
|
|
int N=tmp_queue.size()-1; // The last rule number is N
|
|
for (deque<Rule*>::reverse_iterator k=tmp_queue.rbegin(); k!=tmp_queue.rend(); ++k)
|
|
{
|
|
PolicyRule *r = PolicyRule::cast( *k );
|
|
if (!r->getStr("skip_label").empty()) allrules[r->getStr("skip_label")]=N;
|
|
r->setInt("rule_num",N);
|
|
N--;
|
|
}
|
|
|
|
for (deque<Rule*>::iterator k=tmp_queue.begin(); k!=tmp_queue.end(); ++k)
|
|
{
|
|
PolicyRule *r = PolicyRule::cast( *k );
|
|
string rl=r->getLabel();
|
|
int current_position=r->getPosition();
|
|
|
|
if (r->getAction()==PolicyRule::Skip)
|
|
{
|
|
assert(!r->getStr("skip_to").empty());
|
|
|
|
int to=allrules[r->getStr("skip_to")];
|
|
int n =r->getInt("rule_num");
|
|
r->setInt("no_to_skip",to-n-1);
|
|
}
|
|
/* Action 'Continue' means we need to jump to the next rule in the
|
|
* GUI. We scan rules down from the current one, looking for the first
|
|
* rule that corresponds to the next rule in the GUI.
|
|
*/
|
|
if (r->getAction()==PolicyRule::Continue)
|
|
{
|
|
r->setAction(PolicyRule::Skip);
|
|
r->setBool("quick",false);
|
|
|
|
deque<Rule*>::iterator j=k;
|
|
++j;
|
|
int n=0;
|
|
for ( ; j!=tmp_queue.end(); ++j)
|
|
{
|
|
PolicyRule *r2 = PolicyRule::cast( *j );
|
|
if (r2->getPosition()!=current_position) break;
|
|
/* 'skip' only skips rules with the same setting of 'in' or 'out',
|
|
* that is the same direction
|
|
*/
|
|
if (r2->getDirection()==r->getDirection()) ++n;
|
|
}
|
|
r->setInt("no_to_skip",n);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::checkForKeepState::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
tmp_queue.push_back(rule);
|
|
|
|
Service *srv=compiler->getFirstSrv(rule); assert(srv);
|
|
FWOptions *ruleopt =rule->getOptionsObject();
|
|
|
|
if (! ICMPService::isA(srv) &&
|
|
! UDPService::isA(srv) &&
|
|
! TCPService::isA(srv) ) ruleopt->setBool("stateless",true);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::eliminateDuplicateRules::processNext()
|
|
{
|
|
PolicyCompiler *pcomp = dynamic_cast<PolicyCompiler*>(compiler);
|
|
PolicyRule *rule = getNext(); if (rule==NULL) return false;
|
|
|
|
// Note that if rule has "any" in Interface column, it is
|
|
// implemented as reference to the AnyNetwork object. In this case
|
|
// Compiler::getFirstItf() returns NULL.
|
|
Interface *intf_rule = compiler->getFirstItf(rule);
|
|
int intf_id_rule = (intf_rule) ? intf_rule->getId() : -1;
|
|
|
|
if ( ! rule->getBool("skip_check_for_duplicates"))
|
|
{
|
|
for (deque<PolicyRule*>::iterator i=rules_seen_so_far.begin(); i!=rules_seen_so_far.end(); ++i)
|
|
{
|
|
PolicyRule *r=(*i);
|
|
if (r->getBool("skip_check_for_duplicates") ) continue;
|
|
if (r->getAction()==PolicyRule::Continue ||
|
|
r->getAction()==PolicyRule::Skip) continue;
|
|
|
|
Interface *intf_r = compiler->getFirstItf(r);
|
|
int intf_id_r = (intf_r) ? intf_r->getId() : -1;
|
|
|
|
if (intf_id_r==intf_id_rule &&
|
|
r->getAction()==rule->getAction() &&
|
|
r->getLogging()==rule->getLogging() &&
|
|
pcomp->cmpRules(*r,*rule) )
|
|
{
|
|
// cout << "---------------------------------------" << endl;
|
|
// cout << pcomp->debugPrintRule(r) << endl;
|
|
// cout << pcomp->debugPrintRule(rule) << endl;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
tmp_queue.push_back(rule);
|
|
rules_seen_so_far.push_back(rule);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::processMultiAddressObjectsInRE::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
|
|
|
|
for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
|
|
{
|
|
FWObject *o= *i;
|
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
|
MultiAddressRunTime *atrt = MultiAddressRunTime::cast(o);
|
|
if (atrt!=NULL && atrt->getSubstitutionTypeName()==AddressTable::TYPENAME)
|
|
compiler->abort(
|
|
|
|
rule,
|
|
"Run-time AddressTable objects are not supported.");
|
|
}
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
bool PolicyCompiler_ipf::SplitDirectionIpfilter::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
if (rule->getDirection()==PolicyRule::Both)
|
|
{
|
|
PolicyRule *r= compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
r->setDirection(PolicyRule::Inbound);
|
|
tmp_queue.push_back(r);
|
|
|
|
r= compiler->dbcopy->createPolicyRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
r->setDirection(PolicyRule::Outbound);
|
|
tmp_queue.push_back(r);
|
|
|
|
} else
|
|
tmp_queue.push_back(rule);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
void PolicyCompiler_ipf::compile()
|
|
{
|
|
info(" Compiling policy for " + fw->getName());
|
|
|
|
Compiler::compile();
|
|
|
|
addDefaultPolicyRule();
|
|
bool check_for_recursive_groups=true;
|
|
|
|
if ( fw->getOptionsObject()->getBool ("check_shading") &&
|
|
! inSingleRuleCompileMode())
|
|
{
|
|
add( new Begin ("Detecting rule shadowing" ) );
|
|
add( new printTotalNumberOfRules( ) );
|
|
|
|
add( new ItfNegation("process negation in Itf" ) );
|
|
add( new InterfacePolicyRules(
|
|
"process interface policy rules and store interface ids"));
|
|
|
|
add( new recursiveGroupsInSrc("check for recursive groups in SRC"));
|
|
add( new recursiveGroupsInDst("check for recursive groups in DST"));
|
|
add( new recursiveGroupsInSrv("check for recursive groups in SRV"));
|
|
check_for_recursive_groups=false;
|
|
|
|
add( new ExpandGroups("expand groups") );
|
|
add( new eliminateDuplicatesInSRC("eliminate duplicates in SRC") );
|
|
add( new eliminateDuplicatesInDST("eliminate duplicates in DST") );
|
|
add( new eliminateDuplicatesInSRV("eliminate duplicates in SRV") );
|
|
|
|
add( new swapMultiAddressObjectsInSrc(
|
|
" swap MultiAddress -> MultiAddressRunTime in Src") );
|
|
add( new swapMultiAddressObjectsInDst(
|
|
" swap MultiAddress -> MultiAddressRunTime in Dst") );
|
|
|
|
add( new ExpandMultipleAddressesInSrc(
|
|
"expand objects with multiple addresses in SRC" ) );
|
|
add( new ExpandMultipleAddressesInDst(
|
|
"expand objects with multiple addresses in DST" ) );
|
|
add( new ConvertToAtomic("convert to atomic rules" ) );
|
|
|
|
add( new checkForObjectsWithErrors(
|
|
"check if we have objects with errors in rule elements"));
|
|
|
|
add( new DetectShadowing("Detect shadowing" ) );
|
|
add( new simplePrintProgress() );
|
|
|
|
runRuleProcessors();
|
|
deleteRuleProcessors();
|
|
}
|
|
|
|
|
|
add( new Begin());
|
|
add( new printTotalNumberOfRules() );
|
|
|
|
add( new singleRuleFilter());
|
|
|
|
// add( new MACFiltering( "verify for MAC address filtering" ) );
|
|
add( new setQuickFlag("set 'quick' flag") );
|
|
|
|
if (check_for_recursive_groups)
|
|
{
|
|
add( new recursiveGroupsInSrc("check for recursive groups in SRC"));
|
|
add( new recursiveGroupsInDst("check for recursive groups in DST"));
|
|
add( new recursiveGroupsInSrv("check for recursive groups in SRV"));
|
|
}
|
|
|
|
add( new emptyGroupsInSrc("check for empty groups in SRC") );
|
|
add( new emptyGroupsInDst("check for empty groups in DST") );
|
|
add( new emptyGroupsInSrv("check for empty groups in SRV") );
|
|
|
|
add( new ItfNegation("process negation in Itf" ) );
|
|
add( new InterfacePolicyRules(
|
|
"process interface policy rules and store interface ids") );
|
|
|
|
add( new doSrcNegation("process negation in Src") );
|
|
add( new doDstNegation("process negation in Dst") );
|
|
add( new doSrvNegation("process negation in Srv") );
|
|
add( new ExpandGroups( "expand groups") );
|
|
|
|
add( new CheckForTCPEstablished(
|
|
"check for TCPService objects with flag \"established\"") );
|
|
add( new CheckForUnsupportedUserService("check for user service") );
|
|
|
|
add( new eliminateDuplicatesInSRC("eliminate duplicates in SRC") );
|
|
add( new eliminateDuplicatesInDST("eliminate duplicates in DST") );
|
|
add( new eliminateDuplicatesInSRV("eliminate duplicates in SRV") );
|
|
|
|
add( new swapMultiAddressObjectsInSrc(
|
|
" swap MultiAddress -> MultiAddressRunTime in Src") );
|
|
add( new swapMultiAddressObjectsInDst(
|
|
" swap MultiAddress -> MultiAddressRunTime in Dst") );
|
|
|
|
add( new processMultiAddressObjectsInSrc(
|
|
"process MultiAddress objects in Src") );
|
|
add( new processMultiAddressObjectsInDst(
|
|
"process MultiAddress objects in Dst") );
|
|
|
|
add( new splitIfFirewallInSrc("split rule if firewall is in Src") );
|
|
add( new splitIfFirewallInDst("split rule if firewall is in Dst") );
|
|
add( new fillDirection("determine directions") );
|
|
add( new SplitDirectionIpfilter("split rules with direction 'both'" ) );
|
|
add( new ExpandMultipleAddresses(
|
|
"expand objects with multiple addresses") );
|
|
add( new checkForDynamicInterfacesOfOtherObjects(
|
|
"check for dynamic interfaces of other hosts and firewalls" ));
|
|
add( new MACFiltering("verify for MAC address filtering" ) );
|
|
add( new checkForUnnumbered("check for unnumbered interfaces") );
|
|
add( new specialCaseWithDynInterface(
|
|
"check for a special cases with dynamic interface") );
|
|
add( new addressRanges("expand address range objects") );
|
|
add( new groupServicesByProtocol("split rules with different protocols") );
|
|
add( new separateTCPWithFlags("separate TCP services with flags" ) );
|
|
add( new separateSrcPort("split on TCP and UDP with source ports"));
|
|
add( new verifyCustomServices(
|
|
"verify custom services for this platform") );
|
|
add( new SpecialServices("check for special services" ) );
|
|
add( new expandAnyService("expand ANY service for stateful rules") );
|
|
/*
|
|
* it may make sense to do optimization even before we expand groups
|
|
* (before ExpandGroups). Need to test this idea.
|
|
*/
|
|
if ( fw->getOptionsObject()->getBool ("optimize") )
|
|
{
|
|
add( new optimizeSrc("optimization in SRC") );
|
|
add( new optimizeDst("optimization in DST") );
|
|
add( new optimizeSrv("optimization in SRV") );
|
|
}
|
|
|
|
add( new ConvertToAtomic("convert to atomic rules") );
|
|
add( new checkForZeroAddr("check for zero addresses" ) );
|
|
|
|
if ( fw->getOptionsObject()->getBool ("eliminate_duplicates") )
|
|
add( new eliminateDuplicateRules("eliminate duplicate rules" ) );
|
|
|
|
add( new calculateSkip("calculate argument for skip") );
|
|
add( new checkForKeepState("check for 'keep state'") );
|
|
|
|
add( new checkForObjectsWithErrors(
|
|
"check if we have objects with errors in rule elements"));
|
|
|
|
add( new PrintRule("generate ipf code") );
|
|
add( new simplePrintProgress() );
|
|
|
|
runRuleProcessors();
|
|
|
|
}
|
|
|
|
string PolicyCompiler_ipf::debugPrintRule(Rule *r)
|
|
{
|
|
PolicyRule *rule=PolicyRule::cast(r);
|
|
// FWOptions *ruleopt =rule->getOptionsObject();
|
|
|
|
ostringstream s;
|
|
s << PolicyCompiler::debugPrintRule(rule) << " ";
|
|
|
|
RuleElementItf *intf_re = rule->getItf();
|
|
string rule_interfaces;
|
|
int intf_count = 0;
|
|
for (FWObject::iterator it=intf_re->begin(); it!=intf_re->end(); ++it)
|
|
{
|
|
FWObject *o = *it;
|
|
if (FWReference::cast(o)!=NULL) o = FWReference::cast(o)->getPointer();
|
|
rule_interfaces += " " + o->getName();
|
|
intf_count++;
|
|
}
|
|
if (intf_count > 0)
|
|
{
|
|
s << " intf: ";
|
|
if (intf_count > 1) s << "{ ";
|
|
s << rule_interfaces;
|
|
if (intf_count > 1) s << " }";
|
|
}
|
|
else
|
|
s << " intf: ?";
|
|
|
|
s << " ";
|
|
|
|
if (r->getBool("skip_check_for_duplicates")) s << "skip_check_for_duplicates ";
|
|
if (r->getStr("skip_label")!="") s << "skip_label: " << r->getStr("skip_label") << " ";
|
|
if (r->getStr("skip_to")!="") s << "skip_to: " << r->getStr("skip_to") << " ";
|
|
if (r->getInt("no_to_skip")!=-1) s << "no_to_skip: " << r->getInt("no_to_skip");
|
|
|
|
s << " " << FWObjectDatabase::getStringId(r->getId()) << " (" << r->getId() << ")";
|
|
|
|
return s.str();
|
|
}
|
|
|
|
|
|
void PolicyCompiler_ipf::epilog()
|
|
{
|
|
}
|