#!/usr/bin/perl 
$|=1;

use DBI;
use Switch;
use FindBin qw($Bin);
use POSIX;
use Net::SNMP qw(:snmp);
use Net::SMTP;
use Net::SMTP::SSL;
use Authen::SASL;
use Time::Zone;
require "$Bin/check_ip.pl";

our $force = 0;
while( $_ = shift @ARGV ) {
        $force	= 1	if /^\-f$/;
}

open CONFFILE, "< $Bin/../core/config.php" or die ("Manca file di configurazione\n");
while (<CONFFILE>) {
	if(/^\$db_data_server = "(\S+)"/ ) {
		$db_host = $1;
	}
	if(/^\$db_data_name = "(\S+)"/ ) {
		$db_name = $1;
	}
	if(/^\$db_data_user = "(\S+)"/ ) {
		$db_user = $1;
	}
	if(/^\$db_data_pwd = "(\S+)"/ ) {
		$db_pass = $1;
	}
}
close CONFFILE;

my $sys_error = 0;
if (!lockpid ("lock")) {
	print "Prg in esecuzione";
	exit 0;
}

$dbmysql = DBI->connect("DBI:mysql:;host=$db_host", "$db_user", "$db_pass") or die ($DBI::errstr);
$sts = $dbmysql->prepare("use $db_name");
$sts->execute ();

my $conf_query = "SELECT variabile, valore FROM conf ORDER BY ordine";
my $conf_sts = $dbmysql->prepare($conf_query);
$conf_sts->execute ();
%conf = ();
while (my $conf_dato = $conf_sts->fetchrow_hashref) {
                $nomevar = $$conf_dato{'variabile'};
		$conf{$nomevar} = $$conf_dato{'valore'};
}

#check_ip ();
@tempo = localtime();
dati_ora() if ($tempo[1] == 5);
#dati_ora();
dati_giorno() if ($tempo[1] == 10 && $tempo[2] == 0);
dati_giorno() if ($force);;
dati_settimana() if ($tempo[1] == 15 && $tempo[2] == 0 && $tempo[6] == 1);
dati_mese() if ($tempo[1] == 20 && $tempo[2] == 0 && $tempo[3] == 0);

my $fw_query = "SELECT id, TIMESTAMPDIFF(MINUTE,ultimoconn, NOW()) AS tempo_conn, errore FROM firewall WHERE attivo = 1";
my $fw_sts = $dbmysql->prepare($fw_query);
$fw_sts->execute ();
while (my $fw_dato = $fw_sts->fetchrow_hashref) {
	$fw_id = $$fw_dato{'id'};
	$fw_tempo = $$fw_dato{'tempo_conn'};
	$fw_errore = $$fw_dato{'errore'};
	if (($fw_errore < 2) && ($fw_tempo > $conf{'timeout_server'})) {
		my $fwup_query = "UPDATE firewall SET errore = 2, msg_err = 'Mancata connessione dal server' WHERE id = $fw_id";
		my $fwup_sts = $dbmysql->prepare($fwup_query);
		$fwup_sts->execute ();

		my $login_query = "INSERT INTO log_server SET fw=$fw_id, idazione=0, data=NOW(), stato=2, testo='Mancata connessione dal server'";
		my $login_sts = $dbmysql->prepare($login_query);
		$login_sts->execute ();
	}
}

my $noerr_query = "SELECT id, rate, ceil FROM defrule WHERE stato = 4";
my $noerr_sts = $dbmysql->prepare($noerr_query);
$noerr_sts->execute ();
while (my $noerr_dato = $noerr_sts->fetchrow_hashref) {
	my $id = $$noerr_dato{'id'};
	my $rate = $$noerr_dato{'rate'};
	my $ceil = $$noerr_dato{'ceil'};
	if ($rate > 0 && $ceil >= $rate) {
		my $defrule_query = "UPDATE defrule SET stato = 0 WHERE id = $id";
		my $defrule_sts = $dbmysql->prepare($defrule_query);
		$defrule_sts->execute ();

		$nomeregola = creanome ($id);
		my $login_query = "INSERT INTO log_server SET fw=0, idazione=0, data=NOW(), stato=0, testo='Configurazione regola $nomeregola corretta'";
		my $login_sts = $dbmysql->prepare($login_query);
		$login_sts->execute ();
	}
}

my $err_query = "SELECT id, stato FROM `defrule` WHERE (rate = 0 OR ceil < rate) AND stato != 3";
my $err_sts = $dbmysql->prepare($err_query);
$err_sts->execute ();
my $presenza_errori = 0;
while (my $err_dato = $err_sts->fetchrow_hashref) {
	my $err_id = $$err_dato{'id'};
	my $err_stato = $$err_dato{'stato'};
	$presenza_errori = 1;
	if ($conf{'errore'} != 3) {
		my $conferr_query = "UPDATE conf SET valore = 3 WHERE variabile = 'errore'";
		my $confmsg_query = "UPDATE conf SET valore = 'Errore nei dati di sistema' WHERE variabile = 'errore_msg'";
		my $conferr_sts = $dbmysql->prepare($conferr_query);
		my $confmsg_sts = $dbmysql->prepare($confmsg_query);
		$conferr_sts->execute ();
		$confmsg_sts->execute ();
	}
	if ($err_stato != 4) {
		my $defrule_query = "UPDATE defrule SET stato = 4 WHERE id = $err_id";
		my $defrule_sts = $dbmysql->prepare($defrule_query);
		$defrule_sts->execute ();

		$nomeregola = creanome ($err_id);
		my $login_query = "INSERT INTO log_server SET fw=0, idazione=0, data=NOW(), stato=4, testo='Configurazione regola $nomeregola errata'";
		my $login_sts = $dbmysql->prepare($login_query);
		$login_sts->execute ();
	}
}

if (!$presenza_errori && $conf{'errore'} == 3) {
	my $conferr_query = "UPDATE conf SET valore = 0 WHERE variabile = 'errore'";
	my $confmsg_query = "UPDATE conf SET valore = '' WHERE variabile = 'errore_msg'";
	my $conferr_sts = $dbmysql->prepare($conferr_query);
	my $confmsg_sts = $dbmysql->prepare($confmsg_query);
	$conferr_sts->execute ();
	$confmsg_sts->execute ();
}


lockpid ("unlock");
exit 0;

sub azione_conf {
	my $id = shift;
	my $azioniup_query = "UPDATE azioni SET dataexec= NOW() WHERE id = $id";
	my $azioniup_sts = $dbmysql->prepare($azioniup_query);
	$azioniup_sts->execute ();
}

sub lockpid {
	my $op = shift;
	
	my $pidfile = "/tmp/check_traffico.pid";
	if ($op eq "lock") {
		if (open PIDFILE, "< $pidfile") {
			read PIDFILE, $oldpid, 256;
			my $exists = kill 0, $oldpid;
			if ( $exists ) {
				return 0;
			} else {
				close PIDFILE;
			}
		} else {
			close PIDFILE;
		}
		open PIDFILE, "> $pidfile" || return 0;
		print PIDFILE $$;
		close PIDFILE;
	} elsif ($op eq "unlock") {
		unlink $pidfile;
	}
	return 1;
}

sub creanome {
	my $idparent = shift;
	
	my $query = "SELECT interfacce.device, defrule.idparent, defrule.priorita FROM defrule JOIN interfacce ON defrule.idinterfacce = interfacce.id WHERE defrule.id = '$idparent'";
	my $sts = $dbmysql->prepare($query);
	$sts->execute ();
	my $dato = $sts->fetchrow_hashref;

	if ($$dato{'idparent'} == 0) {
		$ritorno = $$dato{'device'}."-2:".$$dato{'priorita'};
		return $ritorno;
	} else {
		$ritorno = creanome($$dato{'idparent'}).":".$$dato{'priorita'};
		return $ritorno;
	}
}

sub dati_ora {

	my $query1 = "UPDATE dati_traffico SET h=1 WHERE dataunix BETWEEN  UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -1 DAY)) AND UNIX_TIMESTAMP(SUBSTR(NOW(), 1,13))  AND h<2";
	my $query2 = "INSERT INTO dati_ora (data,idfirewall,idinterfacce,iddefrule,max,media,deviazione,traffico) SELECT SUBSTR(data, 1,13), idfirewall, idinterfacce, iddefrule, MAX(rate), AVG(rate), STDDEV(rate), SUM(diff) FROM dati_traffico WHERE dataunix BETWEEN  UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -1 DAY)) AND UNIX_TIMESTAMP(SUBSTR(NOW(), 1,13)) AND h=1 GROUP BY idfirewall, idinterfacce, iddefrule, SUBSTR(data, 1,13)";
	my $query3 = "UPDATE dati_traffico SET h=2 WHERE dataunix BETWEEN  UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -1 DAY)) AND UNIX_TIMESTAMP(SUBSTR(NOW(), 1,13)) AND h=1";

	my $sts1 = $dbmysql->prepare($query1);
	my $sts2 = $dbmysql->prepare($query2);
	my $sts3 = $dbmysql->prepare($query3);

	$sts1->execute ();
	$sts2->execute ();
	$sts3->execute ();
}

sub dati_giorno {
	my $giorno = sprintf "%4d%02d%02d",$tempo[5]+1900,$tempo[4]+1,$tempo[3];
	my $giornout = mktime(59,59,23,$tempo[3],$tempo[4],$tempo[5]);

	my $giornodomut = $giornout + 86400;
	@tempodom = localtime($giornodomut);
	my $giornodom = sprintf "%4d%02d%02d",$tempodom[5]+1900,$tempodom[4]+1,$tempodom[3];

	my $giornoel = $giornout - (86400 * $conf{'giorni'});
	@tempoel = localtime($giornoel);
	$giornoel = sprintf "%4d%02d%02d",$tempoel[5]+1900,$tempoel[4]+1,$tempoel[3];

	my %tabelle = ('dati_traffico', 'dati_ora');

	foreach $worktable (%tabelle) {
		my $query5 = "alter table $worktable DROP PARTITION p$giornoel";
		my $query7 = "alter table $worktable ADD PARTITION (PARTITION p$giornodom VALUES LESS THAN ($giornodomut))";

		my $sts5 = $dbmysql->prepare($query5);
		my $sts7 = $dbmysql->prepare($query7);

		$sts5->execute ();
		$sts7->execute ();
	}

	my $query1 = "UPDATE dati_traffico SET g=1 WHERE dataunix BETWEEN  UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -1 DAY)) AND UNIX_TIMESTAMP(SUBSTR(NOW(), 1,10)) AND g<2";
	my $query2 = "INSERT INTO dati_giorno (data,idfirewall,idinterfacce,iddefrule,max,media,deviazione,traffico) SELECT SUBSTR(data, 1,10), idfirewall, idinterfacce, iddefrule, MAX(rate), AVG(rate), STDDEV(rate), SUM(diff) FROM dati_traffico WHERE dataunix BETWEEN  UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -1 DAY)) AND UNIX_TIMESTAMP(SUBSTR(NOW(), 1,10)) AND g=1 GROUP BY idfirewall, idinterfacce, iddefrule, SUBSTR(data, 1,10)";
	my $query3 = "UPDATE dati_traffico SET g=2 WHERE dataunix BETWEEN  UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -1 DAY)) AND UNIX_TIMESTAMP(SUBSTR(NOW(), 1,10)) AND g=1";

	my $query9 = "OPTIMIZE TABLE  dati_traffico";

	my $sts1 = $dbmysql->prepare($query1);
	my $sts2 = $dbmysql->prepare($query2);
	my $sts3 = $dbmysql->prepare($query3);
	my $sts9 = $dbmysql->prepare($query9);

	$sts1->execute ();
	$sts2->execute ();
	$sts3->execute ();
	$sts9->execute ();
}

sub dati_settimana {
	my $query1 = "UPDATE dati_traffico SET s=1 WHERE WEEK(data) < WEEK(NOW()) OR YEAR(data) < YEAR(NOW()) AND s<2";
	my $query2 = "INSERT INTO dati_settimana (anno,settimana,idfirewall,idinterfacce,iddefrule,max,media,deviazione,traffico) SELECT YEAR(data), WEEK(data), idfirewall, idinterfacce, iddefrule, MAX(rate), AVG(rate), STDDEV(rate), SUM(diff) FROM dati_traffico WHERE s=1 GROUP BY idfirewall, idinterfacce, iddefrule, YEAR(data), WEEK(data)";
	my $query3 = "UPDATE dati_traffico SET s=2 WHERE s=1";

	my $sts1 = $dbmysql->prepare($query1);
	my $sts2 = $dbmysql->prepare($query2);
	my $sts3 = $dbmysql->prepare($query3);

	$sts1->execute ();
	$sts2->execute ();
	$sts3->execute ();
}

sub dati_mese {
	my $query1 = "UPDATE dati_traffico SET m=1 WHERE MONTH(data) < MONT(NOW()) OR YEAR(data) < YEAR(NOW()) AND m<2";
	my $query2 = "INSERT INTO dati_mese (anno,mese,idfirewall,idinterfacce,iddefrule,max,media,deviazione,traffico) SELECT YEAR(data), MONTH(data), idfirewall, idinterfacce, iddefrule, MAX(rate), AVG(rate), STDDEV(rate), SUM(diff) FROM dati_traffico WHERE m=1 GROUP BY idfirewall, idinterfacce, iddefrule, YEAR(data), MONTH(data)";
	my $query3 = "UPDATE dati_traffico SET s=2 WHERE s=1";

	my $sts1 = $dbmysql->prepare($query1);
	my $sts2 = $dbmysql->prepare($query2);
	my $sts3 = $dbmysql->prepare($query3);

	$sts1->execute ();
	$sts2->execute ();
	$sts3->execute ();
}

