diff --git a/build_num b/build_num index 79eb5d3ec..afe7d1271 100644 --- a/build_num +++ b/build_num @@ -1 +1 @@ -#define BUILD_NUM 2470 +#define BUILD_NUM 2477 diff --git a/doc/ChangeLog b/doc/ChangeLog index 9b36b36ec..274f3cbcf 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,24 +1,38 @@ +2010-01-31 vadim + + * NATCompiler_ipt.cpp (AssignInterface::processNext): fixes #1184 + "compiler/GUI crash compiling cluster NAT rule when cluster and + members have dynamic interface". It should be possible to have + cluster interface that is mapped to dynamic interfaces of the + member firewalls and then use this interface or whole cluster + object in rules. Compiler should expand cluster object and replace + it with its interfaces and corresponding interfaces of the member + firewall and then correctly handle dynamic ones. + 2010-01-31 yalovoy - * RuleSetModel.cpp: fixes #1182 rule number column is invisible when very - first rule is created in a rule set - * fixes #1164 focus moves in RuleSetView after paste - If i am in a rule and place the selection to service field of say rule 1 - and ctrl c and then arrow down the selection to service element in rule 2 - and ctrl v the focus then moves back to the rule number element of rule 2 - after the paste instead of staying on the service element. likewise if i - am on an element and do ctrl x it brings the focus back to the rule number element. + * RuleSetModel.cpp: fixes #1182 rule number column is invisible + when very first rule is created in a rule set - my first expectation was that the focus would remain on the service element of - the rule and not brought back to the rule number element. i guess this has - something to do with refresh of the gui and you are not keeping track of which - element the selection was on for the last operation. + * fixes #1164 focus moves in RuleSetView after paste If i am in a + rule and place the selection to service field of say rule 1 and + ctrl c and then arrow down the selection to service element in + rule 2 and ctrl v the focus then moves back to the rule number + element of rule 2 after the paste instead of staying on the + service element. likewise if i am on an element and do ctrl x it + brings the focus back to the rule number element. + + my first expectation was that the focus would remain on the + service element of the rule and not brought back to the rule + number element. i guess this has something to do with refresh of + the gui and you are not keeping track of which element the + selection was on for the last operation. Affected files: FWCmdRule.cpp FWCmdRule.h RuleSetView.cpp - RuleSetView.h + RuleSetView.h 2010-01-30 vadim diff --git a/src/cisco_lib/PolicyCompiler_cisco.cpp b/src/cisco_lib/PolicyCompiler_cisco.cpp index 842ed9508..31c157d33 100644 --- a/src/cisco_lib/PolicyCompiler_cisco.cpp +++ b/src/cisco_lib/PolicyCompiler_cisco.cpp @@ -91,10 +91,11 @@ string PolicyCompiler_cisco::createRuleLabel(const string &txt, string PolicyCompiler_cisco::debugPrintRule(Rule *r) { ostringstream str; - PolicyRule *rule=PolicyRule::cast(r); + PolicyRule *rule = PolicyRule::cast(r); FWObject *rule_iface = dbcopy->findInIndex(rule->getInterfaceId()); string iname = (rule_iface!=NULL)?rule_iface->getName():""; - string dir= rule->getDirectionAsString(); + + string dir = rule->getDirectionAsString(); str << PolicyCompiler::debugPrintRule(rule) << " " << dir << " " << iname << " " << rule->getStr("acl") << diff --git a/src/compiler_lib/CompilerDriver.cpp b/src/compiler_lib/CompilerDriver.cpp index fbe28104a..c40d2f087 100644 --- a/src/compiler_lib/CompilerDriver.cpp +++ b/src/compiler_lib/CompilerDriver.cpp @@ -1029,12 +1029,12 @@ void CompilerDriver::copyFailoverInterface(Cluster *cluster, new_cl_if->getOptionsObject()->setBool("failover_master", master_id == iface_str_id); - - // cluster interface should "inherit" some of the - // attributes of the member interfaces it - // represents. For example, if member interfaces are - // marked "unprotected" or "dedicated failover", so - // should be the cluster interface. What else? + /* + * cluster interface should "inherit" some of the attributes of + * the member interfaces it represents. For example, if member + * interfaces are marked "unprotected" or "dedicated failover", + * should be the cluster interface. What else? + */ new_cl_if->setDedicatedFailover(iface->isDedicatedFailover()); new_cl_if->setUnprotected(iface->isUnprotected()); @@ -1043,8 +1043,35 @@ void CompilerDriver::copyFailoverInterface(Cluster *cluster, /* Add copy of firewall's real interface to the cluster to make sure * compiler recognizes it when it encounters cluster object in rules. * This fixes #15 (makes compiler choose correct chains) + * + * Update 01/31/2010: + * + * Example of rule where this is necessary is anti-spoofing + * rule. When cluster object is placed in rule element, it is + * assumed that it represents its own addresses, plus addresses of + * the members. + * + * A copy of the member interface does not have + * FailoverClusterGroup child object and is not recognized as + * failover interface. This is important when this interface is + * dynamic. When cluster object is used in the rule and then + * replaced with all its interfaces in one of the rule processors, + * this copy interface appears as having cluster as a parent, not + * the firewall that is being compiled. This creates problems with + * processing of dynamic interfaces. They look like they belong to + * some other object and trigger "can use dynamic interface + * because its address is unknown" error. + * + * However there is no need to add a copy of the interface of the + * member to the cluster if this interface is dynamic or + * unnumbered. Corresponding cluster interface inherits isDyn() + * property and is sufficient. This is for ticket #1184 */ - cluster->addCopyOf(iface, true); + if ( ! iface->isDyn() && ! iface->isUnnumbered()) + { + FWObject *new_member_if = cluster->addCopyOf(iface, true); + new_member_if->setBool("member_interface_copy", true); + } } /** diff --git a/src/iptlib/NATCompiler_ipt.cpp b/src/iptlib/NATCompiler_ipt.cpp index f2a77fbb0..8f258db3b 100644 --- a/src/iptlib/NATCompiler_ipt.cpp +++ b/src/iptlib/NATCompiler_ipt.cpp @@ -56,6 +56,7 @@ #include #include +#include #include #include @@ -161,7 +162,13 @@ string NATCompiler_ipt::getNewTmpChainName(NATRule *rule) string NATCompiler_ipt::debugPrintRule(Rule *r) { NATRule *rule = NATRule::cast(r); - string iface_name = rule->getInterfaceStr(); + string iface_name = rule->getInterfaceStr(); + if (iface_name.empty()) + { + int iface_id = rule->getInterfaceId(); + FWObject *iface = dbcopy->findInIndex(iface_id); + if (iface) iface_name = iface->getName(); + } return NATCompiler::debugPrintRule(rule)+ " " + FWObjectDatabase::getStringId(rule->getInterfaceId()) + @@ -821,6 +828,12 @@ bool NATCompiler_ipt::addVirtualAddress::processNext() tmp_queue.push_back(rule); + bool cluster_member = compiler->fw->getOptionsObject()->getBool("cluster_member"); + Cluster *cluster = NULL; + if (cluster_member) + cluster = Cluster::cast( + compiler->dbcopy->findInIndex(compiler->fw->getInt("parent_cluster_id"))); + Address *a=NULL; if (rule->getRuleType()==NATRule::SNAT || rule->getRuleType()==NATRule::DNAT) @@ -834,8 +847,10 @@ bool NATCompiler_ipt::addVirtualAddress::processNext() // addresses for NAT is not supported with address ranges, // regardless of the result of complexMatch() - if ( ! a->isAny() && ! compiler->complexMatch(a,compiler->fw) && - options->getBool("manage_virtual_addr") ) + if ( ! a->isAny() && + ! compiler->complexMatch(a, compiler->fw) && + ! compiler->complexMatch(a, cluster) && + options->getBool("manage_virtual_addr")) { if (AddressRange::cast(a)!=NULL) { @@ -1230,6 +1245,11 @@ void NATCompiler_ipt::checkForDynamicInterfacesOfOtherObjects::findDynamicInterf { if (re->isAny()) return; + bool cluster_member = compiler->fw->getOptionsObject()->getBool("cluster_member"); + FWObject *cluster = NULL; + if (cluster_member) + cluster = compiler->dbcopy->findInIndex(compiler->fw->getInt("parent_cluster_id")); + list cl; for (list::iterator i1=re->begin(); i1!=re->end(); ++i1) { @@ -1238,17 +1258,22 @@ void NATCompiler_ipt::checkForDynamicInterfacesOfOtherObjects::findDynamicInterf if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer(); Interface *ifs =Interface::cast( obj ); - if (ifs!=NULL && ifs->isDyn() && ! ifs->isChildOf(compiler->fw)) + if (ifs!=NULL && ifs->isDyn() && + ! ifs->isChildOf(compiler->fw) && + ! ifs->isChildOf(cluster)) { #if 0 + cerr << endl; cerr << "NATCompiler_ipt::checkForDynamicInterfacesOfOtherObjects" << endl; - cerr << "ifs: " << endl; - ifs->dump(true,true); - cerr << endl; - cerr << "fw: " << endl; - compiler->fw->dump(true,true); - cerr << endl; + cerr << " ifs=" << ifs << " " << ifs->getName().c_str() + << " parent=" << ifs->getParent() + << " " << ifs->getParent()->getName().c_str() + << " dyn=" << ifs->isDyn() + << endl; + cerr << "compiler->fw=" << compiler->fw + << " " << compiler->fw->getName().c_str() << endl; #endif + char errstr[2048]; sprintf(errstr, "Can not build rule using dynamic interface '%s' " "of the object '%s' because its address in unknown.", @@ -2242,29 +2267,37 @@ bool NATCompiler_ipt::AssignInterface::processNext() if (iface) { - if (Cluster::isA(iface->getParentHost()) && - iface->isFailoverInterface()) + if (Cluster::isA(iface->getParentHost())) { - FWObject *failover_group = - iface->getFirstByType(FailoverClusterGroup::TYPENAME); - if (failover_group) + if (iface->isFailoverInterface()) { - for (FWObjectTypedChildIterator it = - failover_group->findByType(FWObjectReference::TYPENAME); - it != it.end(); ++it) + FailoverClusterGroup *failover_group = + FailoverClusterGroup::cast( + iface->getFirstByType(FailoverClusterGroup::TYPENAME)); + + Interface *fw_iface = + failover_group->getInterfaceForMemberFirewall(compiler->fw); + + if (fw_iface) { - Interface *fw_iface = Interface::cast(FWObjectReference::getObject(*it)); - assert(fw_iface); - if (fw_iface->isChildOf(compiler->fw)) - { - iface = fw_iface; - rule->setInterfaceId(iface->getId()); - tmp_queue.push_back(rule); - return true; - } + // this is a bit tricky: we assign rule to the + // member firewall's inteface but TSrc remains + // cluster interface or its address. + iface = fw_iface; + rule->setInterfaceId(iface->getId()); + tmp_queue.push_back(rule); + return true; } + } else + { + // parent is the cluster but there is no failover + // group. This must be a copy of the member interface. + rule->setInterfaceId(iface->getId()); + tmp_queue.push_back(rule); + return true; } + } else { if (iface->isChildOf(compiler->fw)) @@ -2276,6 +2309,14 @@ bool NATCompiler_ipt::AssignInterface::processNext() } } +#if 0 + FWObject *p = iface->getParent(); + qDebug() << "Checkpoint #1" + << " iface=" << iface << " " << iface->getName().c_str() + << " parent=" << p << " " << p->getName().c_str() + << " " << p->getTypeName().c_str(); +#endif + /* if we appear here, then TSrc is not an interface or address of an * interface. This processor will simply pass a rule along if firewall * has no interfaces at all. I wonder if I really have to do this, diff --git a/src/iptlib/PolicyCompiler_ipt.cpp b/src/iptlib/PolicyCompiler_ipt.cpp index c21a04f5d..bc869401d 100644 --- a/src/iptlib/PolicyCompiler_ipt.cpp +++ b/src/iptlib/PolicyCompiler_ipt.cpp @@ -4049,44 +4049,37 @@ bool PolicyCompiler_ipt::checkInterfaceAgainstAddressFamily::processNext() * for ticket #1172 : this is cluster interface that has no * address, check properties of the corresponding member */ - FWObject *failover_group = - rule_iface->getFirstByType(FailoverClusterGroup::TYPENAME); + FailoverClusterGroup *fg = FailoverClusterGroup::cast( + rule_iface->getFirstByType(FailoverClusterGroup::TYPENAME)); + Interface *other_iface = fg->getInterfaceForMemberFirewall(compiler->fw); - for (FWObjectTypedChildIterator it = - failover_group->findByType(FWObjectReference::TYPENAME); - it != it.end(); ++it) + if (other_iface == NULL) { - Interface *other_iface = - Interface::cast(FWObjectReference::getObject(*it)); - assert(other_iface); - - if (other_iface->isChildOf(compiler->fw)) - { - if (other_iface->getByType(addr_type).size() != 0) - { - tmp_queue.push_back(rule); - return true; - } else - { - // member interface also has no addresses - return true; - } - } + // if we get here, this cluster interface does not have + // any corresponding interface of the firewall we are + // compiling right now. What is the right thing to do in + // this case? I suppose we can't check if this interface + // matches address family. Dropping the rule. + QString err("Cluster interface '%1' does not map onto any " + "interface of the firewall '%2' but is used " + "in the 'Interface' rule element. " + "The rule will be dropped because it can " + "not be associated with this interface."); + compiler->warning(rule, + err.arg(rule_iface->getName().c_str()) + .arg(compiler->fw->getName().c_str()).toStdString()); + return true; + } + + if (other_iface->getByType(addr_type).size() != 0) + { + tmp_queue.push_back(rule); + return true; + } else + { + // member interface also has no addresses + return true; } - // if we get here, this cluster interface does not have - // any corresponding interface of the firewall we are - // compiling right now. What is the right thing to do in - // this case? I suppose we can't check if this interface - // matches address family. Dropping the rule. - QString err("Cluster interface '%1' does not map onto any " - "interface of the firewall '%2' but is used " - "in the 'Interface' rule element. " - "The rule will be dropped because it can " - "not be associated with this interface."); - compiler->warning(rule, - err.arg(rule_iface->getName().c_str()) - .arg(compiler->fw->getName().c_str()).toStdString()); - return true; } // interface has no addresses and is not cluster failover interface diff --git a/test/ipt/cluster-tests.fwb b/test/ipt/cluster-tests.fwb index 806144831..68d194807 100644 --- a/test/ipt/cluster-tests.fwb +++ b/test/ipt/cluster-tests.fwb @@ -662,7 +662,7 @@ - + @@ -841,9 +841,10 @@ - - - + + + +