#==========================================================================
# Auteur : mazan olivier
# But    : plugin nagios - récupérer les infos BDD MS-SQL Kaspersky depuis un serveur av Windows
# Maj	 : 31-05-2010 - modification de la requète SQL nombre de virus (prise en compte de la commande RAZ)
#==========================================================================
use warnings;
use strict;

#######récupération arguments
my $winame = $ARGV[0];													#on stocke dans $winame le nom de l'hote
my $t_req=$ARGV[1];														#on stocke dans $t_req le type de requete
my $warn=$ARGV[2];														#on stocke dans $warn le nbre de jour/virus pour warning
my $crit=$ARGV[3];															#on stocke dans $crit le nbre de jour/virus pour critical
#######etats possibles nagios
my $OK=0;																							
my $WARNING=1;
my $CRITICAL=2;
my $UNKNOWN=3;
my $DEPENDENT=4;		

#######Aide si
&Help(0) if (!defined($winame));																#si argument 1 non définit	
&Help(3) if ($winame=~m/\-\-help/);																#si appel de l'aide
&Help(3) if ($winame=~m/\-h/);																	#si appel de l'aide
&Help(0) if (!defined($t_req));																	#si argument non définit
&Help(0) if (!defined($warn));																	#si argument non définit
&Help(0) if (!defined($crit));																	#si argument non définit

&Help(1) if ($warn=~m/\D/);																		#si $warn n'est pas numérique
&Help(1) if ($crit=~m/\D/);																		#si $crit n'est pas numérique
&Help(1) if ($t_req=~m/\D/);																	#si $t_req n'est pas numérique


#######Last Info Update
if ($t_req ==1) {
	my @t = (	"tmLastInfoUpdate", 								#on stocke dans un tableau la structure de la requete
				"KAV.dbo.hosts", 
				"(SELECT tmLastInfoUpdate FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
				"getdate()",
				"strwinhostname='$winame'",
				"since",
				"Last Info Update");
	&Req01(@t);
}
#######Last Update
elsif  ($t_req ==2) {
	my @t = (	"tmLastUpdate", 									#on stocke dans un tableau la structure de la requete
				"KAV.dbo.hosts", 
				"(SELECT tmLastUpdate FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
				"getdate()",
				"strwinhostname='$winame'",
				"since",
				"Last Update");
	&Req01(@t);
}
#######Last Full Scan
elsif  ($t_req ==3) {
	my @t = (	"nLastFullscan", 									#on stocke dans un tableau la structure de la requete
				"KAV.dbo.hosts", 
				"(SELECT nLastFullscan FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
				"getdate()",
				"strwinhostname='$winame'",
				"since",
				"Last Full Scan");
	&Req01(@t);
}
#######Last Visible
elsif  ($t_req ==4) {
	my @t = (	"tmLastVisible", 									#on stocke dans un tableau la structure de la requete
				"KAV.dbo.hosts", 
				"(SELECT tmLastVisible FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
				"getdate()",
				"strwinhostname='$winame'",
				"since",
				"Last Visible");
	&Req01(@t);
}
#######Licence Expiration time
elsif  ($t_req ==5) {
	my @t = (	"tmExpirationTime", 								#on stocke dans un tableau la structure de la requete
				"KAV.dbo.apphostskeys,KAV.dbo.hosts", 
				"getdate()",
				"(SELECT tmExpirationTime FROM KAV.dbo.apphostskeys,KAV.dbo.hosts WHERE KAV.dbo.hosts.nId=KAV.dbo.apphostskeys.nIdhost AND strwinhostname='$winame')",
				"KAV.dbo.hosts.nId=KAV.dbo.apphostskeys.nIdhost AND strwinhostname='$winame'",
				"remaining before",
				"Expiration Time");
	&Req01(@t);
}
#######Virus Count
elsif  ($t_req ==6) {
	my @t = (	"nVirusCount - nVirusCountBase        \"nVirusCount\"", 									#on stocke dans un tableau la structure de la requete
				"KAV.dbo.hosts",
				"strwinhostname='$winame'");
	&Req02(@t);			
}

else {
	&Help(1);	#on rentre dans l'aide pour tout autre valeur
}

#######Fonction Req01********Expiration time, Last Visible, Last Full Scan, Last Update, Last Info Update
sub Req01{
	my $f_req01 = $_[0];
	my $f_req02 = $_[1];
	my $f_req03 = $_[2];
	my $f_req04 = $_[3];
	my $f_req05 = $_[4];
	my $f_mark = $_[5];
	my $f_label = $_[6];	
	
	my @t;							#on déclare un tableau t
	my $i=0;						#on déclare i =0
	
	while (defined($_[$i])){		#on stocke dans le tableau tant que une valeur est définit dans le tableau $_[] (les paramètres de la fonction Req01)
		push(@t,$_[$i]);
		$i++;	
	}
	
	chomp (my @t_res01=`OSQL -E -Q "SELECT CONVERT(VARCHAR, $f_req01,120) FROM $f_req02 WHERE $f_req05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $res01=$t_res01[2];
	while ($res01 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$res01 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}
	
	&State() if (!defined($res01));					#on gere la valeur null
	
	
	#on récupère le jour/moi/année
	my ($annee) = ($res01=~ m/(\d\d\d\d)-\d\d-\d\d/);
	my ($moi) = ($res01=~ m/\d\d\d\d-(\d\d)-\d\d/);
	my ($jour) = ($res01=~ m/\d\d\d\d-\d\d-(\d\d)/);
	#\s signifie un espace
	my ($heure) = ($res01=~ m/.*\s(\d\d)/);
	my ($minute) = ($res01=~ m/:(\d\d):\d\d/);
	my ($seconde) = ($res01=~ m/\d\d:\d\d:(\d\d)/);
	
	&State() if (!defined($annee)) || (!defined($moi)) || (!defined($jour));
	
	my $date = "$jour/$moi/$annee at $heure:$minute:$seconde";
	&State() if ($date eq '/s\\/sat');
	
	#####################
	chomp (my @t_res02=`OSQL -E -Q "SELECT datediff (minute, $f_req03, $f_req04) FROM $f_req02 WHERE $f_req05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $res02=$t_res02[2];
	while ($res02 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$res02 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}

	
	
	&Year($date, $res02, @t) if ($res02 > 525600);									#rentrer dans la fonction Year si temps > 1 année
	&Month($date, $res02, @t) if ($res02 > 44640);									#rentrer dans la fonction Month si temps > 1 mois
	&Day($date, $res02, @t) if ($res02 >= 1440);									#rentrer dans la fonction Day si temps > 1 jour
	&Hour($date, $res02, @t) if ($res02 < 1440);									#rentrer dans la fonction Hour si temps < 1 jour
}

#######Fonction Req02 ********Nbre de Virus
####Role : connexion a la BDD, récupère la valeur nVirusCount
sub Req02{
        my $f_req01 = $_[0];
        my $f_req02 = $_[1];
        my $f_req03 = $_[2];

    
	chomp (my @t_res=`OSQL -E -Q "SELECT $f_req01 FROM $f_req02 WHERE $f_req03"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $res=$t_res[2];
	while ($res =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$res =~ s/^\s//g;							#...on supprime le premier caractere vide
	}
	
	#########affichage
        if ($res ==0){																			#si pas de virus trouvé
                print "KAV - No virus found\n";													
                exit $OK;                                                                                                                                                      #on retourne OK
        }
	else{																					#sinon
                print "KAV - $res virus found\n";												
                exit $CRITICAL if ($res >= $crit);														#etat Critical si > a argument crit
                exit $WARNING if ($res >= $warn);													#etat Warning si > a argument warn
                exit $OK if ($res < $warn);															#etat OK si < a argument warn
                exit $UNKNOWN;
        }
}

#######Fonction Year
sub Year{
        my $f_date = $_[0];        	#résultat au format $jour/$moi/$annee at $heure:$minute:$seconde
        my $f_min = $_[1];       	#résultat en minute
        my $f_part01 = $_[2];   	#ex : "tmLastVisible", 
        my $f_part02 = $_[3];   	#ex : "KAV.dbo.hosts", 
        my $f_part03 = $_[4];   	#ex : "(SELECT tmLastVisible FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
        my $f_part04 = $_[5];   	#ex : "getdate()",
        my $f_part05 = $_[6];   	#ex : "strwinhostname='$winame'",
        my $f_mark = $_[7];      	#ex : "since",
        my $f_label = $_[8];       	#ex: "Last Visible");   

	#########année
	chomp (my @t_year01=`OSQL -E -Q "SELECT datediff (year, $f_part03,  $f_part04) FROM $f_part02 WHERE $f_part05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $year01=$t_year01[2];
	while ($year01 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$year01 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}

	#########mois
        chomp (my @t_month01=`OSQL -E -Q "SELECT datediff (month, $f_part03,  $f_part04) FROM $f_part02 WHERE $f_part05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $month01=$t_month01[2];
	while ($month01 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$month01 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}


        #########affichage
        my $diffmy=($month01-(12*$year01));
        print "KAV - $year01 years and $diffmy months $f_mark $f_label\n" if ($diffmy > 0);
        print "KAV - $year01 years $f_mark $f_label\n" if ($diffmy <= 0);
        print "$f_label : $f_date\n";
        &State($f_min);                       																#on appelle la fonction State
}

#######Fonction Month
sub Month{
         my $f_date = $_[0];        	#résultat au format $jour/$moi/$annee at $heure:$minute:$seconde
        my $f_min = $_[1];       	#résultat en minute
        my $f_part01 = $_[2];   	#ex : "tmLastVisible", 
        my $f_part02 = $_[3];   	#ex : "KAV.dbo.hosts", 
        my $f_part03 = $_[4];   	#ex : "(SELECT tmLastVisible FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
        my $f_part04 = $_[5];   	#ex : "getdate()",
        my $f_part05 = $_[6];   	#ex : "strwinhostname='$winame'",
        my $f_mark = $_[7];      	#ex : "since",
        my $f_label = $_[8];       	#ex: "Last Visible");   

	#########mois
	chomp (my @t_month01=`OSQL -E -Q "SELECT datediff (month, $f_part03,  $f_part04) FROM $f_part02 WHERE $f_part05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $month01=$t_month01[2];
	while ($month01 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$month01 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}

	#########jours
    chomp (my @t_day01=`OSQL -E -Q "SELECT datediff (day, $f_part03,  $f_part04) FROM $f_part02 WHERE $f_part05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $day01=$t_day01[2];
	while ($day01 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$day01 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}

        #########affichage
        my $diffdm=($day01-(29*$month01));
        print "KAV - $month01 months and $diffdm days $f_mark $f_label\n" if ($diffdm > 0);
        print "KAV - $month01 months $f_mark $f_label\n" if ($diffdm <= 0);
        print "$f_label : $f_date\n";

        &State($f_min);                                                                                                                           	#on appelle la fonction State
}

#######Fonction Day
sub Day{
         my $f_date = $_[0];        	#résultat au format $jour/$moi/$annee at $heure:$minute:$seconde
        my $f_min = $_[1];       	#résultat en minute
        my $f_part01 = $_[2];   	#ex : "tmLastVisible", 
        my $f_part02 = $_[3];   	#ex : "KAV.dbo.hosts", 
        my $f_part03 = $_[4];   	#ex : "(SELECT tmLastVisible FROM KAV.dbo.hosts WHERE strwinhostname='$winame')",
        my $f_part04 = $_[5];   	#ex : "getdate()",
        my $f_part05 = $_[6];   	#ex : "strwinhostname='$winame'",
        my $f_mark = $_[7];      	#ex : "since",
        my $f_label = $_[8];       	#ex: "Last Visible");   

	#########jours
	chomp (my @t_day01=`OSQL -E -Q "SELECT datediff (day, $f_part03,  $f_part04) FROM $f_part02 WHERE $f_part05"`);	#on stocke dans un tableau les valeurs retourné par la requete sql
	my $day01=$t_day01[2];
	while ($day01 =~m/^\s/) {						#tant que premier champ de la res est un espace...
		$day01 =~ s/^\s//g;							#...on supprime le premier caractere vide
	}

        my $heure = int($f_min/60);						#récupération heures par rapport au xminutes
        my $diffhj = $heure-($day01*24);				#caclul différence heure/jour

	#########affichage
        print "KAV - $day01 days and $diffhj hours $f_mark $f_label\n" if ($diffhj > 0);
        print "KAV - $day01 days $f_mark $f_label\n" if ($diffhj <= 0);
        print "$f_label : $f_date\n";
	&State($f_min);                                                                                                                                 #on appelle la fonction State
}

#######Fonction Hour
sub Hour{
         my $f_date = $_[0];        	#résultat au format $jour/$moi/$annee at $heure:$minute:$seconde
        my $f_min = $_[1];       	#résultat en minute
        my $f_mark = $_[7];      	#ex : "since",
        my $f_label = $_[8];       	#ex: "Last Visible");   

        #########heures
        my $hour= int($f_min/60);                                                                                				#int permet de récupérer le cotient de la division
        my $minute=$f_min-($hour*60);                                                                       				#on récupère le nombre de minute

	#########affichage
        if ($f_min >= 60){                                                                                                                   		#si plus d'une heure
                print "KAV - $hour hours" ;
                print " and $minute minutes" if ($minute > 0);								#si minutes
                print " $f_mark $f_label\n";
        }
        elsif ($f_min < 60){                                                                                                             		#si moins d'une heure n'afficher que les minutes
		print " $f_min minutes $f_mark $f_label\n" if ($minute > 0);
        }
        if  ($t_req ==5){																#si expiration time
                 print "Licence has expired\n" if ($f_min <= 0);							#afficher licence expiré si temp en min < 0
        }
        print "$f_label : $f_date\n";
        &State($f_min);                                                                                                                      		#on appelle la fonction State
}

#######Fonction State
###Role: retourne état nagios (OK, CRITICAL, WARNING ou UNKNOWN) en fonction des arguments $crit et $warn)
sub State{
        my $f_min = $_[0];                                                                                                 				#résultat en minute
                                                  		

        if (!defined($f_min)){                                                                                                       		#si pas de valeur
                if ($t_req ==5){
                        print "Licence not found\n" ;                                                               			#licence non trouvé si valeur NULL + requete Expiration time
                }
                else
                {
                        print "Null value has been found\n";                                                     		#sinon pas de valeur trouvé
                }
                exit $CRITICAL;                                                                                                      	   		#on sort avec État critique
        }

		my $day= int($f_min/1440);													#int permet d'avoir un entier (sans virgule)
		
        if ($t_req ==5){                                                                                                                              	#si Expiration time
                exit $CRITICAL if ($day <= $crit);                                                                                       	#État critique si nbre jours < nbres de jour sécif                
		exit $WARNING if ($day <= $warn);           										#État warning si nbre jours < nbres de jour sécifié
                exit $OK if ($day > $crit);                                                                                                    	#État ok si nbre jours > nbres de jour sécifié
                exit $UNKNOWN;                                                                                                                         #État inconnu si autre
        }

        exit $CRITICAL if ($day >= $crit);													#État critique si nbre jours > nbres de jour sécif        
		exit $WARNING if ($day >= $warn);											#État warning si nbre jours > nbres de jour sécifié
        exit $OK if ($day < $warn);                                                                                      			#État ok si nbre jours < nbres de jour sécifié
        exit $UNKNOWN;                       														#État inconnu si autre
}




#######Fonction Aide
sub Help{
	my $f_err=$_[0];	
	print "error - please use a numeric value for the 2nd, the 3rd and the 4th arguments\n" if ($f_err==1);
	print "error - four arguments are needed\n" if ($f_err==0);
	print "\ncheck_KAVix v1.1 of May 2010, by MAZAN Olivier.\n";
	print "check_KAV is a perl nagios plugin which check KAV BDD since a Windows computer\n\n";
	print "Usage: check_KAV.pl [winhostname] [req nb] [warning in days or in nb of virus] [Critical in days or in nb of virus]\n";
	print "command nb :\n
			1 - Last Info Update\n
			2 - Last Update\n
			3 - Last Full Scan\n
			4 - Last Visible\n
			5 - Licence Expiration Time\n
			6 - Virus Count\n\n";
	print "Examples :\n";
	print "check_KAV.pl SERV_KAV 2 7 14\n";
	exit $UNKNOWN;
}



