mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-19 17:57:22 +01:00
1324 lines
42 KiB
C++
1324 lines
42 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 "NATCompiler_pf.h"
|
|
|
|
#include "fwcompiler/OSConfigurator.h"
|
|
|
|
#include "fwbuilder/AddressRange.h"
|
|
#include "fwbuilder/AddressTable.h"
|
|
#include "fwbuilder/Cluster.h"
|
|
#include "fwbuilder/FailoverClusterGroup.h"
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/Host.h"
|
|
#include "fwbuilder/ICMPService.h"
|
|
#include "fwbuilder/IPService.h"
|
|
#include "fwbuilder/IPv4.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/Library.h"
|
|
#include "fwbuilder/NAT.h"
|
|
#include "fwbuilder/Network.h"
|
|
#include "fwbuilder/RuleElement.h"
|
|
#include "fwbuilder/TCPService.h"
|
|
#include "fwbuilder/UDPService.h"
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
|
|
#include <assert.h>
|
|
|
|
using namespace libfwbuilder;
|
|
using namespace fwcompiler;
|
|
using namespace std;
|
|
|
|
string NATCompiler_pf::myPlatformName() { return "pf"; }
|
|
|
|
|
|
int NATCompiler_pf::prolog()
|
|
{
|
|
int n=NATCompiler::prolog();
|
|
|
|
if ( n>0 )
|
|
{
|
|
list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
|
{
|
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
|
assert(iface);
|
|
|
|
if ( iface->isDyn())
|
|
{
|
|
iface->setBool("use_var_address",true);
|
|
|
|
/* dynamic interface should not have IPv4 child object(s). We issue a
|
|
* warning if it does in a policy compiler, there is no need to repeat
|
|
* it here
|
|
*/
|
|
list<FWObject*> l3=iface->getByType(IPv4::TYPENAME);
|
|
for (list<FWObject*>::iterator j=l3.begin(); j!=l3.end(); ++j)
|
|
iface->remove(*j);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* pseudo-host with ip address 127.0.0.1 We'll use it for redirection
|
|
* NAT rules
|
|
*/
|
|
//FWObject *grp;
|
|
loopback_address = dbcopy->createIPv4();
|
|
loopback_address->setName("__loopback_address__");
|
|
loopback_address->setId(FWObjectDatabase::generateUniqueId()); // "__loopback_address_id__");
|
|
|
|
IPv4::cast(loopback_address)->setAddress(InetAddr::getLoopbackAddr());
|
|
|
|
persistent_objects->add(loopback_address,false);
|
|
|
|
if (tables)
|
|
{
|
|
tables->init(dbcopy);
|
|
if (!getSourceRuleSet()->isTop())
|
|
tables->setRuleSetName(getRuleSetName());
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
string NATCompiler_pf::debugPrintRule(libfwbuilder::Rule *r)
|
|
{
|
|
NATRule *rule = NATRule::cast(r);
|
|
RuleElementItfOutb *itf_re = rule->getItfOutb();
|
|
FWObject *rule_iface = FWObjectReference::getObject(itf_re->front());
|
|
// FWObject *rule_iface = dbcopy->findInIndex(rule->getInterfaceId());
|
|
|
|
return NATCompiler::debugPrintRule(rule) +
|
|
" " + string( (rule_iface!=NULL)?rule_iface->getName():"") +
|
|
" (type=" + rule->getRuleTypeAsString() + ")";
|
|
}
|
|
|
|
bool NATCompiler_pf::NATRuleType::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
tmp_queue.push_back(rule);
|
|
|
|
if (rule->getRuleType()!=NATRule::Unknown) return true;
|
|
|
|
RuleElementTSrc *tsrcre = rule->getTSrc();
|
|
RuleElementTDst *tdstre = rule->getTDst();
|
|
RuleElementTSrv *tsrvre = rule->getTSrv();
|
|
|
|
Service *osrv=compiler->getFirstOSrv(rule);
|
|
|
|
Address *tsrc = compiler->getFirstTSrc(rule);
|
|
Address *tdst = compiler->getFirstTDst(rule);
|
|
Service *tsrv=compiler->getFirstTSrv(rule);
|
|
|
|
if (rule->getAction() == NATRule::Branch)
|
|
{
|
|
rule->setRuleType(NATRule::NATBranch);
|
|
if (!tsrcre->isAny() || !tdstre->isAny() || !tsrvre->isAny())
|
|
{
|
|
tsrcre->clearChildren();
|
|
tsrcre->setAnyElement();
|
|
|
|
tdstre->clearChildren();
|
|
tdstre->setAnyElement();
|
|
|
|
tsrvre->clearChildren();
|
|
tsrvre->setAnyElement();
|
|
|
|
compiler->warning(
|
|
rule,
|
|
"Translated Src, Dst and Srv are ignored in the NAT "
|
|
"rule with action 'Branch'");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (tsrc->isAny() && tdst->isAny() &&
|
|
(tsrv->isAny() || (tsrv->getId() == osrv->getId()))
|
|
)
|
|
{
|
|
rule->setRuleType(NATRule::NONAT);
|
|
return true;
|
|
}
|
|
|
|
bool osrv_defines_src_port = false;
|
|
bool osrv_defines_dst_port = false;
|
|
bool tsrv_translates_src_port = false;
|
|
bool tsrv_translates_dst_port = false;
|
|
|
|
if (TCPUDPService::cast(osrv))
|
|
{
|
|
TCPUDPService *tu_osrv = TCPUDPService::cast(osrv);
|
|
|
|
osrv_defines_src_port = \
|
|
(tu_osrv->getSrcRangeStart() != 0 && tu_osrv->getDstRangeStart() == 0);
|
|
osrv_defines_dst_port = \
|
|
(tu_osrv->getSrcRangeStart() == 0 && tu_osrv->getDstRangeStart() != 0);
|
|
}
|
|
|
|
if (TCPUDPService::cast(tsrv))
|
|
{
|
|
TCPUDPService *tu_tsrv = TCPUDPService::cast(tsrv);
|
|
|
|
tsrv_translates_src_port = \
|
|
(tu_tsrv->getSrcRangeStart() != 0 && tu_tsrv->getDstRangeStart() == 0);
|
|
tsrv_translates_dst_port = \
|
|
(tu_tsrv->getSrcRangeStart() == 0 && tu_tsrv->getDstRangeStart() != 0);
|
|
}
|
|
|
|
|
|
if (
|
|
(! tsrc->isAny() && tdst->isAny()) ||
|
|
(tsrc->isAny() && tdst->isAny() && tsrv_translates_src_port)
|
|
)
|
|
{
|
|
rule->setRuleType(NATRule::SNAT);
|
|
return true;
|
|
}
|
|
|
|
if (
|
|
(tsrc->isAny() && ! tdst->isAny()) ||
|
|
(tsrc->isAny() && tdst->isAny() && tsrv_translates_dst_port)
|
|
)
|
|
{
|
|
/* this is load balancing rule if there are multiple objects in TDst */
|
|
if ( tdstre->size()>1 ) rule->setRuleType(NATRule::LB);
|
|
else
|
|
{
|
|
|
|
if ( compiler->complexMatch(tdst,compiler->fw) ) rule->setRuleType(NATRule::Redirect);
|
|
else rule->setRuleType(NATRule::DNAT);
|
|
|
|
// if ( tdst->getId()==compiler->fw->getId() ) rule->setRuleType(NATRule::Redirect);
|
|
// else rule->setRuleType(NATRule::DNAT);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (
|
|
( ! tsrc->isAny() && ! tdst->isAny() ) ||
|
|
( ! tsrc->isAny() && tsrv_translates_dst_port) ||
|
|
( ! tdst->isAny() && tsrv_translates_src_port)
|
|
)
|
|
{
|
|
rule->setRuleType(NATRule::SDNAT);
|
|
return true;
|
|
}
|
|
|
|
compiler->abort(rule, "Unsupported translation.");
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* This processor should be called after classifyNATRule. Should call
|
|
* classifyNATRule after this processor again.
|
|
*
|
|
* This algorithm is very much specific to iptables. Platforms where
|
|
* this simple algorithm for SDNAT rules is not appropriate, should
|
|
* either implement equivalent of this processor using different
|
|
* algorithm, or should catch SDNAT rules and abort in their own
|
|
* verifyNATRule processor.
|
|
*/
|
|
bool NATCompiler_pf::splitSDNATRule::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
if ( rule->getRuleType()==NATRule::SDNAT)
|
|
{
|
|
RuleElementODst *odst;
|
|
RuleElementOSrv *osrv;
|
|
RuleElementTSrc *tsrc;
|
|
RuleElementTDst *tdst;
|
|
|
|
/* first rule translates destination and may translate service (depends
|
|
* on the original rule) */
|
|
NATRule *r = compiler->dbcopy->createNATRule();
|
|
r->duplicate(rule);
|
|
compiler->temp_ruleset->add(r);
|
|
r->setRuleType(NATRule::Unknown);
|
|
|
|
tsrc=r->getTSrc();
|
|
tsrc->clearChildren();
|
|
tsrc->setAnyElement();
|
|
|
|
tmp_queue.push_back(r);
|
|
|
|
/* the second rule translates source and uses translated object in
|
|
* ODst. Since the service could have been translated by the first
|
|
* rule, we use TSrv in OSrv */
|
|
r = compiler->dbcopy->createNATRule();
|
|
r->duplicate(rule);
|
|
compiler->temp_ruleset->add(r);
|
|
r->setRuleType(NATRule::Unknown);
|
|
|
|
odst=r->getODst();
|
|
odst->clearChildren();
|
|
for (FWObject::iterator i=rule->getTDst()->begin(); i!=rule->getTDst()->end(); i++)
|
|
{
|
|
FWObject *o = FWReference::getObject(*i);
|
|
odst->addRef(o);
|
|
}
|
|
|
|
if ( ! rule->getTSrv()->isAny())
|
|
{
|
|
/*
|
|
* See "pf flow diagram" at http://homepage.mac.com/quension/pf/flow.png
|
|
* rdr happens first, then nat. This means nat sees packet with
|
|
* translated destination address and port.
|
|
*
|
|
* If the first rule in the pair translated service and
|
|
* changed destination port, we need to match it in the
|
|
* second rule to only trsnslate source in the packets
|
|
* that have been processed by the first rule. However
|
|
* this only applies to the case when destination port has
|
|
* been translated because the first rule uses DNAT which
|
|
* can only translate dest. port. So, if TSrv has zero
|
|
* dest. port range but non-zero source port range, we
|
|
* should not match it here because in this case no
|
|
* dest. port translation occurs. If TSrv translates both
|
|
* source and destination ports, we create new TCP(UDP)
|
|
* service object with only dest. port part and use it to
|
|
* match.
|
|
*/
|
|
Service *tsrv = compiler->getFirstTSrv(rule);
|
|
TCPUDPService *tu_tsrv = TCPUDPService::cast(tsrv);
|
|
if (tu_tsrv && tu_tsrv->getDstRangeStart() != 0)
|
|
{
|
|
TCPUDPService *match_service = NULL;
|
|
if (tu_tsrv->getSrcRangeStart() == 0)
|
|
{
|
|
// no source port tranlsation
|
|
match_service = tu_tsrv;
|
|
} else
|
|
{
|
|
// both source and dest port translation occurs
|
|
match_service = TCPUDPService::cast(
|
|
compiler->dbcopy->create(tsrv->getTypeName()));
|
|
match_service->setName(tsrv->getName() + "_dport");
|
|
compiler->persistent_objects->add(match_service);
|
|
match_service->setDstRangeStart(tu_tsrv->getDstRangeStart());
|
|
match_service->setDstRangeEnd(tu_tsrv->getDstRangeEnd());
|
|
}
|
|
osrv = r->getOSrv();
|
|
osrv->clearChildren();
|
|
osrv->addRef(match_service);
|
|
}
|
|
}
|
|
|
|
tdst=r->getTDst();
|
|
tdst->clearChildren();
|
|
tdst->setAnyElement();
|
|
|
|
tmp_queue.push_back(r);
|
|
}
|
|
else
|
|
tmp_queue.push_back(rule);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NATCompiler_pf::VerifyRules::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
string version = compiler->fw->getStr("version");
|
|
|
|
RuleElementOSrc *osrc=rule->getOSrc(); assert(osrc);
|
|
RuleElementODst *odst=rule->getODst(); assert(odst);
|
|
RuleElementOSrv *osrv=rule->getOSrv(); assert(osrv);
|
|
|
|
RuleElementTSrc *tsrc=rule->getTSrc(); assert(tsrc);
|
|
RuleElementTDst *tdst=rule->getTDst(); assert(tdst);
|
|
RuleElementTSrv *tsrv=rule->getTSrv(); assert(tsrv);
|
|
|
|
/*
|
|
* because of the change in the nat and rdr rules syntax in
|
|
* 4.7, I can no longer implement no-nat rules correctly for
|
|
* this version. They dropped the "no" keyword and their
|
|
* examples suggest using "pass" to implement exclusions for
|
|
* the nat rules. I need no-nat rule to just not translate but
|
|
* not make a decision whether the packet should be passed or
|
|
* dropped. In the new PF model, translation rules are just
|
|
* options on the matching policy rules and they do not offer
|
|
* any keyword or option to not translate.
|
|
*/
|
|
if (rule->getRuleType()==NATRule::NONAT &&
|
|
XMLTools::version_compare(version, "4.7")>=0)
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"No translation rules are not supported for PF 4.7, "
|
|
"use negation to implement exclusions");
|
|
return true;
|
|
}
|
|
|
|
if (osrv->getNeg())
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Negation in original service is not supported.");
|
|
return true;
|
|
}
|
|
|
|
/* bug #1276083: "Destination NAT rules". this restriction is not
|
|
* true at least as of OpenBSD 3.5
|
|
*
|
|
if (rule->getRuleType()==NATRule::DNAT && osrv->isAny())
|
|
compiler->abort("Service must be specified for destination translation rule. Rule "+rule->getLabel());
|
|
*/
|
|
|
|
if (rule->getRuleType()==NATRule::DNAT && osrv->isAny() && !tsrv->isAny())
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Can not translate 'any' into a specific service.");
|
|
return true;
|
|
}
|
|
|
|
if (tsrc->getNeg())
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Can not use negation in translated source.");
|
|
return true;
|
|
}
|
|
|
|
if (tdst->getNeg())
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Can not use negation in translated destination.");
|
|
return true;
|
|
}
|
|
|
|
if (tsrv->getNeg())
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Can not use negation in translated service.");
|
|
return true;
|
|
}
|
|
|
|
if (tsrv->size()!=1)
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Translated service should be 'Original' or should contain single object.");
|
|
return true;
|
|
}
|
|
|
|
FWObject *o=tsrv->front();
|
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
|
|
|
if ( Group::cast(o)!=NULL)
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Can not use group in translated service.");
|
|
return true;
|
|
}
|
|
|
|
#if 0
|
|
if (rule->getRuleType()==NATRule::SNAT )
|
|
{
|
|
Address* o1=compiler->getFirstTSrc(rule);
|
|
if ( Network::cast(o1)!=NULL || AddressRange::cast(o1)!=NULL )
|
|
compiler->abort("Can not use network or address range object in translated source. Rule "+rule->getLabel());
|
|
}
|
|
#endif
|
|
|
|
if (rule->getRuleType()==NATRule::SNAT )
|
|
{
|
|
if (tsrc->isAny())
|
|
{
|
|
compiler->abort(rule,
|
|
"Source translation rule needs an address in "
|
|
"Translated Source.");
|
|
return true;
|
|
}
|
|
|
|
FWObject *o = FWReference::getObject(tsrc->front());
|
|
if (Interface::isA(o) && Interface::cast(o)->isUnnumbered())
|
|
{
|
|
compiler->abort(rule,
|
|
"Can not use unnumbered interface in "
|
|
"Translated Source of a Source translation rule.");
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
if (rule->getRuleType()==NATRule::DNAT || rule->getRuleType()==NATRule::Redirect )
|
|
{
|
|
if (tdst->isAny())
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Destination translation rule needs an address in "
|
|
"Translated Destination.");
|
|
return true;
|
|
}
|
|
|
|
if ( tdst->size()!=1)
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"There should be no more than one object in translated destination");
|
|
return true;
|
|
}
|
|
|
|
Address* o1=compiler->getFirstTDst(rule);
|
|
if ( Network::cast(o1)!=NULL || AddressRange::cast(o1)!=NULL )
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Can not use network or address range object in translated destination.");
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (rule->getRuleType()==NATRule::SNetnat && !tsrc->isAny() )
|
|
{
|
|
Network *a1=Network::cast(compiler->getFirstOSrc(rule));
|
|
Network *a2=Network::cast(compiler->getFirstTSrc(rule));
|
|
if ( a1==NULL || a2==NULL ||
|
|
a1->getNetmaskPtr()->getLength()!=a2->getNetmaskPtr()->getLength() )
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Original and translated source should both be networks of the same size.");
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
if (rule->getRuleType()==NATRule::DNetnat && !tsrc->isAny() )
|
|
{
|
|
Network *a1=Network::cast(compiler->getFirstODst(rule));
|
|
Network *a2=Network::cast(compiler->getFirstTDst(rule));
|
|
if ( a1==NULL || a2==NULL ||
|
|
a1->getNetmaskPtr()->getLength()!=a2->getNetmaskPtr()->getLength() )
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Original and translated destination should both be networks of the same size.");
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
if (rule->getRuleType()==NATRule::NATBranch )
|
|
{
|
|
RuleSet *branch = rule->getBranch();
|
|
if (branch == NULL)
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Action 'Branch' needs NAT rule set to point to");
|
|
return true;
|
|
} else
|
|
{
|
|
if (!NAT::isA(branch))
|
|
{
|
|
compiler->abort(
|
|
rule,
|
|
"Action 'Branch' must point to a NAT rule set "
|
|
"(points to " + branch->getTypeName() + ")");
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
bool NATCompiler_pf::splitOnOSrv::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElementOSrv *osrv=rule->getOSrv(); assert(osrv);
|
|
if (osrv->size()!=1)
|
|
{
|
|
for(list<FWObject*>::iterator i=osrv->begin(); i!=osrv->end(); ++i)
|
|
{
|
|
FWObject *o= *i;
|
|
// if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
|
Service *s=Service::cast( o );
|
|
assert(s);
|
|
|
|
NATRule *r= compiler->dbcopy->createNATRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
RuleElementOSrv *nosrv=r->getOSrv();
|
|
nosrv->clearChildren();
|
|
|
|
nosrv->addRef( s );
|
|
|
|
tmp_queue.push_back( r );
|
|
}
|
|
} else
|
|
tmp_queue.push_back(rule);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NATCompiler_pf::fillTranslatedSrv::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
tmp_queue.push_back(rule);
|
|
|
|
Service *osrv_o=compiler->getFirstOSrv(rule);
|
|
Service *tsrv_o=compiler->getFirstTSrv(rule);
|
|
|
|
if ( ! osrv_o->isAny() && tsrv_o->isAny() )
|
|
{
|
|
RuleElementTSrv *tsrv=rule->getTSrv();
|
|
tsrv->addRef(osrv_o);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool NATCompiler_pf::addVirtualAddress::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
tmp_queue.push_back(rule);
|
|
|
|
Address *a=NULL;
|
|
if (rule->getRuleType()==NATRule::SNAT) a=compiler->getFirstTSrc(rule);
|
|
else
|
|
if (rule->getRuleType()==NATRule::DNAT) a=compiler->getFirstODst(rule);
|
|
else return true;
|
|
assert(a!=NULL);
|
|
const InetAddr *a_addr = a->getAddressPtr();
|
|
|
|
if ( ! a->isAny() && a->getId()!=compiler->getFwId() && a_addr)
|
|
{
|
|
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
|
{
|
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
|
assert(iface);
|
|
const InetAddr *iface_addr = iface->getAddressPtr();
|
|
if (iface_addr && *a_addr == *iface_addr )
|
|
return true;
|
|
}
|
|
compiler->osconfigurator->addVirtualAddressForNAT( a );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NATCompiler_pf::splitForTSrc::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
RuleElementTSrc *tsrc=rule->getTSrc(); assert(tsrc);
|
|
|
|
map<int,list<FWObject*> > interfaceGroups;
|
|
|
|
for(list<FWObject*>::iterator i=tsrc->begin(); i!=tsrc->end(); ++i)
|
|
{
|
|
FWObject *o= *i;
|
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
|
Interface *iface = compiler->findInterfaceFor(Address::cast(o),
|
|
compiler->fw);
|
|
if (iface!=NULL)
|
|
interfaceGroups[iface->getId()].push_back(o);
|
|
}
|
|
|
|
if (interfaceGroups.size()<=1) tmp_queue.push_back(rule);
|
|
else
|
|
{
|
|
map<int,list<FWObject*> >::iterator i;
|
|
for (i=interfaceGroups.begin(); i!=interfaceGroups.end(); i++)
|
|
{
|
|
list<FWObject*> &objSubset = (*i).second;
|
|
|
|
RuleElementTSrc *ntsrc = NULL;
|
|
NATRule *r = compiler->dbcopy->createNATRule();
|
|
r->duplicate(rule);
|
|
compiler->temp_ruleset->add(r);
|
|
|
|
ntsrc=r->getTSrc();
|
|
ntsrc->clearChildren();
|
|
ntsrc->setAnyElement();
|
|
for (FWObject::iterator j=objSubset.begin(); j!=objSubset.end(); j++)
|
|
{
|
|
ntsrc->addRef(*j);
|
|
}
|
|
tmp_queue.push_back(r);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NATCompiler_pf::assignInterfaceToNATRule(NATRule *rule, Address *addr)
|
|
{
|
|
RuleElementItfOutb *itf_re = rule->getItfOutb();
|
|
assert(itf_re!=NULL);
|
|
|
|
if (Interface::isA(addr) || IPv4::isA(addr))
|
|
{
|
|
FWObject *p = addr;
|
|
while ( p && ! Interface::isA(p) ) p = p->getParent();
|
|
Interface *intf = Interface::cast(p);
|
|
|
|
if (intf && intf->isFailoverInterface())
|
|
{
|
|
FailoverClusterGroup *fg = FailoverClusterGroup::cast(
|
|
intf->getFirstByType(FailoverClusterGroup::TYPENAME));
|
|
if (fg)
|
|
intf = fg->getInterfaceForMemberFirewall(fw);
|
|
}
|
|
|
|
if (intf && intf->isChildOf(fw))
|
|
{
|
|
if ( ! itf_re->hasRef(intf)) itf_re->addRef(intf);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool NATCompiler_pf::AssignInterface::processNext()
|
|
{
|
|
NATCompiler_pf *pf_comp = dynamic_cast<NATCompiler_pf*>(compiler);
|
|
NATRule *rule = getNext(); if (rule==NULL) return false;
|
|
|
|
if (rule->getStr(".iface") == "nil")
|
|
{
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
RuleElementItfOutb *itf_re = rule->getItfOutb();
|
|
assert(itf_re!=NULL);
|
|
|
|
if ( ! itf_re->isAny())
|
|
{
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
switch ( rule->getRuleType() )
|
|
{
|
|
case NATRule::SNAT:
|
|
{
|
|
RuleElementTSrc *tsrc_re = rule->getTSrc();
|
|
bool have_interface = false;
|
|
for (FWObject::iterator i1=tsrc_re->begin(); i1!=tsrc_re->end(); ++i1)
|
|
{
|
|
Address *addr = Address::cast(FWObjectReference::getObject(*i1));
|
|
have_interface |= pf_comp->assignInterfaceToNATRule(rule, addr);
|
|
}
|
|
|
|
if (have_interface)
|
|
{
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
/* if we appear here, then TSrc is not an interface or address of
|
|
* an interface. Generate NAT rule without "on iface" clause
|
|
*/
|
|
// rule->setInterfaceStr("");
|
|
itf_re->clearChildren();
|
|
itf_re->setAnyElement();
|
|
}
|
|
break;
|
|
|
|
case NATRule::DNAT:
|
|
{
|
|
RuleElementODst *odst_re = rule->getODst();
|
|
bool have_interface = false;
|
|
for (FWObject::iterator i1=odst_re->begin(); i1!=odst_re->end(); ++i1)
|
|
{
|
|
Address *addr = Address::cast(FWObjectReference::getObject(*i1));
|
|
have_interface |= pf_comp->assignInterfaceToNATRule(rule, addr);
|
|
}
|
|
|
|
if (have_interface)
|
|
{
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
/* if we appear here, then ODst is not an interface or address of an
|
|
* interface. If this is so, just do not specify interface for rdr
|
|
* rule.
|
|
*/
|
|
itf_re->clearChildren();
|
|
itf_re->setAnyElement();
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* I assume that there is always only one object in ODst, TSrc and TDst
|
|
* rule elements. This should have been assured by inspector VerifyRules
|
|
*/
|
|
bool NATCompiler_pf::ReplaceFirewallObjectsODst::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
tmp_queue.push_back(rule);
|
|
|
|
list<FWObject*> cl;
|
|
RuleElementODst *rel;
|
|
Address *obj=NULL;
|
|
|
|
rel = rule->getODst(); assert(rel);
|
|
obj =compiler->getFirstODst(rule); assert(obj);
|
|
|
|
if (obj->getId()==compiler->getFwId() )
|
|
{
|
|
list<FWObject*> l2 = compiler->fw->getByTypeDeep(Interface::TYPENAME);
|
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
|
{
|
|
Interface *interface_ = Interface::cast(*i);
|
|
/*
|
|
* update 03/20/03:
|
|
*
|
|
* generally we assume that if firewall object is used in the rule,
|
|
* then any or all its interface will be used. This means that if
|
|
* firewall is in ODst we should really use all of its interfaces, not
|
|
* only external ones.
|
|
*/
|
|
if (! interface_->isLoopback() ) cl.push_back(interface_);
|
|
|
|
}
|
|
if ( ! cl.empty() )
|
|
{
|
|
rel->clearChildren();
|
|
for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
|
{
|
|
rel->addRef( *i1 );
|
|
}
|
|
}
|
|
/*
|
|
* update for ticket 1397 If firewall object is in ODst, do not assign
|
|
* the rule to any interface. I use attribute ".iface" to signal
|
|
* AssignInterface that it should not do anything.
|
|
*/
|
|
rule->setStr(".iface", "nil");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* I assume that there is always only one object in ODst, TSrc and TDst
|
|
* rule elements. This should have been assured by inspector VerifyRules
|
|
*/
|
|
bool NATCompiler_pf::ReplaceFirewallObjectsTSrc::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
tmp_queue.push_back(rule);
|
|
|
|
list<FWObject*> cl;
|
|
RuleElementTSrc *rel;
|
|
Address *obj=NULL;
|
|
|
|
switch (rule->getRuleType())
|
|
{
|
|
case NATRule::Masq: return true;
|
|
default:
|
|
rel=rule->getTSrc(); assert(rel);
|
|
obj=compiler->getFirstTSrc(rule); assert(obj);
|
|
|
|
if (obj->getId()==compiler->getFwId() )
|
|
{
|
|
Address *odst=compiler->getFirstODst(rule);
|
|
|
|
rel->clearChildren();
|
|
|
|
Interface *iface=compiler->findInterfaceFor(odst,compiler->fw);
|
|
|
|
if (!odst->isAny() && !rule->getODst()->getNeg() && iface!=NULL)
|
|
rel->addRef(iface);
|
|
else // else use all interfaces except loopback and unnumbered ones
|
|
{
|
|
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
|
{
|
|
Interface *iface=Interface::cast(*i);
|
|
if (! iface->isLoopback() &&
|
|
! iface->isUnnumbered() &&
|
|
! iface->isBridgePort())
|
|
rel->addRef( *i );
|
|
}
|
|
for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
|
rel->addRef( *i1 );
|
|
|
|
/* it is an error if rule element is empty at this point. this could have
|
|
* happened if all external interfaces are unnumbered */
|
|
if (rel->size()==0)
|
|
{
|
|
QString err(
|
|
"Could not find suitable interface for the NAT rule %1. "
|
|
"Perhaps all interfaces are unnumbered?");
|
|
compiler->abort(
|
|
rule,
|
|
err.arg(rule->getLabel().c_str()).toStdString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* I assume that there is always only one object in ODst, TSrc and TDst
|
|
* rule elements. This should have been assured by inspector VerifyRules
|
|
*/
|
|
bool NATCompiler_pf::ReplaceObjectsTDst::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
|
|
|
|
tmp_queue.push_back(rule);
|
|
|
|
if (rule->getRuleType()==NATRule::Redirect)
|
|
{
|
|
Service *tsrv=compiler->getFirstTSrv(rule);
|
|
RuleElementTDst *rel=rule->getTDst(); assert(rel);
|
|
Address *otdst=compiler->getFirstTDst(rule);
|
|
Interface *loopback=NULL;
|
|
FWObject *loopback_address=NULL;
|
|
|
|
/* if firewall is used in TDst in redirection rule, replace it with
|
|
* its loopback interface
|
|
*/
|
|
if (otdst->getId()==compiler->fw->getId())
|
|
{
|
|
std::list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
|
for (std::list<FWObject*>::iterator i=l2.begin();
|
|
i!=l2.end(); ++i)
|
|
{
|
|
Interface *iface = dynamic_cast<Interface*>(*i);
|
|
assert(iface);
|
|
if (iface->isLoopback())
|
|
{
|
|
loopback = iface;
|
|
loopback_address = loopback->getFirstByType(IPv4::TYPENAME);
|
|
}
|
|
}
|
|
|
|
if (loopback_address==NULL)
|
|
{
|
|
compiler->abort(rule,
|
|
"Can not configure redirection for the NAT rule "
|
|
"because loopback interface is missing.");
|
|
}
|
|
|
|
rel->clearChildren();
|
|
rel->addRef( loopback_address );
|
|
|
|
pf_comp->redirect_rules.push_back(
|
|
redirectRuleInfo( rule->getLabel(), otdst,
|
|
loopback_address, tsrv ) );
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NATCompiler_pf::swapAddressTableObjectsInRE::processNext()
|
|
{
|
|
NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
|
|
Rule *rule=prev_processor->getNextRule(); if (rule==NULL) return false;
|
|
|
|
RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
|
|
|
|
list<MultiAddress*> cl;
|
|
for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
|
|
{
|
|
FWObject *o= *i;
|
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
|
/*
|
|
* All addressTable objects will be run-time here because we
|
|
* switch them in preprocessor. The difference is: if address
|
|
* table was originally run-time, at this point it will have
|
|
* no children, however if it was compile-time originally, it
|
|
* will have children objects. That is how we distinguish
|
|
* them in this rule processor. Here we only deal with
|
|
* AddressTable objects that originally used to be
|
|
* compile-time because we need to create tables for them.
|
|
*/
|
|
if (AddressTable::cast(o)!=NULL &&
|
|
AddressTable::cast(o)->isRunTime() &&
|
|
o->size() > 0)
|
|
cl.push_back(MultiAddress::cast(o));
|
|
}
|
|
|
|
if (!cl.empty())
|
|
{
|
|
for (list<MultiAddress*>::iterator i=cl.begin(); i!=cl.end(); i++)
|
|
{
|
|
MultiAddress *atbl = *i;
|
|
|
|
// Need to make sure the ID of the MultiAddressRunTime
|
|
// object created here is stable and is always the same
|
|
// for the same MultiAddress object. In particular this
|
|
// ensures that we reuse tables between policy and NAT rules
|
|
string mart_id_str = FWObjectDatabase::getStringId(atbl->getId()) +
|
|
"_runtime";
|
|
int mart_id = FWObjectDatabase::registerStringId(mart_id_str);
|
|
|
|
MultiAddressRunTime *mart =
|
|
MultiAddressRunTime::cast(compiler->dbcopy->findInIndex(mart_id));
|
|
if (mart==NULL)
|
|
{
|
|
mart = new MultiAddressRunTime(atbl);
|
|
|
|
// need to ensure stable ID for the runtime object, so
|
|
// that when the same object is replaced in different
|
|
// rulesets by different compiler passes, chosen
|
|
// runtime object has the same ID and is identified as
|
|
// the same by the compiler.
|
|
|
|
mart->setId( mart_id );
|
|
compiler->dbcopy->addToIndex(mart);
|
|
compiler->persistent_objects->add(mart);
|
|
|
|
// register this object as a table
|
|
string tblname = atbl->getName();
|
|
string tblID = tblname + "_addressTableObject";
|
|
pf_comp->tables->registerTable(tblname,tblID,atbl);
|
|
}
|
|
|
|
re->removeRef(atbl);
|
|
re->addRef(mart);
|
|
}
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NATCompiler_pf::processMultiAddressObjectsInRE::processNext()
|
|
{
|
|
NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
|
|
bool neg = re->getNeg();
|
|
|
|
list<FWObject*> cl;
|
|
|
|
try
|
|
{
|
|
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)
|
|
{
|
|
if (re->size()>1 && neg)
|
|
{
|
|
string err = "AddressTable object can not be used with "
|
|
"negation in combination with other objects "
|
|
"in the same rule element.";
|
|
compiler->abort(rule, err);
|
|
}
|
|
o->setBool("pf_table",true);
|
|
string tblname = o->getName();
|
|
string tblID = tblname + "_addressTableObject";
|
|
pf_comp->tables->registerTable(tblname,tblID,o);
|
|
cl.push_back(o);
|
|
}
|
|
}
|
|
} catch(FWException &ex) // TableFactory::registerTable throws exception
|
|
{
|
|
string err;
|
|
err = "Can not process MultiAddress object in rule " +
|
|
rule->getLabel() + ". Error: " + ex.toString();
|
|
compiler->abort(rule, err);
|
|
}
|
|
|
|
if (!cl.empty())
|
|
{
|
|
RuleElement *nre;
|
|
|
|
for (FWObject::iterator i=cl.begin(); i!=cl.end(); i++)
|
|
{
|
|
NATRule *r= compiler->dbcopy->createNATRule();
|
|
compiler->temp_ruleset->add(r);
|
|
r->duplicate(rule);
|
|
nre=RuleElement::cast( r->getFirstByType(re_type) );
|
|
nre->clearChildren();
|
|
nre->addRef( *i );
|
|
tmp_queue.push_back(r);
|
|
}
|
|
|
|
for (FWObject::iterator i=cl.begin(); i!=cl.end(); i++)
|
|
re->removeRef( *i );
|
|
|
|
if (!re->isAny())
|
|
tmp_queue.push_back(rule);
|
|
|
|
return true;
|
|
}
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
void NATCompiler_pf::checkForDynamicInterfacesOfOtherObjects::findDynamicInterfaces(RuleElement *re,
|
|
Rule *rule)
|
|
{
|
|
if (re->isAny()) return;
|
|
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 && Cluster::isA(ifs->getParent()))
|
|
{
|
|
FailoverClusterGroup *failover_group =
|
|
FailoverClusterGroup::cast(
|
|
ifs->getFirstByType(FailoverClusterGroup::TYPENAME));
|
|
if (failover_group)
|
|
{
|
|
for (FWObjectTypedChildIterator it =
|
|
failover_group->findByType(FWObjectReference::TYPENAME);
|
|
it != it.end(); ++it)
|
|
{
|
|
Interface *member_iface = Interface::cast(FWObjectReference::getObject(*it));
|
|
assert(member_iface);
|
|
if (member_iface->isChildOf(compiler->fw))
|
|
{
|
|
ifs = member_iface;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ifs && ifs->isDyn() && ! ifs->isChildOf(compiler->fw))
|
|
{
|
|
QString err(
|
|
"Can not build rule using dynamic interface '%1' "
|
|
"of the object '%2' because its address is unknown.");
|
|
compiler->abort(
|
|
rule, err
|
|
.arg(ifs->getName().c_str())
|
|
.arg(ifs->getParent()->getName().c_str()).toStdString());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool NATCompiler_pf::checkForDynamicInterfacesOfOtherObjects::processNext()
|
|
{
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
findDynamicInterfaces( rule->getOSrc() , rule );
|
|
findDynamicInterfaces( rule->getODst() , rule );
|
|
findDynamicInterfaces( rule->getTSrc() , rule );
|
|
findDynamicInterfaces( rule->getTDst() , rule );
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
bool NATCompiler_pf::createTables::processNext()
|
|
{
|
|
NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
|
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
RuleElementOSrc *osrc=rule->getOSrc();
|
|
RuleElementODst *odst=rule->getODst();
|
|
|
|
if (osrc->size()!=1) pf_comp->tables->createTablesForRE(osrc,rule);
|
|
if (odst->size()!=1) pf_comp->tables->createTablesForRE(odst,rule);
|
|
|
|
#if 0
|
|
RuleElementTSrc *tsrc=rule->getTSrc();
|
|
RuleElementTDst *tdst=rule->getTDst();
|
|
|
|
if (tsrc->size()!=1) pf_comp->tables->createTablesForRE(tsrc,rule);
|
|
if (tdst->size()!=1) pf_comp->tables->createTablesForRE(tdst,rule);
|
|
#endif
|
|
|
|
tmp_queue.push_back(rule);
|
|
return true;
|
|
}
|
|
|
|
|
|
void NATCompiler_pf::compile()
|
|
{
|
|
bool manage_virtual_addr=fwopt->getBool("manage_virtual_addr");
|
|
|
|
string banner = " Compiling NAT rules for " + fw->getName();
|
|
if (!getRuleSetName().empty()) banner += " ruleset " + getRuleSetName();
|
|
if (ipv6) banner += ", IPv6";
|
|
info(banner);
|
|
|
|
Compiler::compile();
|
|
|
|
add( new Begin());
|
|
add( new printTotalNumberOfRules() );
|
|
|
|
add( new singleRuleFilter());
|
|
|
|
add(new expandGroupsInItfOutb("expand groups in Interface"));
|
|
add(new replaceClusterInterfaceInItfOutb(
|
|
"replace cluster interfaces with member interfaces in "
|
|
"the Interface rule element"));
|
|
add(new ItfOutbNegation("process negation in Itf"));
|
|
|
|
add( new recursiveGroupsInOSrc("check for recursive groups in OSRC") );
|
|
add( new recursiveGroupsInODst("check for recursive groups in ODST") );
|
|
add( new recursiveGroupsInOSrv("check for recursive groups in OSRV") );
|
|
|
|
add( new recursiveGroupsInTSrc("check for recursive groups in TSRC") );
|
|
add( new recursiveGroupsInTDst("check for recursive groups in TDST") );
|
|
add( new recursiveGroupsInTSrv("check for recursive groups in TSRV") );
|
|
|
|
add( new emptyGroupsInOSrc( "check for empty groups in OSRC" ) );
|
|
add( new emptyGroupsInODst( "check for empty groups in ODST" ) );
|
|
add( new emptyGroupsInOSrv( "check for empty groups in OSRV" ) );
|
|
|
|
add( new emptyGroupsInTSrc( "check for empty groups in TSRC" ) );
|
|
add( new emptyGroupsInTDst( "check for empty groups in TDST" ) );
|
|
add( new emptyGroupsInTSrv( "check for empty groups in TSRV" ) );
|
|
|
|
add( new ExpandGroups( "expand groups" ) );
|
|
add( new eliminateDuplicatesInOSRC( "eliminate duplicates in OSRC") );
|
|
add( new eliminateDuplicatesInODST( "eliminate duplicates in ODST") );
|
|
add( new eliminateDuplicatesInOSRV( "eliminate duplicates in OSRV") );
|
|
|
|
add( new swapMultiAddressObjectsInOSrc(
|
|
" swap MultiAddress -> MultiAddressRunTime in OSrc") );
|
|
add( new swapMultiAddressObjectsInODst(
|
|
" swap MultiAddress -> MultiAddressRunTime in ODst") );
|
|
|
|
add( new swapAddressTableObjectsInOSrc(
|
|
"AddressTable -> MultiAddressRunTime in OSrc") );
|
|
add( new swapAddressTableObjectsInODst(
|
|
"AddressTable -> MultiAddressRunTime in ODst") );
|
|
add( new swapAddressTableObjectsInTDst(
|
|
"AddressTable -> MultiAddressRunTime in TDst") );
|
|
|
|
add( new processMultiAddressObjectsInOSrc(
|
|
"process MultiAddress objects in OSrc") );
|
|
add( new processMultiAddressObjectsInODst(
|
|
"process MultiAddress objects in ODst") );
|
|
add( new processMultiAddressObjectsInTDst(
|
|
"process MultiAddress objects in TDst") );
|
|
|
|
add( new splitOnOSrv( "split rule on original service" ) );
|
|
add( new fillTranslatedSrv( "fill translated service" ) );
|
|
|
|
//add( new doOSrcNegation( "process negation in OSrc" ) );
|
|
//add( new doODstNegation( "process negation in ODst" ) );
|
|
//add( new doOSrvNegation( "process negation in OSrv" ) );
|
|
|
|
add( new NATRuleType( "determine NAT rule types" ) );
|
|
add( new splitSDNATRule("split SDNAT rules" ) );
|
|
add( new NATRuleType( "determine NAT rule types" ) );
|
|
add( new VerifyRules( "verify NAT rules" ) );
|
|
|
|
add( new ReplaceFirewallObjectsODst(
|
|
"replace references to the firewall in ODst" ) );
|
|
add( new ReplaceFirewallObjectsTSrc(
|
|
"replace references to the firewall in TSrc" ) );
|
|
|
|
add( new ReplaceObjectsTDst( "replace objects in TDst" ) );
|
|
|
|
add( new ExpandMultipleAddresses( "expand multiple addresses" ) );
|
|
|
|
// we might get empty RE after expanding multiple addresses,
|
|
// for example when unnumbered interface is used in TSRC. Note
|
|
// that VerifyRules should not allow this, but we may still
|
|
// get here in the test mode. Calling dropRuleWithEmptyRE works
|
|
// as a fail-safe and prevents crash.
|
|
add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
|
|
|
|
if ( manage_virtual_addr )
|
|
add( new addVirtualAddress("add virtual addresses for NAT rules"));
|
|
|
|
add( new checkForUnnumbered("check for unnumbered interfaces" ) );
|
|
add( new checkForDynamicInterfacesOfOtherObjects(
|
|
"check for dynamic interfaces of other hosts and firewalls"));
|
|
add( new ExpandAddressRanges( "expand address range objects" ) );
|
|
|
|
add( new splitForTSrc(
|
|
"split if addresses in TSrc belong to different networks" ));
|
|
|
|
add( new AssignInterface( "assign rules to interfaces" ) );
|
|
|
|
add( new checkForObjectsWithErrors(
|
|
"check if we have objects with errors in rule elements"));
|
|
|
|
add( new createTables("create tables"));
|
|
// add( new PrintTables( "print tables" ) );
|
|
|
|
add( new PrintRule("generate pf code") );
|
|
add( new simplePrintProgress() );
|
|
|
|
runRuleProcessors();
|
|
|
|
}
|
|
|
|
|
|
void NATCompiler_pf::epilog()
|
|
{
|
|
}
|
|
|
|
NATCompiler_pf::~NATCompiler_pf()
|
|
{
|
|
//if (tables) tables->detach();
|
|
}
|
|
|