2017-11-14 15:17:27 +01:00
package PandoraFMS::PluginTools ;
################################################################################
#
# Pandora FMS Plugin functions library
#
# (c) Fco de Borja Sanchez <fborja.sanchez@artica.es>
2017-11-30 17:00:28 +01:00
#
# Requirements:
# Library Centos package
# ------- --------------
# LWP::UserAgent perl-libwww-perl
2017-11-14 15:17:27 +01:00
#
################################################################################
use strict ;
use warnings ;
use LWP::UserAgent ;
use HTTP::Cookies ;
use HTTP::Request::Common ;
2019-01-21 18:06:44 +01:00
use Socket qw( inet_ntoa inet_aton ) ;
2017-11-14 15:17:27 +01:00
use File::Copy ;
use Scalar::Util qw( looks_like_number ) ;
use Time::HiRes qw( time ) ;
2020-01-28 20:15:53 +01:00
eval "use POSIX::strftime::GNU;1" if ( $^O =~ /win/i ) ;
2017-11-14 15:17:27 +01:00
use POSIX qw( strftime setsid floor ) ;
use MIME::Base64 ;
2018-06-18 20:47:58 +02:00
use JSON qw( decode_json encode_json ) ;
2020-07-30 13:20:00 +02:00
use PerlIO::encoding ;
2017-11-14 15:17:27 +01:00
use base 'Exporter' ;
our @ ISA = qw( Exporter ) ;
# version: Defines actual version of Pandora Server for this module only
2021-01-25 11:52:43 +01:00
my $ pandora_version = "7.0NG.752" ;
2021-03-23 01:00:17 +01:00
my $ pandora_build = "210323" ;
2017-11-14 15:17:27 +01:00
our $ VERSION = $ pandora_version . " " . $ pandora_build ;
our % EXPORT_TAGS = ( 'all' = > [ qw( ) ] ) ;
our @ EXPORT_OK = ( @ { $ EXPORT_TAGS { 'all' } } ) ;
our @ EXPORT = qw(
2019-01-21 18:06:44 +01:00
__ip_to_long
__long_to_ip
2017-11-16 14:53:17 +01:00
api_available
2018-05-21 14:42:27 +02:00
api_call
2017-11-16 14:53:17 +01:00
api_create_custom_field
2017-11-14 15:17:27 +01:00
api_create_tag
api_create_group
call_url
2018-06-27 12:21:21 +02:00
check_lib_version
2019-01-17 18:42:38 +01:00
csv_to_obj
2017-11-14 15:17:27 +01:00
decrypt
empty
encrypt
2018-03-02 14:21:01 +01:00
extract_dbpass
2017-11-30 17:00:28 +01:00
extract_key_map
2018-03-05 14:27:51 +01:00
get_addresses
2018-05-22 17:18:11 +02:00
get_current_utime_milis
2017-11-29 13:31:27 +01:00
get_lib_version
2017-11-14 15:17:27 +01:00
get_unit
get_unix_time
get_sys_environment
2018-05-22 17:18:11 +02:00
get_value_translated
2017-11-14 15:17:27 +01:00
getCurrentUTimeMilis
head
in_array
init
is_enabled
2018-06-18 20:47:58 +02:00
join_by_field
2017-11-14 15:17:27 +01:00
load_perl_modules
logger
2019-01-17 18:42:38 +01:00
mask_to_decimal
2017-11-14 15:17:27 +01:00
merge_hashes
parse_arguments
parse_configuration
parse_php_configuration
process_performance
post_url
print_agent
2019-01-17 18:42:38 +01:00
print_discovery_module
2017-11-14 15:17:27 +01:00
print_error
print_execution_result
print_message
print_module
print_warning
print_stderror
2017-11-30 17:00:28 +01:00
read_configuration
2020-04-30 15:19:19 +02:00
read_file
2017-11-14 15:17:27 +01:00
simple_decode_json
snmp_data_switcher
snmp_get
snmp_walk
2018-03-01 09:29:36 +01:00
seconds2readable
2017-11-14 15:17:27 +01:00
tail
to_number
transfer_xml
trim
) ;
2018-03-05 14:27:51 +01:00
# ~ compat
my $ DevNull = ( $^O =~ /win/i ) ? '/NUL' : '/dev/null' ;
2017-11-29 13:31:27 +01:00
################################################################################
2018-06-27 12:21:21 +02:00
# Returns current library version
2017-11-29 13:31:27 +01:00
################################################################################
sub get_lib_version {
return $ VERSION ;
}
2018-06-27 12:21:21 +02:00
################################################################################
# Check version compatibility
################################################################################
sub check_lib_version {
my ( $ plugin_version ) = @ _ ;
$ plugin_version = "0NG.0" if empty ( $ plugin_version ) ;
my ( $ main , $ oum ) = split /NG./ , $ plugin_version ;
$ main = 0 if empty ( $ main ) || ! looks_like_number ( $ main ) ;
$ oum = 0 if empty ( $ oum ) || ! looks_like_number ( $ oum ) ;
my ( $ libmain , $ liboum ) = split /NG./ , $ pandora_version ;
if ( ( $ liboum < $ oum )
|| ( $ libmain != $ main ) ) {
return 0 ;
}
return 1 ;
}
2017-11-14 15:17:27 +01:00
2019-01-21 18:06:44 +01:00
###############################################################################
# Returns IP address(v4) in longint format
###############################################################################
sub __ip_to_long {
my $ ip_str = shift ;
return unpack "N" , inet_aton ( $ ip_str ) ;
}
###############################################################################
# Returns IP address(v4) in longint format
###############################################################################
sub __long_to_ip {
my $ ip_long = shift ;
return inet_ntoa pack ( "N" , ( $ ip_long ) ) ;
}
2019-01-17 18:42:38 +01:00
################################################################################
# Convert CSV string to hash
################################################################################
sub csv_to_obj {
my ( $ csv ) = @ _ ;
my @ ahr ;
my @ lines = split /\n/ , $ csv ;
return [] unless $# lines >= 0 ;
# scan headers
my @ hr_headers = split /,/ , shift @ lines ;
# Clean \n\r
@ hr_headers = map { $ _ =~ s/\"//g ; trim ( $ _ ) ; } @ hr_headers ;
foreach my $ line ( @ lines ) {
2019-02-04 19:32:54 +01:00
next if empty ( $ line ) ;
2019-01-17 18:42:38 +01:00
my $ i = 0 ;
my % hr = map { $ _ =~ s/\"//g ; $ hr_headers [ $ i + + ] = > trim ( $ _ ) } split /,/ , $ line ;
push @ ahr , \ % hr ;
}
return \ @ ahr ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# Get current time (milis)
################################################################################
2018-01-26 15:18:06 +01:00
sub get_current_utime_milis { return getCurrentUTimeMilis ( ) ; }
2017-11-27 18:19:32 +01:00
sub getCurrentUTimeMilis {
2017-11-14 15:17:27 +01:00
#return trim (`date +"%s%3N"`); # returns 1449681679712
return floor ( time * 1000 ) ;
}
2019-01-17 18:42:38 +01:00
################################################################################
# Mask to decimal
################################################################################
sub mask_to_decimal {
my $ mask = shift ;
my ( $ a , $ b , $ c , $ d ) = $ mask =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ ;
$ a = sprintf "%08b" , $ a ;
$ b = sprintf "%08b" , $ b ;
$ c = sprintf "%08b" , $ c ;
$ d = sprintf "%08b" , $ d ;
my $ str = $ a . $ b . $ c . $ d ;
$ str =~ s/0.*$// ;
return length ( $ str ) ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# Mix hashses
################################################################################
sub merge_hashes {
my $ _h1 = shift ;
my $ _h2 = shift ;
2017-11-29 18:27:31 +01:00
if ( ref ( $ _h1 ) ne "HASH" ) {
return \ % { $ _h2 } if ( ref ( $ _h2 ) eq "HASH" ) ;
}
if ( ref ( $ _h2 ) ne "HASH" ) {
return \ % { $ _h1 } if ( ref ( $ _h1 ) eq "HASH" ) ;
}
if ( ( ref ( $ _h1 ) ne "HASH" ) && ( ref ( $ _h2 ) ne "HASH" ) ) {
return { } ;
}
2017-11-14 15:17:27 +01:00
my % ret = ( % { $ _h1 } , % { $ _h2 } ) ;
return \ % ret ;
}
################################################################################
# Regex based tail command
################################################################################
2017-11-27 18:19:32 +01:00
sub tail {
2017-11-14 15:17:27 +01:00
my $ string = shift ;
my $ n = shift ;
my $ reverse_flag = shift ;
my $ nlines = $ string =~ tr /\n/ / ;
if ( empty ( $ string ) ) {
return "" ;
}
if ( defined ( $ reverse_flag ) ) {
$ n = $ n - 1 ;
}
else {
$ n = $ nlines - $ n ;
}
$ string =~ s/^(?:.*\n){0,$n}// ;
return $ string ;
}
################################################################################
# Regex based head command
################################################################################
2017-11-27 18:19:32 +01:00
sub head {
2017-11-14 15:17:27 +01:00
my $ string = shift ;
my $ n = shift ;
my $ reverse_flag = shift ;
my $ nlines = $ string =~ tr /\n/ / ;
if ( empty ( $ string ) ) {
return "" ;
}
if ( defined ( $ reverse_flag ) ) {
$ n = $ nlines - $ n + 1 ;
}
my $ str = "" ;
my @ lines = split /\n/ , $ string ;
for ( my $ x = 0 ; $ x < $ n ; $ x + + ) {
$ str . = $ lines [ $ x ] . "\n" ;
}
return $ str ;
}
################################################################################
# Check if a given variable contents a number
################################################################################
2017-11-27 18:19:32 +01:00
sub to_number {
2017-11-14 15:17:27 +01:00
my $ n = shift ;
if ( empty ( $ n ) ) {
return undef ;
}
if ( $ n =~ /[\d+,]*\d+\.\d+/ ) {
# American notation
$ n =~ s/,//g ;
}
elsif ( $ n =~ /[\d+\.]*\d+,\d+/ ) {
# Spanish notation
$ n =~ s/\.//g ;
$ n =~ s/,/./g ;
}
if ( looks_like_number ( $ n ) ) {
return $ n ;
}
return undef ;
}
################################################################################
# Erase blank spaces before and after the string
################################################################################
2017-11-27 18:19:32 +01:00
sub trim {
2017-11-14 15:17:27 +01:00
my $ string = shift ;
if ( empty ( $ string ) ) {
return "" ;
}
$ string =~ s/\r//g ;
chomp ( $ string ) ;
$ string =~ s/^\s+//g ;
$ string =~ s/\s+$//g ;
return $ string ;
}
################################################################################
# Empty
################################################################################
2017-11-27 18:19:32 +01:00
sub empty {
2017-11-14 15:17:27 +01:00
my $ str = shift ;
if ( ! ( defined ( $ str ) ) ) {
return 1 ;
}
if ( looks_like_number ( $ str ) ) {
return 0 ;
}
if ( ref ( $ str ) eq "ARRAY" ) {
return ( ( $# { $ str } < 0 ) ? 1 : 0 ) ;
}
if ( ref ( $ str ) eq "HASH" ) {
my @ tmp = keys % { $ str } ;
return ( ( $# tmp < 0 ) ? 1 : 0 ) ;
}
if ( $ str =~ /^\ *[\n\r]{0,2}\ *$/ ) {
return 1 ;
}
return 0 ;
}
2017-11-30 17:00:28 +01:00
################################################################################
# Assing a value to a string key as subkeys in a hash map
################################################################################
sub extract_key_map ;
sub extract_key_map {
my ( $ hash , $ string , $ value ) = @ _ ;
my ( $ key , $ str ) = split /\./ , $ string , 2 ;
if ( empty ( $ str ) ) {
$ hash - > { $ key } = $ value ;
return $ hash ;
}
$ hash - > { $ key } = extract_key_map ( $ hash - > { $ key } , $ str , $ value ) ;
return $ hash ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# Check if a value is in an array
################################################################################
2017-11-27 18:19:32 +01:00
sub in_array {
2017-11-14 15:17:27 +01:00
my ( $ array , $ value ) = @ _ ;
if ( empty ( $ value ) ) {
return 0 ;
}
my % params = map { $ _ = > 1 } @ { $ array } ;
if ( exists ( $ params { $ value } ) ) {
return 1 ;
}
return 0 ;
}
################################################################################
# Get unit
################################################################################
2017-11-27 18:19:32 +01:00
sub get_unit {
2017-11-14 15:17:27 +01:00
my $ str = shift ;
$ str =~ s/[\d\.\,]//g ;
return $ str ;
}
2018-05-22 17:18:11 +02:00
################################################################################
# Get unit
################################################################################
sub get_value_translated {
my $ str = shift ;
if ( empty ( $ str ) ) {
return $ str ;
}
$ str = trim ( $ str ) ;
my $ value = $ str ;
my $ unit = get_unit ( $ str ) ;
if ( empty ( $ unit ) ) {
return $ str ;
}
$ value =~ s/$unit//g ;
if ( $ unit =~ /kb/i ) { return $ value * ( 2 ** 10 ) ; }
if ( $ unit =~ /kib/i ) { return $ value * ( 2 ** 10 ) ; }
if ( $ unit =~ /mb/i ) { return $ value * ( 2 ** 20 ) ; }
if ( $ unit =~ /mib/i ) { return $ value * ( 2 ** 20 ) ; }
if ( $ unit =~ /gb/i ) { return $ value * ( 2 ** 30 ) ; }
if ( $ unit =~ /gib/i ) { return $ value * ( 2 ** 30 ) ; }
if ( $ unit =~ /tb/i ) { return $ value * ( 2 ** 40 ) ; }
return $ value ;
}
2017-11-14 15:17:27 +01:00
################################################################################
## Decodes a json strin into an hash
################################################################################
2017-11-27 18:19:32 +01:00
sub simple_decode_json ;
sub simple_decode_json {
2017-11-14 15:17:27 +01:00
my $ json = shift ;
my $ hash_reference ;
if ( empty ( $ json ) ) {
return undef ;
}
if ( $ json =~ /^\".*\"\:\{.*}$/ ) { # key => tree
my @ data = split /:/ , $ json , 2 ;
# data[0] it's key, remove "
$ data [ 0 ] =~ s/^\"// ;
$ data [ 0 ] =~ s/\"$// ;
$ hash_reference - > { $ data [ 0 ] } = simple_decode_json ( $ data [ 1 ] ) ;
return $ hash_reference ;
}
if ( $ json =~ /^\{(.*)\}$/ ) { # parse tree
$ hash_reference = simple_decode_json ( $ 1 ) ;
return $ hash_reference ;
}
if ( $ json =~ /^(\".*[\"|\}]),(\".*[\"|\}])/ ) { # multi keys
my @ data = split /,/ , $ json , 2 ;
if ( $ data [ 0 ] =~ /{/ ) {
@ data = split /},/ , $ json , 2 ;
$ data [ 0 ] . = "}" ;
}
my $ left_tree ;
my $ right_tree ;
$ left_tree = simple_decode_json ( $ data [ 0 ] ) ;
$ right_tree = simple_decode_json ( $ data [ 1 ] ) ;
# join both sides
foreach ( keys % { $ left_tree } ) {
$ hash_reference - > { $ _ } = $ left_tree - > { $ _ } ;
}
foreach ( keys % { $ right_tree } ) {
$ hash_reference - > { $ _ } = $ right_tree - > { $ _ } ;
}
return $ hash_reference ;
}
if ( $ json =~ /^\"(.*)\"\:(\".*\")$/ ) { # return key => value
$ hash_reference - > { $ 1 } = simple_decode_json ( $ 2 ) ;
return $ hash_reference ;
}
if ( $ json =~ /^"(.*)"$/ ) {
return $ 1 ;
}
return $ hash_reference ;
}
################################################################################
# print_agent
################################################################################
sub print_agent {
my ( $ config , $ agent_data , $ modules_def , $ str_flag ) = @ _ ;
my $ xml = "<?xml version='1.0' encoding='UTF-8'?>\n" ;
# print header
$ xml . = "<agent_data " ;
2021-01-07 16:37:13 +01:00
my $ group_password_specified = 0 ;
2017-11-14 15:17:27 +01:00
foreach my $ kad ( keys % { $ agent_data } ) {
no warnings "uninitialized" ;
$ xml . = $ kad . "='" ;
$ xml . = $ agent_data - > { $ kad } . "' " ;
2021-01-07 16:37:13 +01:00
if ( $ kad eq 'group_password' ) {
$ group_password_specified = 1 ;
}
}
if ( $ group_password_specified == 0 && ! empty ( $ config - > { 'group_password' } ) ) {
$ xml . = " group_password='" . $ config - > { 'group_password' } . "' " ;
2017-11-14 15:17:27 +01:00
}
$ xml . = ">" ;
2019-01-17 18:42:38 +01:00
if ( ref ( $ modules_def ) eq "ARRAY" ) {
foreach my $ module ( @ { $ modules_def } ) {
2019-01-21 18:06:44 +01:00
if ( ref ( $ module ) eq "HASH" && ( defined $ module - > { 'name' } ) ) {
$ xml . = print_module ( $ config , $ module , 1 ) ;
} elsif ( ref ( $ module ) eq "HASH" && ( defined $ module - > { 'discovery' } ) ) {
$ xml . = print_discovery_module ( $ config , $ module , 1 ) ;
}
2019-01-17 18:42:38 +01:00
}
} elsif ( ref ( $ modules_def ) eq "HASH" && ( defined $ modules_def - > { 'name' } ) ) {
$ xml . = print_module ( $ config , $ modules_def , 1 ) ;
} elsif ( ref ( $ modules_def ) eq "HASH" && ( defined $ modules_def - > { 'discovery' } ) ) {
$ xml . = print_discovery_module ( $ config , $ modules_def , 1 ) ;
2017-11-14 15:17:27 +01:00
}
# print tail
$ xml . = "</agent_data>\n" ;
if ( is_enabled ( $ str_flag ) ) {
print $ xml ;
}
return $ xml ;
}
2019-01-17 18:42:38 +01:00
################################################################################
# print_module
################################################################################
sub print_discovery_module {
my ( $ conf , $ global_data , $ not_print_flag ) = @ _ ;
return undef if ( ref ( $ global_data ) ne "HASH" || ! defined ( $ global_data - > { 'discovery' } ) ) ;
return "" if empty ( $ global_data ) ;
my $ data = $ global_data - > { 'discovery' } ;
my $ xml_module = "<discovery><![CDATA[" ;
$ xml_module . = encode_base64 ( encode_json ( $ data ) ) ;
$ xml_module . = "]]></discovery>\n" ;
if ( empty ( $ not_print_flag ) ) {
print $ xml_module ;
}
return $ xml_module ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# print_module
################################################################################
sub print_module {
2018-07-18 17:56:35 +02:00
my ( $ conf , $ data , $ not_print_flag ) = @ _ ;
2017-11-14 15:17:27 +01:00
if ( ( ref ( $ data ) ne "HASH" ) || ( ! defined $ data - > { name } ) ) {
return undef ;
}
my $ xml_module = "" ;
# If not a string type, remove all blank spaces!
if ( $ data - > { type } !~ m/string/ ) {
$ data - > { value } = trim ( $ data - > { value } ) ;
}
2018-04-03 17:12:31 +02:00
$ data - > { value } = '' if empty ( $ data - > { value } ) ;
2018-07-18 17:56:35 +02:00
$ data - > { tags } = ( $ data - > { tags } ?
$ data - > { tags } : ( $ conf - > { MODULE_TAG_LIST } ?
$ conf - > { MODULE_TAG_LIST } : ( $ conf - > { module_tag_list } ?
$ conf - > { module_tag_list } : undef ) ) ) ;
$ data - > { interval } = ( $ data - > { interval } ?
$ data - > { interval } : ( $ conf - > { MODULE_INTERVAL } ?
$ conf - > { MODULE_INTERVAL } : ( $ conf - > { module_interval } ?
$ conf - > { module_interval } : undef ) ) ) ;
$ data - > { module_group } = ( $ data - > { module_group } ?
$ data - > { module_group } : ( $ conf - > { MODULE_GROUP } ?
$ conf - > { MODULE_GROUP } : ( $ conf - > { module_group } ?
$ conf - > { module_group } : undef ) ) ) ;
2018-04-03 17:12:31 +02:00
2017-11-14 15:17:27 +01:00
# Global instructions (if defined)
$ data - > { unknown_instructions } = $ conf - > { unknown_instructions } unless ( defined ( $ data - > { unknown_instructions } ) || ( ! defined ( $ conf - > { unknown_instructions } ) ) ) ;
$ data - > { warning_instructions } = $ conf - > { warning_instructions } unless ( defined ( $ data - > { warning_instructions } ) || ( ! defined ( $ conf - > { warning_instructions } ) ) ) ;
$ data - > { critical_instructions } = $ conf - > { critical_instructions } unless ( defined ( $ data - > { critical_instructions } ) || ( ! defined ( $ conf - > { critical_instructions } ) ) ) ;
2018-03-05 14:27:51 +01:00
# Translation compatibility
$ data - > { 'min_warning' } = $ data - > { 'wmin' } if empty ( $ data - > { 'min_warning' } ) ;
$ data - > { 'max_warning' } = $ data - > { 'wmax' } if empty ( $ data - > { 'max_warning' } ) ;
$ data - > { 'min_critical' } = $ data - > { 'cmin' } if empty ( $ data - > { 'min_critical' } ) ;
$ data - > { 'max_critical' } = $ data - > { 'cmax' } if empty ( $ data - > { 'max_critical' } ) ;
$ data - > { 'warning_inverse' } = $ data - > { 'winv' } if empty ( $ data - > { 'warning_inverse' } ) ;
$ data - > { 'critical_inverse' } = $ data - > { 'cinv' } if empty ( $ data - > { 'critical_inverse' } ) ;
$ data - > { 'str_warning' } = $ data - > { 'wstr' } if empty ( $ data - > { 'str_warning' } ) ;
$ data - > { 'str_critical' } = $ data - > { 'cstr' } if empty ( $ data - > { 'str_critical' } ) ;
2017-11-14 15:17:27 +01:00
$ xml_module . = "<module>\n" ;
$ xml_module . = "\t<name><![CDATA[" . $ data - > { name } . "]]></name>\n" ;
$ xml_module . = "\t<type>" . $ data - > { type } . "</type>\n" ;
if ( ref ( $ data - > { value } ) eq "ARRAY" ) {
$ xml_module . = "\t<datalist>\n" ;
foreach ( @ { $ data - > { value } } ) {
2018-02-01 13:59:22 +01:00
if ( ( ref ( $ _ ) eq "HASH" ) && defined ( $ _ - > { value } ) ) {
$ xml_module . = "\t<data>\n" ;
$ xml_module . = "\t\t<value><![CDATA[" . $ _ - > { value } . "]]></value>\n" ;
if ( defined ( $ _ - > { timestamp } ) ) {
$ xml_module . = "\t\t<timestamp><![CDATA[" . $ _ - > { timestamp } . "]]></timestamp>\n" ;
}
$ xml_module . = "\t</data>\n" ;
}
2017-11-14 15:17:27 +01:00
}
$ xml_module . = "\t</datalist>\n" ;
}
else {
$ xml_module . = "\t<data><![CDATA[" . $ data - > { value } . "]]></data>\n" ;
}
if ( ! ( empty ( $ data - > { desc } ) ) ) {
$ xml_module . = "\t<description><![CDATA[" . $ data - > { desc } . "]]></description>\n" ;
}
if ( ! ( empty ( $ data - > { unit } ) ) ) {
$ xml_module . = "\t<unit><![CDATA[" . $ data - > { unit } . "]]></unit>\n" ;
}
if ( ! ( empty ( $ data - > { interval } ) ) ) {
$ xml_module . = "\t<module_interval><![CDATA[" . $ data - > { interval } . "]]></module_interval>\n" ;
}
if ( ! ( empty ( $ data - > { tags } ) ) ) {
$ xml_module . = "\t<tags>" . $ data - > { tags } . "</tags>\n" ;
}
if ( ! ( empty ( $ data - > { module_group } ) ) ) {
$ xml_module . = "\t<module_group>" . $ data - > { module_group } . "</module_group>\n" ;
}
if ( ! ( empty ( $ data - > { module_parent } ) ) ) {
$ xml_module . = "\t<module_parent>" . $ data - > { module_parent } . "</module_parent>\n" ;
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { min_warning } ) ) ) {
$ xml_module . = "\t<min_warning><![CDATA[" . $ data - > { min_warning } . "]]></min_warning>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { max_warning } ) ) ) {
$ xml_module . = "\t<max_warning><![CDATA[" . $ data - > { max_warning } . "]]></max_warning>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { min_critical } ) ) ) {
$ xml_module . = "\t<min_critical><![CDATA[" . $ data - > { min_critical } . "]]></min_critical>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { max_critical } ) ) ) {
$ xml_module . = "\t<max_critical><![CDATA[" . $ data - > { max_critical } . "]]></max_critical>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { str_warning } ) ) ) {
$ xml_module . = "\t<str_warning><![CDATA[" . $ data - > { str_warning } . "]]></str_warning>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { str_critical } ) ) ) {
$ xml_module . = "\t<str_critical><![CDATA[" . $ data - > { str_critical } . "]]></str_critical>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { critical_inverse } ) ) ) {
$ xml_module . = "\t<critical_inverse><![CDATA[" . $ data - > { critical_inverse } . "]]></critical_inverse>\n" ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( ! ( empty ( $ data - > { warning_inverse } ) ) ) {
$ xml_module . = "\t<warning_inverse><![CDATA[" . $ data - > { warning_inverse } . "]]></warning_inverse>\n" ;
2017-11-14 15:17:27 +01:00
}
2020-09-09 12:34:51 +02:00
if ( ! ( empty ( $ data - > { min_warning_forced } ) ) ) {
2020-06-17 13:17:22 +02:00
$ xml_module . = "\t<min_warning_forced><![CDATA[" . $ data - > { min_warning_forced } . "]]></min_warning_forced>\n" ;
}
2020-09-09 12:34:51 +02:00
if ( ! ( empty ( $ data - > { max_warning_forced } ) ) ) {
2020-06-17 13:17:22 +02:00
$ xml_module . = "\t<max_warning_forced><![CDATA[" . $ data - > { max_warning_forced } . "]]></max_warning_forced>\n" ;
}
2020-09-09 12:34:51 +02:00
if ( ! ( empty ( $ data - > { min_critical_forced } ) ) ) {
2020-06-17 13:17:22 +02:00
$ xml_module . = "\t<min_critical_forced><![CDATA[" . $ data - > { min_critical_forced } . "]]></min_critical_forced>\n" ;
}
2020-09-09 12:34:51 +02:00
if ( ! ( empty ( $ data - > { max_critical_forced } ) ) ) {
2020-06-17 13:17:22 +02:00
$ xml_module . = "\t<max_critical_forced><![CDATA[" . $ data - > { max_critical_forced } . "]]></max_critical_forced>\n" ;
}
2020-09-09 12:34:51 +02:00
if ( ! ( empty ( $ data - > { str_warning_forced } ) ) ) {
2020-06-17 13:17:22 +02:00
$ xml_module . = "\t<str_warning_forced><![CDATA[" . $ data - > { str_warning_forced } . "]]></str_warning_forced>\n" ;
}
2020-09-09 12:34:51 +02:00
if ( ! ( empty ( $ data - > { str_critical_forced } ) ) ) {
2020-06-17 13:17:22 +02:00
$ xml_module . = "\t<str_critical_forced><![CDATA[" . $ data - > { str_critical_forced } . "]]></str_critical_forced>\n" ;
}
2017-11-14 15:17:27 +01:00
if ( ! ( empty ( $ data - > { max } ) ) ) {
$ xml_module . = "\t<max><![CDATA[" . $ data - > { max } . "]]></max>\n" ;
}
if ( ! ( empty ( $ data - > { min } ) ) ) {
$ xml_module . = "\t<min><![CDATA[" . $ data - > { min } . "]]></min>\n" ;
}
if ( ! ( empty ( $ data - > { post_process } ) ) ) {
$ xml_module . = "\t<post_process><![CDATA[" . $ data - > { post_process } . "]]></post_process>\n" ;
}
if ( ! ( empty ( $ data - > { disabled } ) ) ) {
$ xml_module . = "\t<disabled><![CDATA[" . $ data - > { disabled } . "]]></disabled>\n" ;
}
if ( ! ( empty ( $ data - > { min_ff_event } ) ) ) {
$ xml_module . = "\t<min_ff_event><![CDATA[" . $ data - > { min_ff_event } . "]]></min_ff_event>\n" ;
}
if ( ! ( empty ( $ data - > { status } ) ) ) {
$ xml_module . = "\t<status><![CDATA[" . $ data - > { status } . "]]></status>\n" ;
}
if ( ! ( empty ( $ data - > { timestamp } ) ) ) {
$ xml_module . = "\t<timestamp><![CDATA[" . $ data - > { timestamp } . "]]></timestamp>\n" ;
}
if ( ! ( empty ( $ data - > { custom_id } ) ) ) {
$ xml_module . = "\t<custom_id><![CDATA[" . $ data - > { custom_id } . "]]></custom_id>\n" ;
}
if ( ! ( empty ( $ data - > { critical_instructions } ) ) ) {
$ xml_module . = "\t<critical_instructions><![CDATA[" . $ data - > { critical_instructions } . "]]></critical_instructions>\n" ;
}
if ( ! ( empty ( $ data - > { warning_instructions } ) ) ) {
$ xml_module . = "\t<warning_instructions><![CDATA[" . $ data - > { warning_instructions } . "]]></warning_instructions>\n" ;
}
if ( ! ( empty ( $ data - > { unknown_instructions } ) ) ) {
$ xml_module . = "\t<unknown_instructions><![CDATA[" . $ data - > { unknown_instructions } . "]]></unknown_instructions>\n" ;
}
if ( ! ( empty ( $ data - > { quiet } ) ) ) {
$ xml_module . = "\t<quiet><![CDATA[" . $ data - > { quiet } . "]]></quiet>\n" ;
}
if ( ! ( empty ( $ data - > { module_ff_interval } ) ) ) {
$ xml_module . = "\t<module_ff_interval><![CDATA[" . $ data - > { module_ff_interval } . "]]></module_ff_interval>\n" ;
}
if ( ! ( empty ( $ data - > { crontab } ) ) ) {
$ xml_module . = "\t<crontab><![CDATA[" . $ data - > { crontab } . "]]></crontab>\n" ;
}
if ( ! ( empty ( $ data - > { min_ff_event_normal } ) ) ) {
$ xml_module . = "\t<min_ff_event_normal><![CDATA[" . $ data - > { min_ff_event_normal } . "]]></min_ff_event_normal>\n" ;
}
if ( ! ( empty ( $ data - > { min_ff_event_warning } ) ) ) {
$ xml_module . = "\t<min_ff_event_warning><![CDATA[" . $ data - > { min_ff_event_warning } . "]]></min_ff_event_warning>\n" ;
}
if ( ! ( empty ( $ data - > { min_ff_event_critical } ) ) ) {
$ xml_module . = "\t<min_ff_event_critical><![CDATA[" . $ data - > { min_ff_event_critical } . "]]></min_ff_event_critical>\n" ;
}
2019-03-29 14:59:31 +01:00
if ( ! ( empty ( $ data - > { ff_type } ) ) ) {
$ xml_module . = "\t<ff_type><![CDATA[" . $ data - > { ff_type } . "]]></ff_type>\n" ;
}
2017-11-14 15:17:27 +01:00
if ( ! ( empty ( $ data - > { ff_timeout } ) ) ) {
$ xml_module . = "\t<ff_timeout><![CDATA[" . $ data - > { ff_timeout } . "]]></ff_timeout>\n" ;
}
if ( ! ( empty ( $ data - > { each_ff } ) ) ) {
$ xml_module . = "\t<each_ff><![CDATA[" . $ data - > { each_ff } . "]]></each_ff>\n" ;
}
if ( ! ( empty ( $ data - > { parent_unlink } ) ) ) {
$ xml_module . = "\t<module_parent_unlink><![CDATA[" . $ data - > { parent_unlink } . "]]></module_parent_unlink>\n" ;
}
if ( ! ( empty ( $ data - > { alerts } ) ) ) {
foreach my $ alert ( @ { $ data - > { alerts } } ) {
$ xml_module . = "\t<alert_template><![CDATA[" . $ alert . "]]></alert_template>\n" ;
}
}
if ( defined ( $ conf - > { global_alerts } ) ) {
foreach my $ alert ( @ { $ conf - > { global_alerts } } ) {
$ xml_module . = "\t<alert_template><![CDATA[" . $ alert . "]]></alert_template>\n" ;
}
}
$ xml_module . = "</module>\n" ;
if ( empty ( $ not_print_flag ) ) {
print $ xml_module ;
}
return $ xml_module ;
}
################################################################################
# transfer_xml
################################################################################
2017-11-27 18:19:32 +01:00
sub transfer_xml {
2017-11-14 15:17:27 +01:00
my ( $ conf , $ xml , $ name ) = @ _ ;
my $ file_name ;
my $ file_path ;
if ( ! ( empty ( $ name ) ) ) {
2019-10-16 13:40:46 +02:00
$ file_name = $ name . "." . sprintf ( "%d" , getCurrentUTimeMilis ( ) . ( rand ( ) * 10000 ) ) . ".data" ;
2017-11-14 15:17:27 +01:00
}
else {
# Inherit file name
( $ file_name ) = $ xml =~ /\s+agent_name='(.*?)'\s+.*$/m ;
if ( empty ( $ file_name ) ) {
( $ file_name ) = $ xml =~ /\s+agent_name="(.*?)"\s+.*$/m ;
}
if ( empty ( $ file_name ) ) {
$ file_name = trim ( `hostname` ) ;
}
2019-01-17 18:42:38 +01:00
$ file_name . = "." . sprintf ( "%d" , time ( ) ) . ".data" ;
2017-11-14 15:17:27 +01:00
}
2018-04-03 17:14:11 +02:00
logger ( $ conf , "transfer_xml" , "Failed to generate file name." ) if empty ( $ file_name ) ;
2018-04-03 09:46:44 +02:00
$ conf - > { temp } = $ conf - > { tmp } if ( empty ( $ conf - > { temp } ) && defined ( $ conf - > { tmp } ) ) ;
$ conf - > { temp } = $ conf - > { temporal } if ( empty ( $ conf - > { temp } ) && defined ( $ conf - > { temporal } ) ) ;
$ conf - > { temp } = $ conf - > { __system } - > { tmp } if ( empty ( $ conf - > { temp } ) && defined ( $ conf - > { __system } ) ) && ( ref ( $ conf - > { __system } ) eq "HASH" ) ;
2019-01-17 18:42:38 +01:00
$ conf - > { temp } = $ ENV { 'TMP' } if empty ( $ conf - > { temp } ) && $^O =~ /win/i ;
$ conf - > { temp } = '/tmp' if empty ( $ conf - > { temp } ) && $^O =~ /lin/i ;
2018-03-05 14:27:51 +01:00
2017-11-14 15:17:27 +01:00
$ file_path = $ conf - > { temp } . "/" . $ file_name ;
#Creating XML file in temp directory
if ( - e $ file_path ) {
sleep ( 1 ) ;
2019-01-17 18:42:38 +01:00
$ file_name = $ name . "." . sprintf ( "%d" , time ( ) ) . ".data" ;
2017-11-14 15:17:27 +01:00
$ file_path = $ conf - > { temp } . "/" . $ file_name ;
}
2018-03-05 14:27:51 +01:00
my $ r = open ( my $ FD , ">>" , $ file_path ) ;
if ( empty ( $ r ) ) {
print_stderror ( $ conf , "Cannot write to [" . $ file_path . "]" , $ conf - > { 'debug' } ) ;
return undef ;
}
2017-11-14 15:17:27 +01:00
my $ bin_opts = ':raw:encoding(UTF8)' ;
if ( $^O eq "Windows" ) {
$ bin_opts . = ':crlf' ;
}
2018-03-05 14:27:51 +01:00
binmode ( $ FD , $ bin_opts ) ;
2017-11-14 15:17:27 +01:00
2018-03-05 14:27:51 +01:00
print $ FD $ xml ;
2017-11-14 15:17:27 +01:00
2018-03-05 14:27:51 +01:00
close ( $ FD ) ;
2017-11-14 15:17:27 +01:00
2018-01-10 10:19:46 +01:00
# Reassign default values if not present
$ conf - > { tentacle_client } = "tentacle_client" if empty ( $ conf - > { tentacle_client } ) ;
2018-06-27 18:54:35 +02:00
$ conf - > { tentacle_port } = "41121" if empty ( $ conf - > { tentacle_port } ) ;
$ conf - > { tentacle_opts } = "" if empty ( $ conf - > { tentacle_opts } ) ;
2017-11-29 19:48:15 +01:00
$ conf - > { mode } = $ conf - > { transfer_mode } if empty ( $ conf - > { mode } ) ;
2018-01-10 10:19:46 +01:00
2017-11-29 19:48:15 +01:00
if ( empty ( $ conf - > { mode } ) ) {
print_stderror ( $ conf , "[ERROR] Nor \"mode\" nor \"transfer_mode\" defined in configuration." ) ;
2017-11-27 18:19:32 +01:00
return undef ;
}
2017-11-14 15:17:27 +01:00
#Transfering XML file
if ( $ conf - > { mode } eq "tentacle" ) {
2018-06-27 18:54:35 +02:00
my $ msg = "" ;
my $ r = - 1 ;
2017-11-14 15:17:27 +01:00
#Send using tentacle
if ( $^O =~ /win/i ) {
2018-06-27 18:54:35 +02:00
$ msg = `$conf->{tentacle_client} -v -a $conf->{tentacle_ip} -p $conf->{tentacle_port} $conf->{tentacle_opts} "$file_path"` ;
$ r = $? ;
2017-11-14 15:17:27 +01:00
}
else {
2018-06-27 18:54:35 +02:00
$ msg = `$conf->{tentacle_client} -v -a $conf->{tentacle_ip} -p $conf->{tentacle_port} $conf->{tentacle_opts} "$file_path" 2>&1` ;
$ r = $? ;
2017-11-14 15:17:27 +01:00
}
#If no errors were detected delete file
2018-06-27 18:54:35 +02:00
if ( $ r == 0 ) {
2017-11-14 15:17:27 +01:00
unlink ( $ file_path ) ;
2018-06-27 18:54:35 +02:00
}
2017-11-14 15:17:27 +01:00
else {
2018-06-27 18:54:35 +02:00
print_stderror ( $ conf , trim ( $ msg ) . " File [$file_path]" ) ;
return undef ;
}
}
else {
2017-11-14 15:17:27 +01:00
#Copy file to local folder
my $ dest_dir = $ conf - > { local_folder } ;
my $ rc = copy ( $ file_path , $ dest_dir ) ;
#If there was no error, delete file
if ( $ rc == 0 ) {
2017-11-29 19:48:15 +01:00
print_stderror ( $ conf , "[ERROR] There was a problem copying local file to $dest_dir: $!" ) ;
2017-11-14 15:17:27 +01:00
return undef ;
}
else {
unlink ( $ file_path ) ;
}
}
return 1 ;
}
################################################################################
# Plugin mesage as module
################################################################################
sub print_message {
my ( $ conf , $ data ) = @ _ ;
if ( is_enabled ( $ conf - > { 'as_server_plugin' } ) ) {
print $ data - > { value } ;
}
else { # as agent plugin
print_module ( $ conf , $ data ) ;
}
}
################################################################################
# Module warning
# - tag: name
# - value: severity (default 0)
# - msg: description of the message
################################################################################
sub print_warning {
my ( $ conf , $ tag , $ msg , $ value ) = @ _ ;
if ( ! ( is_enabled ( $ conf - > { informational_modules } ) ) ) {
return 0 ;
}
print_module ( $ conf , {
name = > "Plugin message" . ( $ tag ? " " . $ tag: "" ) ,
type = > "generic_data" ,
value = > ( defined ( $ value ) ? $ value:0 ) ,
desc = > $ msg ,
wmin = > 1 ,
cmin = > 3 ,
} ) ;
}
################################################################################
# Plugin mesage as module
################################################################################
sub print_execution_result {
my ( $ conf , $ msg , $ value ) = @ _ ;
if ( ! ( is_enabled ( $ conf - > { informational_modules } ) ) ) {
return 0 ;
}
print_module ( $ conf , {
2018-04-03 09:46:44 +02:00
name = > "Plugin execution result " . $ 0 ,
2017-11-14 15:17:27 +01:00
type = > "generic_proc" ,
value = > ( defined ( $ value ) ? $ value:0 ) ,
desc = > $ msg ,
} ) ;
}
################################################################################
## Plugin devolution in case of error
################################################################################
sub print_error {
2018-04-03 09:46:44 +02:00
my ( $ conf , $ msg , $ value , $ always_show ) = @ _ ;
2018-03-05 14:27:51 +01:00
$ value = 0 unless defined ( $ value ) ;
2017-11-14 15:17:27 +01:00
2018-04-03 09:46:44 +02:00
if ( ! ( is_enabled ( $ conf - > { informational_modules } ) || is_enabled ( $ always_show ) ) ) {
exit 1 ;
2017-11-14 15:17:27 +01:00
}
2018-03-05 14:27:51 +01:00
if ( is_enabled ( $ conf - > { 'as_server_plugin' } ) ) {
print STDERR $ msg . "\n" ;
print $ value . "\n" ;
2021-02-05 13:23:45 +01:00
exit 0 ;
2018-03-05 14:27:51 +01:00
}
2017-11-14 15:17:27 +01:00
print_module ( $ conf , {
2018-04-03 09:46:44 +02:00
name = > ( empty ( $ conf - > { 'global_plugin_module' } ) ? "Plugin execution result " . $ 0: $ conf - > { 'global_plugin_module' } ) ,
2017-11-14 15:17:27 +01:00
type = > "generic_proc" ,
2018-03-05 14:27:51 +01:00
value = > $ value ,
2017-11-14 15:17:27 +01:00
desc = > $ msg ,
} ) ;
2021-02-05 13:23:45 +01:00
exit 0 ;
2017-11-14 15:17:27 +01:00
}
################################################################################
## Plugin message to SDTDOUT
################################################################################
sub print_stderror {
my ( $ conf , $ msg , $ always_show ) = @ _ ;
if ( is_enabled ( $ conf - > { debug } ) || ( is_enabled ( $ always_show ) ) ) {
2017-11-29 19:48:15 +01:00
print STDERR strftime ( "%Y-%m-%d %H:%M:%S" , localtime ( ) ) . ": " . $ msg . "\n" ;
2017-11-14 15:17:27 +01:00
}
}
################################################################################
# Log data
################################################################################
my $ log_aux_flag = 0 ;
sub logger {
my ( $ conf , $ tag , $ message ) = @ _ ;
2018-04-03 09:46:44 +02:00
my $ file = $ conf - > { 'log' } ;
2021-02-05 13:20:56 +01:00
print_error ( $ conf , "[ERROR] Log file is not defined." , 0 , 1 ) unless defined ( $ file ) ;
2021-02-05 13:07:54 +01:00
2021-02-05 13:20:56 +01:00
# Log rotation
if ( defined ( $ file ) && - e $ file && ( stat ( $ file ) ) [ 7 ] > 32000000 ) {
rename ( $ file , $ file . '.old' ) ;
}
my $ LOGFILE ;
if ( $ log_aux_flag == 0 ) {
# Log starts
if ( ! open ( $ LOGFILE , "> $file" ) ) {
2018-04-03 09:46:44 +02:00
print_error ( $ conf , "[ERROR] Could not open logfile '$file'" , 0 , 1 ) ;
2017-11-14 15:17:27 +01:00
}
$ log_aux_flag = 1 ;
}
else {
if ( ! open ( $ LOGFILE , ">> $file" ) ) {
2018-04-03 09:46:44 +02:00
print_error ( $ conf , "[ERROR] Could not open logfile '$file'" , 0 , 1 ) ;
2017-11-14 15:17:27 +01:00
}
}
2018-04-03 09:46:44 +02:00
if ( empty ( $ message ) ) {
$ message = $ tag ;
$ message = "" if empty ( $ message ) ;
}
else {
$ message = "[" . $ tag . "] " . $ message unless empty ( $ tag ) ;
}
2017-11-14 15:17:27 +01:00
2018-04-03 09:46:44 +02:00
if ( ! ( empty ( $ conf - > { 'agent_name' } ) ) ) {
$ message = "[" . $ conf - > { 'agent_name' } . "] " . $ message ;
2017-11-14 15:17:27 +01:00
}
print $ LOGFILE strftime ( "%Y-%m-%d %H:%M:%S" , localtime ( ) ) . " - " . $ message . "\n" ;
close ( $ LOGFILE ) ;
}
################################################################################
# is Enabled
################################################################################
2017-11-27 18:19:32 +01:00
sub is_enabled {
2017-11-14 15:17:27 +01:00
my $ value = shift ;
2018-04-03 09:46:44 +02:00
if ( ( defined ( $ value ) ) && looks_like_number ( $ value ) && ( $ value > 0 ) ) {
2017-11-14 15:17:27 +01:00
# return true
return 1 ;
}
#return false
return 0 ;
}
################################################################################
# Launch URL call
################################################################################
sub call_url {
my $ conf = shift ;
my $ call = shift ;
my @ options = @ _ ;
my $ _PluginTools_system = get_sys_environment ( $ conf ) ;
if ( empty ( $ _PluginTools_system - > { ua } ) ) {
return {
error = > "Uninitialized, please initialize UserAgent first"
} ;
}
my $ response = $ _PluginTools_system - > { ua } - > get ( $ call , @ options ) ;
if ( $ response - > is_success ) {
return $ response - > decoded_content ;
2018-09-03 11:26:01 +02:00
} elsif ( ! empty ( $ response - > { '_msg' } ) ) {
print_stderror ( $ conf , 'Failed: ' . $ response - > { '_msg' } ) ;
2017-11-14 15:17:27 +01:00
}
2018-09-03 11:26:01 +02:00
2017-11-16 14:53:17 +01:00
return undef ;
2017-11-14 15:17:27 +01:00
}
################################################################################
# Launch URL call (POST)
################################################################################
sub post_url {
my $ conf = shift ;
my $ url = shift ;
my @ options = @ _ ;
my $ _PluginTools_system = $ conf - > { '__system' } ;
if ( empty ( $ _PluginTools_system - > { ua } ) ) {
return {
error = > "Uninitialized, please initialize UserAgent first"
} ;
}
my $ response = $ _PluginTools_system - > { ua } - > request ( POST "$url" , @ options ) ;
if ( $ response - > is_success ) {
return $ response - > decoded_content ;
2018-09-03 11:26:01 +02:00
} elsif ( ! empty ( $ response - > { '_msg' } ) ) {
print_stderror ( $ conf , 'Failed: ' . $ response - > { '_msg' } ) ;
2017-11-14 15:17:27 +01:00
}
2018-09-03 11:26:01 +02:00
2017-11-14 15:17:27 +01:00
return undef ;
}
################################################################################
# initialize plugin (advanced - hashed configuration)
################################################################################
2017-11-27 18:19:32 +01:00
sub init {
2017-11-14 15:17:27 +01:00
my $ options = shift ;
my $ conf ;
eval {
$ conf = init_system ( $ options ) ;
if ( defined ( $ options - > { lwp_enable } ) ) {
if ( empty ( $ options - > { lwp_timeout } ) ) {
$ options - > { lwp_timeout } = 3 ;
}
$ conf - > { '__system' } - > { ua } = LWP::UserAgent - > new ( ( keep_alive = > "10" ) ) ;
$ conf - > { '__system' } - > { ua } - > timeout ( $ options - > { lwp_timeout } ) ;
# Enable environmental proxy settings
$ conf - > { '__system' } - > { ua } - > env_proxy ;
# Enable in-memory cookie management
$ conf - > { '__system' } - > { ua } - > cookie_jar ( { } ) ;
if ( defined ( $ options - > { ssl_verify } ) && ( ( $ options - > { ssl_verify } eq "no" ) || ( ! is_enabled ( $ options - > { ssl_verify } ) ) ) ) {
# Disable verify host certificate (only needed for self-signed cert)
$ conf - > { '__system' } - > { ua } - > ssl_opts ( 'verify_hostname' = > 0 ) ;
$ conf - > { '__system' } - > { ua } - > ssl_opts ( 'SSL_verify_mode' = > 0x00 ) ;
2018-09-03 11:26:01 +02:00
# Disable library extra checks
BEGIN {
$ ENV { PERL_NET_HTTPS_SSL_SOCKET_CLASS } = "Net::SSL" ;
$ ENV { PERL_LWP_SSL_VERIFY_HOSTNAME } = 0 ;
}
2017-11-14 15:17:27 +01:00
}
}
} ;
if ( $@ ) {
# Failed
return {
error = > $@
} ;
}
return $ conf ;
}
2018-07-04 18:39:06 +02:00
################################################################################
# Update internal UA timeout
################################################################################
sub ua_set_timeout {
my ( $ config , $ timeout ) = @ _ ;
return unless looks_like_number ( $ timeout ) and $ timeout > 0 ;
my $ sys = get_sys_environment ( $ config ) ;
return unless defined ( $ sys - > { 'ua' } ) ;
$ sys - > { 'ua' } - > timeout ( $ timeout ) ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# initialize plugin (basic)
################################################################################
sub init_system {
my ( $ conf ) = @ _ ;
my % system ;
if ( $^O =~ /win/i ) {
$ system { devnull } = "NUL" ;
$ system { cat } = "type" ;
$ system { os } = "Windows" ;
$ system { ps } = "tasklist" ;
$ system { grep } = "findstr" ;
$ system { echo } = "echo" ;
$ system { wcl } = "wc -l" ;
2018-04-03 09:46:44 +02:00
$ system { tmp } = ".\\" ;
2020-10-01 19:34:05 +02:00
$ system { cmdsep } = "\&" ;
2017-11-14 15:17:27 +01:00
}
else {
$ system { devnull } = "/dev/null" ;
$ system { cat } = "cat" ;
$ system { os } = "Linux" ;
2017-11-29 13:31:27 +01:00
$ system { ps } = "ps -eo pmem,pcpu,comm" ;
2017-11-14 15:17:27 +01:00
$ system { grep } = "grep" ;
$ system { echo } = "echo" ;
$ system { wcl } = "wc -l" ;
2018-04-03 09:46:44 +02:00
$ system { tmp } = "/tmp" ;
2020-10-01 19:34:05 +02:00
$ system { cmdsep } = ";" ;
2017-11-14 15:17:27 +01:00
if ( $^O =~ /hpux/i ) {
$ system { os } = "HPUX" ;
2017-11-29 13:31:27 +01:00
$ system { ps } = "ps -eo pmem,pcpu,comm" ;
}
if ( $^O =~ /solaris/i ) {
$ system { os } = "solaris" ;
$ system { ps } = "ps -eo pmem,pcpu,comm" ;
2017-11-14 15:17:27 +01:00
}
}
$ conf - > { '__system' } = \ % system ;
return $ conf ;
}
2018-06-18 20:47:58 +02:00
################################################################################
# Return a string with the concatenation of a hash array based on a field
################################################################################
sub join_by_field {
my ( $ separator , $ field , $ array_hashref ) = @ _ ;
$ separator = ',' if empty ( $ separator ) ;
my $ str = '' ;
foreach my $ item ( @ { $ array_hashref } ) {
$ str . = ( defined ( $ item - > { $ field } ) ? $ item - > { $ field } : '' ) . $ separator ;
}
chop ( $ str ) ;
return $ str ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# Return system environment
################################################################################
sub get_sys_environment {
my $ conf = shift ;
if ( ref ( $ conf ) eq "HASH" ) {
return $ conf - > { '__system' } ;
}
return undef ;
}
2017-11-30 17:00:28 +01:00
################################################################################
# Parses any configuration, from file (1st arg to program) or direct arguments
2018-04-03 09:46:44 +02:00
#
# Custom evals are defined in an array reference of hash references:
#
# $custom_eval = [
# {
# 'exp' => 'regular expression to match',
# 'target' => \&target_custom_method_to_parse_line
# },
# {
# 'exp' => 'another regular expression to search',
# 'target' => \&target_custom_method_to_parse_line2
# },
# ]
#
# Target is an user defined function wich will be invoked with following
# arguments:
#
# $config : The configuration read to the point the regex matches
# $exp : The matching regex which fires this action
# $line : The complete line readed from the file
# $file_pointer : A pointer to the file which is being parsed.
# $current_entity : The current_entity (optional) when regex matches
#
# E.g.
#
# sub target_custom_method_to_parse_line {
# my ($config, $exp, $line, $file_pointer, $current_entity) = @_;
#
# if ($line =~ /$exp/) {
# $config->{'my_key'} = complex_operation_on_data($1,$2,$3);
# }
#
# return $config;
# }
#
2017-11-30 17:00:28 +01:00
################################################################################
sub read_configuration {
my ( $ config , $ separator , $ custom_eval ) = @ _ ;
if ( ( ! empty ( @ ARGV ) ) && ( - f $ ARGV [ 0 ] ) ) {
$ config = merge_hashes ( $ config , parse_configuration ( shift @ ARGV , $ separator , $ custom_eval ) ) ;
}
$ config = merge_hashes ( $ config , parse_arguments ( \ @ ARGV ) ) ;
2018-04-03 18:22:38 +02:00
if ( is_enabled ( $ config - > { 'as_agent_plugin' } ) ) {
$ config - > { 'as_server_plugin' } = 0 if ( empty ( $ config - > { 'as_server_plugin' } ) ) ;
}
else {
$ config - > { 'as_server_plugin' } = 1 if ( empty ( $ config - > { 'as_server_plugin' } ) ) ;
}
if ( is_enabled ( $ config - > { 'as_server_plugin' } ) ) {
$ config - > { 'as_agent_plugin' } = 0 if ( empty ( $ config - > { 'as_agent_plugin' } ) ) ;
}
else {
$ config - > { 'as_agent_plugin' } = 1 if ( empty ( $ config - > { 'as_agent_plugin' } ) ) ;
}
2017-11-30 17:00:28 +01:00
return $ config ;
}
2020-04-30 15:19:19 +02:00
################################################################################
## Reads a file and returns entire content or undef if error.
################################################################################
sub read_file {
my $ path = shift ;
my $ _FILE ;
if ( ! open ( $ _FILE , "<" , $ path ) ) {
# failed to open, return undef
return undef ;
}
# Slurp configuration file content.
my $ content = do { local $/ ; <$_FILE> } ;
# Close file
close ( $ _FILE ) ;
return $ content ;
}
2017-11-14 15:17:27 +01:00
################################################################################
# General arguments parser
################################################################################
2017-11-27 18:19:32 +01:00
sub parse_arguments {
2017-11-14 15:17:27 +01:00
my $ raw = shift ;
my @ args ;
if ( defined ( $ raw ) ) {
@ args = @ { $ raw } ;
}
else {
return { } ;
}
my % data ;
for ( my $ i = 0 ; $ i < $# args ; $ i += 2 ) {
my $ key = trim ( $ args [ $ i ] ) ;
$ key =~ s/^-// ;
2018-10-04 17:30:48 +02:00
if ( $ key =~ /^\s*global_alerts/ ) {
push ( @ { $ data { global_alerts } } , trim ( $ args [ $ i + 1 ] ) ) ;
next ;
}
2017-11-14 15:17:27 +01:00
$ data { $ key } = trim ( $ args [ $ i + 1 ] ) ;
}
return \ % data ;
}
2018-03-01 18:02:43 +01:00
2017-11-14 15:17:27 +01:00
################################################################################
# General configuration file parser
#
2018-03-01 18:02:43 +01:00
# Custom evals are defined in an array reference of hash references:
#
# $custom_eval = [
# {
# 'exp' => 'regular expression to match',
# 'target' => \&target_custom_method_to_parse_line
# },
# {
# 'exp' => 'another regular expression to search',
# 'target' => \&target_custom_method_to_parse_line2
# },
# ]
#
# Target is an user defined function wich will be invoked with following
# arguments:
#
# $config : The configuration read to the point the regex matches
# $exp : The matching regex which fires this action
# $line : The complete line readed from the file
2018-03-02 09:09:54 +01:00
# $file_pointer : A pointer to the file which is being parsed.
2018-03-01 18:02:43 +01:00
# $current_entity : The current_entity (optional) when regex matches
2017-11-14 15:17:27 +01:00
#
################################################################################
2018-04-03 09:46:44 +02:00
sub parse_configuration ;
2017-11-27 18:19:32 +01:00
sub parse_configuration {
2018-03-01 18:02:43 +01:00
my ( $ conf_file , $ separator , $ custom_eval , $ detect_entities , $ entities_list ) = @ _ ;
2017-11-14 15:17:27 +01:00
2018-04-03 09:46:44 +02:00
my @ arguments = @ _ ;
shift ( @ arguments ) ;
2018-03-01 18:02:43 +01:00
$ separator = "=" unless defined ( $ separator ) ;
2017-11-14 15:17:27 +01:00
2018-04-03 09:46:44 +02:00
2018-03-01 18:02:43 +01:00
my $ _CFILE ;
2017-11-14 15:17:27 +01:00
my $ _config ;
if ( empty ( $ conf_file ) ) {
return {
error = > "Configuration file not specified"
} ;
}
if ( ! open ( $ _CFILE , "<" , "$conf_file" ) ) {
return {
error = > "Cannot open configuration file"
} ;
}
2018-03-01 18:02:43 +01:00
my $ current_entity = '' ;
my $ new_entity = '' ;
my $ global_config ;
2017-11-14 15:17:27 +01:00
while ( my $ line = <$_CFILE> ) {
if ( ( $ line =~ /^ *\r*\n*$/ )
|| ( $ line =~ /^#/ ) ) {
# skip blank lines and comments
next ;
}
2018-03-01 18:02:43 +01:00
my ( $ key , $ value ) = split /$separator/ , $ line , 2 ;
2018-03-02 09:09:54 +01:00
# Clear entity detection is only compatible with specific entities declaration
if ( empty ( $ value ) && ( $ line =~ /^(\w+?)\r*\n*$/ )
&& is_enabled ( $ detect_entities )
&& in_array ( $ entities_list , trim ( $ key ) ) ) {
2018-03-01 18:02:43 +01:00
# possible Entity detected - compatibility vmware-plugin
2018-03-02 09:09:54 +01:00
$ new_entity = $ key ;
2018-03-01 18:02:43 +01:00
}
if ( ( $ line =~ /\[(.*?)\]\r*\n*$/ ) && is_enabled ( $ detect_entities ) ) {
# Entity detected
$ new_entity = $ 1
}
if ( ! empty ( $ new_entity ) ) {
if ( empty ( $ current_entity ) ) {
$ global_config = merge_hashes ( $ global_config , $ _config ) ;
}
else {
$ global_config - > { $ current_entity } = $ _config ;
}
$ current_entity = trim ( $ new_entity ) ;
undef ( $ new_entity ) ;
# Initialize reference
$ global_config - > { $ current_entity } = { } ;
$ _config = $ global_config - > { $ current_entity } ;
next ;
}
2017-11-14 15:17:27 +01:00
if ( $ line =~ /^\s*global_alerts/ ) {
2018-03-01 18:02:43 +01:00
push ( @ { $ _config - > { global_alerts } } , trim ( $ value ) ) ;
2017-11-14 15:17:27 +01:00
next ;
}
if ( ref ( $ custom_eval ) eq "ARRAY" ) {
my $ f = 0 ;
foreach my $ item ( @ { $ custom_eval } ) {
2018-03-01 18:02:43 +01:00
if ( $ line =~ /$item->{'exp'}/ ) {
2017-11-14 15:17:27 +01:00
$ f = 1 ;
my $ aux ;
eval {
2018-03-02 09:09:54 +01:00
$ aux = $ item - > { 'target' } - > ( $ _config , $ item - > { 'exp' } , $ line , $ _CFILE , $ current_entity ) ;
2017-11-14 15:17:27 +01:00
} ;
if ( empty ( $ _config ) ) {
$ _config = $ aux ;
}
elsif ( ! empty ( $ aux ) && ( ref ( $ aux ) eq "HASH" ) ) {
$ _config = merge_hashes ( $ _config , $ aux ) ;
}
}
}
if ( is_enabled ( $ f ) ) {
next ;
}
}
2018-04-03 09:46:44 +02:00
if ( $ key =~ /^include$/i ) {
my $ file_included = trim ( $ value ) ;
my $ aux ;
eval {
$ aux = parse_configuration ( $ file_included , @ arguments ) ;
} ;
if ( $@ ) {
Carp:: croak ( "Failed to parse configuration" ) ;
}
if ( empty ( $ _config ) ) {
$ _config = $ aux ;
}
elsif ( ! empty ( $ aux ) && ( ref ( $ aux ) eq "HASH" ) ) {
$ _config = merge_hashes ( $ _config , $ aux ) ;
}
next ;
}
2018-03-01 18:02:43 +01:00
$ _config - > { trim ( $ key ) } = trim ( $ value ) ;
2017-11-14 15:17:27 +01:00
}
close ( $ _CFILE ) ;
2018-03-02 14:21:01 +01:00
if ( is_enabled ( $ detect_entities ) ) {
if ( empty ( $ current_entity ) && ( ! empty ( $ global_config ) ) ) {
$ global_config = merge_hashes ( $ global_config , $ _config ) ;
}
else {
$ global_config - > { $ current_entity } = $ _config ;
}
2018-03-01 18:02:43 +01:00
2018-03-02 14:21:01 +01:00
return $ global_config unless empty ( $ global_config ) ;
}
2018-04-03 09:46:44 +02:00
2017-11-14 15:17:27 +01:00
return $ _config ;
}
################################################################################
# PHP file parser
#
# log=/PATH/TO/LOG/FILE
#
################################################################################
2017-11-27 18:19:32 +01:00
sub parse_php_configuration {
2017-11-14 15:17:27 +01:00
my $ conf_file = shift ;
my $ separator = shift ;
if ( ! defined ( $ separator ) ) {
$ separator = "=" ;
}
my % _config ;
open ( my $ _CFILE , "<" , "$conf_file" ) or return undef ;
my $ comment_block = 0 ;
my $ in_php = 0 ;
while ( my $ line = <$_CFILE> ) {
if ( $ line =~ /.*\<\?php/ ) {
$ in_php = 1 ;
$ line =~ s/<\?php//g ;
}
if ( $ line =~ /.*\<\?/ ) {
$ in_php = 1 ;
$ line =~ s/<\?//g ;
}
if ( $ in_php == 1 ) {
if ( ( $ comment_block == 1 )
&& ( $ line =~ /\*\// ) ) { # search multiline comment end
# remove commented content:
$ line =~ s/.*?(\*\/)//g ;
$ comment_block = 0 ;
}
if ( $ comment_block == 1 ) { # ignore lines in commented block
next ;
}
$ line =~ /\/\*[^(?\*\/)]*/ ; # remove block comment
if ( $ line =~ /\/\*/ ) {
# multiline block comment detected!
$ comment_block = 1 ;
next ;
}
if ( $ line =~ /.*\?\>/ ) {
$ in_php = 0 ;
$ line =~ s/\?\>.*//g ;
}
$ line =~ s/\/\*.*\*\///g ; # Erase inline comments
$ line =~ s/\/\/.*//g ; # Erase inline comments
chomp ( $ line ) ;
if ( $ line =~ /^\s*$/ ) {
# skip blank and empty lines
next ;
}
my @ parsed = split /$separator/ , $ line , 2 ;
$ _config { trim ( $ parsed [ 0 ] ) } = trim ( $ parsed [ 1 ] ) ;
$ _config { trim ( $ parsed [ 0 ] ) } =~ s/[";]//g ;
}
}
close ( $ _CFILE ) ;
return % _config ;
}
################################################################################
# Process performance
################################################################################
sub process_performance {
my ( $ conf , $ process , $ mod_name , $ only_text_flag ) = @ _ ;
my $ _PluginTools_system = $ conf - > { '__system' } ;
2018-03-01 09:29:36 +01:00
if ( empty ( $ _PluginTools_system ) ) {
$ _PluginTools_system = init_system ( ) ;
$ _PluginTools_system = get_sys_environment ( $ _PluginTools_system ) ;
}
2017-11-14 15:17:27 +01:00
my $ cpu ;
my $ mem ;
my $ instances ;
my $ runit = "%" ;
my $ cunit = "%" ;
2017-11-29 18:27:31 +01:00
$ mod_name = $ process if empty ( $ mod_name ) ;
2017-11-14 15:17:27 +01:00
2017-11-29 18:27:31 +01:00
if ( empty ( $ process ) ) {
$ process = "" if empty ( $ process ) ;
$ mod_name = "" if empty ( $ mod_name ) ;
$ cpu = 0 ;
$ mem = 0 ;
$ instances = 0 ;
}
elsif ( $^O =~ /win/i ) {
2017-11-14 15:17:27 +01:00
my $ out = trim ( `(FOR /F \"skip=2 tokens=2 delims=,\" %P IN ('typeperf \"\\Proceso($process)\\% de tiempo de procesador\" -sc 1') DO \@echo %P) | find /V /I \"...\" 2> $_PluginTools_system->{devnull}` ) ;
if ( ( $ out =~ /member/i )
|| ( $ out =~ /error/i )
|| ( ! $ out =~ /satisfact/i ) ) {
$ out = trim ( `(FOR /F \"skip=2 tokens=2 delims=,\" %P IN ('typeperf \"\\Process($process)\\% Processor Time\" -sc 1') DO \@echo %P) | find /V /I \"...\" 2> $_PluginTools_system->{devnull}` ) ;
}
if ( ( $ out =~ /member/i )
|| ( $ out =~ /error/i )
|| ( ! $ out =~ /successfully/i ) ) {
$ cpu = 0 ;
}
$ out =~ s/\"//g ;
if ( ! looks_like_number ( $ out ) ) {
print STDERR "CPU usage [$out] is not numeric\n" ;
$ out = 0 ;
}
$ cpu = sprintf '%.2f' , $ out ;
$ mem = ( split /\s+/ , trim ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} \"$process\"` ) ) [ - 2 ] ;
if ( ! empty ( $ mem ) ) {
$ mem =~ s/,/./ ;
}
else {
$ mem = 0 ;
}
$ runit = "K" ;
$ instances = trim ( head ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} "$process"| $_PluginTools_system->{wcl}` , 1 ) ) ;
2018-06-27 12:21:21 +02:00
}
2017-11-14 15:17:27 +01:00
elsif ( $^O =~ /linux/i ) {
$ cpu = trim ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | awk 'BEGIN {sum=0} {sum+=\$2} END{print sum}'` ) ;
2017-11-29 18:27:31 +01:00
$ mem = trim ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | awk 'BEGIN {sum=0} {sum+=\$1} END{print sum}'` ) ;
2017-11-14 15:17:27 +01:00
$ instances = trim ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | $_PluginTools_system->{wcl}` ) ;
}
elsif ( $^O =~ /hpux/ ) {
$ cpu = trim ( `UNIX95= ps -eo pcpu,comm | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | awk 'BEGIN {sum=0} {sum+=\$1} END{printf("\%.2f",sum)}'` ) ;
$ mem = trim ( `UNIX95= ps -eo vsz,comm | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | awk 'BEGIN {sum=0} {sum+=(\$1*4096/1048576)} END{printf("\%.2f",sum)}'` ) ;
$ instances = trim ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | $_PluginTools_system->{wcl}` ) ;
$ runit = "MB" ;
}
elsif ( $^O =~ /solaris/i ) {
$ cpu = trim ( `UNIX95= ps -eo pcpu,comm | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | awk 'BEGIN {sum=0} {sum+=\$1} END{printf("\%.2f",sum)}'` ) ;
$ mem = trim ( `UNIX95= ps -eo pmem,comm | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | awk 'BEGIN {sum=0} {sum+=\$1} END{printf("\%.2f",sum)}'` ) ;
$ instances = trim ( `$_PluginTools_system->{ps} | $_PluginTools_system->{grep} -w "$process" | $_PluginTools_system->{grep} -v grep | $_PluginTools_system->{wcl}` ) ;
$ runit = "%" ;
}
elsif ( $^O =~ /aix/i ) {
$ cpu = trim ( `ps -Ao comm,pcpu |grep $process | grep -v grep | awk 'BEGIN {sum=0} {sum+=\$2} END {print sum}'` ) ;
$ mem = trim ( `ps au -A | grep $process | grep -v grep | awk 'BEGIN {sum=0} {sum+=\$4} END {print sum}'` ) ;
$ instances = trim ( `ps -ef | grep "$process"|grep -v grep| wc -l` ) ;
$ runit = "MB" ;
}
# print
if ( ! looks_like_number ( $ instances ) ) {
$ instances = 0 ;
}
print_module ( $ conf , {
name = > "$mod_name" ,
type = > "generic_proc" ,
desc = > "Presence of $process ($instances instances)" ,
value = > ( ( $ instances > 0 ) ? 1 : 0 ) ,
} , $ only_text_flag ) ;
if ( $ instances > 0 ) {
print_module ( $ conf , {
name = > "$mod_name CPU usage" ,
type = > "generic_data" ,
desc = > "CPU usage of $process ($instances instances)" ,
value = > $ cpu ,
unit = > $ cunit
} , $ only_text_flag ) ;
print_module ( $ conf , {
name = > "$mod_name RAM usage" ,
type = > "generic_data" ,
desc = > "RAM usage of $process ($instances instances)" ,
value = > $ mem ,
unit = > $ runit
} , $ only_text_flag ) ;
}
2017-11-29 18:27:31 +01:00
return {
cpu = > $ cpu ,
mem = > $ mem ,
2018-03-01 09:29:36 +01:00
instances = > $ instances ,
runit = > $ runit ,
cunit = > $ cunit ,
2017-11-29 18:27:31 +01:00
} ;
2017-11-14 15:17:27 +01:00
}
2017-11-16 14:53:17 +01:00
#########################################################################################
# Check api availability
#########################################################################################
2017-11-27 18:19:32 +01:00
sub api_available {
2017-11-16 14:53:17 +01:00
my ( $ conf , $ apidata ) = @ _ ;
my ( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = ( '' , '' , '' , '' , '' ) ;
if ( ref $ apidata eq "ARRAY" ) {
( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = @ { $ apidata } ;
}
2018-05-21 11:10:05 +02:00
$ api_url = $ conf - > { 'api_url' } if empty ( $ api_url ) ;
$ api_pass = $ conf - > { 'api_pass' } if empty ( $ api_pass ) ;
$ api_user = $ conf - > { 'api_user' } if empty ( $ api_user ) ;
$ api_user_pass = $ conf - > { 'api_user_pass' } if empty ( $ api_user_pass ) ;
2017-11-16 14:53:17 +01:00
my $ op = "get" ;
my $ op2 = "test" ;
my $ call = $ api_url . "?" ;
$ call . = "op=" . $ op . "&op2=" . $ op2 ;
$ call . = "&apipass=" . $ api_pass . "&user=" . $ api_user . "&pass=" . $ api_user_pass ;
my $ rs = call_url ( $ conf , $ call ) ;
if ( ref $ rs eq "HASH" ) {
return {
rs = > 1 ,
error = > $ rs - > { error }
} ;
}
else {
return {
rs = > ( empty ( $ rs ) ? 1 : 0 ) ,
error = > ( empty ( $ rs ) ? "Empty response." : undef ) ,
id = > ( empty ( $ rs ) ? undef : trim ( $ rs ) )
}
}
2018-05-21 14:42:27 +02:00
}
2017-11-16 14:53:17 +01:00
2018-05-21 14:42:27 +02:00
#########################################################################################
# Pandora API call
# apidata->{other} = [field1,field2,...,fieldi,...,fieldn]
#########################################################################################
sub api_call {
2018-06-18 20:47:58 +02:00
my ( $ conf , $ apidata , $ decode_json ) = @ _ ;
2018-05-21 14:42:27 +02:00
my ( $ api_url , $ api_pass , $ api_user , $ api_user_pass ,
2018-06-18 20:47:58 +02:00
$ op , $ op2 , $ id , $ id2 , $ other_mode , $ other , $ return_type ) ;
2018-05-21 14:42:27 +02:00
my $ separator ;
if ( ref $ apidata eq "ARRAY" ) {
( $ api_url , $ api_pass , $ api_user , $ api_user_pass ,
2018-06-18 20:47:58 +02:00
$ op , $ op2 , $ id , $ id2 , $ return_type , $ other_mode , $ other ) = @ { $ apidata } ;
2018-05-21 14:42:27 +02:00
}
if ( ref $ apidata eq "HASH" ) {
$ api_url = $ apidata - > { 'api_url' } ;
$ api_pass = $ apidata - > { 'api_pass' } ;
$ api_user = $ apidata - > { 'api_user' } ;
$ api_user_pass = $ apidata - > { 'api_user_pass' } ;
$ op = $ apidata - > { 'op' } ;
$ op2 = $ apidata - > { 'op2' } ;
2018-06-18 20:47:58 +02:00
$ id = $ apidata - > { 'id' } ;
$ id2 = $ apidata - > { 'id2' } ;
2018-05-21 14:42:27 +02:00
$ return_type = $ apidata - > { 'return_type' } ;
$ other_mode = "url_encode_separator_" . $ apidata - > { 'url_encode_separator' } unless empty ( $ apidata - > { 'url_encode_separator' } ) ;
$ other_mode = "url_encode_separator_|" if empty ( $ other_mode ) ;
( $ separator ) = $ other_mode =~ /url_encode_separator_(.*)/ ;
}
$ api_url = $ conf - > { 'api_url' } if empty ( $ api_url ) ;
$ api_pass = $ conf - > { 'api_pass' } if empty ( $ api_pass ) ;
$ api_user = $ conf - > { 'api_user' } if empty ( $ api_user ) ;
$ api_user_pass = $ conf - > { 'api_user_pass' } if empty ( $ api_user_pass ) ;
$ op = $ conf - > { 'op' } if empty ( $ op ) ;
$ op2 = $ conf - > { 'op2' } if empty ( $ op2 ) ;
2018-06-18 20:47:58 +02:00
$ id = $ conf - > { 'id' } if empty ( $ id ) ;
$ id2 = $ conf - > { 'id2' } if empty ( $ id2 ) ;
2018-05-21 14:42:27 +02:00
$ return_type = $ conf - > { 'return_type' } if empty ( $ return_type ) ;
$ return_type = 'json' if empty ( $ return_type ) ;
if ( ref ( $ apidata - > { 'other' } ) eq "ARRAY" ) {
$ other_mode = "url_encode_separator_|" if empty ( $ other_mode ) ;
( $ separator ) = $ other_mode =~ /url_encode_separator_(.*)/ ;
if ( empty ( $ separator ) ) {
$ separator = "|" ;
$ other_mode = "url_encode_separator_|" ;
}
$ other = join $ separator , @ { $ apidata - > { 'other' } } ;
}
2018-05-21 18:08:36 +02:00
else {
$ other = $ apidata - > { 'other' } ;
}
2018-05-21 14:42:27 +02:00
2018-06-18 20:47:58 +02:00
$ other = '' if empty ( $ other ) ;
$ id = '' if empty ( $ id ) ;
$ id2 = '' if empty ( $ id2 ) ;
2018-05-21 14:42:27 +02:00
my $ call ;
$ call = $ api_url . '?' ;
2018-06-18 20:47:58 +02:00
$ call . = 'op=' . $ op . '&op2=' . $ op2 . '&id=' . $ id ;
2018-05-21 14:42:27 +02:00
$ call . = '&other_mode=url_encode_separator_' . $ separator ;
$ call . = '&other=' . $ other ;
$ call . = '&apipass=' . $ api_pass . '&user=' . $ api_user . '&pass=' . $ api_user_pass ;
$ call . = '&return_type=' . $ return_type ;
2017-11-16 14:53:17 +01:00
2018-05-21 14:42:27 +02:00
my $ rs = call_url ( $ conf , "$call" ) ;
if ( ref ( $ rs ) ne "HASH" ) {
2018-06-18 20:47:58 +02:00
if ( is_enabled ( $ decode_json ) ) {
eval {
my $ tmp = decode_json ( $ rs ) ;
$ rs = $ tmp ;
} ;
if ( $@ ) {
print_stderror ( $ conf , "Error: " . $@ ) ;
}
}
2018-05-21 14:42:27 +02:00
return {
rs = > ( empty ( $ rs ) ? 1 : 0 ) ,
error = > ( empty ( $ rs ) ? "Empty response." : undef ) ,
id = > ( empty ( $ rs ) ? undef : trim ( $ rs ) ) ,
response = > ( empty ( $ rs ) ? undef : $ rs ) ,
}
}
else {
return {
rs = > 1 ,
error = > $ rs - > { 'error' } ,
}
}
2017-11-16 14:53:17 +01:00
}
#########################################################################################
# Pandora API create custom field
#########################################################################################
sub api_create_custom_field {
my ( $ conf , $ apidata , $ name , $ display , $ password ) = @ _ ;
my ( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = ( '' , '' , '' , '' , '' ) ;
if ( ref $ apidata eq "ARRAY" ) {
( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = @ { $ apidata } ;
}
2018-05-21 11:10:05 +02:00
$ api_url = $ conf - > { 'api_url' } if empty ( $ api_url ) ;
$ api_pass = $ conf - > { 'api_pass' } if empty ( $ api_pass ) ;
$ api_user = $ conf - > { 'api_user' } if empty ( $ api_user ) ;
$ api_user_pass = $ conf - > { 'api_user_pass' } if empty ( $ api_user_pass ) ;
2017-11-16 14:53:17 +01:00
$ display = 0 unless defined ( $ display ) ;
$ password = 0 unless defined ( $ password ) ;
my $ call ;
# 1st try to get previous custom field id
my $ op = "get" ;
my $ op2 = "custom_field" ;
$ call = $ api_url . "?" ;
$ call . = "op=" . $ op . "&op2=" . $ op2 ;
# Extra arguments
if ( ! empty ( $ name ) ) {
$ call . = "&other=" . $ name ;
}
if ( ! empty ( $ display ) ) {
$ call . = "%7C" . $ display ;
}
if ( ! empty ( $ password ) ) {
$ call . = "%7C" . $ password ;
}
$ call . = "&other_mode=url_encode_separator=%7C&" ;
$ call . = "apipass=" . $ api_pass . "&user=" . $ api_user . "&pass=" . $ api_user_pass ;
my $ rs = call_url ( $ conf , "$call" ) ;
if ( ref ( $ rs ) ne "HASH" ) {
$ rs = trim ( $ rs ) ;
}
else {
# Failed to reach API, return with error
return {
rs = > 1 ,
error = > 'Failed to reach API'
} ;
}
if ( empty ( $ rs ) || ( $ rs !~ /^\d+$/ || $ rs eq "0" ) ) {
# Custom field is not defined
# 2nd create only if the custom field does not exist
$ op = "set" ;
$ op2 = "create_custom_field" ;
$ call = $ api_url . "?" ;
$ call . = "op=" . $ op . "&op2=" . $ op2 ;
$ call . = "&other=" . $ name . "%7C" . $ display . "%7C" . $ password ;
$ call . = "&other_mode=url_encode_separator=%7C&" ;
$ call . = "apipass=" . $ api_pass . "&user=" . $ api_user . "&pass=" . $ api_user_pass ;
$ rs = call_url ( $ conf , "$call" ) ;
}
if ( ref ( $ rs ) ne "HASH" ) {
$ rs = trim ( $ rs ) ;
}
else {
# Failed to reach API, return with error
return {
rs = > 1 ,
error = > 'Failed to reach API while creating custom field [' . $ name . ']'
} ;
}
if ( empty ( $ rs ) || ( $ rs !~ /^\d+$/ || $ rs eq "0" ) ) {
return {
rs = > 1 ,
error = > 'Failed while creating custom field [' . $ name . '] => [' . $ rs . ']'
} ;
}
# Return the valid id
return {
rs = > 0 ,
id = > $ rs
} ;
}
2017-11-14 15:17:27 +01:00
#########################################################################################
# Pandora API create tag
#########################################################################################
sub api_create_tag {
2017-11-16 14:53:17 +01:00
my ( $ conf , $ apidata , $ tag , $ desc , $ url , $ email ) = @ _ ;
my ( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = ( '' , '' , '' , '' , '' ) ;
if ( ref $ apidata eq "ARRAY" ) {
( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = @ { $ apidata } ;
}
2018-05-21 11:10:05 +02:00
$ api_url = $ conf - > { 'api_url' } if empty ( $ api_url ) ;
$ api_pass = $ conf - > { 'api_pass' } if empty ( $ api_pass ) ;
$ api_user = $ conf - > { 'api_user' } if empty ( $ api_user ) ;
$ api_user_pass = $ conf - > { 'api_user_pass' } if empty ( $ api_user_pass ) ;
2017-11-14 15:17:27 +01:00
my $ op = "set" ;
my $ op2 = "create_tag" ;
2017-11-16 14:53:17 +01:00
$ desc = 'Created by PluginTools' unless defined $ desc ;
2017-11-14 15:17:27 +01:00
my $ call = $ api_url . "?" ;
$ call . = "op=" . $ op . "&op2=" . $ op2 ;
2017-11-16 14:53:17 +01:00
$ call . = "&other=" ;
if ( ! empty ( $ tag ) ) {
$ call . = $ tag . "%7C" ;
}
if ( ! empty ( $ desc ) ) {
$ call . = $ desc . "%7C" ;
}
if ( ! empty ( $ url ) ) {
$ call . = $ url . "%7C" ;
}
if ( ! empty ( $ email ) ) {
$ call . = $ email ;
}
$ call . = "&other_mode=url_encode_separator=%7C&" ;
2017-11-14 15:17:27 +01:00
$ call . = "apipass=" . $ api_pass . "&user=" . $ api_user . "&pass=" . $ api_user_pass ;
2017-11-16 14:53:17 +01:00
my $ rs = call_url ( $ conf , $ call ) ;
if ( ref $ rs eq "HASH" ) {
return {
rs = > 1 ,
error = > $ rs - > { error }
} ;
}
else {
return {
rs = > ( empty ( $ rs ) ? 1 : 0 ) ,
error = > ( empty ( $ rs ) ? "Empty response." : undef ) ,
id = > ( empty ( $ rs ) ? undef : trim ( $ rs ) )
}
}
2017-11-14 15:17:27 +01:00
}
#########################################################################################
# Pandora API create group
#########################################################################################
2017-11-27 18:19:32 +01:00
sub api_create_group {
2017-11-16 14:53:17 +01:00
my ( $ conf , $ apidata , $ group_name , $ group_config , $ email ) = @ _ ;
my ( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) ;
if ( ref $ apidata eq "ARRAY" ) {
( $ api_url , $ api_pass , $ api_user , $ api_user_pass ) = @ { $ apidata } ;
}
2017-11-14 15:17:27 +01:00
2017-11-16 14:53:17 +01:00
if ( empty ( $ group_config - > { icon } ) ) {
2017-11-14 15:17:27 +01:00
return {
2017-11-16 14:53:17 +01:00
rs = > 1 ,
2017-11-14 15:17:27 +01:00
error = > "No icon set"
} ;
}
2017-11-16 14:53:17 +01:00
# Group config:
my $ other = '' ;
$ other . = $ group_config - > { icon } . '%7C&' ;
$ other . = ( empty ( $ group_config - > { parent } ) ? '' : $ group_config - > { parent } . '%7C&' ) ;
$ other . = ( empty ( $ group_config - > { desc } ) ? '' : $ group_config - > { desc } . '%7C&' ) ;
$ other . = ( empty ( $ group_config - > { propagate } ) ? '' : $ group_config - > { propagate } . '%7C&' ) ;
$ other . = ( empty ( $ group_config - > { disabled } ) ? '' : $ group_config - > { disabled } . '%7C&' ) ;
$ other . = ( empty ( $ group_config - > { custom_id } ) ? '' : $ group_config - > { custom_id } . '%7C&' ) ;
$ other . = ( empty ( $ group_config - > { contact } ) ? '' : $ group_config - > { contact } . '%7C&' ) ;
$ other . = ( empty ( $ group_config - > { other } ) ? '' : $ group_config - > { other } . '%7C&' ) ;
$ api_url = $ conf - > { 'api_url' } unless defined $ api_url ;
$ api_pass = $ conf - > { 'api_pass' } unless defined $ api_pass ;
$ api_user = $ conf - > { 'api_user' } unless defined $ api_user ;
$ api_user_pass = $ conf - > { 'api_user_pass' } unless defined $ api_user_pass ;
my $ op = "set" ;
my $ op2 = "create_group" ;
2017-11-14 15:17:27 +01:00
my $ call = $ api_url . "?" ;
$ call . = "op=" . $ op . "&op2=" . $ op2 ;
$ call . = "&id=" . $ group_name ;
2017-11-16 14:53:17 +01:00
$ call . = "&other=" . $ other . "&other_mode=url_encode_separator=%7C&" ;
2017-11-14 15:17:27 +01:00
$ call . = "apipass=" . $ api_pass . "&user=" . $ api_user . "&pass=" . $ api_user_pass ;
2017-11-16 14:53:17 +01:00
my $ rs = call_url ( $ conf , $ call ) ;
if ( ref $ rs eq "HASH" ) {
return {
rs = > 1 ,
error = > $ rs - > { error }
} ;
}
else {
return {
rs = > ( empty ( $ rs ) ? 1 : 0 ) ,
error = > ( empty ( $ rs ) ? "Empty response." : undef ) ,
id = > ( empty ( $ rs ) ? undef : trim ( $ rs ) )
}
}
2017-11-14 15:17:27 +01:00
}
################################################################################
# SNMP walk value
# will return the snmpwalk output
#
# $community (v1,2,2c)
# -> means $context (v3)
#
# Configuration hash
2021-02-12 15:25:41 +01:00
# $snmp{version}
# $snmp{community}
# $snmp{host}
# $snmp{oid}
# $snmp{port}
# $snmp{securityName}
# $snmp{context
# $snmp{securityLevel}
# $snmp{authProtocol}
# $snmp{authKey}
# $snmp{privProtocol}
# $snmp{privKey}
2017-11-14 15:17:27 +01:00
################################################################################
2017-11-27 18:19:32 +01:00
sub snmp_walk {
2017-11-14 15:17:27 +01:00
my $ snmp = shift ;
my $ cmd ;
my $ timeout = 2 ;
if ( ! empty ( $ snmp - > { timeout } ) ) {
$ timeout = $ snmp - > { timeout } ;
}
2019-02-26 18:16:10 +01:00
if ( $^O =~ /lin/i && "`which snmpwalk`" eq "" ) {
return {
'error' = > 'snmpwalk not found'
} ;
}
2018-10-30 17:53:57 +01:00
$ snmp - > { extra } = '' unless defined $ snmp - > { extra } ;
2017-11-14 15:17:27 +01:00
if ( defined ( $ snmp - > { version } )
&& ( ( $ snmp - > { version } eq "1" )
|| ( $ snmp - > { version } eq "2" )
|| ( $ snmp - > { version } eq "2c" ) ) ) {
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -c $snmp->{community} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -c $snmp->{community} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
elsif ( defined ( $ snmp - > { version } )
&& ( $ snmp - > { version } eq "3" ) ) { # SNMP v3
# Authentication required
# $securityLevel = (noAuthNoPriv|authNoPriv|authPriv);
# unauthenticated request
2018-10-30 17:53:57 +01:00
# Ex. snmpwalk -t $timeout $snmp->{extra} -On -v 3 -n "" -u noAuthUser -l noAuthNoPriv test.net-snmp.org sysUpTime
2017-11-14 15:17:27 +01:00
# authenticated request
2018-10-30 17:53:57 +01:00
# Ex. snmpwalk -t $timeout $snmp->{extra} -On -v 3 -n "" -u MD5User -a MD5 -A "The Net-SNMP Demo Password" -l authNoPriv test.net-snmp.org sysUpTime
2017-11-14 15:17:27 +01:00
# authenticated and encrypted request
2018-10-30 17:53:57 +01:00
# Ex. snmpwalk -t $timeout $snmp->{extra} -On -v 3 -n "" -u MD5DESUser -a MD5 -A "The Net-SNMP Demo Password" -x DES -X "The Net-SNMP Demo Password" -l authPriv test.net-snmp.org system
2017-11-14 15:17:27 +01:00
if ( $ snmp - > { securityLevel } =~ /^noAuthNoPriv$/i ) {
# Unauthenticated request
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -l $snmp->{securityLevel} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -l $snmp->{securityLevel} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
elsif ( $ snmp - > { securityLevel } =~ /^authNoPriv$/i ) {
# Authenticated request
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -a $snmp->{authProtocol} -A $snmp->{authKey} -l $snmp->{securityLevel} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -a $snmp->{authProtocol} -A $snmp->{authKey} -l $snmp->{securityLevel} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
elsif ( $ snmp - > { securityLevel } =~ /^authPriv$/i ) {
# Authenticated and encrypted request
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -l $snmp->{securityLevel} -a $snmp->{authProtocol} -A $snmp->{authKey} -x $snmp->{privProtocol} -X $snmp->{privKey} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpwalk -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -l $snmp->{securityLevel} -a $snmp->{authProtocol} -A $snmp->{authKey} -x $snmp->{privProtocol} -X $snmp->{privKey} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
}
else {
return {
error = > "Only SNMP 1 2 2c and 3 are supported."
}
}
#print STDERR "Launching $cmd\n";
my $ result = `$cmd 2>/dev/null` ;
if ( $? != 0 ) {
return {
error = > "No response from " . trim ( $ snmp - > { host } )
} ;
}
return $ result ;
}
################################################################################
# SNMP get value
# will return a hash with the data and datatype
#
# $community (v1,2,2c)
# -> means $context (v3)
#
# Configuration hash
#
# $snmp{version}
# $snmp{community}
# $snmp{host}
# $snmp{oid}
# $snmp{port}
2018-06-27 12:21:21 +02:00
# $snmp{securityName}
# $snmp{context
# $snmp{securityLevel}
# $snmp{authProtocol}
# $snmp{authKey}
# $snmp{privProtocol}
# $snmp{privKey}
2017-11-14 15:17:27 +01:00
################################################################################
2017-11-27 18:19:32 +01:00
sub snmp_get {
2017-11-14 15:17:27 +01:00
my $ snmp = shift ;
my $ cmd ;
my $ timeout = 2 ;
my $ retries = 1 ;
if ( ! empty ( $ snmp - > { retries } ) ) {
$ retries = $ snmp - > { retries } ;
}
if ( ! empty ( $ snmp - > { timeout } ) ) {
$ timeout = $ snmp - > { timeout } ;
}
2019-02-26 18:16:10 +01:00
if ( $^O =~ /lin/i && "`which snmpwalk`" eq "" ) {
return {
'error' = > 'snmpwalk not found'
} ;
}
2018-10-30 17:53:57 +01:00
$ snmp - > { extra } = '' unless defined $ snmp - > { extra } ;
2017-11-14 15:17:27 +01:00
if ( defined ( $ snmp - > { version } )
&& ( ( $ snmp - > { version } eq "1" )
|| ( $ snmp - > { version } eq "2" )
|| ( $ snmp - > { version } eq "2c" ) ) ) {
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -c $snmp->{community} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -c $snmp->{community} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
elsif ( defined ( $ snmp - > { version } )
&& ( $ snmp - > { version } eq "3" ) ) { # SNMP v3
# Authentication required
# $securityLevel = (noAuthNoPriv|authNoPriv|authPriv);
# unauthenticated request
2018-10-30 17:53:57 +01:00
# Ex. snmpget -r $retries -t $timeout $snmp->{extra} -On -v 3 -n "" -u noAuthUser -l noAuthNoPriv test.net-snmp.org sysUpTime
2017-11-14 15:17:27 +01:00
# authenticated request
2018-10-30 17:53:57 +01:00
# Ex. snmpget -r $retries -t $timeout $snmp->{extra} -On -v 3 -n "" -u MD5User -a MD5 -A "The Net-SNMP Demo Password" -l authNoPriv test.net-snmp.org sysUpTime
2017-11-14 15:17:27 +01:00
# authenticated and encrypted request
2018-10-30 17:53:57 +01:00
# Ex. snmpget -r $retries -t $timeout $snmp->{extra} -On -v 3 -n "" -u MD5DESUser -a MD5 -A "The Net-SNMP Demo Password" -x DES -X "The Net-SNMP Demo Password" -l authPriv test.net-snmp.org system
2017-11-14 15:17:27 +01:00
if ( $ snmp - > { securityLevel } =~ /^noAuthNoPriv$/i ) {
# Unauthenticated request
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -l $snmp->{securityLevel} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -l $snmp->{securityLevel} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
elsif ( $ snmp - > { securityLevel } =~ /^authNoPriv$/i ) {
# Authenticated request
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -a $snmp->{authProtocol} -A $snmp->{authKey} -l $snmp->{securityLevel} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -a $snmp->{authProtocol} -A $snmp->{authKey} -l $snmp->{securityLevel} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
elsif ( $ snmp - > { securityLevel } =~ /^authPriv$/i ) {
# Authenticated and encrypted request
if ( defined $ snmp - > { port } ) {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -l $snmp->{securityLevel} -a $snmp->{authProtocol} -A $snmp->{authKey} -x $snmp->{privProtocol} -X $snmp->{privKey} $snmp->{host}:$snmp->{port} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
else {
2018-10-30 17:53:57 +01:00
$ cmd = "snmpget -r $retries -t $timeout $snmp->{extra} -On -v $snmp->{version} -n \"$snmp->{context}\" -u $snmp->{securityName} -l $snmp->{securityLevel} -a $snmp->{authProtocol} -A $snmp->{authKey} -x $snmp->{privProtocol} -X $snmp->{privKey} $snmp->{host} $snmp->{oid}" ;
2017-11-14 15:17:27 +01:00
}
}
}
else {
return {
error = > "Only SNMP 1 2 2c and 3 are supported."
}
}
#print STDERR "Launched: $cmd\n";
my $ result = `$cmd` ;
if ( $? != 0 ) {
return {
error = > "No response from " . trim ( $ snmp - > { host } )
} ;
}
return snmp_data_switcher ( ( split /=\ / , $ result ) [ 1 ] ) ;
}
################################################################################
# returns a hash with [type->datatype][data->value]
################################################################################
2017-11-27 18:19:32 +01:00
sub snmp_data_switcher {
2017-11-14 15:17:27 +01:00
my @ st_data = split /\: / , $ _ [ 0 ] ;
my % data ;
my $ pure_data = trim ( $ st_data [ 1 ] ) or undef ;
$ data { data } = $ pure_data ;
if ( uc ( $ st_data [ 0 ] ) eq uc ( "INTEGER" ) ) {
$ data { type } = "generic_data" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Integer32" ) ) {
$ data { type } = "generic_data" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "octect string" ) ) {
$ data { type } = "generic_data" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "bits" ) ) {
$ data { type } = "generic_data" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "object identifier" ) ) {
$ data { type } = "generic_data_string" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "IpAddress" ) ) {
$ data { type } = "generic_data_string" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Counter" ) ) {
$ data { type } = "generic_data_inc" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Counter32" ) ) {
$ data { type } = "generic_data_inc" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Gauge" ) ) {
$ data { type } = "generic_data" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Unsigned32" ) ) {
$ data { type } = "generic_data_inc" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "TimeTicks" ) ) {
$ data { type } = "generic_data_string" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Opaque" ) ) {
$ data { type } = "generic_data_string" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "Counter64" ) ) {
$ data { type } = "generic_data_inc" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "UInteger32" ) ) {
$ data { type } = "generic_data" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "BIT STRING" ) ) {
$ data { type } = "generic_data_string" ;
}
elsif ( uc ( $ st_data [ 0 ] ) eq uc ( "STRING" ) ) {
$ data { type } = "generic_data_string" ;
}
else {
$ data { type } = "generic_data_string" ;
}
if ( $ data { type } eq "generic_data" ) {
( $ data { data } = $ pure_data ) =~ s/\D*//g ;
}
return \ % data ;
}
################################################################################
# returns a encrypted string
# $1 => string to be encrypted
# $2 => salt to use (default default_salt)
################################################################################
2017-11-27 18:19:32 +01:00
sub encrypt {
2017-11-14 15:17:27 +01:00
my ( $ str , $ salt , $ iv ) = @ _ ;
return undef unless ( load_perl_modules ( 'Crypt::CBC' , 'Crypt::OpenSSL::AES' , 'Digest::SHA' ) == 1 ) ;
if ( empty ( $ salt ) ) {
$ salt = "default_salt" ;
}
2017-11-29 17:13:12 +01:00
my $ processed_salt = substr ( Digest::SHA:: hmac_sha256_base64 ( $ salt , '' ) , 0 , 16 ) ;
2017-11-14 15:17:27 +01:00
if ( empty ( $ iv ) ) {
$ iv = "0000000000000000" ;
}
my $ cipher = Crypt::CBC - > new ( {
'key' = > $ processed_salt ,
'cipher' = > 'Crypt::OpenSSL::AES' ,
'iv' = > $ iv ,
'literal_key' = > 1 ,
'header' = > 'none' ,
'keysize' = > 128 / 8
} ) ;
my $ encrypted = encode_base64 ( $ cipher - > encrypt ( $ str ) ) ;
return $ encrypted ;
}
################################################################################
# returns a decrypted string from an encrypted one
# $1 => string to be decrypted
# $2 => salt to use (default default_salt)
################################################################################
2017-11-27 18:19:32 +01:00
sub decrypt {
2017-11-14 15:17:27 +01:00
my ( $ encrypted_str , $ salt , $ iv ) = @ _ ;
return undef unless ( load_perl_modules ( 'Crypt::CBC' , 'Crypt::OpenSSL::AES' , 'Digest::SHA' ) == 1 ) ;
if ( empty ( $ salt ) ) {
$ salt = "default_salt" ;
}
2017-11-29 17:13:12 +01:00
my $ processed_salt = substr ( Digest::SHA:: hmac_sha256_base64 ( $ salt , '' ) , 0 , 16 ) ;
2017-11-14 15:17:27 +01:00
if ( empty ( $ iv ) ) {
$ iv = "0000000000000000" ;
}
my $ cipher = Crypt::CBC - > new ( {
'key' = > $ processed_salt ,
'cipher' = > 'Crypt::OpenSSL::AES' ,
'iv' = > $ iv ,
'literal_key' = > 1 ,
'header' = > 'none' ,
'keysize' = > 128 / 8
} ) ;
my $ decrypted = $ cipher - > decrypt ( decode_base64 ( $ encrypted_str ) ) ;
return $ decrypted ;
}
################################################################################
# Return unix timestamp from a given string
################################################################################
sub get_unix_time {
my ( $ str_time , $ separator_dates , $ separator_hours ) = @ _ ;
2019-01-17 18:42:38 +01:00
return 0 if empty ( $ str_time ) ;
2017-11-14 15:17:27 +01:00
if ( empty ( $ separator_dates ) ) {
$ separator_dates = "\/" ;
}
if ( empty ( $ separator_hours ) ) {
$ separator_hours = ":" ;
}
2019-01-17 18:42:38 +01:00
my $ time ;
eval {
use Time::Local ;
my ( $ mday , $ mon , $ year , $ hour , $ min , $ sec ) = split ( /[\s$separator_dates$separator_hours]+/ , $ str_time ) ;
2020-01-02 15:46:27 +01:00
$ time = strftime ( "%s" , $ sec , $ min , $ hour , $ mday , $ mon - 1 , $ year ) ;
2019-01-17 18:42:38 +01:00
} ;
if ( $@ ) {
return 0 ;
}
2017-11-14 15:17:27 +01:00
return $ time ;
}
################################################################################
# Load required modules.
################################################################################
sub load_perl_modules {
my @ missing_modules = ( ) ;
foreach ( @ _ ) {
eval "require $_" ;
push @ missing_modules , $ _ if $@ ;
}
if ( @ missing_modules ) {
print "Missing perl modules: @missing_modules\n" ;
return 0 ;
}
return 1 ;
}
2018-03-01 09:29:36 +01:00
################################################################################
# Transforms an absolute seconds value into a readable count
################################################################################
sub seconds2readable {
my ( $ tseconds , $ format ) = @ _ ;
return '' unless looks_like_number ( $ tseconds ) ;
if ( empty ( $ format ) ) {
return int ( $ tseconds / ( 24 * 60 * 60 ) ) . " d, "
. ( $ tseconds / ( 60 * 60 ) ) % 24 . "h, "
. ( $ tseconds / 60 ) % 60 . "m, "
. $ tseconds % 60 . "s" ;
}
my $ str = $ format ;
# %d -> days
if ( $ format =~ /\%d/ ) {
my $ days = ( $ tseconds / ( 24 * 60 * 60 ) ) | 0 ;
$ tseconds -= $ days * 24 * 60 * 60 ;
$ str =~ s/%d/$days/g ;
}
# %h -> hours
if ( $ format =~ /\%h/ ) {
my $ hours = ( $ tseconds / ( 60 * 60 ) ) | 0 ;
$ tseconds -= $ hours * 60 * 60 ;
$ str =~ s/%h/$hours/g ;
}
# %m -> minutes
if ( $ format =~ /\%m/ ) {
my $ min = ( $ tseconds / 60 ) | 0 ;
$ tseconds -= $ min * 60 ;
$ str =~ s/%m/$min/g ;
}
# %s -> seconds
if ( $ format =~ /\%s/ ) {
$ str =~ s/%s/$tseconds/g ;
}
2017-11-14 15:17:27 +01:00
2018-03-01 09:29:36 +01:00
return $ str ;
}
2017-11-14 15:17:27 +01:00
2018-03-02 14:21:01 +01:00
################################################################################
# Extracts a database password from file or environment
################################################################################
sub extract_dbpass {
my ( $ config ) = @ _ ;
return $ config - > { 'dbpass' } unless empty ( $ config - > { 'dbpass' } ) ;
2017-11-14 15:17:27 +01:00
2018-03-02 14:21:01 +01:00
if ( ! empty ( $ config - > { 'dbpass_file' } ) ) {
if ( - f $ config - > { 'dbpass_file' } ) {
eval {
open ( my $ pf , "<" , $ config - > { 'dbpass_file' } ) or die ( "Cannot open file " . $ config - > { 'dbpass_file' } ) ;
$ config - > { 'dbpass' } = trim ( <$pf> ) ;
close ( $ pf ) ;
} ;
if ( $@ ) {
print_error ( $ config , "Failed to read password file" . $@ , 1 ) ;
exit ;
}
}
else {
print_error ( $ config , "Failed to read password file" , 1 ) ;
exit ;
}
}
elsif ( ! empty ( $ config - > { 'dbpass_env_var_name' } ) ) {
if ( ! empty ( $ ENV { $ config - > { 'dbpass_env_var_name' } } ) ) {
$ config - > { 'dbpass' } = $ ENV { $ config - > { 'dbpass_env_var_name' } } ;
}
if ( empty ( $ config - > { 'dbpass' } ) ) {
print_error ( $ config , "Failed to read password from environment" , 1 ) ;
exit ;
}
}
return $ config - > { 'dbpass' } ;
}
2018-03-05 14:27:51 +01:00
################################################################################
# Extracts IP addresses (IPv4) from current system
################################################################################
sub get_addresses {
my ( $ config ) = @ _ ;
my $ address = '' ;
if ( is_enabled ( $ config - > { 'local' } ) ) {
$ address = $ config - > { 'dbhost' } ;
}
elsif ( $^O !~ /win/i ) {
my @ address_list ;
if ( - x "/bin/ip" || - x "/sbin/ip" || - x "/usr/sbin/ip" ) {
@ address_list = `ip addr show 2>$DevNull | sed -e '/127.0.0/d' -e '/[0-9]*\\.[0-9]*\\.[0-9]*/!d' -e 's/^[ \\t]*\\([^ \\t]*\\)[ \\t]*\\([^ \\t]*\\)[ \\t].*/\\2/' -e 's/\\/.*//'` ;
}
else {
@ address_list = `ifconfig -a 2>$DevNull | sed -e '/127.0.0/d' -e '/[0-9]*\\.[0-9]*\\.[0-9]*/!d' -e 's/^[ \\t]*\\([^ \\t]*\\)[ \\t]*\\([^ \\t]*\\)[ \\t].*/\\2/' -e 's/.*://'` ;
}
for ( my $ i = 0 ; $ i <= $# address_list ; $ i + + ) {
chomp ( $ address_list [ $ i ] ) ;
if ( $ i > 0 ) {
$ address . = ',' ;
}
$ address . = $ address_list [ $ i ] ;
}
}
return $ address ;
}
2017-11-14 15:17:27 +01:00
1 ;