From 3798b71c9c5849888b5c4b6c1643efa3c5c1f5c7 Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Tue, 27 May 2008 18:12:41 +0000 Subject: [PATCH] NAT and ipv6 --- src/fwcompiler/Compiler.cpp | 93 +++++++++++++++++++--------------- src/fwcompiler/Compiler.h | 4 ++ src/fwcompiler/NATCompiler.cpp | 13 +++-- 3 files changed, 64 insertions(+), 46 deletions(-) diff --git a/src/fwcompiler/Compiler.cpp b/src/fwcompiler/Compiler.cpp index b12ff969a..a71b42274 100644 --- a/src/fwcompiler/Compiler.cpp +++ b/src/fwcompiler/Compiler.cpp @@ -386,6 +386,7 @@ void Compiler::_expand_addr_recursive(Rule *rule, FWObject *s, if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); assert(o); + // this condition includes Host, Firewall and Interface if (Address::cast(o) && !Address::cast(o)->hasInetAddress()) { @@ -393,6 +394,7 @@ void Compiler::_expand_addr_recursive(Rule *rule, FWObject *s, continue; } + // IPv4, IPv6, Network, NetworkIPv6 if (Address::cast(o) && Address::cast(o)->hasInetAddress() && MatchesAddressFamily(o)) @@ -499,20 +501,18 @@ void Compiler::_expandAddr(Rule *rule, FWObject *s) _expand_addr_recursive(rule, s, cl); - if ( ! cl.empty() ) + s->clearChildren(); + + for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1) { - s->clearChildren(); - for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1) - { -/* - cerr << "Compiler::_expandAddr: adding object: (*i1)->name="; - cerr << (*i1)->getName(); - cerr << " (*i1)->id=" << (*i1)->getId(); - cerr << " type=" << (*i1)->getTypeName(); - cerr << endl; -*/ - s->addRef( *i1 ); - } +#if 0 + cerr << "Compiler::_expandAddr: adding object: (*i1)->name="; + cerr << (*i1)->getName(); + cerr << " (*i1)->id=" << (*i1)->getId(); + cerr << " type=" << (*i1)->getTypeName(); + cerr << endl; +#endif + s->addRef( *i1 ); } } @@ -575,6 +575,37 @@ void Compiler::normalizePortRange(int &rs,int &re) } +bool Compiler::_complexMatchWithAddress(const InetAddr *obj1_addr, + Interface *iface, + const string &address_type, + bool recognize_broadcasts) +{ + FWObjectTypedChildIterator k = iface->findByType(address_type); + for ( ; k!=k.end(); ++k ) + { + Address *addr_obj = Address::cast(*k); + + if ( *(addr_obj->getAddressPtr())==*(obj1_addr) ) return true; + const InetAddr *addr = addr_obj->getAddressPtr(); + const InetAddr *netm = addr_obj->getNetmaskPtr(); + if (addr) + { + InetAddrMask n(*addr, *netm); +/* + * bug #1040773: need to match network address as well as + * broadcast. Packets sent to the network address (192.168.1.0 for net + * 192.168.1.0/24) go in the broadcast frame and behave just like IP + * broadcast packets (sent to 192.168.1.1255 for the same net) + * + */ + if (recognize_broadcasts && ( + *(n.getNetworkAddressPtr())==*(obj1_addr) || + *(n.getBroadcastAddressPtr())==*(obj1_addr) + )) return true; + } + } + return false; +} bool Compiler::_complexMatchWithInterface(Address *obj1, Interface *iface, @@ -592,33 +623,9 @@ bool Compiler::_complexMatchWithInterface(Address *obj1, if ( iface->isRegular() ) { - FWObjectTypedChildIterator k = iface->findByType(IPv4::TYPENAME); - for ( ; k!=k.end(); ++k ) - { - Address *ipv4 = Address::cast(*k); - - if ( *(ipv4->getAddressPtr())==*(obj1_addr) ) return true; - const InetAddr *addr = ipv4->getAddressPtr(); - const InetAddr *netm = ipv4->getNetmaskPtr(); - if (addr) - { - InetAddrMask n(*addr, *netm); -/* - * bug #1040773: need to match network address as well as - * broadcast. Packets sent to the network address (192.168.1.0 for net - * 192.168.1.0/24) go in the broadcast frame and behave just like IP - * broadcast packets (sent to 192.168.1.1255 for the same net) - * - */ - if (recognize_broadcasts) - { -/* obj1 is an individual address - IPv4 or Address object */ - if (*(n.getAddressPtr())==*(obj1_addr) || - *(n.getBroadcastAddressPtr())==*(obj1_addr)) - return true; - } - } - } + string address_type = (ipv6) ? IPv6::TYPENAME : IPv4::TYPENAME; + return _complexMatchWithAddress( + obj1_addr, iface, address_type, recognize_broadcasts); } return false; } @@ -634,8 +641,8 @@ bool Compiler::_complexMatchWithInterface(Address *obj1, */ bool Compiler::complexMatch(Address *obj1, Address *obj2, - bool recognize_broadcasts, - bool recognize_multicasts) + bool recognize_broadcasts, + bool recognize_multicasts) { if (Network::isA(obj1)) { @@ -694,6 +701,8 @@ bool Compiler::complexMatch(Address *obj1, while ( (p=p->getParent())!=NULL ) // it is faster to search this way if (p->getId()==obj2->getId()) return true; + // TODO: this can be expensive since we create and return temporary + // list object only to get its size. Need method FWObject::countByType if ((obj1->getByType(IPv4::TYPENAME)).size()>1) return false; const InetAddr *obj1_addr = obj1->getAddressPtr(); diff --git a/src/fwcompiler/Compiler.h b/src/fwcompiler/Compiler.h index 5bb055db6..fd62573a6 100644 --- a/src/fwcompiler/Compiler.h +++ b/src/fwcompiler/Compiler.h @@ -135,6 +135,10 @@ namespace fwcompiler { libfwbuilder::Interface *iface, bool recognize_broadcasts=true); + bool _complexMatchWithAddress(const libfwbuilder::InetAddr *obj1_addr, + libfwbuilder::Interface *iface, + const std::string &address_type, + bool recognize_broadcasts); protected: int _cntr_; diff --git a/src/fwcompiler/NATCompiler.cpp b/src/fwcompiler/NATCompiler.cpp index 63402f79d..6ccb19564 100644 --- a/src/fwcompiler/NATCompiler.cpp +++ b/src/fwcompiler/NATCompiler.cpp @@ -228,23 +228,28 @@ bool NATCompiler::ExpandMultipleAddresses::processNext() tmp_queue.push_back(rule); RuleElement *rel; - if (rule->getRuleType()==NATRule::NONAT) { + if (rule->getRuleType()==NATRule::NONAT || + rule->getRuleType()==NATRule::Return) + { rel=rule->getOSrc(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getODst(); assert(rel); compiler->_expandAddr(rule,rel); } - if (rule->getRuleType()==NATRule::SNAT) { + if (rule->getRuleType()==NATRule::SNAT) + { rel=rule->getOSrc(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getODst(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getTSrc(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getTDst(); assert(rel); compiler->_expandAddr(rule,rel); } - if (rule->getRuleType()==NATRule::DNAT) { + if (rule->getRuleType()==NATRule::DNAT) + { rel=rule->getOSrc(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getODst(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getTSrc(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getTDst(); assert(rel); compiler->_expandAddr(rule,rel); } - if (rule->getRuleType()==NATRule::Redirect) { + if (rule->getRuleType()==NATRule::Redirect) + { rel=rule->getOSrc(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getODst(); assert(rel); compiler->_expandAddr(rule,rel); rel=rule->getTSrc(); assert(rel); compiler->_expandAddr(rule,rel);