2011-10-10 16:21:00 +02:00
#!/usr/bin/perl
# (c) Dario Rodriguez 2011 <dario.rodriguez@artica.es>
# Intel DCM Discovery
use POSIX qw( setsid strftime strftime ceil ) ;
use strict ;
use warnings ;
use IO::Socket::INET ;
use NetAddr::IP ;
# Default lib dir for RPM and DEB packages
use lib '/usr/lib/perl5' ;
use PandoraFMS::Tools ;
use PandoraFMS::DB ;
use PandoraFMS::Core ;
use PandoraFMS::Config ;
##########################################################################
# Global variables so set behaviour here:
2012-05-09 09:40:24 +02:00
my $ pkg_count = 3 ; #Number of ping pkgs
my $ pkg_timeout = 3 ; #Pkg ping timeout wait
2011-10-10 16:21:00 +02:00
##########################################################################
# Code begins here, do not touch
##########################################################################
2014-05-10 04:09:44 +02:00
my $ OSNAME = $^O ;
my $ pandora_conf ;
if ( $ OSNAME eq "freebsd" ) {
$ pandora_conf = "/usr/local/etc/pandora/pandora_server.conf" ;
} else {
$ pandora_conf = "/etc/pandora/pandora_server.conf" ;
}
2011-10-10 16:21:00 +02:00
my $ task_id = $ ARGV [ 0 ] ; # Passed automatically by the server
my $ target_group = $ ARGV [ 1 ] ; # Defined by user
my $ create_incident = $ ARGV [ 2 ] ; # Defined by user
# Used Custom Fields in this script
my $ target_network = $ ARGV [ 3 ] ; # Filed1 defined by user
my $ username = $ ARGV [ 4 ] ; # Field2 defined by user
my $ password = $ ARGV [ 5 ] ; # Field3 defined by user
##########################################################################
# Update recon task status.
##########################################################################
sub update_recon_task ($$$) {
my ( $ dbh , $ id_task , $ status ) = @ _ ;
db_do ( $ dbh , 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?' , time ( ) , $ status , $ id_task ) ;
}
##########################################################################
# Show help
##########################################################################
sub show_help {
print "\nSpecific Pandora FMS Intel DCM Discovery\n" ;
print "(c) Artica ST 2011 <info\@artica.es>\n\n" ;
print "Usage:\n\n" ;
print " $0 <task_id> <group_id> <create_incident_flag> <custom_field1> <custom_field2> <custom_field3>\n\n" ;
print " * custom_field1 = network. i.e.: 192.168.100.0/24\n" ;
print " * custom_field2 = username \n" ;
print " * custom_fiedl3 = password \n" ;
exit ;
}
##########################################################################
# Get SNMP response.
##########################################################################
2012-05-09 09:40:24 +02:00
sub ipmi_ping ($$$) {
2011-10-10 16:21:00 +02:00
my $ addr = shift ;
2012-05-09 09:40:24 +02:00
my $ pkg_count = shift ;
my $ pkg_timeout = shift ;
2011-10-10 16:21:00 +02:00
2012-05-09 09:40:24 +02:00
my $ cmd = "ipmiping $addr -c $pkg_count -t $pkg_timeout" ;
2011-10-10 16:21:00 +02:00
my $ res = `$cmd` ;
if ( $ res =~ /100\.0% packet loss/ ) {
return 0 ;
}
return 1 ;
}
sub create_ipmi_modules ($$$$$$) {
my ( $ conf , $ dbh , $ addr , $ user , $ pass , $ id_agent ) = @ _ ;
my $ cmd = "ipmi-sensors -h $addr -u $user -p $pass" ;
my $ res = `$cmd` ;
my @ lines = split ( /\n/ , $ res ) ;
2012-05-09 09:40:24 +02:00
2011-10-10 16:21:00 +02:00
my $ ipmi_plugin_id = get_db_value ( $ dbh , "SELECT id FROM tplugin WHERE name = '" . safe_input ( "IPMI Plugin" ) . "'" ) ;
2012-05-09 09:40:24 +02:00
for ( my $ i = 1 ; $ i < $# lines ; $ i + + ) {
my $ line = $ lines [ $ i ] ;
my @ aux = split ( /\|/ , $ line ) ;
2011-10-10 16:21:00 +02:00
my $ name = $ aux [ 1 ] ;
#Trim name
$ name =~ s/^\s+// ;
$ name =~ s/\s+$// ;
2012-05-09 09:40:24 +02:00
2011-10-10 16:21:00 +02:00
my $ module_type = "generic_data_string" ;
2012-05-09 09:40:24 +02:00
my $ value_read = $ aux [ 3 ] ;
#Trim name
$ value_read =~ s/^\s+// ;
$ value_read =~ s/\s+$// ;
#Check if value read is integer or boolean
if ( $ value_read =~ m/^\d+.\d+$/ || $ value_read =~ m/^\d+$/ ) {
2011-10-10 16:21:00 +02:00
$ module_type = "generic_data" ;
}
2012-05-09 09:40:24 +02:00
2011-10-10 16:21:00 +02:00
my $ id_module_type = get_module_id ( $ dbh , $ module_type ) ;
my $ params = "-s $aux[0]" ;
my % parameters ;
$ parameters { "nombre" } = safe_input ( $ name ) ;
$ parameters { "id_tipo_modulo" } = $ id_module_type ;
$ parameters { "id_agente" } = $ id_agent ;
$ parameters { "id_plugin" } = $ ipmi_plugin_id ;
$ parameters { "ip_target" } = $ addr ;
$ parameters { "plugin_user" } = $ user ;
$ parameters { "plugin_pass" } = $ pass ;
$ parameters { "id_modulo" } = 4 ;
$ parameters { "plugin_parameter" } = $ params ;
pandora_create_module_from_hash ( $ conf , \ % parameters , $ dbh ) ;
}
}
##########################################################################
##########################################################################
# M A I N C O D E
##########################################################################
##########################################################################
if ( $# ARGV == - 1 ) {
show_help ( ) ;
}
# Pandora server configuration
my % conf ;
$ conf { "quiet" } = 0 ;
$ conf { "verbosity" } = 1 ; # Verbose 1 by default
$ conf { "daemon" } = 0 ; # Daemon 0 by default
$ conf { 'PID' } = "" ; # PID file not exist by default
$ conf { 'pandora_path' } = $ pandora_conf ;
# Read config file
pandora_load_config ( \ % conf ) ;
# Connect to the DB
2012-05-09 09:40:24 +02:00
my $ dbh = db_connect ( 'mysql' , $ conf { 'dbname' } , $ conf { 'dbhost' } , '3306' , $ conf { 'dbuser' } , $ conf { 'dbpass' } ) ;
2011-10-10 16:21:00 +02:00
# Start the network sweep
# Get a NetAddr::IP object for the target network
my $ net_addr = new NetAddr:: IP ( $ target_network ) ;
if ( ! defined ( $ net_addr ) ) {
logger ( \ % conf , "Invalid network " . $ target_network . " for Intel DCM Discovery task" , 1 ) ;
update_recon_task ( $ dbh , $ task_id , - 1 ) ;
return - 1 ;
}
# Scan the network for host
my ( $ total_hosts , $ hosts_found , $ addr_found ) = ( $ net_addr - > num , 0 , '' ) ;
my $ last = 0 ;
for ( my $ i = 1 ; $ net_addr <= $ net_addr - > broadcast ; $ i + + , $ net_addr + + ) {
if ( $ last == 1 ) {
last ;
}
my $ net_addr_temp = $ net_addr + 1 ;
if ( $ net_addr eq $ net_addr_temp ) {
$ last = 1 ;
}
if ( $ net_addr =~ /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.(\d{1,3})\b/ ) {
if ( $ 1 eq '0' || $ 1 eq '255' ) {
next ;
}
}
my $ addr = ( split ( /\// , $ net_addr ) ) [ 0 ] ;
$ hosts_found + + ;
# Update the recon task
update_recon_task ( $ dbh , $ task_id , ceil ( $ i / ($total_hosts / 100 ) ) ) ;
2012-05-09 09:40:24 +02:00
2011-10-10 16:21:00 +02:00
my $ alive = 0 ;
2012-05-09 09:40:24 +02:00
if ( ipmi_ping ( $ addr , $ pkg_count , $ pkg_timeout ) == 1 ) {
2011-10-10 16:21:00 +02:00
$ alive = 1 ;
}
2012-05-09 09:40:24 +02:00
2011-10-10 16:21:00 +02:00
next unless ( $ alive > 0 ) ;
# Resolve the address
my $ host_name = gethostbyaddr ( inet_aton ( $ addr ) , AF_INET ) ;
$ host_name = $ addr unless defined ( $ host_name ) ;
logger ( \ % conf , "Intel DCM Device found host $host_name." , 10 ) ;
# Check if the agent exists
my $ agent_id = get_agent_id ( $ dbh , $ host_name ) ;
# If the agent doesnt exist we create it
if ( $ agent_id == - 1 ) {
# Create a new agent
$ agent_id = pandora_create_agent ( \ % conf , $ conf { 'servername' } , $ host_name , $ addr , $ target_group , 0 , 11 , '' , 300 , $ dbh ) ;
create_ipmi_modules ( \ % conf , $ dbh , $ addr , $ username , $ password , $ agent_id ) ;
}
# Generate an event
pandora_event ( \ % conf , "[RECON] New Intel DCM host [$host_name] detected on network [" . $ target_network . ']' , $ target_group , $ agent_id , 2 , 0 , 0 , 'recon_host_detected' , 0 , $ dbh ) ;
}
# Mark recon task as done
update_recon_task ( $ dbh , $ task_id , - 1 ) ;
# End of code