2010-10-21 11:28:32 +02:00
#!/usr/bin/perl
# (c) Sancho Lerena 2010 <slerena@artica.es>
# SNMP Recon App script
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:
my $ target_timeout = 5 ; # Fixed to 5 secs by default
my $ target_interval = 600 ;
##########################################################################
# Code begins here, do not touch
##########################################################################
2010-12-09 10:08:05 +01:00
my $ pandora_conf = "/etc/pandora/pandora_server.conf" ;
2010-10-21 11:28:32 +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
2010-11-02 17:43:44 +01:00
my $ target_network = $ ARGV [ 3 ] ; # Filed1 defined by user
my $ target_community = $ ARGV [ 4 ] ; # Field2 defined by user
2011-06-30 18:33:05 +02:00
my $ all_mode = $ ARGV [ 5 ] ; # Field3 defined by user
$ all_mode = '' unless defined ( $ all_mode ) ;
2010-10-21 11:28:32 +02:00
# Unused Custom Fields in this script
# my $field4 = $ARGV[6]; # 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 SNMP Recon Plugin for SNMP device autodiscovery\n" ;
2011-06-30 18:33:05 +02:00
print "(c) Artica ST 2011 <info\@artica.es>\n\n" ;
2010-10-21 11:28:32 +02:00
print "Usage:\n\n" ;
2011-06-30 18:33:05 +02:00
print " $0 <task_id> <group_id> <create_incident_flag> <custom_field1> <custom_field2> <custom_field3>\n\n" ;
2010-11-02 17:43:44 +01:00
print " * custom_field1 = network. i.e.: 192.168.100.0/24\n" ;
2011-07-07 10:48:38 +02:00
print " * custom_field2 = snmp_community. \n" ;
2011-06-30 18:33:05 +02:00
print " * custom_field3 = optative parameter to force process downed interfaces (use: '-a'). Only up interfaces are processed by default \n\n" ;
2010-11-02 17:43:44 +01:00
print " Additional information:\nWhen the script is called from a recon task, 'task_id' parameter is automatically filled, " ;
print "group_id and create_incident_flag are passed from interface form combos and custom fields manually filled.\n\n\n" ;
2010-10-21 11:28:32 +02:00
exit ;
}
##########################################################################
# Return the ID of the agent with the given IP.
##########################################################################
sub get_agent_from_addr ($$) {
my ( $ dbh , $ ip_address ) = @ _ ;
return 0 if ( ! defined ( $ ip_address ) || $ ip_address eq '' ) ;
my $ agent_id = get_db_value ( $ dbh , ' SELECT id_agent FROM taddress , taddress_agent , tagente
WHERE tagente . id_agente = taddress_agent . id_agent
AND taddress_agent . id_a = taddress . id_a
AND ip = ? ' , $ ip_address ) ;
return ( defined ( $ agent_id ) ) ? $ agent_id : - 1 ;
}
##########################################################################
# Get SNMP response.
##########################################################################
sub get_snmp_response ($$$) {
my ( $ target_timeout , $ target_community , $ addr ) = @ _ ;
# The OID used is the SysUptime OID
my $ buffer = `/usr/bin/snmpget -v 1 -r0 -t$target_timeout -OUevqt -c '$target_community' $addr .1.3.6.1.2.1.1.3.0 2>/dev/null` ;
2011-06-30 18:33:05 +02:00
2010-10-21 11:28:32 +02:00
# Remove forbidden caracters
$ buffer =~ s/\l|\r|\"|\n|\<|\>|\&|\[|\]//g ;
return $ buffer ;
}
##########################################################################
# Process a SNMP requestr and create the module XML
##########################################################################
sub process_module_snmp ($$$$$$$$$) {
2010-11-02 17:43:44 +01:00
my ( $ dbh , $ target_community , $ addr , $ oid , $ type , $ module_name , $ module_type_name , $ module_description , $ conf ) = @ _ ;
2010-10-21 11:28:32 +02:00
my % parameters ;
2010-11-02 17:43:44 +01:00
# Obtain the type id from the type name
$ parameters { 'id_tipo_modulo' } = get_module_id ( $ dbh , $ module_type_name ) ;
$ parameters { 'nombre' } = safe_input ( $ module_name ) ;
2010-10-21 11:28:32 +02:00
$ parameters { 'descripcion' } = $ module_description ;
$ parameters { 'id_agente' } = get_agent_from_addr ( $ dbh , $ addr ) ;
$ parameters { 'ip_target' } = $ addr ;
$ parameters { 'tcp_send' } = 1 ;
$ parameters { 'snmp_community' } = $ target_community ;
$ parameters { 'snmp_oid' } = $ oid ;
2010-11-02 17:43:44 +01:00
2010-10-21 11:28:32 +02:00
# id_modulo = 2 for snmp modules
$ parameters { 'id_modulo' } = 2 ;
2011-06-30 18:33:05 +02:00
my $ module_id = get_agent_module_id ( $ dbh , $ module_name , $ parameters { 'id_agente' } ) ;
2010-10-21 11:28:32 +02:00
2011-06-30 18:33:05 +02:00
if ( $ module_id == - 1 ) {
pandora_create_module_from_hash ( $ conf , \ % parameters , $ dbh ) ;
}
else {
2011-07-07 10:48:38 +02:00
pandora_update_module_from_hash ( $ conf , \ % parameters , 'id_agente_modulo' , $ module_id , $ dbh ) ;
2011-06-30 18:33:05 +02:00
}
2010-10-21 11:28:32 +02:00
}
##########################################################################
##########################################################################
# 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
my $ dbh = db_connect ( 'mysql' , $ conf { 'dbname' } , $ conf { 'dbhost' } , '3306' , $ conf { 'dbuser' } , $ conf { 'dbpass' } ) ;
# 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 SNMP Recon App task" , 1 ) ;
update_recon_task ( $ dbh , $ task_id , - 1 ) ;
return - 1 ;
}
# Scan the network for hosts
my ( $ total_hosts , $ hosts_found , $ addr_found ) = ( $ net_addr - > num , 0 , '' ) ;
2011-07-07 10:48:38 +02:00
my $ last = 0 ;
for ( my $ i = 1 ; $ net_addr <= $ net_addr - > broadcast ; $ i + + , $ net_addr + + ) {
if ( $ last == 1 ) {
last ;
}
if ( $ net_addr eq $ net_addr + + ) {
$ 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 ;
}
}
2010-10-21 11:28:32 +02:00
my $ addr = ( split ( /\// , $ net_addr ) ) [ 0 ] ;
$ hosts_found + + ;
# Update the recon task
update_recon_task ( $ dbh , $ task_id , ceil ( $ i / ($total_hosts / 100 ) ) ) ;
my $ alive = 0 ;
if ( pandora_ping ( \ % conf , $ addr ) == 1 ) {
$ alive = 1 ;
}
next unless ( $ alive > 0 ) ;
# Resolve the address
my $ host_name = gethostbyaddr ( inet_aton ( $ addr ) , AF_INET ) ;
$ host_name = $ addr unless defined ( $ host_name ) ;
2011-06-30 18:33:05 +02:00
#/usr/bin/snmpwalk -OUevqt -c 'public' -v 1 192.168.50.100 SNMPv2-MIB::sysName.0
2010-10-21 11:28:32 +02:00
logger ( \ % conf , "SNMP Recon App found host $host_name." , 10 ) ;
# Add the new address if it does not exist
my $ addr_id = get_addr_id ( $ dbh , $ addr ) ;
my $ resp ;
my $ oid ;
my $ module_type ;
my $ module_description ;
my $ module_name ;
my $ xml = "" ;
my $ ax ; # Counter
my $ conf = \ % conf ;
$ resp = "" ;
# Obtain SNMP response
$ resp = get_snmp_response ( $ target_timeout , $ target_community , $ addr ) ;
# No valid SNMP response.
if ( $ resp eq "" ) {
next ;
}
# Create agent if really has SNMP information
$ addr_id = add_address ( $ dbh , $ addr ) unless ( $ addr_id > 0 ) ;
if ( $ addr_id <= 0 ) {
logger ( \ % conf , "Could not add address '$addr' for host '$host_name'" , 3 ) ;
next ;
}
2011-06-30 18:33:05 +02:00
# Check if the agent exists
my $ agent_id = get_agent_id ( $ dbh , $ host_name ) ;
2010-10-21 11:28:32 +02:00
2011-06-30 18:33:05 +02:00
# 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 ) ;
}
2010-10-21 11:28:32 +02:00
# Assign the new address to the agent
2011-04-13 Ramon Novoa <rnovoa@artica.es>
* lib/PandoraFMS/SNMPServer.pm,
lib/PandoraFMS/Config.pm,
lib/PandoraFMS/NetworkServer.pm,
lib/PandoraFMS/WMIServer.pm,
lib/PandoraFMS/PluginServer.pm,
lib/PandoraFMS/DB.pm,
lib/PandoraFMS/ProducerConsumerServer.pm,
lib/PandoraFMS/PredictionServer.pm,
lib/PandoraFMS/Core.pm,
lib/PandoraFMS/ReconServer.pm,
bin/pandora_server,
util/pandora_db.pl,
util/pandora_manage.pl,
util/recon_scripts/snmpdevices.pl: Adding support for PostgreSQL and
Oracle (not complete).
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@4213 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
2011-04-13 18:28:59 +02:00
db_do ( $ dbh , 'INSERT INTO taddress_agent (`id_a`, `id_agent`) VALUES (?, ?)' , $ addr_id , $ agent_id ) ;
2011-06-30 18:33:05 +02:00
2010-10-21 11:28:32 +02:00
# Generate an event
2011-06-30 18:33:05 +02:00
pandora_event ( \ % conf , "[RECON] New SNMP host [$host_name] detected on network [" . $ target_network . ']' , $ target_group , $ agent_id , 2 , 0 , 0 , 'recon_host_detected' , 0 , $ dbh ) ;
2010-10-21 11:28:32 +02:00
# SysUptime
2010-11-02 17:43:44 +01:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.1.3.0" , "ticks" , "SysUptime" , "remote_snmp_string" , "System uptime reported by SNMP" , $ conf ) ;
2010-10-21 11:28:32 +02:00
# SysName
2010-11-02 17:43:44 +01:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.1.5.0" , "" , "SysName" , "remote_snmp_string" , "System name reported by SNMP" , $ conf ) ;
2010-10-21 11:28:32 +02:00
# Local system total traffic
2010-11-02 17:43:44 +01:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.4.3.0" , "" , "Local InReceives" , "remote_snmp_inc" , "System local incoming traffic (bytes)" , $ conf ) ;
2010-10-21 11:28:32 +02:00
2010-11-02 17:43:44 +01:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.4.10.0" , "" , "Local OutRequests" , "remote_snmp_inc" , "System local outgoing traffic (bytes)" , $ conf ) ;
2010-10-21 11:28:32 +02:00
# Process interface list
2010-12-07 17:43:11 +01:00
# Get interface indexes
2011-03-15 18:43:59 +01:00
my $ interface_indexes = `/usr/bin/snmpwalk -Ouvq -c '$target_community' -v 1 $addr ifIndex 2>/dev/null` ;
2011-06-30 18:33:05 +02:00
2010-12-07 17:43:11 +01:00
my @ ids = split ( "\n" , $ interface_indexes ) ;
2010-10-21 11:28:32 +02:00
2010-12-07 17:43:11 +01:00
foreach my $ ax ( @ ids ) {
2011-06-30 18:33:05 +02:00
my $ oper_status = `/usr/bin/snmpwalk -OUevqt -c '$target_community' -v 1 $addr .1.3.6.1.2.1.2.2.1.8.$ax 2>/dev/null` ;
# If switch_mode is active and the interface is not up, we avoid it
if ( $ all_mode ne '-a' && $ oper_status != 1 ) {
next ;
}
2010-10-21 11:28:32 +02:00
my $ interface = `/usr/bin/snmpget -v 1 -r0 -t$target_timeout -OUevqt -c '$target_community' $addr RFC1213-MIB::ifDescr.$ax 2>/dev/null` ;
2011-06-30 18:33:05 +02:00
my $ ip_address = `/usr/bin/snmpwalk -OnQ -c '$target_community' -v 1 $addr .1.3.6.1.2.1.4.20.1.2 | sed 's/.1.3.6.1.2.1.4.20.1.2.//' | grep "= $ax" | awk '{print \$1}'` ;
if ( $ ip_address eq '' ) {
$ ip_address = 'N/A' ;
}
else {
chomp ( $ ip_address ) ;
$ ip_address =~ s/\n/,/g ;
}
2010-10-21 11:28:32 +02:00
# Remove forbidden caracters
$ interface =~ s/\"|\n|\<|\>|\&|\[|\]//g ;
2011-06-30 18:33:05 +02:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.2.2.1.8.$ax" , "interface" , "$interface Status" , "remote_snmp_proc" , "Operative status for $interface at position $ax. IP Address: $ip_address" , $ conf ) ;
2010-10-21 11:28:32 +02:00
2010-11-02 17:43:44 +01:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.2.2.1.10.$ax" , "" , "$interface Inbound bps" , "remote_snmp_inc" , "Incoming traffic for $interface" , $ conf ) ;
2010-10-21 11:28:32 +02:00
2010-11-02 17:43:44 +01:00
process_module_snmp ( $ dbh , $ target_community , $ addr , ".1.3.6.1.2.1.2.2.1.16.$ax" , "" , "$interface Outbound bps" , "remote_snmp_inc" , "Outgoing traffic for $interface" , $ conf ) ;
2010-10-21 11:28:32 +02:00
# Do a grace sleep to avoid destination server ban me
sleep 1 ;
}
}
# Mark recon task as done
update_recon_task ( $ dbh , $ task_id , - 1 ) ;
# End of code