From 1f5ab1b9eca8ebbc897835783d4b4190b6fb895b Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Sat, 3 Oct 2009 19:18:42 +0000 Subject: [PATCH] 2009-10-03 vadim * PolicyCompiler_ipt.cpp (PolicyCompiler_ipt::insertFailoverRule): Added support for heartbeat over unicast. Protocol options dialog for heartbeat offers checkbox "Use unicast" (off by default, when checked, address input field for the multicast heartbeat address becomes disabled). When checkbox is checked, compiler automatically adds rules to permit unicast heartbeat health checks between addresses of interfaces which are members of the failover group. --- build_num | 2 +- doc/ChangeLog | 11 +++++ src/gui/heartbeatOptionsDialog.cpp | 12 +++++ src/gui/heartbeatOptionsDialog.h | 1 + src/gui/heartbeatoptionsdialog_q.ui | 55 +++++++++++++++++---- src/iptlib/PolicyCompiler_ipt.cpp | 74 ++++++++++++++++++++++++----- src/iptlib/PolicyCompiler_ipt.h | 12 ++--- 7 files changed, 138 insertions(+), 29 deletions(-) diff --git a/build_num b/build_num index ec05c7720..d599eafa0 100644 --- a/build_num +++ b/build_num @@ -1 +1 @@ -#define BUILD_NUM 1537 +#define BUILD_NUM 1541 diff --git a/doc/ChangeLog b/doc/ChangeLog index ce5c5b0ac..016ce0f07 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,14 @@ +2009-10-03 vadim + + * PolicyCompiler_ipt.cpp (PolicyCompiler_ipt::insertFailoverRule): + Added support for heartbeat over unicast. Protocol options dialog + for heartbeat offers checkbox "Use unicast" (off by default, when + checked, address input field for the multicast heartbeat address + becomes disabled). When checkbox is checked, compiler + automatically adds rules to permit unicast heartbeat health checks + between addresses of interfaces which are members of the failover + group. + 2009-09-30 vadim * ObjectManipulator.cpp (ObjectManipulator::setAttributesColumnEnabled): diff --git a/src/gui/heartbeatOptionsDialog.cpp b/src/gui/heartbeatOptionsDialog.cpp index 1e42cff01..e055d8b38 100644 --- a/src/gui/heartbeatOptionsDialog.cpp +++ b/src/gui/heartbeatOptionsDialog.cpp @@ -68,6 +68,9 @@ heartbeatOptionsDialog::heartbeatOptionsDialog(QWidget *parent, FWObject *o) string port = gropt->getStr("heartbeat_port"); if (port.empty()) gropt->setStr("heartbeat_port", default_port); + data.registerOption(m_dialog->use_unicast, + gropt, + "heartbeat_unicast"); data.registerOption(m_dialog->heartbeat_address, gropt, "heartbeat_address"); @@ -75,6 +78,8 @@ heartbeatOptionsDialog::heartbeatOptionsDialog(QWidget *parent, FWObject *o) gropt, "heartbeat_port"); data.loadAll(); + + toggleUseUnicast(); } heartbeatOptionsDialog::~heartbeatOptionsDialog() @@ -118,3 +123,10 @@ bool heartbeatOptionsDialog::validate() return true; } +void heartbeatOptionsDialog::toggleUseUnicast() +{ + bool onoff = m_dialog->use_unicast->isChecked(); + m_dialog->heartbeat_address->setEnabled( ! onoff ); + m_dialog->heartbeat_address_label->setEnabled( ! onoff ); +} + diff --git a/src/gui/heartbeatOptionsDialog.h b/src/gui/heartbeatOptionsDialog.h index 558c742bd..684433334 100644 --- a/src/gui/heartbeatOptionsDialog.h +++ b/src/gui/heartbeatOptionsDialog.h @@ -53,6 +53,7 @@ private: protected slots: virtual void accept(); virtual void reject(); + virtual void toggleUseUnicast(); }; #endif // __HEARTBEATOPTIONSDIALOG_H_ diff --git a/src/gui/heartbeatoptionsdialog_q.ui b/src/gui/heartbeatoptionsdialog_q.ui index 1dc8dae10..a3972d059 100644 --- a/src/gui/heartbeatoptionsdialog_q.ui +++ b/src/gui/heartbeatoptionsdialog_q.ui @@ -6,7 +6,7 @@ 0 0 402 - 282 + 263 @@ -79,17 +79,33 @@ :/Icons/Options:/Icons/Options - - + + + + Heartbeat should be configured to use unicast address +of each firewall member for health checks. Firewall Builder +will add policy rules to permit these automatically. + + + Use unicast address for heartbeat + + + + + Address: - - + + + + Enter multicat address used for heartbeat health checks here. + + - + Qt::Horizontal @@ -102,21 +118,21 @@ - + Port number (udp): - + 65535 - + Qt::Horizontal @@ -129,7 +145,7 @@ - + Qt::Vertical @@ -190,5 +206,24 @@ + + use_unicast + toggled(bool) + heartbeatOptionsDialog_q + toggleUseUnicast() + + + 204 + 51 + + + 200 + 131 + + + + + toggleUseUnicast() + diff --git a/src/iptlib/PolicyCompiler_ipt.cpp b/src/iptlib/PolicyCompiler_ipt.cpp index b432b0ba8..58aa5f5fa 100644 --- a/src/iptlib/PolicyCompiler_ipt.cpp +++ b/src/iptlib/PolicyCompiler_ipt.cpp @@ -74,10 +74,14 @@ #include +#include + + using namespace libfwbuilder; using namespace fwcompiler; using namespace std; + static int chain_no=0; static std::list standard_chains; @@ -4748,6 +4752,29 @@ void PolicyCompiler_ipt::insertFailoverRule() if (failover_group->getStr("type") == "heartbeat") { + /* + * Note that iface is a copy of the cluster inetrface. + * Find interface of the member firewall fw that corresponds + * to the cluster interface iface + */ + + string fw_iface_id = iface->getOptionsObject()->getStr("base_interface_id"); + Interface *fw_iface = + Interface::cast( + dbcopy->findInIndex(FWObjectDatabase::getIntId(fw_iface_id))); + if (fw_iface == NULL) + { + warning( + QString("Can not find interface of the firewall " + "for the cluster failover group %1. " + "Falling back using cluster interface object.") + .arg(failover_group->getName().c_str()).toStdString()); + fw_iface = iface; + } + + bool ucast = FailoverClusterGroup::cast(failover_group)-> + getOptionsObject()->getBool("heartbeat_unicast"); + string addr = FailoverClusterGroup::cast(failover_group)-> getOptionsObject()->getStr("heartbeat_address"); if (addr.empty()) addr = default_heartbeat_address; @@ -4774,12 +4801,35 @@ void PolicyCompiler_ipt::insertFailoverRule() heartbeat_srv->setComment("HEARTBEAT UDP port"); dbcopy->add(heartbeat_srv); - rule = addMgmtRule(NULL, heartbeat_dst, heartbeat_srv, iface, - PolicyRule::Inbound, PolicyRule::Accept, - "heartbeat"); - rule = addMgmtRule(fw, heartbeat_dst, heartbeat_srv, iface, - PolicyRule::Outbound, PolicyRule::Accept, - "heartbeat"); + // Heartbeat can use either multicast or unicast + if (ucast) + { + for (FWObjectTypedChildIterator it = + failover_group->findByType(FWObjectReference::TYPENAME); + it != it.end(); ++it) + { + Interface *other_iface = + Interface::cast(FWObjectReference::getObject(*it)); + assert(other_iface); + rule = addMgmtRule(other_iface, + fw_iface, + heartbeat_srv, + fw_iface, + PolicyRule::Inbound, + PolicyRule::Accept, + "heartbeat"); + } + } else + { + rule = addMgmtRule(NULL, heartbeat_dst, heartbeat_srv, + fw_iface, + PolicyRule::Inbound, PolicyRule::Accept, + "heartbeat"); + rule = addMgmtRule(fw, heartbeat_dst, heartbeat_srv, + fw_iface, + PolicyRule::Outbound, PolicyRule::Accept, + "heartbeat"); + } } if (failover_group->getStr("type") == "openais") @@ -4830,12 +4880,12 @@ void PolicyCompiler_ipt::insertFailoverRule() /* TODO: Add error-handling (exceptions) */ -PolicyRule* PolicyCompiler_ipt::addMgmtRule(Address* const src, - Address* const dst, - Service* const service, - Interface* const iface, - PolicyRule::Direction direction, - PolicyRule::Action action, +PolicyRule* PolicyCompiler_ipt::addMgmtRule(Address* src, + Address* dst, + Service* service, + Interface* iface, + const PolicyRule::Direction direction, + const PolicyRule::Action action, const string label, const bool related) { diff --git a/src/iptlib/PolicyCompiler_ipt.h b/src/iptlib/PolicyCompiler_ipt.h index 4c6529ea5..2a9f21e7e 100644 --- a/src/iptlib/PolicyCompiler_ipt.h +++ b/src/iptlib/PolicyCompiler_ipt.h @@ -94,12 +94,12 @@ namespace fwcompiler void insertFailoverRule(); libfwbuilder::PolicyRule* addMgmtRule( - libfwbuilder::Address* const src, - libfwbuilder::Address* const dst, - libfwbuilder::Service* const service, - libfwbuilder::Interface* const iface, - libfwbuilder::PolicyRule::Direction direction, - libfwbuilder::PolicyRule::Action action, + libfwbuilder::Address* src, + libfwbuilder::Address* dst, + libfwbuilder::Service* service, + libfwbuilder::Interface* iface, + const libfwbuilder::PolicyRule::Direction direction, + const libfwbuilder::PolicyRule::Action action, const std::string label, const bool related = false);