--- /dev/null
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+ */
+
+#include "config/configurationoptions.h"
+
+#include <iostream>
+
+#include <boost/assert.hpp>
+#include <boost/foreach.hpp>
+
+#include <logfunc.hpp>
+
+using namespace std;
+using boost::program_options::options_description;
+using boost::program_options::value;
+using boost::program_options::variables_map;
+using I2n::Logger::GlobalLogger;
+
+//-----------------------------------------------------------------------------
+// ConfigurationOptions
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief Default constructor.
+ */
+ConfigurationOptions::ConfigurationOptions() :
+ HelpCmdStr( "help" ),
+ HelpCmdDesc( "Print this help and exit." ),
+ VersionCmdStr( "version" ),
+ VersionCmdDesc( "Print the version string and exit." ),
+ DaemonCmdStr( "daemon" ),
+ DaemonCmdDesc( "Run the evil in background." ),
+ DefaultConfigFileName( "/etc/pingcheck.conf" ),
+ ConfigFileCmdStr( "config-file" ),
+ ConfigFileCmdDesc( "Name of the configuration file." ),
+ SourceNetworkInterfaceCmdStr( "source-network-interface" ),
+ SourceNetworkInterfaceCmdDesc( "The network interface from where the packets will be received and originated" ),
+ DefaultNameServer( "127.0.0.1" ),
+ NameServerCmdStr( "nameserver" ),
+ NameServerCmdDesc( "The local address from where the DNS query will be made." ),
+ PingProtocolCmdStr( "ping-protocol" ),
+ PingProtocolCmdDesc( "Defines which protocol will be used to ping the destination." ),
+ DefaultHostsDownLimit( 0 ), // no host down
+ HostsDownLimitCmdStr( "hosts-down-limit" ),
+ HostsDownLimitCmdDesc( "Limit of host that have to be down in order to notify." ),
+ DefaultPingFailLimit( 50 ), // 50 pings can fail at most
+ PingFailLimitCmdStr( "ping-fail-limit" ),
+ PingFailLimitCmdDesc( "Maximum percentage of pings that can fail for a given host." ),
+ StatusNotifierCmdCmdStr( "status-notifier-cmd" ),
+ StatusNotifierCmdCmdDesc( "The command to execute to alert about host status." ),
+ DefaultLinkUpIntervalInMin( 5 ), // 5 minutes
+ LinkUpIntervalCmdStr( "link-up-interval" ),
+ LinkUpIntervalCmdDesc( "How long the link must be responsive in order to consider it stable." ),
+ DefaultLinkDownIntervalInMin( 2 ), // 2 minutes
+ LinkDownIntervalCmdStr( "link-down-interval" ),
+ LinkDownIntervalCmdDesc( "How long the link must be offline in order to consider it down." ),
+ HostNameCmdStr( "host.name" ),
+ HostNameCmdDesc( "Host address" ),
+ DefaultHostPort( 80 ), // HTTP port
+ HostPortCmdStr( "host.port" ),
+ HostPortCmdDesc( "Host port number" ),
+ DefaultHostIntervalInSec( 60 ), // 60 seconds
+ HostIntervalCmdStr( "host.interval" ),
+ HostIntervalCmdDesc( "Interval between each ping to the host" )
+{
+}
+
+/**
+ * @brief Destructor.
+ */
+ConfigurationOptions::~ConfigurationOptions()
+{
+}
+
+/**
+ * @brief TODO
+ *
+ * @return
+ */
+options_description ConfigurationOptions::get_generic_options() const
+{
+ options_description options( "Generic options" );
+ options.add_options()
+ ( HelpCmdStr.c_str(), HelpCmdDesc.c_str() )
+ ( VersionCmdStr.c_str(), VersionCmdDesc.c_str() )
+ ( DaemonCmdStr.c_str(), DaemonCmdDesc.c_str() )
+ ( ConfigFileCmdStr.c_str(), value<string>()->default_value( DefaultConfigFileName ), ConfigFileCmdDesc.c_str() )
+ ;
+
+ return options;
+}
+
+/**
+ * @brief TODO
+ *
+ * @return
+ */
+options_description ConfigurationOptions::get_configuration_options() const
+{
+ options_description options( "Configuration" );
+ options.add_options()
+ ( SourceNetworkInterfaceCmdStr.c_str(), value<string>(), SourceNetworkInterfaceCmdDesc.c_str() )
+ ( NameServerCmdStr.c_str(), value<string>()->default_value( DefaultNameServer ), NameServerCmdDesc.c_str() )
+ ( PingProtocolCmdStr.c_str(), value<string>(), PingProtocolCmdDesc.c_str() )
+ ( HostsDownLimitCmdStr.c_str(), value<int>()->default_value( DefaultHostsDownLimit ), HostsDownLimitCmdDesc.c_str() )
+ ( PingFailLimitCmdStr.c_str(), value<int>()->default_value( DefaultPingFailLimit ), PingFailLimitCmdDesc.c_str() )
+ ( StatusNotifierCmdCmdStr.c_str(), value<string>(), StatusNotifierCmdCmdDesc.c_str() )
+ ( LinkUpIntervalCmdStr.c_str(), value<int>()->default_value( DefaultLinkUpIntervalInMin ), LinkUpIntervalCmdDesc.c_str() )
+ ( LinkDownIntervalCmdStr.c_str(), value<int>()->default_value( DefaultLinkDownIntervalInMin ), LinkDownIntervalCmdDesc.c_str() )
+ ( HostNameCmdStr.c_str(), value< vector<string> >(), HostNameCmdDesc.c_str() )
+ ( HostPortCmdStr.c_str(), value< vector<int> >(), HostPortCmdDesc.c_str() )
+ ( HostIntervalCmdStr.c_str(), value< vector<int> >(), HostIntervalCmdDesc.c_str() )
+ ;
+
+ return options;
+}
+
+/**
+ * @brief TODO
+ *
+ * @param
+ * @param
+ *
+ * @return
+ */
+bool ConfigurationOptions::parse_generic_options(
+ const variables_map& vm,
+ Configuration *configuration
+)
+{
+ // help
+ if ( vm.count( HelpCmdStr ) > 0)
+ {
+ options_description generic = get_generic_options();
+ options_description config = get_configuration_options();
+
+ options_description visible_options( "Allowed options" );
+ visible_options.add( generic ).add( config );
+
+ // TODO return a string with help, does not print to interface
+ cout << visible_options << endl;
+ return true;
+ }
+
+ // version
+ if ( vm.count( VersionCmdStr ) > 0 )
+ {
+ cout << PROJECT_NAME << " version " << VERSION_STRING << endl;
+ return true;
+ }
+
+ // daemon
+ bool have_daemon = ( vm.count( DaemonCmdStr ) > 0 );
+ configuration->set_daemon( have_daemon );
+ GlobalLogger.info() << DaemonCmdStr << "="
+ << have_daemon << endl;
+
+ // config-file
+ if ( vm.count( ConfigFileCmdStr ) > 0 )
+ {
+ string config_file_name = vm[ ConfigFileCmdStr ].as<string> ();
+ configuration->set_config_file_name( config_file_name );
+
+ GlobalLogger.info() << ConfigFileCmdStr << "="
+ << config_file_name << endl;
+ }
+
+ return false;
+}
+
+/**
+ * @brief TODO
+ *
+ * @param
+ * @param
+ *
+ * @return
+ */
+bool ConfigurationOptions::parse_configuration_options(
+ const variables_map &vm,
+ Configuration *configuration
+)
+{
+ // source-network-interface
+ if ( vm.count( SourceNetworkInterfaceCmdStr ) > 0 )
+ {
+ string source_network_interface =
+ vm[ SourceNetworkInterfaceCmdStr ].as<string> ();
+ configuration->set_source_network_interface( source_network_interface );
+
+ GlobalLogger.info() << SourceNetworkInterfaceCmdStr << "="
+ << source_network_interface << endl;
+ }
+
+ // nameserver
+ if ( vm.count( NameServerCmdStr ) > 0 )
+ {
+ string nameserver = vm[ NameServerCmdStr ].as<string> ();
+ configuration->set_nameserver( nameserver );
+
+ GlobalLogger.info() << NameServerCmdStr << "="
+ << nameserver << endl;
+ }
+
+ // ping-protocol
+ if ( vm.count( PingProtocolCmdStr ) > 0 )
+ {
+ string protocol_string = vm[ PingProtocolCmdStr ].as<string> ();
+ PingProtocol protocol = get_ping_protocol_from_string( protocol_string );
+ configuration->set_ping_protocol( protocol );
+
+ GlobalLogger.info() << PingProtocolCmdStr << "="
+ << protocol_string << endl;
+ }
+
+ // hosts-down-limit
+ int host_down_limit = 0;
+ if ( vm.count( HostsDownLimitCmdStr ) > 0 )
+ {
+ host_down_limit = vm[ HostsDownLimitCmdStr ].as<int> ();
+ configuration->set_hosts_down_limit( host_down_limit );
+
+ GlobalLogger.info() << HostsDownLimitCmdStr << "="
+ << host_down_limit << endl;
+ }
+
+ // ping-fail-limit
+ if ( vm.count( PingFailLimitCmdStr ) > 0 )
+ {
+ int ping_fail_limit = vm[ PingFailLimitCmdStr ].as<int> ();
+ configuration->set_ping_fail_limit( ping_fail_limit );
+
+ GlobalLogger.info() << PingFailLimitCmdStr << "="
+ << ping_fail_limit << endl;
+ }
+
+ // status-notifier-cmd
+ if ( vm.count( StatusNotifierCmdCmdStr ) > 0 )
+ {
+ string status_notifier_cmd = vm[ StatusNotifierCmdCmdStr ].as<string>();
+ configuration->set_status_notifier_cmd( status_notifier_cmd );
+
+ GlobalLogger.info() << StatusNotifierCmdCmdStr << "="
+ << status_notifier_cmd << endl;
+ }
+
+ // link-up-interval
+ if ( vm.count( LinkUpIntervalCmdStr ) > 0 )
+ {
+ int link_up_interval_in_min = vm[ LinkUpIntervalCmdStr ].as<int>();
+ configuration->set_link_up_interval_in_min( link_up_interval_in_min );
+
+ GlobalLogger.info() << LinkUpIntervalCmdStr << "="
+ << link_up_interval_in_min << endl;
+ }
+
+ // link-down-interval
+ if ( vm.count( LinkDownIntervalCmdStr ) > 0 )
+ {
+ int link_down_interval_in_min = vm[ LinkDownIntervalCmdStr ].as<int>();
+ configuration->set_link_down_interval_in_min( link_down_interval_in_min );
+
+ GlobalLogger.info() << LinkDownIntervalCmdStr << "="
+ << link_down_interval_in_min << endl;
+ }
+
+ // [host] name
+ size_t hosts_names_count = 0;
+ if ( vm.count( HostNameCmdStr ) > 0 )
+ {
+ HostList hosts_list;
+
+ vector<string> hosts_names = vm[ HostNameCmdStr ].as< vector<string> > ();
+ BOOST_FOREACH( string host_name, hosts_names )
+ {
+ BOOST_ASSERT( !host_name.empty() );
+
+ HostItem host_item( new Host( host_name ) );
+ hosts_list.push_back( host_item );
+
+ GlobalLogger.info() << HostNameCmdStr << "="
+ << host_name << endl;
+ }
+
+ configuration->set_hosts( hosts_list );
+
+ hosts_names_count = hosts_names.size();
+
+ BOOST_ASSERT( hosts_names_count >= static_cast<size_t>( host_down_limit ) );
+ }
+
+ // [host] port
+ size_t host_port_count = 0;
+ if ( vm.count( HostPortCmdStr ) > 0 )
+ {
+ HostList hosts_list = configuration->get_hosts();
+ HostList::iterator hosts_it = hosts_list.begin();
+
+ vector<int> hosts_ports = vm[ HostPortCmdStr ].as< vector<int> >();
+ BOOST_FOREACH( int host_port, hosts_ports )
+ {
+ BOOST_ASSERT( ( 0 <= host_port ) && ( host_port <= numeric_limits<uint16_t>::max() ) );
+
+ HostItem host_item = *hosts_it;
+ host_item->set_port( static_cast<uint16_t>(host_port) );
+ ++hosts_it;
+
+ GlobalLogger.info() << HostPortCmdStr << "=" << host_port << endl;
+ }
+
+ host_port_count = hosts_ports.size();
+ }
+
+ // [host] interval
+ size_t hosts_interval_count = 0;
+ if ( vm.count( HostIntervalCmdStr ) > 0 )
+ {
+ HostList hosts_list = configuration->get_hosts();
+ HostList::iterator hosts_it = hosts_list.begin();
+
+ vector<int> hosts_intervals = vm[ HostIntervalCmdStr ].as< vector<int> >();
+ BOOST_FOREACH( int host_interval_in_sec, hosts_intervals )
+ {
+ BOOST_ASSERT( 0 < host_interval_in_sec );
+
+ HostItem host_item = *hosts_it;
+ host_item->set_interval_in_sec( host_interval_in_sec );
+ ++hosts_it;
+
+ GlobalLogger.info() << HostIntervalCmdStr << "="
+ << host_interval_in_sec << endl;
+ }
+
+ hosts_interval_count = hosts_intervals.size();
+ }
+
+ // make sure there is always an interval for each host
+ if ( hosts_names_count != hosts_interval_count )
+ {
+ GlobalLogger.error() << "Could not parse configuration file." <<
+ " Missing an interval entry for one of the hosts." << endl;
+ return false;
+ }
+
+ BOOST_ASSERT( hosts_names_count == host_port_count );
+ BOOST_ASSERT( hosts_names_count == hosts_interval_count );
+
+ return true;
+}
+
+/**
+ * @return which options must abort the application. Like the --version.
+ * TODO rename to is_haltable?
+ */
+bool ConfigurationOptions::halt_on_generic_options( const variables_map &vm ) const
+{
+ bool is_help = ( vm.count( HelpCmdStr ) > 0 );
+ bool is_version = ( vm.count( VersionCmdStr ) > 0 );
+ bool terminate_app = is_help || is_version;
+
+ return terminate_app;
+}
--- /dev/null
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+ */
+
+#ifndef CONFIGURATIONOPTIONS_H
+#define CONFIGURATIONOPTIONS_H
+
+#include <string>
+
+#include <boost/program_options.hpp>
+
+#include "config/configuration.h"
+
+//-----------------------------------------------------------------------------
+// ConfigurationOptions
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief Options for configuration.
+ */
+class ConfigurationOptions
+{
+public:
+ ConfigurationOptions();
+ virtual ~ConfigurationOptions();
+
+ boost::program_options::options_description get_generic_options() const;
+ boost::program_options::options_description get_configuration_options() const;
+
+ bool parse_generic_options(
+ const boost::program_options::variables_map &vm,
+ Configuration *configuration
+ );
+ bool parse_configuration_options(
+ const boost::program_options::variables_map &vm,
+ Configuration *configuration
+ );
+
+ bool halt_on_generic_options(
+ const boost::program_options::variables_map &vm
+ ) const;
+
+public: // TODO change to private
+ const std::string HelpCmdStr;
+ const std::string HelpCmdDesc;
+ const std::string VersionCmdStr;
+ const std::string VersionCmdDesc;
+ const std::string DaemonCmdStr;
+ const std::string DaemonCmdDesc;
+ const std::string DefaultConfigFileName;
+ const std::string ConfigFileCmdStr;
+ const std::string ConfigFileCmdDesc;
+ const std::string SourceNetworkInterfaceCmdStr;
+ const std::string SourceNetworkInterfaceCmdDesc;
+ const std::string DefaultNameServer;
+ const std::string NameServerCmdStr;
+ const std::string NameServerCmdDesc;
+ const std::string PingProtocolCmdStr;
+ const std::string PingProtocolCmdDesc;
+ const int DefaultHostsDownLimit;
+ const std::string HostsDownLimitCmdStr;
+ const std::string HostsDownLimitCmdDesc;
+ const int DefaultPingFailLimit;
+ const std::string PingFailLimitCmdStr;
+ const std::string PingFailLimitCmdDesc;
+ const std::string StatusNotifierCmdCmdStr;
+ const std::string StatusNotifierCmdCmdDesc;
+ const int DefaultLinkUpIntervalInMin;
+ const std::string LinkUpIntervalCmdStr;
+ const std::string LinkUpIntervalCmdDesc;
+ const int DefaultLinkDownIntervalInMin;
+ const std::string LinkDownIntervalCmdStr;
+ const std::string LinkDownIntervalCmdDesc;
+ const std::string HostNameCmdStr;
+ const std::string HostNameCmdDesc;
+ const int DefaultHostPort;
+ const std::string HostPortCmdStr;
+ const std::string HostPortCmdDesc;
+ const int DefaultHostIntervalInSec;
+ const std::string HostIntervalCmdStr;
+ const std::string HostIntervalCmdDesc;
+
+};
+
+#endif // CONFIGURATIONOPTIONS_H