#!/usr/bin/perl
# nagios: -epn
# ============================== SUMMARY =====================================
#
# Program : check_xml2snmp.pl
# Version : 1.4.4
# Date    : 05 27 2015
# Author  : Fabien Bizet - tokiess@gmail.com
# Summary : This is a nagios plugin Translate a XML file to snmp request
#           monitored SNMP and return nagios code
#
# Licence : GPL - summary below, full text at http://www.fsf.org/licenses/gpl.txt
#
# 1.4.4 may 27 2015
# ADD option warning-custom =xml type name ex => fgHaStatsSesCount in fortigate xml file
#            warning = value
#            critical = value 
#            ex -w 80000 -c 90000 --warning-custom fgHaStatsSesCount
# 1.4.3 oct 08 2013
#           accept : value-secondary idlike part oid index filter
#	  --value-secondary idlike=1.1922986878
#          in XML definition  : section seuil_oid can use warning_oid and critical_oid
# 1.4.2 aout 01 2013
#           modif function show for no exit with no response snmp get table
#	  when use --value-secondary  and [dev or if ]not init can be paste must put not use in value
# 1.4.1 April 03 2013 
#           add  function show for interpret array show in xml file
# 1.4.0 Mars 18 2013 default is unknow 
# 	add sub analyze_array_to_secondary can determine in array describ the good oid index
# 	manage in analyze_array_to_secondary sub a conditional with multiple enter
#        condition is aruba-ap mac address and name ESSID  give the index oid 
#        ex --value-secondary dev1=0x6cf37fc42818:condition=and:dev2=MY_ESSID
# 1.3.1  mars 06 2013 can use maxbw only for option --value-secondary 
#                with all type can use --value-secondary 
#               optimization request snmp with filter --value-secondary
#              can use option id=index oid with --value-secondary
# 1.3.0	 can specifie return integer value in counter type
#        define screen return in table screen
#        can specifie value referer or snmp referer in counter pourcent type
# 1.2.2  compatible strict and epn
# 1.2.1  3 type counter Calc pourcent, simple, average 
# 1.2.0  support counter variable with tmp file in directory /var/lib/nagios
#        2 type counter Calc pourcent and simple
#        can be use a new variable : value-secondary for select a part off return 
# 1.1.2 bug in calc_p100_mem  div on 0
# 1.1.1 return data compatible graph ex PNP4 ...
# 1.1.0 perform calc_p100_mem can use memory pourcent from total with type use_total or free_total
# =========================== PROGRAM LICENSE =================================
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ===================== INFORMATION ABOUT THIS PLUGIN =========================
#
# This plugin is a new generation : analyse data from XML file   of objects monitored via SNMP
# and returns OK, WARNING, CRITICAL or UNKNOWN.  If a failure occurs it will
# describe the subsystem that failed and the failure code.
#
# This program is written and maintained by:
#   Fabien Bizet - tokiess(at)gmail.com
#
#
# Using information from
# 
# different tables :
# 
# global_oids
# this table contain all OID use
# in xml file        : <table name="global_oids"></table>
# in program         : $data_xml->{'table'}->{'global_oid'}
# in XML definition  : <sysObjectID>1.3.6.1.2.1.1.2</sysObjectID>
# in prog definition : $data_xml->{'table'}->{'global_oid'}->{'sysObjectID'}='1.3.6.1.2.1.1.2'
#
# system_types
# this table contain the referer by option -T 
# each enregistrement give the OIDS for options 
# in xml file        : <table name="system_types"></table>
# in program         : $data_xml->{'table'}->{'system_types'}
# in XML definition  : <env>cpmCPUTotalPhysicalIndex</env>
#                      <env>ciscoEnvMonFanState</env>
#                      <env>ciscoEnvMonSupplyState</env>
# in prog definition : $data_xml->{'table'}->{'system_types'}->{'env'}=>[
#                                                                         'cpmCPUTotalPhysicalIndex',
#                                                                         'ciscoEnvMonFanState',
#                                                                         'ciscoEnvMonSupplyState'
#                                                                       ]
#
# correspond
# This table translate the value of respoonse SNMP in string value
# in xml file        : <table name="correspond">
# in program         : $data_xml->{'table'}->{'correspond'}
# in XML definition  : <cHsrpGrpStandbyState>
#                       <value index="1">initial</value>
#                       <value index="2">learn</value>
#                       <value index="3">listen</value>
#                       <value index="4">speak</value>
#                       <value index="5">standby</value>
#                       <value index="6">active</value>
#                      </cHsrpGrpStandbyState>
# in prog definition : $data_xml->{'table'}->{'system_types'}->{'cHsrpGrpStandbyState'}=>{
#                                                         'value' => [{'index' => '1','content' => 'initial'},
#                                                                     {'index' => '2','content' => 'learn'},
#                                                                     {'index' => '3','content' => 'listen'},
#                                                                     {'index' => '4','content' => 'speak'},
#                                                                     {'index' => '5','content' => 'standby'},
#                                                                     {'index' => '6','content' => 'active'}]
#                                                                                           
#
# value_statuscode
# this table give the nagios code to the correspond value
# in xml file        : <table name="value_statuscode">
# in program         : $data_xml->{'table'}->{'value_statuscode'}
# in XML definition  : <cHsrpGrpStandbyState>
#                        <initial>WARNING</initial>
#                        <learn>WARNING</learn>
#                        <listen>WARNING</listen>
#                        <speak>WARNING</speak>
#                        <standby>OK</standby>
#                        <active>OK</active>
#                      </cHsrpGrpStandbyState>
# in prog definition : $data_xml->{'table'}->{'system_types'}->{'cHsrpGrpStandbyState' => {
#                                                                     'speak' => 'WARNING',
#                                                                     'standby' => 'OK',
#                                                                     'listen' => 'WARNING',
#                                                                     'active' => 'OK',
#                                                                     'initial' => 'WARNING',
#                                                                     'learn' => 'WARNING'
#                                                                  },
#
# relation_oid
# with this table you can give a describ from index for a responce SNMP
# ex : the test is on 'cswSwitchState' but it's a value for a index 
#      and you don't know what is this 
#      with the index number you can have the describ at 'entPhysicalModelName'
# in xml file        : <table name="relation_oid">
# in program         : $data_xml->{'table'}->{'relation_oid'}
# in XML definition  : <cswSwitchState>entPhysicalModelName</cswSwitchState>
# in prog definition : $data_xml->{'table'}->{'relation_oid'}->{'cswSwitchState' => 'entPhysicalModelName'}
#
#
# seuil
# table determined the threshold warning and critical for a value 
# the threshold can be up or down
# ex : for perCentCPUUtilization warning = 75 critical = 90 type = up
# in xml file        : <table name="seuil">
# in program         : $data_xml->{'table'}->{'seuil'}
# in XML definition  :   <perCentCPUUtilization>
#                           <WARNING>75</WARNING>
#                           <CRITICAL>90</CRITICAL>
#                           <type>up</type>
#                        </perCentCPUUtilization>
# in prog definition : $data_xml->{'table'}->{'seuil'}->{'perCentCPUUtilization' => {                                                                        
#                                                           'WARNING' => '75',                                                                            
#                                                           'CRITICAL' => '90',                                                                              
#                                                           'type' => 'up'                                                                                   
#                                                         }
#
# seuil_oid
# it's same seuil but value and other information are in other OIDs
# the threshold can be up, down, memory or status
# ex : cpmCPUTotalPhysicalIndex value cpmCPUTotal5sec warning = 75 critical = 90 type = up
# in xml file        : <table name="seuil_oid">
# in program         : $data_xml->{'table'}->{'seuil_oid'}
# in XML definition  :   <cpmCPUTotalPhysicalIndex>
#                           <WARNING>75</WARNING>
#                           <CRITICAL>90</CRITICAL>
#                           <value>cpmCPUTotal5sec</value>
#                           <type>up</type>
#                        </perCentCPUUtilization>
# in prog definition : $data_xml->{'table'}->{'seuil_oid'}->{'perCentCPUUtilization' => {
#                                                           'WARNING' => '75',
#                                                           'CRITICAL' => '90',
#                                                           'CRITICAL' => 'cpmCPUTotal5sec',
#                                                           'type' => 'up'
#                                                         }
# for memory more information is requiered for calcule % : mem_free, mem_use and mem_type (use or free)
# ex : ciscoMemoryPoolValid 
# in XML definition  :  <ciscoMemoryPoolValid>
#                          <mem_use>ciscoMemoryPoolUsed</mem_use>
#                          <mem_free>ciscoMemoryPoolFree</mem_free>
#                          <type>memory</type>
#                          <mem_type>use</mem_type>
#                          <warning>80</warning>
#                          <critical>95</critical>
#                        </ciscoMemoryPoolValid>
#
# show
# This table translate the value of respoonse SNMP in string value
# in xml file        : <table name="show">
# in program         : $data_xml->{'table'}->{'show'}
# in XML definition  :  
# <option>
#      <option_type>
#		<cell>1</cell> -->position in screen array
#		<OID>ifDescr</OID> --> name oid for do a get table
#	</option_type>
#	<option_describ>Describ Interface : Index Interface</option_describ> --> header array to see
#  </option> 
    
# option
# it's definition of parameter for all test in the xml file . see the diferents options when help is use
# definition: 
# option_type                  =>   parameter for -T 
# option_type_secondary        =>   parameter for type-secondary secondary of -T option
# option_type_secondary_list   =>   list of type of secondary option
# option_type_describ          =>   a simply describ of differents types
# 




 use strict;
use Data::Dumper;
use Getopt::Long;
use Math::Round;
# use Parse::File::Metadata;
# use XML::Parser;
# use XML::Simple;





my %sensor = ();
my %seuil =();
my %tmp =();
my %value_statuscode =();
my %relation_oid =();
my %seuil_oid =();
my %tmp_seuil =();
my %varlist = ();
my %data_xml= ();
my $data_xml = undef;
my $xml = undef;
my $data_dir="/var/lib/nagios";

# table of list name => oid



#use check_table_snmp;
# require 'check_table_snmp.pm';
# print Dumper %global_oids;

my %global_oids = ();
my @array_screen_name = ();
my @array_screen_value = ();
my @array_screen_value_complement = ();
my @array_screen_value_origine = ();
my @array_screen_nagios = ();

# $xml = new XML::Simple;


my ($session,$error);
my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);

my $Version='1.4.3';
my $o_host=     undef;          # hostname
my $o_community= undef;         # community
my $o_port=     161;            # SNMP port
my $o_help=     undef;          # help option
my $o_verb=     undef;          # verbose mode
my $o_version=  undef;          # version info option
my $o_warn=     undef;          # warning level option
my $o_warn_custom= undef;       # warning custom
my @o_warnL=    ();             # array for above list
my $o_crit=     undef;          # Critical level option
my @o_critL=    ();             # array for above list
my $o_timeout=  5;              # Default 5s Timeout
my $o_version2= undef;          # use snmp v2c
# SNMPv3 specific
my $o_login=    undef;          # Login for snmpv3
my $o_passwd=   undef;          # Pass for snmpv3
my $o_attr=     undef;          # What attribute(s) to check (specify more then one separated by '.')
my @o_attrL=    ();             # array for above list
my $o_unkdef=   2;              # Default value to report for unknown attributes
my $o_type=     undef;          # Type of system to check
my $o_show=     undef;          # Type of system to check
my $o_type_secondary=undef;        # Type of system to check
my $o_debug=	undef;		# mode debug
my $o_fw_cluster= undef;	# definit if fw is cluster 
my $o_fw_session= undef;        # definit the max sessions open fw 
my $o_value_secondary = undef;
my $o_file = undef;

my $new_oid = undef;
  my $tmp_value_secondary = undef; # var system_type_to_analyse when o_value_secondary must be init
#my $attr = undef;


sub print_version { print "$0: $Version\n" };




sub print_usage {
        print "Usage: $0 [-v] -H <host> -C <snmp_community> [-2] | (-l login -x passwd)  [-P <port>] -F <XML data> -T ".$data_xml->{'table'}->{'option'}->{'option_type'}." [-t <timeout>] [-V] [-u <unknown_default>] --type-secondary\n";
}

sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; }

# Get the alarm signal (just in case snmp timout screws up)
$SIG{'ALRM'} = sub {
     print ("ERROR: Alarm signal (Nagios time-out)\n");
          exit $ERRORS{"UNKNOWN"};
};


sub help {
        my $ko = undef;
	my $aff_type_secondary = undef;
	my $count_secondary = undef;
        print "\nXML TO SNMP  Monitor for Nagios version ",$Version,"\n";
	print " by Fabien Bizet - tokiess(at)gmail.com\n\n";
	&print_usage();
	if(&is_array($data_xml->{'table'}->{'option'}{'option_type_secondary'})){
	  #my $count_secondary = @{$data_xml->{'table'}->{'option'}{'option_type_secondary'}};
	  $count_secondary = @{$data_xml->{'table'}->{'option'}{'option_type_secondary'}};
	}
        if($count_secondary >> 0){
          my $x=0;
          foreach $ko (@{$data_xml->{'table'}->{'option'}{'option_type_secondary'}})
          {
            $aff_type_secondary.="--type-secondary=".$data_xml->{'table'}->{'option'}{'option_type_secondary_list'}{$ko}."\n";
            $aff_type_secondary.="This allows use with type $ko \n";
            $x++;
          }
        }elsif(defined($data_xml->{'table'}->{'option'}{'option_type_secondary'})){
            $ko=$data_xml->{'table'}->{'option'}{'option_type_secondary'};
            $aff_type_secondary.="--type-secondary=".$data_xml->{'table'}->{'option'}{'option_type_secondary_list'}{$ko}."\n";
            $aff_type_secondary.="     This allows use with type $ko \n";
        }
        print <<EOD;
-v, --verbose
        print extra debugging information
-h, --help
        print this help message
-H, --hostname=HOST
        name or IP address of host to check
-C, --community=COMMUNITY NAME
        community name for the host's SNMP agent (implies v 1 protocol)
-2, --v2c
        use SNMP v2 (instead of SNMP v1)
-P, --port=PORT
        SNMPd port (Default 161)
-t, --timeout=INTEGER
        timeout for SNMP in seconds (Default: 5)
-w, --warning=integer
        value work only with warning-custom
-c, --critical=integer
        value work only with warning-custom
--warning-custom only with -c and -w
        find in xml file  seuil section value you want custom
-V, --version
        prints version number
-F, --file XML data
--show
-T, --type=$data_xml->{'table'}->{'option'}->{'option_type'}
        $data_xml->{'table'}->{'option'}->{'option_type_describ'}
$aff_type_secondary
EOD
}


sub is_array {
  my $ref = shift;
  return 0 unless ref $ref;
  if ( ref($ref) eq "ARRAY" ) { return 1; } else { return 0; }
}


sub calc_p100_mem {
  my $use=$_[0];
  my $free=$_[1];
  my $total=$_[2];
  my $type=$_[3];
  my $return=0;
  if($use > 0 || $free >0){
   if($type eq "free" ){
	$return = round(($free*100)/($use+$free));
   }elsif($type eq "use" ){
 	$return = round(($use*100)/($use+$free));
   }elsif($type eq "use_total" ){
        $return = round(($use*100)/($total));
   }elsif($type eq "free_total" ){
        $return = round(($free*100)/($total));
   }
  }elsif($type eq "free_total" ){$return=100;}
  if($o_debug){print "calc mem de use => $use free => $free total => $total recupe type $type => $return \n";}
  return $return;
}

sub check_options {
    Getopt::Long::Configure ("bundling");
    GetOptions(
	        'v'     => \$o_verb,            'verbose'       => \$o_verb,
	        'h'     => \$o_help,            'help'          => \$o_help,
	        'H:s'   => \$o_host,            'hostname:s'    => \$o_host,
	        'P:i'   => \$o_port,            'port:i'        => \$o_port,
	        'C:s'   => \$o_community,       'community:s'   => \$o_community,
	        'l:s'   => \$o_login,           'login:s'       => \$o_login,
	        'x:s'   => \$o_passwd,          'passwd:s'      => \$o_passwd,
	        't:i'   => \$o_timeout,         'timeout:i'     => \$o_timeout,
	        'V'     => \$o_version,         'version'       => \$o_version,
	        '2'     => \$o_version2,        'v2c'           => \$o_version2,
	        'u:i'   => \$o_unkdef,          'unknown_default:i' => \$o_unkdef,
	        'T:s'   => \$o_type,            'type:s'        => \$o_type,
	        'w:i'   => \$o_warn,            'warning:s'        => \$o_warn,
	        'c:s'   => \$o_crit,            'critical:s'        => \$o_crit,

			'F:s'	=> \$o_file,		'file:s'	=> \$o_file,	
		'type-secondary:s' => \$o_type_secondary,
		'value-secondary:s' => \$o_value_secondary,
		'fw-cluster' => \$o_fw_cluster,
		'max-session:i' => \$o_fw_session,
		'warning-custom:s' => \$o_warn_custom,
        'show'           => \$o_show,
		'D'     => \$o_debug,         'debug'       => \$o_debug,
    );

    if($o_debug){print "begin check options\n";}
    if (defined($o_help) ) {
      if(defined($o_file)){&load_xml($o_file);} 
      help(); exit $ERRORS{"UNKNOWN"}; 
    }
    if (defined($o_version)) { print_version(); exit $ERRORS{"UNKNOWN"}; }
    if (! defined($o_host) ) # check host and filter
    { print "No host defined!\n";print_usage(); exit $ERRORS{"UNKNOWN"}; }
    if (! defined($o_file))
    {print "No file XML defined!\n";print_usage(); exit $ERRORS{"UNKNOWN"};}
    else{
      if(!load_xml($o_file)){print "file XML no exist!\n";print_usage(); exit $ERRORS{"UNKNOWN"};}
    }
    # check snmp information
    if (!defined($o_community) && (!defined($o_login) || !defined($o_passwd)) )
    { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; }
    if (defined($o_show) ) {
      if(defined($o_file)){&load_xml($o_file);}
	  &connect_snmp();
      &show(); 
    }
    
	if (!defined($o_type)) { print "Must define system type!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; }
    # $data_xml = $xml->XMLin('/home/tokiess/nagios/data.xml');
    if (defined ($o_type)) {
	    if ($o_type eq "test"){
       		print "TEST MODE:\n";
    	    } #elsif (!defined($system_types{$o_type}))  {
      		#print "Unknown system type $o_type !\n"; print_usage(); exit $ERRORS{"UNKNOWN"};
    	    #}

      if(defined ($o_fw_session)){
        $seuil{'cfwConnectionStatValue'}{'CRITICAL'}=$o_fw_session;
        $seuil{'cfwConnectionStatValue'}{'WARNING'}= round($o_fw_session * 0.9 );
      }
    }
}

sub load_xml {
  if(-e $_[0]){$data_xml = $xml->XMLin($_[0]);return 1;}
  else{return 0;}
}


sub Delete_Tab
{
    my $Position = shift;
    my @OldTab = @_;
    my @NewTab;
 
    for (my $i = 0; $i < scalar(@OldTab); ++$i)
    {
        push(@NewTab, $OldTab[$i]) if ($OldTab[$i] ne $Position);
    }
 
    return @NewTab;
}


sub my_sort_key{
	my $array_sort = shift;
	my $ref = undef;
	my $x=0;
	my $ref_count = @{$array_sort};
	my $ref_return = 0;
	my @return_sort =();
	if($o_debug){print "my sort key : nb $ref_count input : \n";print Dumper $array_sort;}
	#if(&is_array($array_sort)){
		while ($ref_return ne $ref_count ){
			$x=0;
			foreach my $value (@{$array_sort}){
				if($value=~m/^\d+$/){
					if($o_debug){print "my key is numeric only $value\n";}
					if($x == 0){$ref=$value;}
					if($ref > $value){$ref=$value;}
				}else{
					if($o_debug){print "my key is no numeric only $value\n";}
					$ref_return =$ref_count;
				}
				$x++;
			}
			if(defined($ref)){
				push(@return_sort,$ref);
				$ref_return = @return_sort;
				@{$array_sort}=Delete_Tab($ref,@{$array_sort});
				if($o_debug){
					print "my sort key : small value $ref\n";
					print "my sort key : array return $ref_return on $ref_count\n";
					print Dumper @return_sort;
					print Dumper $array_sort;
		
				}
			
			}else{
				@return_sort=@{$array_sort};
			}
		}
	#}
	return @return_sort;
}




sub show_option {
#$_[0] value in show option : option_type and option_describ
#return screen option
	my $return = undef;
	
	my $array_option = shift;
	my $index = undef;
	my @snmpoids = ();
	my %result_array = ();
	my %array_screen =();
	my %option_type = ();
	if($o_debug){
			print "show_option : hash input\n";
			print Dumper $array_option;
	}
		
	if(defined($array_option->{'option_describ'})){
		if($o_debug){print "show option : option describ =>".$array_option->{'option_describ'}."\n";}
		if(defined($array_option->{'option_type'})){
			if(&is_array($array_option->{'option_type'})){
				foreach my $kr (@{$array_option->{'option_type'}}){
					%option_type=%{$kr};
					if($o_debug){
						print Dumper %option_type;
						print "show option : option type =>".$option_type{'OID'}." ".$data_xml->{'table'}->{'global_oids'}->{$option_type{'OID'}}."\n";
					}
				
					$result_array{$option_type{'OID'}}{'SNMP'} = &my_snmp_get_table($data_xml->{'table'}->{'global_oids'}->{$option_type{'OID'}});
					$result_array{$option_type{'OID'}}{'CELL'} = $option_type{'cell'};
				
				}
			}else{
				%option_type=%{$array_option->{'option_type'}};
				if($o_debug){
					print Dumper %option_type;
					print "show option : option type =>".$option_type{'OID'}." ".$data_xml->{'table'}->{'global_oids'}->{$option_type{'OID'}}."\n";
				}
				
				$result_array{$option_type{'OID'}}{'SNMP'} = &my_snmp_get_table($data_xml->{'table'}->{'global_oids'}->{$option_type{'OID'}});
				$result_array{$option_type{'OID'}}{'CELL'} = $option_type{'cell'};
				
			}
			if($o_debug){print "show option : array snmp get table \n";print Dumper %result_array;}
			
			foreach my $kr (keys %result_array){
				if($o_debug){print "show option : result array =>".$kr." ".$data_xml->{'table'}->{'global_oids'}->{$kr}."\n";print Dumper $result_array{$kr};}
				#if(&is_array($result_array{$kr}{'SNMP'})){
					foreach my $oid (keys %{ $result_array{$kr}{'SNMP'} }){
						my $index = $oid;
						$index =~ s/$data_xml->{'table'}->{'global_oids'}->{$kr}\.//g ;
				
						if($o_debug){print "show option : dans $kr oid ".$oid." value ".$result_array{$kr}{'SNMP'}{$oid}." index :".$index."\n";}
						if($result_array{$kr}{'SNMP'}{$oid}){
							$array_screen{$index}[$result_array{$kr}{'CELL'}]=$result_array{$kr}{'SNMP'}{$oid};
						}
					}
				#}
				
			}
		}
		$return="---------".$array_option->{'option_describ'}."---------\n";
		if($o_debug){print "show option : array screen \n";print Dumper %array_screen;}
		
		my @keys_array = sort keys %array_screen;
		@keys_array = my_sort_key(\@keys_array);
		if($o_debug){print "show option : array KEY SORT \n";print Dumper @keys_array;}
		
		foreach $index ( @keys_array){
			$return.=join(' : ',@{$array_screen{$index}});
			$return.=" : index : $index \n";
			
		}
			
	}
	
	return $return;
}


sub show {

	my $return = undef;
	if(defined($data_xml->{'table'}->{'show'})){
		if($o_debug){
			print "show : show exist in xml\n";
			print Dumper($data_xml);
		}
		#my $nb = scalar @{$data_xml->{'table'}->{'show'}->{'option'}};
		#if($o_debug){print "show nb option $nb \n";}
		if(&is_array($data_xml->{'table'}->{'show'}->{'option'})){
			if($o_debug){print "show option is array \n";}
			foreach my $kr (@{$data_xml->{'table'}->{'show'}->{'option'}}){
				if($o_debug){print "show each option  \n";print Dumper $kr;}
				my %array_transmit=%{$kr};
				$return.=&show_option(\%array_transmit);
			}
		}else{
			if($o_debug){print "show option is single \n";}
			$return.=&show_option(\%{$data_xml->{'table'}->{'show'}->{'option'}});
		}
		#foreach my $kr (keys(%{$data_xml->{'table'}->{'show'}->{'option'}}))
		#{
		#}
      
        
	}else{
		if($o_debug){print "show : show no exist in xml\n";}
        
	}
	
	print $return;
	exit;
}


sub variable_status {
	# $_[0] = $attr
	# $_[1] = 
        my $return = '';
        my $nrm = '';
        my $type_nrm ='';
        my $val_max = undef;
        my $val_min = undef;
	my %norme = ();
	my %value_norme = ();
        if($o_debug){print "variable status to nagios $_[0] $_[1] ";}
        if(!defined($data_xml->{'table'}->{'global_oids'}->{$_[0]})){return "error variable";}
        elsif( defined($data_xml->{'table'}->{'value_statuscode'}->{$_[0]}) )
        {
          if($o_debug){print " value statuscode ".$data_xml->{'table'}->{'value_statuscode'}->{$_[0]}{$_[1]}."\n";}
          $return=$data_xml->{'table'}->{'value_statuscode'}->{$_[0]}{$_[1]};
        }
        elsif( defined($value_norme{$_[0]}) ){
          for my $k_n (keys %{$value_norme{$_[0]}} ) {
            $nrm = $k_n;
            $type_nrm = $value_norme{$_[0]}{$k_n};
          }
          $val_max = $norme{$nrm}{$type_nrm.'_max'};
          $val_min = $norme{$nrm}{$type_nrm.'_min'};
          if($val_min < $_[1] && $val_max > $_[1]){$return='OK';}
          else{$return='WARNING';}
          if($o_debug){
            print " value $_[1] norme $nrm $type_nrm $val_max $val_min $return \n";
            print Dumper $value_norme{$_[0]} ;
          }
        }
        else{
		
			if(defined($o_warn_custom)){
		#if($o_debug){print "seuil_relation replace ok $o_warn_custom && $_[0] \n";}
				if( $o_warn_custom eq $_[0]){
					if(defined($o_warn) && defined($o_crit)){
						if($o_debug){
							print "seuil_relation variable_status replace $_[0] OK ";
							print $data_xml->{'table'}->{'seuil'}->{$_[0]}{'WARNING'}." warn && crit ".$data_xml->{'table'}->{'seuil'}->{$_[0]}{'CRITICAL'};
							print " to $o_warn && $o_crit \n"
						}
						$data_xml->{'table'}->{'seuil'}->{$_[0]}{'WARNING'} = $o_warn;
						$data_xml->{'table'}->{'seuil'}->{$_[0]}{'CRITICAL'} = $o_crit;
						
						if($o_debug){
							print "variable status to nagios seuil_relation variable_status replace $_[0] ";
							print $data_xml->{'table'}->{'seuil'}->{$_[0]}{'WARNING'}." warn && crit ".$data_xml->{'table'}->{'seuil'}->{$_[0]}{'CRITICAL'};
							print "\n";
						}
						
					}
				}
			}
		
          if(defined($data_xml->{'table'}->{'seuil'}->{$_[0]})){
            if( $data_xml->{'table'}->{'seuil'}->{$_[0]}{'type'} eq 'up' ){
              $return='OK';
              if( $_[1] >= $data_xml->{'table'}->{'seuil'}->{$_[0]}{'WARNING'} ){
                $return='WARNING';
              }
              if( $_[1] >= $data_xml->{'table'}->{'seuil'}->{$_[0]}{'CRITICAL'} ){
                $return='CRITICAL';
              }
            }
         
          if( $data_xml->{'table'}->{'seuil'}->{$_[0]}{'type'} eq 'down' ){
            $return='OK';
            if( $_[1] <= $data_xml->{'table'}->{'seuil'}->{$_[0]}{'WARNING'} ){
              $return='WARNING';
            }
            if( $_[1] <= $data_xml->{'table'}->{'seuil'}->{$_[0]}{'CRITICAL'} ){
              $return='CRITICAL';
            }
          }
          if($o_debug){
            print "variable status to nagios : simple  ";
			print $data_xml->{'table'}->{'seuil'}->{$_[0]}{'WARNING'}." ".$data_xml->{'table'}->{'seuil'}->{$_[0]}{'CRITICAL'};
			print " $_[1] ".$data_xml->{'table'}->{'seuil'}->{$_[0]}{'type'}." $return \n";
          }
        }
       }

	if($o_debug){print " $return \n";}
	return $return;
}

#sub affiche_resultat {
#  print Dump $_;
#  print " dump affichage \n";
#  for $attr (sort keys %{$_[0]}){
    #print @{$_0{$attr}};
#    foreach my $ligne (@{$_[0]{$attr}}){
      #print @{$ligne};
      #print "\n";
#      print " \'${$ligne}[0]\'  \'${$ligne}[1]\'  \'${$ligne}[2]\'  \'${$ligne}[3]\' \'${$ligne}[4]\'\n";
#    }
#  }
#}

sub seuil_to_nagios {
# arg 0 => value
# arg 1 => warning
# arg 2 => critical
# arg 3 => type up|down
  my $return_nagios=undef;

  if( defined($_[0]) && defined($_[1]) && defined($_[2]) && defined($_[3]) ){
    if($_[3] eq "up"){
      if($o_debug){print "seuil value : test UP \n";}
      if( $_[0] >= $_[1] ){ $return_nagios='WARNING'; }
      if( $_[0] >= $_[2]){ $return_nagios='CRITICAL'; }
      if(!defined($return_nagios)){ $return_nagios='OK'; }

    }

    if($_[3] eq "down"){
      if($o_debug){print "seuil value : test DOWN \n";}
      if( $_[1] >= $_[0] ){ $return_nagios='WARNING'; }
      if( $_[2] >= $_[0]){ $return_nagios='CRITICAL'; }
      if(!defined($return_nagios)){ $return_nagios='OK'; }

    }
  }
  if($o_debug){print "seuil value : $_[0] warn $_[1] crit $_[2] type $_[3] result $return_nagios \n";}
  return $return_nagios;
}

sub seuil_relation_oid_to_value {
# arg 0 => attr
# arg 1 => index
# arg 2 => value attr
# arg 3 => num table oid
  my $oid_relation = undef;
  my $info_relation = undef;
  my $type_seuil = undef;
  my $critical_nagios = undef;
  my $warning_nagios = undef;
  my $value_nagios = undef;
  my $tmp_name = undef;
  my $kr = undef;

  my %return = ();
  if($o_debug){print "seuil_relation_oid_to_value : begin : attr  ".$_[0]." : index ".$_[1]." : value ".$_[2]." : num tab oid ".$_[3]."\n";}
    
  if(defined($_[3])){
    if($o_debug){print "seuil_relation_oid_to_value : sueil_oid : ".$_[3]."\n";print Dumper($data_xml->{'table'}->{'seuil_oid'});}
    $tmp_seuil{'name'}[$_[3]]=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'value'}[$_[3]];
    # recupere OID.index de value en court et on passe snmpget
    $oid_relation="$data_xml->{'table'}->{'global_oids'}{$tmp_seuil{'name'}[$_[3]]}.$_[1]";
    $tmp_seuil{'value'}[$_[3]] = &my_snmp_get($oid_relation);
	$tmp_seuil{'type'}[$_[3]] = $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'type'}[$_[3]];
	
	if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning_oid'}[$_[3]])){
        $tmp_name=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning_oid'}[$_[3]];
		$oid_relation="$data_xml->{'table'}->{'global_oids'}{$tmp_name}.$_[1]";
		$tmp_seuil{'warning'}[$_[3]] = &my_snmp_get($oid_relation);
     }else{
		$tmp_seuil{'warning'}[$_[3]] = $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'}[$_[3]];
     }
	
	if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical_oid'}[$_[3]])){
        $tmp_name=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical_oid'}[$_[3]];
		$oid_relation="$data_xml->{'table'}->{'global_oids'}{$tmp_name}.$_[1]";
		$tmp_seuil{'critical'}[$_[3]] = &my_snmp_get($oid_relation);
     }else{
		$tmp_seuil{'critical'}[$_[3]] = $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'}[$_[3]];
     }
	
	
	if($o_debug){print "seuil_relation_oid_to_value : tmp_seuil : ".$tmp_seuil{'name'}[$_[3]]." oid relation ".$oid_relation." value : ".$tmp_seuil{'value'}[$_[3]]." type : ".$tmp_seuil{'type'}[$_[3]]." warning : ".$tmp_seuil{'warning'}[$_[3]]." critical : ".$tmp_seuil{'critical'}[$_[3]]."\n";}
    
  }else{
    $_[3]=0;
	if($o_debug){print "seuil_relation_oid_to_value : sueil_oid : \n";print Dumper($data_xml->{'table'}->{'seuil_oid'});}
    $tmp_seuil{'name'}[0]=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'value'};
    # recupere OID.index de value en court et on passe snmpget
	if(defined $data_xml->{'table'}->{'global_oids'}{$tmp_seuil{'name'}[0]}){
    $oid_relation="$data_xml->{'table'}->{'global_oids'}{$tmp_seuil{'name'}[0]}.$_[1]";
	}else{}
    $tmp_seuil{'value'}[0] = &my_snmp_get($oid_relation);
	
	$tmp_seuil{'type'}[0] = $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'type'};
	
	if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning_oid'})){
        $tmp_name=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning_oid'};
		$oid_relation="$data_xml->{'table'}->{'global_oids'}{$tmp_name}.$_[1]";
		$tmp_seuil{'warning'}[0] = &my_snmp_get($oid_relation);
     }else{
		$tmp_seuil{'warning'}[0] = $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'};
     }
	
	if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical_oid'})){
        $tmp_name=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical_oid'};
		$oid_relation="$data_xml->{'table'}->{'global_oids'}{$tmp_name}.$_[1]";
		$tmp_seuil{'critical'}[0] = &my_snmp_get($oid_relation);
     }else{
		$tmp_seuil{'critical'}[0] = $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'};
     }
	
	
		if($o_debug){print "seuil_relation_oid_to_value : tmp_seuil : ".$tmp_seuil{'name'}[$_[3]]." oid relation ".$oid_relation." value : ".$tmp_seuil{'value'}[$_[3]]." type : ".$tmp_seuil{'type'}[$_[3]]." warning : ".$tmp_seuil{'warning'}[$_[3]]." critical : ".$tmp_seuil{'critical'}[$_[3]]."\n";}
    
}

  if($o_debug){print "seuil_relation_oid_to_value : ".$_[0]." : ".$tmp_seuil{'name'}[$_[3]]." => $oid_relation get = ".$tmp_seuil{'value'}[$_[3]]."\n";}

  # verif correspondence sur cette value
  if(defined($data_xml->{'table'}->{'correspond'}{$tmp_seuil{'name'}[$_[3]]})){
    $tmp_seuil{'value'}[$_[3]]=${$data_xml->{'table'}->{'correspond'}{$tmp_seuil{'name'}[$_[3]]}}[$tmp_seuil{'value'}[$_[3]]];
    if($o_debug){print "seuil_relation_oid_to_value : correspond seuil ".$tmp_seuil{'name'}[$_[3]]." tmp_seuil{'value'}[$_[3]] => ".$tmp_seuil{'value'}[$_[3]]."\n";}
  }


  #if($o_debug){print " $_[0] $_[1] => $oid_relation = ".$return{'value'}[$num_oid]."\n";}

  # if seuil oid type =>

  if(defined($tmp_seuil{'type'}[$_[3]])){

    $value_nagios = $tmp_seuil{'value'}[$_[3]];
    $warning_nagios = $tmp_seuil{'warning'}[$_[3]];
    $critical_nagios = $tmp_seuil{'critical'}[$_[3]];
    $type_seuil = $tmp_seuil{'type'}[$_[3]];
     # recup nagios value fonction seuil value
     $tmp_seuil{'statusnagios'}[$_[3]]=&seuil_to_nagios($tmp_seuil{'value'}[$_[3]],$tmp_seuil{'warning'}[$_[3]],$tmp_seuil{'critical'}[$_[3]],$tmp_seuil{'type'}[$_[3]]);
     $tmp_seuil{'status'}[$_[3]]=$tmp_seuil{'statusnagios'}[$_[3]];


    if($o_debug){print "seuil_relation_oid_to_value test type OID ".$tmp_seuil{'type'}[$_[3]]." pour ".$tmp_seuil{'name'}[$_[3]]." value ".$tmp_seuil{'value'}[$_[3]]." seuil ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'}[$_[3]]." ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical'}[$_[3]]." nagios : ".$tmp_seuil{'statusnagios'}[$_[3]]."\n";}

  }

  # if snmpget status exist
  if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'})){
    if($o_debug){print "test status OID ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}." pour ".$tmp_seuil{'name'}[$_[3]]."\n";}
    # snmpget status
    $oid_relation="$data_xml->{'table'}->{'global_oids'}{$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}}.$_[1]";
    $info_relation =  $session->get_request( -varbindlist => [$oid_relation]);
    if($o_debug){print "$oid_relation OID pour ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}."\n";}
    foreach $kr (keys(%{$info_relation}))
    {
      if($o_debug){print $info_relation->{$kr}." retour de $kr status ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}."\n";}
      $return{'status'}[$_[3]]=$info_relation->{$kr};
      $tmp_seuil{'status'}[$_[3]]=$return{'status'}[$_[3]];
      if(defined($data_xml->{'table'}->{'global_oids'}{$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}})){
        $return{'status'}[$_[3]]=translate_value($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'},$info_relation->{$kr});
        if($o_debug){
          print "correspond exist pour status ";
          print $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}." => ".$return{'status'}[$_[3]]."\n";
        }
        #$return{'status'}[$_[3]] = ${$data_xml->{'table'}->{'corespond'}{$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'}}}[$info_relation->{$kr}];
        $tmp_seuil{'status'}[$_[3]]=$return{'status'}[$_[3]];
        $return{'statusnagios'}[$_[3]] = &variable_status($_[0],$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'status'},$return{'status'}[$_[3]]);
        $tmp_seuil{'statusnagios'}[$_[3]]=$return{'statusnagios'}[$_[3]];
      }
    }
  }

}

sub seuil_relation_oid {
#
# arg 0 => attr
# arg 1 => index
# arg 2 => value attr
  my %return = ();
  my $num_oid = undef;
  %tmp_seuil = ();
 my $count_oid = undef;

  if($o_debug){
	print "seuil relation oid  nb $count_oid oid value ".$_[0]." index ".$_[1]." => ".$_[2]."\n";
	 print Dumper($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'value'});
  }
  # nb seuil oid pour attr ( _[0]) 
  if(defined $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'value'} && ref($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'value'}) eq 'ARRAY'){
  $count_oid = @{$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'value'}};
  }else{$count_oid=0;}
  if($count_oid>0){
    # pour chaque reference seuil_oid lier a attr
    for(my $num_oid=0;$num_oid < $count_oid;$num_oid++){

      &seuil_relation_oid_to_value($_[0],$_[1],$_[2],$num_oid,);

    }
  }else{&seuil_relation_oid_to_value($_[0],$_[1],$_[2]);}
}

sub my_snmp_get {
# arg 0 => oid get
    my $return_get = undef;
    my $kr = undef;
    my $info_relation = undef;

    $info_relation =  $session->get_request( -varbindlist => [$_[0]]);
    if($o_debug){print "get OID pour ".$_[0]."\n";}
    # parcourt le tableau de get avoir 
    foreach $kr (keys(%{$info_relation})){
      if($o_debug){print $info_relation->{$kr}." retour de $kr use \n";}
      $return_get=$info_relation->{$kr};
    }
    
   return $return_get;
}



sub seuil_relation_memory {
#
# arg 0 => attr
# arg 1 => index
# arg 2 => value attr
# recup dans xml table => get snmp la type de mem calcule return code nagios
# variable interne sub
# mem_type => use | free  
# info_snmp => table get snmp mem use | mem free | mem total
# list_mem_snmp => mem use | mem free | mem total


  %tmp_seuil = ();
  my $mem_type = undef;
  my %info_snmp = ();
  my $oid_relation = undef;
  my $mem_base = undef;

  my @list_mem_type = ('mem_use','mem_free','mem_total');

  if($o_debug){print "test $_[0] $_[1] $_[2] <=> $o_type_secondary seuil relation OID memory \n";}
  $mem_type=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'mem_type'};

  # pour chaque element memoire (mem_use mem_free mem_total) si exist dans la bases XML get snmp de l'index _[1]
  # save in info_snmp[element memoire]
 
  foreach $mem_base (@list_mem_type){
    if($o_debug){print " test in base => $mem_base " ;}
    # defini in XML data_base
    if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{$mem_base})){
      # if($o_debug){print " value => ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{$mem_base}." \n";}
      $oid_relation="$data_xml->{'table'}->{'global_oids'}{$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{$mem_base}}.$_[1]";
      $info_snmp{$mem_base}=&my_snmp_get($oid_relation);
    }
    
  }

  # $tmp_seuil{'name'}[0]=$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'type'}." ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'mem_type'};

  # part cal mem
  $tmp_seuil{'value'}[0] = calc_p100_mem($info_snmp{'mem_use'},$info_snmp{'mem_free'},$info_snmp{'mem_total'},$mem_type);
  
  # convert value en nagios code
  if( $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'mem_type'} eq 'use' || $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'mem_type'} eq 'use_total'){
    if( $tmp_seuil{'value'}[0] >= $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'} ){
      $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='WARNING';
    }
    if( $tmp_seuil{'value'}[0] >= $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical'}){
      $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='CRITICAL';
    }
    if(!defined($tmp_seuil{'statusnagios'}[0])){
      $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='OK';
    }
  }

  if( $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'mem_type'} eq 'free' || $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'mem_type'} eq 'free_total'){
    if( $tmp_seuil{'value'}[0] <= $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'} ){
      $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='WARNING';
    }
    if( $tmp_seuil{'value'}[0] <= $data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical'}){
      $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='CRITICAL';
    }
    if(!defined($tmp_seuil{'statusnagios'}[0])){
      $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='OK';
    }
  }


 if($o_debug){print " test seuil memory pour ".$tmp_seuil{'name'}[0]." ".$tmp_seuil{'value'}[0]." =>  warning : ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'warning'}." critical : ".$data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'critical'}." code retour :  ".$tmp_seuil{'statusnagios'}[0]."\n";}

}

sub my_split_input {
# split sting in hash array:
# [name]=[value]:[warning]=[value]:[critical]=[value],[name]=[value]:[warning]=[value]:[critical]=[value] ......
# arg 0 => string
  my $x=0;
  my  %return_split=();
  my $name_value = undef;
  my $name_arg = undef;
  my $list_arg = undef;
  my $list_value = undef;
  my @list_test = ();
  my @list_input = undef;

  if($o_debug){print "part split input $_[0] \n";}
  if($_[0] ne ""){
    @list_input=split(/\,/,$_[0]);
    foreach $list_value (@list_input){
      @list_test=split(/:/,$list_value);
      foreach $list_arg (@list_test){
        ($name_arg,$name_value)=split(/=/,$list_arg);
        $return_split{$x}{$name_arg}=$name_value;
        if($o_debug){print "split string $x => $name_arg <=> $name_value \n";}
      }
      $x++;
    }
    return %return_split; 
  }else{
     return 0;
  }
}

sub referer_value_secondary {
 # return value and type off value secondary referer
 # type : Mbits/s
 # arg0 => value input 
  
 my @return = ();
 #$input_value=$_[0];
 if( $_[0] =~ s/Mb//g )
 {
    @return=($_[0],'Mbits/s');
 }
 if($o_debug){print "referer value secondary input $return[0] type $return[1] \n";}

 return @return;
}


sub seuil_relation {
# 
# arg 0 => attr
# arg 1 => index
# arg 2 => secondary attr
# arg 3 => name translate
  my %return = ();
  my $val_proc_test = undef;
  my $unit = undef;
  my $count_val = undef;
  my $data_interval = undef;
  my $time_interval = undef;
  my %flg_created = ();
  my $file_tmp = undef;
  my $div = undef; 
  my $type_counter = undef;
  my $referer_table_value = undef;
  my $referer_value = undef;
  my $referer = undef;
  my $factor = undef;
  my $type_return = undef;
  my $oid_relation = undef;
  my $update_time = undef;
  my %last_data  = ();
  my $row = undef;
  my $refer_active = undef;
  my $eval_array = undef;
  my $keyref = undef;

  my %last_check_time = ();
  my @refer_secondary = ();
  my %referer_secondary = ();
  

  %tmp_seuil = ();

   # test et split secondary value
    if($o_value_secondary){%referer_secondary=my_split_input($o_value_secondary);}
    #$eval_array=%referer_secondary;

  if($o_debug){print "test seuil relation OID $_[0] $_[1] $_[2] $_[3]<=> $o_value_secondary  || $o_type_secondary \n";}
  if($o_debug){print "seuil_relation replace $_[0] => $o_warn_custom => $o_warn  && $o_crit \n";}
  
  if(defined($o_warn_custom)){
		#if($o_debug){print "seuil_relation replace ok $o_warn_custom && $_[0] \n";}
	if( $o_warn_custom eq $_[0]){
		if(defined($o_warn) && defined($o_crit)){
			if($o_debug){print "seuil_relation replace $_[0] OK \n";}
			
		}
	}
  }
	
  # attr is in array seuil_oid ?
  if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]})){
    # filter sensor actif ?
	
    if(!$o_type_secondary || $o_type_secondary eq $_[2]){

      # type = memory
      if(defined($data_xml->{'table'}->{'seuil_oid'}{$_[0]})){
        if($data_xml->{'table'}->{'seuil_oid'}{$_[0]}{'type'} eq 'memory'){
          seuil_relation_memory($_[0],$_[1],$_[2]);
          # si seuil oid => attr exist
        }else{
          seuil_relation_oid($_[0],$_[1],$_[2]);
        }
      }  

    }
  }

# test attr seuil counter
  if(defined($data_xml->{'table'}->{'seuil_counter'}{$_[0]})){
   # init variables
    #%referer_secondary=();
    $refer_active= 1;
    $val_proc_test=undef;
    $file_tmp="$data_dir/".$_[0]."_".$_[1]."_".$o_host.".tmp";
    $factor=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'factor'};
    $div=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'div'};
    $unit=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'unit'};
    $referer=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'referer'};
	$referer_table_value=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'referer_value'};
    $type_counter=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'type'};
	$type_return=$data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'return'};

    @refer_secondary=();
    

    # test et split secondary value
    #if($o_value_secondary){%referer_secondary=my_split_input($o_value_secondary);}
    $eval_array=%referer_secondary;
    # if referer secondary exist test if value = referer secondary 
    if(!($eval_array == 0)){
       $refer_active=0;
       foreach $keyref ( keys(%referer_secondary)){
         # test if refer intfarce or test is positif
         if((defined($referer_secondary{$keyref}{'if'}) || defined($referer_secondary{$keyref}{'dev'}) || defined($referer_secondary{$keyref}{'id'})) && !($refer_active == 1)){
            if($referer_secondary{$keyref}{'if'} eq $_[3] || $referer_secondary{$keyref}{'dev'} eq $_[3] || $referer_secondary{$keyref}{'id'} eq $_[1]){
	          $refer_active=1;
	          if(defined($referer_secondary{$keyref}{'maxbw'})){
	            @refer_secondary=&referer_value_secondary($referer_secondary{$keyref}{'maxbw'});
	          }
	        }else{$refer_active=2;}
            if($o_debug){
	       print "test referer secondary : ".$referer_secondary{$keyref}{'if'}." $_[3] $refer_active index $_[1] $refer_secondary[0]\n";
	    }
         }elsif(defined($referer_secondary{$keyref}{'maxbw'})){
		$refer_active=1;
		@refer_secondary=&referer_value_secondary($referer_secondary{$keyref}{'maxbw'});
	 
	}
       }
    }

    # si file exist recup data [time]:[last counter]
    if($o_debug){
	print "test seuil relation OID counter :  $_[0] $_[1] $_[2] <=> $o_value_secondary $file_tmp $type_counter $eval_array $refer_active\n";
        print "table split string : ".$referer_secondary{0}{'if'}."\n";	
    }
    $update_time = time;
    if(($eval_array == 0) || $refer_active ==1){
      if($o_debug){print "part analyse counter $_[0] $_[3] $type_counter \n";}
      if (-e $file_tmp) {
        open(FILE,"<",$file_tmp);
        while($row = <FILE>){
             # value from file last time and last data
             my @last_values = split(":",$row);
             $last_check_time{$_[0]}{$_[1]} = $last_values[0];
             $last_data{$_[0]}{$_[1]} = $last_values[1];
             $flg_created{$_[0]}{$_[1]} = 1;
        }
        close(FILE);
        
        # calc interval values
        $flg_created{$_[0]}{$_[1]} = 1;
        $time_interval = $update_time - $last_check_time{$_[0]}{$_[1]};
        $data_interval = $_[2] - $last_data{$_[0]}{$_[1]};
        if($o_debug){print "data from file : ".$last_check_time{$_[0]}{$_[1]}.":".$last_data{$_[0]}{$_[1]}." data input ".$_[2]."\n";}

      }else{
        $flg_created{$_[0]}{$_[1]} = 0;
        if($o_debug){print "file dont exist :$file_tmp \n";}
      }
    
      # $update_time = time;
      if($flg_created{$_[0]}{$_[1]}){

        # if secondary referer
        if(@refer_secondary){
          if($refer_secondary[1] eq 'Mbits/s')
		  {
              if($refer_secondary[0]>0){$referer_value=($refer_secondary[0]*1024*1024)/8;}

			  $val_proc_test=calc_p100_mem(round($data_interval / $time_interval),0,$referer_value,'use_total');
			if($o_debug){print "calc referer value $data_interval time interval $time_interval secondary $referer_value for pourcent ".$val_proc_test."\n";}
		  }
         
      
        # if referer OID calc Pourcent
        }elsif(defined($referer)){
		  
          # get value referer
          $oid_relation="$data_xml->{'table'}->{'global_oids'}{$referer}.$_[1]";
          $referer_value = &my_snmp_get($oid_relation);
          # calc %
	  
          if($referer_value >0 ){$val_proc_test=calc_p100_mem($data_interval,0,$referer_value,'total_use');}
        }elsif(defined($referer_table_value)){
		  
          # get value referer
          # $oid_relation="$data_xml->{'table'}->{'global_oids'}{$referer}.$_[1]";
          #$referer_value = &my_snmp_get($oid_relation);
          # calc %
	  
          if($referer_table_value >0 ){$val_proc_test=calc_p100_mem($data_interval,0,$referer_table_value,'total_use');}
        }
        
	if($type_counter eq 'pourcent'){
          # factor data if exist
          if(defined($factor)){$data_interval=$data_interval*$factor;}
          $count_val = ($data_interval / $time_interval);
	  if($o_debug){print "calc count factor time $count_val \n";}
          # div data if existe
          if(defined($div) && $div > 0){$count_val=$count_val/$div;}
	  
	  if($type_return eq 'integer'){
		$tmp_seuil{'value'}[0]=round($count_val);
	  }else{$tmp_seuil{'value'}[0]=sprintf("%.3f",$count_val).$unit;}
	  $tmp_seuil{'complement'}[0]=$val_proc_test."%";
  	  if($o_debug){print "part counter pourcent : $data_interval $time_interval => $count_val  $val_proc_test \n";}

	}
	elsif($type_counter eq 'simple'){
 	  $tmp_seuil{'value'}[0]=$data_interval;
	  $val_proc_test=$data_interval;
	  if($o_debug){print "part counter simple : $data_interval $time_interval => $val_proc_test \n";}
	}
	elsif($type_counter eq 'average'){
	  $val_proc_test=round($data_interval/$time_interval);
      if(defined($div) && $div > 0){$val_proc_test=$val_proc_test/$div;}
	  #elsif(defined($div) && $div > 0 && $type_return){$val_proc_test=round($val_proc_test/$div);}
      if($type_return eq 'integer'){
		$tmp_seuil{'value'}[0]=round($val_proc_test);
	  }else{$tmp_seuil{'value'}[0]=sprintf("%.3f",$val_proc_test);}
	  if($o_debug){print "part counter average : $data_interval $time_interval => $val_proc_test \n";}
	}

      
      }
      unless (open(FILE,">".$file_tmp)){
        if($o_debug){print "Unknown - $file_tmp !\n";}
      }
      print FILE "$update_time:$_[2]";
      close(FILE);
      #if ($flg_created[$i] eq 0){
#		if($o_debug){print "First execution : Buffer in creation.... \n";}
#      }
    
	
	  if(defined($o_warn_custom)){
		#if($o_debug){print "seuil_relation replace ok $o_warn_custom && $_[0] \n";}
		if( $o_warn_custom eq $_[0]){
			if(defined($o_warn) && defined($o_crit)){
				if($o_debug){print "seuil_relation replace $_[0] OK \n";}
			
			}
		}
	  }
	
	
      if( $val_proc_test >= $data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'warning'} ){
        $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='WARNING';
      }
      if( $val_proc_test >= $data_xml->{'table'}->{'seuil_counter'}{$_[0]}{'critical'}){
        $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='CRITICAL';
      }
      if(!defined($tmp_seuil{'statusnagios'}[0])){
        $tmp_seuil{'statusnagios'}[0]=$tmp_seuil{'status'}[0]='OK';
      }
      if($o_debug){
        print "data interval time : $_[3] $time_interval data interval : $data_interval => $count_val ".sprintf("%.3f",$count_val)." $unit ".$val_proc_test." % ";
        print ${$tmp_seuil{'statusnagios'}}[0]." ".$tmp_seuil{'value'}[0]."\n";
      }
      # $tmp_seuil{'value'}[0]=sprintf("%.3f",$count_val).$unit;
    }
  }
}


# sub for ident all particular exception 
sub test_condition_system_type {
# $_[0] = type
# $_[1] = attr
  my $return=1;

  # for firewall if not in cluster all cfw hardware status are critical => falte positive
  if($_[0] eq "firewall"){
     if(!defined($o_fw_cluster) && ($_[1] eq "cfwHardwareStatusValue")){
	$return=0;
     }
  }

  if($o_debug){print "in $_[0] test do $_[1] $return\n";}
  return $return;
}

sub describ_relation_oid {
# _[0] name_oid
# _[1] index oid
 
 my $oid_relation=$data_xml->{'table'}->{'global_oids'}{$_[0]}.".$_[1]";
 if($o_debug){print "relation_oid => $_[0] => $oid_relation \n";}
 # get relation oid
 return &my_snmp_get($oid_relation);

}

sub translate_value {
# _[0] attr
# _[1] value
# _[2] $index facultatif
  my $return_translate = undef;
  my $v_correspond = undef;

  my $list_correspond=$data_xml->{'table'}->{'correspond'}{$_[0]};

  foreach $v_correspond (@{$list_correspond->{'value'}}){
    if($o_debug){print "\n test v_c=".$v_correspond->{'index'}." <=> ".$v_correspond->{'content'}." index : ".$_[2]." Valeur=".$_[1]."\n";}
    if($v_correspond->{'index'} == $_[1]){$return_translate=$v_correspond->{'content'};}
  }
  if($o_debug){
    print "translate value $_[0] $_[1] => correspond : ".$return_translate." ";
    #print Dumper $list_correspond."translate value \n";
  }
  return $return_translate;
}

sub analyse_oid {
# _[0] return snmp request
# _[1] oid ref for snmpwalk
# _[2] attr
  my $retour_relation= undef;
  my $varstatus = undef;
  my $valget = undef;
  my $valoriginal = undef;
  my $k = undef;
  my $count = undef;
  my $count_oid = undef;
  my $valtrans = undef;
  my $num_oid = undef;
  my $valtest = undef;
  my $index = undef;
  my $nb_element = 0;
  my $attr = undef;
  
  my %correspond_flag = ();
  my @char = ();
  my $tmp_relation_oid =$data_xml->{'table'}->{'relation_oid'}{$_[2]};
  my $list_correspond=$data_xml->{'table'}->{'correspond'}{$_[2]};
  # my $correspond_flag{$_[2]}=$data_xml->{'table'}->{'correspond_flag'}{$_[2]};
  if($o_debug){print Dumper($_[0]); print "analyse_oid snmp return\n";print "debug analyse_oid tmp relation oid :"; print Dumper($tmp_relation_oid);}

  foreach $k (keys(%{$_[0]}))
  {
    # init variable
    $valtrans ='';
    $varstatus='';
    $valtest='';
    $retour_relation='';
    # oid in use
    $new_oid=$k;
    $index=0;
    my $nosave=0;
    %tmp_seuil =();

    if($o_debug){print "analyse_oid  pattern => $_[1] oid => $new_oid\n";}
    # oid correct ?
    if( $new_oid =~ s/$_[1]\.//g )
    {
      # index oid in use 
      $index=$new_oid;
      $new_oid=$k;
      # if exist relation_oid get describ
      if (defined($tmp_relation_oid))
      {
		if(&is_array($tmp_relation_oid)){
			$nb_element= scalar @{$tmp_relation_oid};
		}
		if($o_debug){ print $nb_element."analyse_oid relation oid nb element test $nb_element\n";}
		
		# is array 
		if($nb_element>0){
			# for each test de system type _[0]
			for $attr ( @{$tmp_relation_oid} ) {

				if($o_debug){print "analyse_oid relation oid  => $attr\n";}
				$retour_relation.=" ".&describ_relation_oid($attr,$index);

			}
		# single type
		}else{
			
			$retour_relation=&describ_relation_oid($tmp_relation_oid,$index);
			if($o_debug){print "analyse_oid relation oid  => $retour_relation\n";}
				
		}
		
		
		
        
      }
      
      if($o_debug){print "Clef=$k index : $index Valeur=".$_[0]->{$k};}

      if (defined($list_correspond))
      {
        $valtrans=&translate_value($_[2],$_[0]->{$k},$index);
      }
      if($o_debug){
         print "\n";
         print "sub seuil relation OID : $_[1] => index $index $retour_relation value trans : $valtrans value : ".$_[0]->{$k}."\n";
      }

      # in a value list flag juste each char = 1 are use
      # and the position X give the signification  
      if (defined($correspond_flag{$_[2]}))
      {
	# split each char
        @char=split(//,$_[0]->{$k});
        my $x=0;
        my $val=$x+1;
        foreach my $c (@char)
        {
	  # if flag = 1 search the correspond x in correspond_flag
          if($c){
            #print "   ".$val.": ".${$correspond_flag{$_[2]}}[$x]."\n";
            $valtrans.=${$correspond_flag{$_[2]}}[$x]."\n";
          }
          $x++;
          $val++;
        }
      }
	  $valoriginal=$_[0]->{$k};
	  if($o_debug){print "analyse_oid value original get : ";print Dumper($valoriginal);}
      if($valtrans){$valtest=$valtrans;}
      else{$valtest=$_[0]->{$k};}
      $varstatus= &variable_status($_[2],$valtest);
      $valget = $_[0]->{$k};


      %tmp_seuil =();
      # test value seuil oid
      &seuil_relation($_[2],$index,$valtest,$retour_relation);

      
      # not error code and value
      if(!defined($tmp_seuil{'errorcode'}) && $tmp_seuil{'value'}){
        if($o_debug){print Dumper @{$tmp_seuil{'value'}};print "sub seuil relation table value\n";}
          # for each value 
        $count_oid=@{$tmp_seuil{'value'}};
        for($num_oid = 0; $num_oid < $count_oid ;$num_oid++){
           if($o_debug){print " sub seuil relation $num_oid sur $count_oid : ".$tmp_seuil{'value'}[$num_oid]." ".$tmp_seuil{'status'}[$num_oid]." ".$tmp_seuil{'statusnagios'}[$num_oid]." ".$tmp_seuil{'name'}[$num_oid]."\n";}
           $varstatus = $tmp_seuil{'statusnagios'}[$num_oid];
           $valget=$tmp_seuil{'value'}[$num_oid];

	   if(&is_array($varlist{$_[2]})){$count = @{$varlist{$_[2]}};}

           @{$varlist{$_[2]}[$count]}=($k, $valget,$valtrans,$varstatus,$retour_relation,$tmp_seuil{'name'}[$num_oid],$tmp_seuil{'complement'}[$num_oid],$index,$valoriginal);
           if($o_debug){print "dump line return ".Dumper @{$varlist{$_[2]}[$count]};}
        }
        $nosave=1;
      }elsif($tmp_seuil{'errorcode'}==1){$nosave=1;}

      if(&is_array($varlist{$_[2]})){ $count = @{$varlist{$_[2]}};}
      @{$varlist{$_[2]}[$count]}=($k, $valget,$valtrans,$varstatus,$retour_relation)if(!$nosave);
      if($o_debug){print $varlist{$_[2]}[$count][4]."  num $_[0] $varlist{$_[2]}[$count][3]\n";}
        #print " $x \n";
    }elsif($varstatus){@{$varlist{$_[2]}[$count]}=($k, $valget,$valtrans,$varstatus,$retour_relation);}
  }
  
}
sub stop{
	if($o_debug){
	print "sub stop\n";
	print $_[0];
	}
}


sub my_snmp_get_table {

# _[0] oid get table
my $result = undef;
	$result = $session->get_request($_[0]);
	if($o_debug){ print "my_snmp_get_table get oid $_[0] "; print Dumper($result);} 
	#sleep 10;
	if ( !defined( $result = $session->get_table($_[0]) ) ) {
		my $answer = $session->error;
		#$session->close;
		stop("UNKNOWN: SNMP error: $answer\n", "UNKNOWN");
		$result = undef;
	}
	return $result;
}



sub analyze_array_to_secondary {


# _[0]  hash table attr->{ snmp get table }
# _[1] hask --values-secondary
# return hash {index oid}  =nb math {referer}=nb describ   if nb(index oid) == nb(referer) condition=true


my ($tmp_value, $tmp_secondary )= @_;
my %array_value =%$tmp_value;
my %array_secondary =%$tmp_secondary;
my @array_define = ();
my $keyref = undef;
my %return_info = ();
my $x=0;

if($o_debug){
	print "analyze_array_to_secondary table value to test \n";
	print Dumper(%array_value);
	print "analyze_array_to_secondary table value referere \n";
	print Dumper(%array_secondary);
}

foreach $keyref ( keys(%array_secondary)){
         # test if refer intfarce or test is positif
	if($o_debug){
		print "analyze_array_to_secondary begin test secondary $keyref test dev :".$array_secondary{$keyref}{'dev'}." | int :".$array_secondary{$keyref}{'int'}." | id : ".$array_secondary{$keyref}{'id'}." | idlike : ".$array_secondary{$keyref}{'idlike'}." | condition : ".$array_secondary{$keyref}{'condition'}." | id : ".$array_secondary{$keyref}{'maxbw'}."\n";
	}
				
	if((defined($array_secondary{$keyref}{'if'}) || defined($array_secondary{$keyref}{'dev'}) || defined($array_secondary{$keyref}{'id'}) || defined($array_secondary{$keyref}{'idlike'}) || defined($array_secondary{$keyref}{'maxbw'}) ) && !defined($array_secondary{$keyref}{'condition'}) && defined(%array_value)){
		foreach my $keyvalue ( keys(%array_value)){
			if($o_debug){print "analyze_array_to_secondary key value $keyvalue \n";}
			foreach my $keyoid ( keys (%{$array_value{$keyvalue}})){
			
				my $index = $keyoid;
				$index =~ s/$data_xml->{'table'}->{'global_oids'}->{$keyvalue}\.//g ;
				
				my $value = $array_value{$keyvalue}{$keyoid};
				if($o_debug){
					print "analyze_array_to_secondary key oid if | id | maxbw $array_secondary{$keyref}{'if'} $array_secondary{$keyref}{'dev'} $array_secondary{$keyref}{'id'} $array_secondary{$keyref}{'idlike'}\n";
					print "analyze_array_to_secondary key oid if | id | maxbw $keyoid  index $index value : $value keyref :$keyref \n";
				}
				my $index_tmp=$index;
				if($array_secondary{$keyref}{'if'} eq $value || $array_secondary{$keyref}{'dev'} eq $value || $array_secondary{$keyref}{'id'} == $index ||$index_tmp=~ m/$array_secondary{$keyref}{'idlike'}/){
					#$return_info{'index'}[$x]=$index;
					if(defined($return_info{'index'}{$index})){$return_info{'index'}{$index}++;}
					else{$return_info{'index'}{$index}=1;}
					if($o_debug){print "analyze_array_to_secondary add to return index $index value : ".$return_info{'index'}{$index}."\n";}
					$return_info{'maxbw'}{$index}=$array_secondary{$keyref}{'maxbw'};
				}elsif(!defined($array_secondary{$keyref}{'if'})&&!defined($array_secondary{$keyref}{'dev'})&&!defined($array_secondary{$keyref}{'id'})&&!defined($array_secondary{$keyref}{'idlike'})&&defined($array_secondary{$keyref}{'maxbw'}) ){
					if(defined($return_info{'index'}{$index})){$return_info{'index'}{$index}++;}
					else{$return_info{'index'}{$index}=1;}
					$return_info{'maxbw'}{$index}=$array_secondary{$keyref}{'maxbw'};
			
					if($o_debug){print "analyze_array_to_secondary add to return index with maxbw $index value : ".$return_info{'index'}{$index}."\n";}
				}
			}
		}
		
		
		my $y=0;
		if($return_info{'index'}){
			foreach my $index (keys(%{$return_info{'index'}})){
				$x=0;
				my $referer = 0;
				if($o_debug){print "analyze_array_to_secondary test $index all value \n";}
				foreach my $keyvalue ( keys(%array_value)){
					my $keyoid = $data_xml->{'table'}->{'global_oids'}->{$keyvalue}.".".$index;
					if(defined($array_value{$keyvalue}{$keyoid})){$x++;}
					if($o_debug){print "analyze_array_to_secondary value $keyvalue $x\n";}
					$referer++;
				}
				$return_info{'index'}{$index}=$x;
				$return_info{'referer'}=$referer;
			
			
				$y++;
			}
		}
		
		
	}elsif(defined($array_secondary{$keyref}{'condition'})){
	# part test condition
		if($array_secondary{$keyref}{'condition'} eq 'and'){
		# if condition is and
		# push define value in array
			
			foreach my $keyvalue ( keys(%array_value)){
				if($o_debug){print "analyze_array_to_secondary key value $keyvalue \n";}
				foreach my $keyoid ( keys(%{$array_value{$keyvalue}})){
			
					my $index = $keyoid;
					$index =~ s/$data_xml->{'table'}->{'global_oids'}->{$keyvalue}\.//g ;
					my $value = $array_value{$keyvalue}{$keyoid};
					if($o_debug){print "analyze_array_to_secondary key oid $keyoid  index $index value : $value keyref : $keyref\n";}
				
					# TEST VALUE
					$x=0;
					foreach my $defined_value ( keys (%{$array_secondary{$keyref}})){
						if($defined_value ne 'condition' && $defined_value ne 'maxbw'){
							$x++;
							if($o_debug){print "analyze_array_to_secondary push array define $defined_value ".$array_secondary{$keyref}{$defined_value}." <==> $value \n";}
						
							if($array_secondary{$keyref}{$defined_value} eq $value){
								if(defined($return_info{'index'}{$index})){$return_info{'index'}{$index}++;}
								else{$return_info{'index'}{$index}=1;}
								if($o_debug){print "analyze_array_to_secondary add to return index $index value : ".$return_info{'index'}{$index}."\n";}
								if(defined($array_secondary{$keyref}{'maxbw'})){$return_info{'maxbw'}{$index}=$array_secondary{$keyref}{'maxbw'};}
							}
						}
					}
					$return_info{'referer_condition'}=$x;
				
				
				}
			}
			
			
			if($o_debug){print "analyze_array_to_secondary value to valide return \n";print Dumper(%return_info);}
			foreach my $index (keys(%{$return_info{'index'}})){
				$x=0;
				my $referer = 0;
				if($o_debug){print "analyze_array_to_secondary test $index all value \n";}
				foreach my $keyvalue ( keys(%array_value)){
					my $keyoid = $data_xml->{'table'}->{'global_oids'}->{$keyvalue}.".".$index;
					if(defined($array_value{$keyvalue}{$keyoid})){$x++;}
					if($o_debug){print "analyze_array_to_secondary value $index $keyvalue $x\n";}
					$referer++;
				}
				if($return_info{'referer_condition'} == $return_info{'index'}{$index}){
					$return_info{'index'}{$index}=$x;
					$return_info{'referer'}=$referer;
				}else{$return_info{'index'}{$index}=0;}
			
			}
		
		}
	}
	if($o_debug){
			print "analyze_array_to_secondary array return \n";
			print Dumper(%return_info);
		}
	return %return_info;
}

}


sub analyse_relation_oid {
# _[0] attr

my $tmp_relation_oid = undef;
my %new_oid_relation_array =();
my $new_oid_relation = undef;

if($data_xml->{'table'}->{'relation_oid'}->{$_[0]}){
		$tmp_relation_oid=$data_xml->{'table'}->{'relation_oid'}->{$_[0]};
		#$data_xml->{'table'}->{'global_oids'}->{}
		if($o_debug){
			print Dumper($tmp_relation_oid);
		}
		if(is_array($tmp_relation_oid)){
			if($o_debug){
				print "analyse_relation_oid oid_relation array\n";
			}
			for my $attr ( @{$tmp_relation_oid} ) {

				if($o_debug){print "analyse_relation_oid relation oid  => $attr\n";}
				$new_oid_relation_array{$attr}=$data_xml->{'table'}->{'global_oids'}->{$attr};
			}
			
			if($o_debug){print Dumper(%new_oid_relation_array);}
			#return %new_oid_relation_array;
		}else{
		  $new_oid_relation=$data_xml->{'table'}->{'global_oids'}->{$data_xml->{'table'}->{'relation_oid'}->{$_[0]}};
		  if($o_debug){print "analyse_relation_oid oid_relation single ".$new_oid_relation." \n";}
		  #return $new_oid_relation;
		}
	}
	
	return ('single'=>$new_oid_relation,'array'=>%new_oid_relation_array);
}



sub system_type_to_analyse {

# _[0] system type
# _[1] attr


  my $oid_ref = undef;
  my $result = undef;
  my $result_error = undef;
  my $next=1;
  my %referer_secondary = ();
  my %new_oid_relation_array = ();
  my $eval_array= undef;
  my $new_oid_relation;
  my $keyref = undef;
  my $key_index = undef;
  my $refer_active = undef;
  my $index = undef;
  my $tmp_relation_oid = undef;
  my $key_relation = undef;
  my %result_array = ();
  my $message_snmp_error='OBJECT IDENTIFIER in dotted notation';


  if( test_condition_system_type($_[0],$_[1]) ) {
	
    $new_oid=$data_xml->{'table'}->{'global_oids'}->{$_[1]};
    $oid_ref=$new_oid;
    
	############## part Value secondary ##########################################
	if(!defined($tmp_value_secondary)){$tmp_value_secondary=$o_value_secondary;}
	if($tmp_value_secondary){%referer_secondary=my_split_input($tmp_value_secondary);}
	
	############## part relation oid simple / multiple ####################################
	if($data_xml->{'table'}->{'relation_oid'}->{$_[1]}){
		$tmp_relation_oid=$data_xml->{'table'}->{'relation_oid'}->{$_[1]};
		#$data_xml->{'table'}->{'global_oids'}->{}
		if($o_debug){
			print Dumper($tmp_relation_oid);
		}
		if(is_array($tmp_relation_oid)){
			if($o_debug){
				print "system_type_to_analyse oid_relation array\n";
			}
			for my $attr ( @{$tmp_relation_oid} ) {

				if($o_debug){print "system_type_to_analyse relation oid  => $attr\n";}
				$new_oid_relation_array{$attr}=$data_xml->{'table'}->{'global_oids'}->{$attr};
			}
			
			if($o_debug){print Dumper(%new_oid_relation_array);}
		}else{
		  $new_oid_relation=$data_xml->{'table'}->{'global_oids'}->{$data_xml->{'table'}->{'relation_oid'}->{$_[1]}};
		  if($o_debug){print "system_type_to_analyse oid_relation single ".$new_oid_relation." \n";}
		}
	}else{
		$new_oid_relation=$new_oid;
	}
	
	my %return_analyse_relation_oid=&analyse_relation_oid($_[1]);
	if($o_debug){
		print "system_type_to_analyse begin snmp request $oid_ref <=> $new_oid => $new_oid_relation\n";
		print "system_type_to_analyse begin snmp request $tmp_value_secondary\n"; print Dumper(%referer_secondary);
		
	}
	
	$eval_array=%referer_secondary;
    # if referer secondary exist test if value = referer secondary 
	
	if(!($eval_array == 0)){
	################# Part referer secondary is array ######################
    	foreach $keyref ( keys(%referer_secondary)){
         # test if refer intfarce or test is positif
			if($o_debug){
				print "system_type_to_analyse begin snmp request reference $keyref test dev :".$referer_secondary{$keyref}{'dev'}." | int :".$referer_secondary{$keyref}{'int'}." | id : ".$referer_secondary{$keyref}{'id'}." | id like : ".$referer_secondary{$keyref}{'idlike'}." | condition : ".$referer_secondary{$keyref}{'condition'}." | Bandwith : ".$referer_secondary{$keyref}{'maxbw'}."\n";
			}
			################## defined If || DEV || id || condition || maxbw ############################	
			if((defined($referer_secondary{$keyref}{'if'}) || defined($referer_secondary{$keyref}{'dev'}) || defined($referer_secondary{$keyref}{'id'}) ||defined($referer_secondary{$keyref}{'idlike'}) || defined($referer_secondary{$keyref}{'condition'}) || defined($referer_secondary{$keyref}{'maxbw'})) && !($refer_active == 1) ){
		 
				if($o_debug){
					print "system_type_to_analyse enter for analyse with snmp\n";
				}
				################# si oid relation is single get table ####################################
				if(defined($new_oid_relation)){
					if ( !defined( $result = $session->get_table($new_oid_relation) ) ) {
						my $answer = $session->error;
						$session->close;
						stop("UNKNOWN: SNMP error: $answer\n", "UNKNOWN");
					}
			
					######################### for each element table relatio oid #######################
					foreach $key_index ( keys %{$result} ) {

  # remove trailing 0 Byte for Windows
						my $resp=$result->{$key_index};
				
						$index = undef;
						if( $key_index =~ s/$new_oid_relation\.//g ){$index=$key_index;}
				
						if($o_debug){
							print "system_type_to_analyse begin snmp request reference index $key_index => $resp test ".$referer_secondary{$keyref}{'dev'}." | ".$referer_secondary{$keyref}{'if'}." | ".$referer_secondary{$keyref}{'id'}."\n";
						}
						if(!$referer_secondary{$keyref}{'if'}){$referer_secondary{$keyref}{'if'}="NOT DO";}
						if(!$referer_secondary{$keyref}{'dev'}){$referer_secondary{$keyref}{'dev'}="NOT DO";}
						
						#################### element table relation oid == value secondary if|| dev|| id ################################
						my $index_tmp=$index;
						if($referer_secondary{$keyref}{'if'} eq $resp || $referer_secondary{$keyref}{'dev'} eq $resp || $referer_secondary{$keyref}{'id'} eq $index||$index_tmp=~ m/$referer_secondary{$keyref}{'idlike'}/){
							if( $index )
							{
								my $new_oid_tmp = $oid_ref.".".$index;
								my $resultmp=$session->get_request( -varbindlist => [$new_oid_tmp]);
								if($o_debug){
									print "system_type_to_analyse test referer secondary : OK ".$referer_secondary{$keyref}{'dev'}." | ";
									print $referer_secondary{$keyref}{'if'}." | ".$referer_secondary{$keyref}{'id'}." $resp $refer_active index $_[1] $index \n";
									print "system_type_to_analyse test referer secondary : OK test $new_oid_tmp \n";print Dumper($resultmp);
						
								}
								&analyse_oid($resultmp,$oid_ref,$_[1]);						
							}
						#################### element table relation oid == maxbw only ################################
						}elsif($referer_secondary{$keyref}{'maxbw'} && (!defined($referer_secondary{$keyref}{'if'}) && !defined($referer_secondary{$keyref}{'dev'})  && !defined($referer_secondary{$keyref}{'id'}) && !defined($referer_secondary{$keyref}{'idlike'}) )){
							my $new_oid_tmp = $oid_ref.".".$index;
							my $resultmp=$session->get_request( -varbindlist => [$new_oid_tmp]);
							if($o_debug){
								print "system_type_to_analyse test referer secondary : OK ".$referer_secondary{$keyref}{'dev'};
								print $referer_secondary{$keyref}{'if'}.$referer_secondary{$keyref}{'id'}." $resp $refer_active index $_[1] $index \n";
								print "system_type_to_analyse test referer secondary : OK test $new_oid_tmp \n";print Dumper($resultmp);
						
							}
							####################### if ok do analyse new oid index id||if||dev ##################################
							&analyse_oid($resultmp,$oid_ref,$_[1]);	
						}
					}
				####################### if oid relation is array ##################################
				}elsif((scalar(%new_oid_relation_array)) > 0){
					####################### for each oid relation get table ##################################
					foreach $key_relation (keys %new_oid_relation_array){
						$new_oid_relation = $new_oid_relation_array{$key_relation};
						$result_array{$key_relation} = &my_snmp_get_table($new_oid_relation);
						if($o_debug){print "system_type_to_analyse get table from $key_relation oid $new_oid_relation\n";}
						
					}
					if($o_debug){
						print "system_type_to_analyse result get table snmp\n";
						print Dumper(%result_array);
					}
					####################### analyse array oid relation return match with secondary ##################################
					#if(defined(%result_array)){
						my %result_analyse=&analyze_array_to_secondary(\%result_array,\%referer_secondary);
					#}
					my $x=0;
					if(defined($result_analyse{'index'})){
						foreach my $keyindex (keys(%{$result_analyse{'index'}})){
							if($o_debug){print "system_type_to_analyse index get value snmp $keyindex\n";	}
							if($result_analyse{'index'}{$keyindex} == $result_analyse{'referer'}){
								if($o_debug){print "system_type_to_analyse index get is OK $keyindex  $oid_ref\n";	}
								my $new_oid_tmp = $oid_ref.".".$keyindex;
								my $resultmp=$session->get_request( -varbindlist => [$new_oid_tmp]);
								if($o_debug){print "system_type_to_analyse test referer secondary : OK test $new_oid_tmp \n";print Dumper($resultmp);}
								if(defined($result_analyse{'maxbw'}{$keyindex})){
									$o_value_secondary="maxbw=".$result_analyse{'maxbw'}{$keyindex};
								}else{$o_value_secondary="";}
								&analyse_oid($resultmp,$oid_ref,$_[1]);
							}
						}
					}
				}
		 
			}
		 
		 
            
         }
       
	##################### no value secondary analyse each value ################################ 
	}else{
	
	
		while($next)
		{
			# si on a une valeur get snmp sur OID next =1 continu
			$result=$session->get_next_request( -varbindlist => [$new_oid]);
			if($result_error=$session->error()){
				$next=0;
				if($o_debug){print "system_type_to_analyse no next oid ".$result_error."  ".$new_oid."\n";}
			}
			# si oid ref est dans oid next =1
			if($new_oid =~ m/$oid_ref/ && $next){
				$next=1;
				$index=$1;
				if($o_debug){print "system_type_to_analyse oid return index : $index \n";}
			}else{
				$next=0;
				if($o_debug){print "system_type_to_analyse no oid content referer oid \n";}
			}


			if($o_debug){print "system_type_to_analyse  test oid $_[0] ref $oid_ref sur $new_oid => $next\n";}
			# analyse oid in use
			&analyse_oid($result,$oid_ref,$_[1]);

		}
	}
	
  }
}




sub test_system_type {
  my $attr = undef;
  my $nb_element = undef;
  my $statuscode = undef;
  my $statusinfo = undef;
  # _[0] system type
  # test si le type exist et referencer dans la XML
  if($_[0] && $data_xml->{'table'}->{'system_types'}{$_[0]} ){
    if(&is_array($data_xml->{'table'}->{'system_types'}->{$_[0]})){
       $nb_element= scalar @{$data_xml->{'table'}->{'system_types'}->{$_[0]}};
    }
    if($o_debug){ print $nb_element." nb element test\n";}

   # is array 
    if($nb_element>0){
      # for each test de system type _[0]
      for $attr ( @{$data_xml->{'table'}->{'system_types'}->{$_[0]} } ) {

        if($o_debug){print "test_system_type test attr  array $_[0] => $attr\n";}
        &system_type_to_analyse($_[0],$attr);

       }
    # single type
    }else{
      $attr = $data_xml->{'table'}->{'system_types'}->{$_[0]};
      if($o_debug){print "test_system_type test attr $_[0] => $attr\n";}
      &system_type_to_analyse($_[0],$attr);
    }
  }else{
     $statuscode='CRITICAL';
     $statusinfo='ERROR Bad TYPE';
     printf("$statuscode:$statusinfo");
     print "\n";
	 &help();
     &verb("\nEXIT CODE: $ERRORS{$statuscode} STATUS CODE: $statuscode");
     exit $ERRORS{$statuscode};
  }
}

sub get_data_file {
   # sub get data in file and create if not exist
   # $_[0] file with directory

}

sub maj_data_file {
  # sub for 
}

sub connect_snmp {
 my  $statuscode = undef;
 my $statusinfo = undef;
 eval "use Net::SNMP";
  if($o_debug){print "eval Net::SNMP \n";print $@;}
 if ($@) {
  verb("ERROR: You do NOT have the Net:".":SNMP library \n"
  . "  Install it by running: \n"
  . "  perl -MCPAN -e shell \n"
  . "  cpan[1]> install Net::SNMP \n");
  exit 1;
  } else {
    if($o_debug){
      verb("The Net:".":SNMP library is available on your server \n");
    }
  }

  # SNMP Connection to the host
  if($o_debug){print "start snmp OK\n";}
  if (defined($o_login) && defined($o_passwd)) {
  # SNMPv3 login
	  verb("SNMPv3 login");
	  ($session, $error) = Net::SNMP->session(
	   -hostname         => $o_host,
	   -version          => '3',
	   -username         => $o_login,
	   -authpassword     => $o_passwd,
	   -authprotocol     => 'md5',
	   -privpassword     => $o_passwd,
	   -timeout          => $o_timeout
	   );
  } else {

   if (defined ($o_version2)) {
   # SNMPv2 Login
      ($session, $error) = Net::SNMP->session(
       -hostname  => $o_host,
       -version   => 2,
       -community => $o_community,
       -port      => $o_port,
       -timeout   => $o_timeout
       );
	  if($o_debug){
         print " Net:".":SNMP connect version 2 \n";
	  }
   } else {
   # SNMPV1 login
     ($session, $error) = Net::SNMP->session(
      -hostname  => $o_host,
      -community => $o_community,
      -port      => $o_port,
      -timeout   => $o_timeout
      );
   }
  }
   if(!$session->get_request( -varbindlist => [".1.3.6.1.2.1.1.1.0"])){
     print "SNMP NOK\n";
     $statuscode='CRITICAL';
     $statusinfo='ERROR connexion snmp';
     printf("$statuscode:$statusinfo");
     print "\n";
     verb("\nEXIT CODE: $ERRORS{$statuscode} STATUS CODE: $statuscode");
     exit $ERRORS{$statuscode};
   }
}



sub screen_array{
	# $_[0] type 
	# $_[1] array line
	# $_[2] attr

	my $message=undef;
	my $complement=undef;
	if($o_debug){
		print "screen array type :".$_[0]." ".${$_[1]}[3]."\n";print Dumper(@{$_[1]});
		print "screen array column : $_[0] => $_[2] :".$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}."\n";

	}

	$message="${$_[1]}[1] ${$_[1]}[2]";
	if(defined(${$_[1]}[6])){$message.="(${$_[1]}[6])";$complement=${$_[1]}[6];}
		


	$array_screen_value[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]=$message;
	 $array_screen_value_complement[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]=$complement;
	$array_screen_value_origine[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]=${$_[1]}[8];
	$array_screen_name[${$_[1]}[7]]=${$_[1]}[4];
	$array_screen_nagios[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]=${$_[1]}[3];

	if($o_debug){
print "screen array return : value ".$array_screen_value[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]."\n";;
print "screen array return : value compl ".$array_screen_value_complement[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]."\n";
print "screen array return : value origine ".$array_screen_value_origine[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]."\n";;
print "screen array return : name ".$array_screen_name[${$_[1]}[7]]."\n";;
print "screen array return : nagios ".$array_screen_nagios[${$_[1]}[7]][$data_xml->{'table'}->{'screen'}->{$_[0]}->{$_[2]}->{'column'}]."\n";
	}
	

}


sub screen_column2ref{
	# $_[0] type 
	# $_[1] $num_column
	my $return=undef;
	foreach my $ref_column (keys %{$data_xml->{'table'}->{'screen'}->{$_[0]}} ) {
		if($ref_column ne 'header' && $ref_column ne 'datagraph'){
    		if($_[1] eq $data_xml->{'table'}->{'screen'}->{$_[0]}->{$ref_column}->{'column'}){
				$return=$ref_column;
			}
			if($o_debug){
				print "correspond column to ref : num ".$_[1]." ref ".$ref_column." column ";
				print  $data_xml->{'table'}->{'screen'}->{$_[0]}->{$ref_column}->{'column'}."\n";
			
			}
		}
	}
	if($o_debug){print "correspond column to ref : return ".$return."\n";}
	return $return;

}


# main prog

# test directory temp for counteur exist
if (! -e $data_dir) {
   mkdir ($data_dir,0755) || die ("Err. Cr. directory\n");
}
sub test_module{
 eval "use $_[0]";
 if ($@) {
   verb("ERROR: You do NOT have the ".$_[0]." library \n"
   . "  Install it by running: \n"
   . "  perl -MCPAN -e shell \n"
   . "  cpan[1]> install $_[0] \n");
    exit 1;
  } else {
   verb("The ".$_[0]." library is available on your server \n");
  }
}




my $i;
my $oid;
my $line;
my $resp;
my $k;
my @tmp;
my $statuscode;
my $statusinfo;
my $statusunknown = undef;
my $statuscritical = undef;
my $statuswarning = undef;
my $statusok = undef;
my  $system_test = undef;
my $attr = undef;



&test_module('XML::Simple');
$xml = new XML::Simple;

&check_options();
if($o_debug){print "data xml insert \n".Dumper($data_xml);}
&connect_snmp();


if ( $o_type eq "test" ) {
}
else{

  &test_system_type($o_type);
}


# part return and screen
#verb("\nXML2NAGIOS Status to Nagios Status mapping...");
my $graph_data="";
my $message_line=undef;
for $attr (sort keys %varlist){
  foreach my $ligne (@{$varlist{$attr}}){

	if($o_debug){
	print "return table screen \'$attr\' \'${$ligne}[0]\'  \'${$ligne}[1]\'  \'${$ligne}[2]\'  \'${$ligne}[3]\' \'${$ligne}[4]\' \'${$ligne}[5]\' \'${$ligne}[6]\' \'${$ligne}[7]\' \'${$ligne}[8]\'\n";
    }
    
	if($data_xml->{'table'}->{'screen'}->{$o_type}){
		&screen_array($o_type,$ligne,$attr);

	}else{

		$message_line="${$ligne}[3] $attr ${$ligne}[4] ${$ligne}[5] - $attr ${$ligne}[4] ${$ligne}[5] = ${$ligne}[1] ${$ligne}[2]";
		if(defined(${$ligne}[6])){$message_line.="(${$ligne}[6])";}
		if(${$ligne}[3]){
			if(!${$ligne}[5]){$graph_data.="$attr\(${$ligne}[4]\)=${$ligne}[1] ";}
			else{$graph_data.="$attr\(${$ligne}[5]\)=${$ligne}[1] ";}
		}
	
		if (${$ligne}[3] eq "CRITICAL"){
			verb("\nStatus $attr CRITICAL...");
			$statuscritical = "1";
			#$statuscode="CRITICAL";
			$statusinfo .= ", " if ($statusinfo);
			$statusinfo .=  $message_line."\n";
		}
		elsif (${$ligne}[3] eq "WARNING") {
			verb("\nStatus $attr WARNING...");
			$statuswarning = "1";
			#$statuscode="WARNING";
			$statusinfo .= ", " if ($statusinfo);
			$statusinfo .= $message_line.", ";
		}
		elsif (${$ligne}[3] eq "UNKNOWN") {
			verb("\nStatus $attr UNKNOWN...");
			$statusunknown = "1";
			#$statuscode="UNKNOWN";
			$statusinfo .= ", " if ($statusinfo);
			$statusinfo .= $message_line.", ";
		}
		elsif (${$ligne}[3] eq "OK") {
			verb("Status $message_line");
			$statusok = "1";
			$statusinfo .= $message_line.",  ";
			$statuscode="OK";
		}
	}
  }
}

if($data_xml->{'table'}->{'screen'}->{$o_type}){
	my $x=0;
	my $y=0;
	my $name_desc=undef;
	$statusinfo=undef;
	my $count=@array_screen_name;
	my $count_n=@array_screen_nagios;
	if( $data_xml->{'table'}->{'screen'}->{$o_type}->{'header'} ){
		$statusinfo=$data_xml->{'table'}->{'screen'}->{$o_type}->{'header'}."\n";
	}

	for ($x=0;$x<=$count;$x++)
	{
	#foreach $name_desc (@array_screen_name) {
		my $statuscritical_line=0;
		my $statuswarning_line=0;
		my $statusunknown_line=0;
		if($array_screen_name[$x]){
			$statusinfo.=$array_screen_name[$x]." = ";
			$statusinfo.=join(',', @{$array_screen_value[$x]});
			for ($y=0;$y<=$count_n ;$y++) {
				

				if ($array_screen_nagios[$x][$y] eq "CRITICAL"){
					$statuscritical_line=1;
					$statuscritical=1;
					$statusinfo.=",".&screen_column2ref($o_type,$y)." CRITICAL";
				}				
				if ($array_screen_nagios[$x][$y] eq "WARNING"){
					$statuswarning_line=1;
					$statuswarning=1;
					$statusinfo.=",".&screen_column2ref($o_type,$y)." WARNING";
				}
				if ($array_screen_nagios[$x][$y] eq "UNKNOWN"){
					$statusunknown_line=1;
					$statusunknown=1;
					$statusinfo.=",".&screen_column2ref($o_type,$y)." UNKNOWN";
				}
				#&screen_column2ref($o_type,$y);
			}
			if($statuscritical_line){$statuscode="CRITICAL";}
			elsif($statuswarning_line){$statuscode="WARNING";}
			elsif($statusunknown_line){$statuscode="UNKNOWN";}
			else{$statuscode="OK";}
			$statusinfo.=",".$statuscode."\n";
			
		}
	}

	if($o_debug){
		print "list des data in array for screen \n";
		print Dumper(@array_screen_value);
		print Dumper(@array_screen_name);
		#print $statusinfo;
	}
	
}



$statuscode="UNKNOWN";

if ($statuscritical eq '1'){
  $statuscode="CRITICAL";
}
elsif ($statuswarning eq '1'){
  $statuscode="WARNING";
}
elsif($statusok eq '1'){
	$statuscode="OK";
}

    printf("$statuscode $statusinfo|$graph_data\n");

if($o_debug){
 verb("\nEXIT CODE: $ERRORS{$statuscode} STATUS CODE: $statuscode");
}
exit $ERRORS{$statuscode};


