#!/usr/bin/php -q
<?php
if (PHP_VERSION_ID < 60000) {
	mb_internal_encoding("UTF-8");
	set_time_limit(0);
	ob_implicit_flush();
	declare(ticks = 1);
	date_default_timezone_set("Europe/Paris");
}
$config = array();
$config['num_thread_do_something']=8;
$__server_listening = true;
$thread_list=array();
error_reporting(-1);
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
ini_set('log_errors', true);
ini_set('error_log', '/var/log/wprotect/wprotect.log');
require_once("/opt/wprotect/class/mycurl.php");
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ FUNCTION DECLARATION §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
function get_infos_net_iface($iface) {
	$result=array();
	$tmp = myexec("ifconfig ".$iface);
	foreach ($tmp AS $key => $value) {
		preg_match("/^.*inet\saddr\:(?P<ip>([0-9.]*))\s+Bcast\:(?P<bcast>([0-9.]*))\s+Mask\:(?P<netmask>([0-9.]*)).*$/", $value, $match);
		if (isset($match['ip'])) {
			$result["ip"]=$match['ip'];
			$result["netmask"]=$match['netmask'];
			$result["bcast"]=$match['bcast'];
		}
		preg_match("/^.*inet\sadr\:(?P<ip>([0-9.]*))\s+Bcast\:(?P<bcast>([0-9.]*))\s+Masque\:(?P<netmask>([0-9.]*)).*$/", $value, $match);
		if (isset($match['ip'])) {
			$result["ip"]=$match['ip'];
			$result["netmask"]=$match['netmask'];
			$result["bcast"]=$match['bcast'];
		}
		preg_match("/^.*inet\s(?P<ip>([0-9.]*))\s+netmask\s(?P<netmask>([0-9.]*))\s+broadcast\s(?P<bcast>([0-9.]*)).*$/", $value, $match);
		if (isset($match['ip'])) {
			$result["ip"]=$match['ip'];
			$result["netmask"]=$match['netmask'];
			$result["bcast"]=$match['bcast'];
		}
	}
	logme("GET IFACE ".$iface." IP:".$result['ip']." netmask:".$result['netmask']." Bcast:".$result['bcast']);
	return $result;
}
//-----------------------------------------------------------------------------
function update_certs() {
	logme("UPDATE CERTIFICATS started ...");
	$cert = file_get_contents("https://connectoo.fr/wprotect/cert", false);
	$key = file_get_contents("https://connectoo.fr/wprotect/key", false);
	$old_cert=file_get_contents("/etc/ssl/certs/acces-wifi.ovh.crt");
	$old_key=file_get_contents("/etc/ssl/private/acces-wifi.ovh.key");
	if (isset($cert) AND $cert!="" AND isset($key) AND $key!="") {
		if (($old_key!=$key) OR ($old_cert!=$cert)) {
			logme("UPDATE CERTIFICATS : NEW cert Update IT");
			file_put_contents("/etc/ssl/certs/acces-wifi.ovh.crt", $cert);
			file_put_contents("/etc/ssl/private/acces-wifi.ovh.key", $key);
			logme("UPDATE CERTIFICATS : restarting apache");
			myexec("/etc/init.d/apache2 reload");
			if (get_option_from_mysql("nginx_proxy_cache")) {
				logme("UPDATE CERTIFICATS : restarting nginx proxy");
				myexec("/etc/init.d/nginx reload");
			}
		}
		else {
			logme("UPDATE CERTIFICATS : no need update");
		}
		logme("UPDATE CERTIFICATS : OK");
		return true;
	}
	logme("UPDATE CERTIFICATS : FAILED ...");
	return false;
}
//-----------------------------------------------------------------------------
function send_mail($to, $subject, $body) {
	@require_once "Mail.php";
	global $config;
	global $connbdd;
	$from = get_option ("smtp_from");
	$server = get_option ("smtp_server");
	$port = get_option ("smtp_port");
	$username = get_option ("smtp_username");
	$password = get_option ("smtp_password");
	
	$headers = array ('From' => $from,
      'To' => $to,
      'Subject' => $subject,
	  'MIME-Version' => 1,
	  'Content-type' => 'text/html;charset=utf-8');
	  
	if ($username=="" AND $password=="") {
		$smtp = @Mail::factory('smtp',
		array ('host' => $server,
			'port' => $port,
			'auth' => FALSE,
			'username' => $username,
			'password' => $password));
	}
	else {
		$smtp = @Mail::factory('smtp',
		array ('host' => $server,
			'port' => $port,
			'auth' => TRUE,
			'username' => $username,
			'password' => $password));
	}
	
    

    $mail = @$smtp->send($to, $headers, $body);

    if (@PEAR::isError($mail)) {
      return $mail->getMessage();
    } else {
      return 0;
    }
}
//-----------------------------------------------------------------------------
function thread_send_login_by_mail($id=false) {
	global $config;
	global $connbdd;
	sleep(1);
	proc_nice(19);
	$mypid = getmypid();
	exec_mysql("INSERT INTO thread SET pid='".$mypid."', name='mail', status='running'");
	$result = exec_mysql("SELECT * FROM login INNER JOIN network ON login.network=network.id WHERE id_login='".$id."'");
	$val = mysqli_fetch_array($result);
	if (isset($val['email']) AND isset($val['login']) AND isset($val['password']) AND $val['email'] != "") {
		$mail = $val['email']; // destinataire
		logme("SEND_LOGIN_BY_MAIL : to ".$mail);
		if (!preg_match("#^[a-z0-9._-]+@(hotmail|live|msn).[a-z]{2,4}$#", $mail)) {
			$passage_ligne = "\r\n";
		}
		else {
			$passage_ligne = "\n";
		}
		$message_txt = "";
		$result = exec_mysql("SELECT * FROM pages WHERE type='6' AND lang='".$val['language']."'");
		$val2 = mysqli_fetch_array($result);
		$message_html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional //FR\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
						<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>
						<title></title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">
						<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"></head><body>".$val2['page'];
		$message_html = $message_html."</body></html>";
		$message_html = str_replace("{NETWORK_NAME}",$val['name'],$message_html);
		$message_html = str_replace("{LOGIN}",$val['login'],$message_html);
		$message_html = str_replace("{PASSWORD}",$val['password'],$message_html);
		$boundary = "-----=".md5(rand());
		$sujet = "test";
		$header = "From: \"Camping TEST\"<krok@totalynet.fr>".$passage_ligne;
		$header.= "Reply-to: \"Camping TEST\" <krok@totalynet.fr>".$passage_ligne;
		$header.= "MIME-Version: 1.0".$passage_ligne;
		$header.= "Content-Type: multipart/alternative;".$passage_ligne." boundary=\"$boundary\"".$passage_ligne;
		$message = $passage_ligne."--".$boundary.$passage_ligne;
		$message.= "Content-Type: text/plain; charset=\"ISO-8859-1\"".$passage_ligne;
		$message.= "Content-Transfer-Encoding: 8bit".$passage_ligne;
		$message.= $passage_ligne.$message_txt.$passage_ligne;
		$message.= $passage_ligne."--".$boundary.$passage_ligne;
		$message.= "Content-Type: text/html; charset=\"ISO-8859-1\"".$passage_ligne;
		$message.= "Content-Transfer-Encoding: 8bit".$passage_ligne;
		$message.= $passage_ligne.$message_html.$passage_ligne;
		$message.= $passage_ligne."--".$boundary."--".$passage_ligne;
		$message.= $passage_ligne."--".$boundary."--".$passage_ligne;
		//mail($mail,$sujet,$message,$header);
		$r=send_mail($mail, $sujet, $message_html);
		if ($r==0) {
			exec_mysql("UPDATE thread SET status='ok' WHERE pid='".$mypid."' AND name='mail' AND status='running'");
		}
		else {
			exec_mysql("UPDATE thread SET status='".$r."' WHERE pid='".$mypid."' AND name='mail' AND status='running'");
		}
		exit(0);
	}
	else {
		exec_mysql("UPDATE thread SET status='failed missing parameters' WHERE pid='".$mypid."' AND name='mail' AND status='running'");
		exit(0);
	}
	exit(0);
}
//-----------------------------------------------------------------------------
function upgrade_passthrought_dns() {
	global $config;
	global $connbdd;
	while (TRUE) {
		logme("Upgrade DNS passtrought ...");
		$result = exec_mysql("SELECT DISTINCT dns FROM firewall_certificat");
		while ($val = mysqli_fetch_array($result)) {
			$r=gethostbynamel($val['dns']);
			if (is_array($r)) {
				exec_mysql("DELETE FROM firewall_certificat WHERE dns='".$val['dns']."'");
				foreach  ($r AS $k => $v) {
					exec_mysql("INSERT INTO firewall_certificat SET dns='".$val['dns']."', ip='".$v."'");
				}
			}
		}
		logme("Upgrade DNS passtrought END");
		reload_passthrought_certificat();
		sleep(3600);
	}
	exit();
}
//-----------------------------------------------------------------------------
class Thread {
    const FUNCTION_NOT_CALLABLE     = 10;
    const COULD_NOT_FORK            = 15;
    private $errors = array(
        Thread::FUNCTION_NOT_CALLABLE   => 'ERROR : No valid function given to THREAD function...',
        Thread::COULD_NOT_FORK          => 'ERROR : Fork process failed...',
    );
    protected $runnable;
    private $pid;
	//--------------------------------------------
    public static function available() {
        $required_functions = array(
            'pcntl_fork',
        );
        
        foreach( $required_functions as $function ) {
            if ( !function_exists( $function ) ) {
                return false;
            }
        }
        
        return true;
    }
	//-------------------------------------------------
    public function __construct( $_runnable = null ) {
    	if( $_runnable !== null ) {
        	$this->setRunnable( $_runnable );
    	}
    }
    //-------------------------------------------------
    public function setRunnable( $_runnable ) {
        if( self::runnableOk( $_runnable ) ) {
            $this->runnable = $_runnable;
        }
        else {
            throw new Exception( $this->getError( Thread::FUNCTION_NOT_CALLABLE ), Thread::FUNCTION_NOT_CALLABLE );
        }
    }
	//-------------------------------------------------
    public function getRunnable() {
        return $this->runnable;
    }
	//--------------------------------------------------
    public static function runnableOk( $_runnable ) {
        return ( function_exists( $_runnable ) && is_callable( $_runnable ) );
    }
	//--------------------------------------------------
    public function getPid() {
        return $this->pid;
    }
	//---------------------------------------------------
    public function isAlive() {
        $pid = pcntl_waitpid( $this->pid, $status, WNOHANG );
        return ( $pid === 0 );
        
    }
	//---------------------------------------------------------
    public function start() {
        $pid = @ pcntl_fork();
        if( $pid == -1 ) {
            throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK );
        }
        if( $pid ) {
            $this->pid = $pid;
        }
        else {
            pcntl_signal( SIGTERM, array( $this, 'signalHandler' ) );
            $arguments = func_get_args();
            if ( !empty( $arguments ) ) {
                call_user_func_array( $this->runnable, $arguments );
            }
            else {
                call_user_func( $this->runnable );
            }
            
            exit( 0 );
        }
    }
	//------------------------------------------------------------------------
    public function stop( $_signal = SIGTERM, $_wait = false ) {
        if( $this->isAlive() ) {
            posix_kill( $this->pid, $_signal );
            if( $_wait ) {
                pcntl_waitpid( $this->pid, $status = 0 );
            }
        }
    }
	//------------------------------------------------------------------------
    public function kill( $_signal = SIGKILL, $_wait = false ) {
        posix_kill( $this->pid, $_signal );
    }
    //------------------------------------------------------------------------
    public function getError( $_code ) {
        if ( isset( $this->errors[$_code] ) ) {
            return $this->errors[$_code];
        }
        else {
            return "error " . $_code;
        }
    }
	//--------------------------------------------------------------------------
    protected function signalHandler( $_signal ) {
        switch( $_signal ) {
            case SIGTERM:
                echo "SIGTERM via TREAD";
				exit( 0 );
            break;
        }
    }
	//---------------------------------------------------------------------------
}
//-----------------------------------------------------------------------------
function reload_forbidden_network () { 
	global $config;
	global $connbdd;
	$config['forbidden_network'] = array();
	if ($result = exec_mysql("SELECT * FROM forbidden_network")) {
		while ($val = mysqli_fetch_array($result)) {
			$config['forbidden_network'][$val['id']] = $val['network'];
		}
	}
	logme("Reloading forbidden network rules ...");
	myexec ("iptables -t filter -F forbidden_network");
	myexec ("iptables -t filter -A forbidden_network -j RETURN");
	myexec ("iptables -t nat -F forbidden_network");
	myexec ("iptables -t nat -A forbidden_network -j RETURN");
	foreach ($config['forbidden_network'] AS $key=>$value) {
		myexec ("iptables -t filter -I forbidden_network -d ".$value." -m physdev --physdev-is-bridged -j pk_log_drop");
		myexec ("iptables -t nat -I forbidden_network -d ".$value." -m physdev --physdev-is-bridged -j ACCEPT");
	}
	logme("forbidden network rules loaded...");
}
//-----------------------------------------------------------------------------
function reload_passthrought_certificat() { // recharge la liste des ip et dns en libre accés comme le certificats de acces-wifi.ovh
	global $config;
	global $connbdd;
	logme("reloading passthrought certificat ....");
	$tmp="";
	myexec ("iptables -t filter -F passthrought_certificat");
	myexec ("iptables -t filter -A passthrought_certificat -j RETURN");
	$result = exec_mysql("SELECT * FROM firewall_certificat"); // on laisse lpassez les ip pour verfieé des certificats de confiance
	while ($val = mysqli_fetch_array($result)) {
		if (($val['ip']!="0.0.0.0") AND ($val['ip']!="")) {
			myexec ("iptables -t filter -m physdev --physdev-is-bridged -I passthrought_certificat -d ".$val['ip']." -p tcp --dport 80 -j ACCEPT -m comment --comment \"passtrought certificat verification\"");
			myexec ("iptables -t filter -m physdev --physdev-is-bridged -I passthrought_certificat -s ".$val['ip']." -p tcp --sport 80 -j ACCEPT -m comment --comment \"passtrought certificat verification\"");
			myexec ("iptables -t filter -m physdev --physdev-is-bridged -I passthrought_certificat -d ".$val['ip']." -p tcp --dport 443 -j ACCEPT -m comment --comment \"passtrought certificat verification\"");
			myexec ("iptables -t filter -m physdev --physdev-is-bridged -I passthrought_certificat -s ".$val['ip']." -p tcp --sport 443 -j ACCEPT -m comment --comment \"passtrought certificat verification\"");
			$tmp = $tmp . $val['ip'] . " " . $val['dns'] . "\n";
		}
	}
	file_put_contents ( "/etc/wprotect/hosts.perso" , $tmp );
	reload_dns(TRUE);
	logme("reloading passthrought certificat -> DONE");
}
//-----------------------------------------------------------------------------
function reload_firewall_client() { // recharge les règle de pare-feu des clients wifi
	global $config;
	global $connbdd;
	logme("reloading firewall client ....");
	$tmp="";
	myexec ("iptables -t filter -F firewall_client");
	myexec ("iptables -t filter -A firewall_client -j pk_log_drop");
	//---------------------------------------Passtrought VPN----------------
	$result = exec_mysql("SELECT * FROM options WHERE name='firewall_allow_vpn'");
	$val = mysqli_fetch_array($result);
	if ($val['value']==1) {
		myexec ("iptables -t filter -I firewall_client -p 50 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p 51 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p 47 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p udp --dport 500 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p udp --dport 1194 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p tcp --dport 1194 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p tcp --dport 1723 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p udp --dport 1723 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p tcp --dport 445 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p udp --dport 445 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p tcp --dport 1701 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p udp --dport 1701 -m physdev --physdev-is-bridged -j pk_log_accept");
		myexec ("iptables -t filter -I firewall_client -p udp --dport 4500 -m physdev --physdev-is-bridged -j pk_log_accept");
	}
	//-----------------------------------------------------------------------------
	$result = exec_mysql("SELECT * FROM firewall_client_out");
	while ($val = mysqli_fetch_array($result)) {
		myexec ("iptables -t filter -I firewall_client -p ".$val['proto']." --dport ".$val['port']." -m physdev --physdev-is-bridged -j pk_log_accept");
	}
	logme("reloading firewall client -> DONE");
}
//-----------------------------------------------------------------------------
function set_time_idle_disconnect() { //modifie le ageing time en seconde des bridges pour détecter si un client est déconnecté
	global $config;
	global $connbdd;
	if (($timesec = get_option("time_idle_disconnect")) != -2) {
		foreach ($config['bridge_interface'] AS $k => $v) {
			system ("brctl setageing ".$config['bridge_interface'][$k]." ".$timesec);
		}
	}
}
//-----------------------------------------------------------------------------
function get_option ($option) { // obtenir la valeur d'une option depuis mysql
	global $config;
	global $connbdd;
	if ($result = exec_mysql("SELECT value FROM options WHERE name='".$option."'")) {
		$val = mysqli_fetch_array($result);
		return $val['value'];
	}
	else {
		return -2;
	}
}
//------------------------------------------------------------------------------
function is_backup_running() {
	global $config;
	$is_running=apc_fetch("backup_running");
	if ($is_running==1) {
		return TRUE;
	}
	else {
		return FALSE;
	}
}
//------------------------------------------------------------------------------
function create_backup_wprotect($without_log=FALSE) {  //creation de backup Wprotect
	global $config;
	global $connbdd;
	proc_nice(19);
	apc_store("backup_running", 1);
	logme ("BACKUP : start backup wprotect ...");
	sleep(2); // pour ne pas avoir de boublons sur les noms de fichier de sauvegarde
	exec_mysql("INSERT INTO thread SET pid='".getmypid()."', name='".$nametask."', status='running'");
	if (!file_exists("/backup/tmp")) {
		mkdir ("/backup/tmp", 0777, true);
		if (!file_exists("/backup/tmp")) {
			logme("Erreur impossible de créer  le dossier /backup/tmp");
			logme("BACKUP : failed ...");
			apc_store("backup_running", 0);
			exec_mysql("UPDATE thread SET status='ERROR', date_end=NOW() WHERE pid='".getmypid()."' AND status='running'");
			exit();
		}
	}
	system ("chmod -R 777 /backup");
	system ("rm -f -r /backup/tmp/*");
	if (!$without_log) {
		system ("mkdir /backup/tmp/log");
	}
	system ("mkdir /backup/tmp/etc");
	system ("mkdir /backup/tmp/etc/wprotect");
	system ("mkdir /backup/tmp/etc/network");
	system ("cp -R /etc/wprotect/* /backup/tmp/etc/wprotect/");
	system ("cp /etc/network/interfaces /backup/tmp/etc/network/interfaces");
	system ("cp -R /var/www/admin/fileman/Uploads /backup/tmp/");
	system ("mv /backup/tmp/Uploads /backup/tmp/portal_files");
	if (!$without_log) {
		system ("cp -R /var/log/wprotect/netwo* /backup/tmp/log/");
	}
	system ("cp -R /etc/wprotect /backup/tmp/");
	$result = exec_mysql("SHOW TABLES FROM wprotect");
	while ($val = mysqli_fetch_array($result)) {
		$tablename=$val[0];
		system ("mysqldump -h ".$config['config_mysql_host']." -u ".$config['config_mysql_user']." -p".$config['config_mysql_password']." ".$config['config_mysql_db']." ".$tablename." > /backup/tmp/".$tablename.".sql");
	}
	$date = date("Y-m-d_h-i-s");
	if (!file_exists("/backup/backup_".$config["hostname"]."-".$date.".tar.bz2")) {
		system ("cd /backup/tmp && tar cfj /backup/backup_".$config["hostname"]."-".$date.".tar.bz2 *");
		system ("rm -f -r /backup/tmp/*");
	}
	else {
		logme("BACKUP : ERROR -> the file backup name already exist ABORDING backup...");
		exec_mysql("UPDATE thread SET status='ERROR', date_end=NOW() WHERE pid='".getmypid()."' AND status='running'");
		apc_store("backup_running", 0);
		exit();
	}
	if (file_exists("/backup/backup_".$config["hostname"]."-".$date.".tar.bz2")) {
		exec_mysql("UPDATE thread SET status='OK', date_end=NOW() WHERE pid='".getmypid()."' AND status='running'");
		logme ("BACKUP : backup finish with success ...");
		apc_store("backup_running", 0);
		exit();
	}
	else {
		exec_mysql("UPDATE thread SET status='ERROR', date_end=NOW() WHERE pid='".getmypid()."' AND status='running'");
		logme ("BACKUP : backup failed the archive doesnt exist ...");
		apc_store("backup_running", 0);
		exit();
	}
	apc_store("backup_running", 0);
}
//------------------------------------------------------------------------------
function readconfig_master() { // lit le fichier de configuration
	global $config;
	global $connbdd;
	$tmp=myexec("hostname -f");
	$config["hostname"]=$tmp[0];
	$reader = new XMLReader(); 
	$reader->open("/etc/wprotect/wprotect.conf"); 
	while ($reader->read()) { 
		switch ($reader->nodeType)  { 
			case (XMLREADER::ELEMENT): 
				if ($reader->name == "security_key") { $reader->read(); $config['config_security_key'] = trim( $reader->value ); break; }
				if ($reader->name == "master_ip") { $reader->read(); $config['master_ip'] = trim( $reader->value ); break; }
				if ($reader->name == "master_port") { $reader->read(); $config['master_port'] = trim( $reader->value ); break; }
				if ($reader->name == "config_mysql_host") { $reader->read(); $config['config_mysql_host'] = trim( $reader->value ); break; }
				if ($reader->name == "config_mysql_user") { $reader->read(); $config['config_mysql_user'] = trim( $reader->value ); break; }
				if ($reader->name == "config_mysql_password") { $reader->read(); $config['config_mysql_password'] = trim( $reader->value ); break; }
				if ($reader->name == "config_mysql_db") { $reader->read(); $config['config_mysql_db'] = trim( $reader->value ); break; }
				if ($reader->name == "admin_interface") { $reader->read(); $config['admin_interface'] = trim( $reader->value ); break; }
				if ($reader->name == "theme") { $reader->read(); $config['theme'] = trim( $reader->value ); break; }
				if ($reader->name == "debug") { $reader->read(); $config['debug'] = trim( $reader->value ); break; }
				if ($reader->name == "wifi_access_point_ip") { $reader->read(); $config['wifi_access_point_ip'] = trim( $reader->value ); break; }
				if ($reader->name == "wifi_access_point_mac") { $reader->read(); $config['wifi_access_point_mac'] = trim( $reader->value ); break; }
				if ($reader->name == "public_interface") { $reader->read(); $config['public_interface'][1] = trim( $reader->value ); break; }
				if ($reader->name == "private_interface") { $reader->read(); $config['private_interface'][1] = trim( $reader->value ); break; }
				if ($reader->name == "bridge_interface") { $reader->read(); $config['bridge_interface'][1] = trim( $reader->value ); break; }
				if ($reader->name == "public2_interface") { $reader->read(); $config['public_interface'][2] = trim( $reader->value ); break; }
				if ($reader->name == "private2_interface") { $reader->read(); $config['private_interface'][2] = trim( $reader->value ); break; }
				if ($reader->name == "bridge2_interface") { $reader->read(); $config['bridge_interface'][2] = trim( $reader->value ); break; }
				if ($reader->name == "public3_interface") { $reader->read(); $config['public_interface'][3] = trim( $reader->value ); break; }
				if ($reader->name == "private3_interface") { $reader->read(); $config['private_interface'][3] = trim( $reader->value ); break; }
				if ($reader->name == "bridge3_interface") { $reader->read(); $config['bridge_interface'][3] = trim( $reader->value ); break; }
				if ($reader->name == "public4_interface") { $reader->read(); $config['public_interface'][4] = trim( $reader->value ); break; }
				if ($reader->name == "private4_interface") { $reader->read(); $config['private_interface'][4] = trim( $reader->value ); break; }
				if ($reader->name == "bridge4_interface") { $reader->read(); $config['bridge_interface'][4] = trim( $reader->value ); break; }
				if ($reader->name == "hotspot") { $reader->read(); $config['hotspot'] = trim( $reader->value ); break; }
		}
	}
	get_system_version();
	//----------find public IP-------------------------
	logme("WPROTECT: Get system interface ...");
	foreach ($config['bridge_interface'] AS $k => $v) {
		$tmp = get_infos_net_iface($config['bridge_interface'][$k]);
		logme("WPROTECT: get ".$config['bridge_interface'][$k]." ...");
		foreach ($tmp AS $key => $value) {
			if (isset($tmp['ip'])) {
				$config['public_ip'][$k] = $tmp['ip'];
				$bcast = ip2long($tmp['bcast']);
				$smask = ip2long($tmp['netmask']);
				$nmask = $bcast & $smask;
				$config['public_network'][$k]=long2ip($nmask);
				if ($tmp['netmask']=="255.255.0.0") {
					$config['public_network_cdir'][$k]=$config['public_network'][$k]."/16";
				}
				if ($tmp['netmask']=="255.255.255.0") {
					$config['public_network_cdir'][$k]=$config['public_network'][$k]."/24";
				}
				break;
			}
		}
		if (!isset($config['public_ip'][$k])) {
			logme("WPROTECT: impossible de trouver la configuration de ".$config['bridge_interface'][$k]);
		}
		logme("WPROTECT: ".$config['bridge_interface'][$k]." IP ".$config['public_ip'][$k]." Network ".$config['public_network'][$k]." (".$config['public_network_cdir'][$k].")");
	}
	//------Wifi access point passthrought---------------------
	get_config_ap_list();
	//----------------mac ignore list---------------
	$config['mac_ignore_list'] = array();
	if ($result = exec_mysql("SELECT * FROM mac_ignore_list")) {
		while ($val = mysqli_fetch_array($result)) {
			$config['mac_ignore_list'][$val['id']] = $val['mac'];
		}
	}
	//----------------------------------------------
	$config['net_connection']=array();
	$result = exec_mysql("select * from net_connection");
	while ($val = mysqli_fetch_array($result)) {
		$config['net_connection'][$val['id']]['ip']=$val['ip_to_check'];
		$config['net_connection'][$val['id']]['name']=$val['name'];
	}
}
//-----------------------------------------------------------------------------
function get_config_ap_list() { //récupère les infos des bornes ou les met à jour si necessaire (comparaison par un checksum de la table bornes)
	global $config;
	global $connbdd;
	$val = mysqli_fetch_array(exec_mysql("CHECKSUM TABLE bornes"));
	$current_checksum=$val['Checksum'];
	if ((!isset($config['wifi_access_point_list_checksum'])) OR ($current_checksum!=$config['wifi_access_point_list_checksum'])) {
		$config['wifi_access_point_list_checksum']=$current_checksum;
		$config['wifi_access_point_ip'] = array();
		$config['wifi_access_point_mac'] = array();
		$config['wifi_access_point_network'] = array();
		if ($result = exec_mysql("SELECT * FROM bornes")) {
			while ($val = mysqli_fetch_array($result)) {
				if (substr($val['ip'],0,3) != "169") {
					$config['wifi_access_point_ip'][$val['id']] = $val['ip'];
					$config['wifi_access_point_mac'][$val['id']] = $val['mac'];
					$config['wifi_access_point_network'][$val['id']] = $val['network'];
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
function GenerationCle($Texte,$CleDEncryptage) { // génère la cle de cryptage pour la comunication des daemons
	global $config;
	global $connbdd;
  $CleDEncryptage = md5($CleDEncryptage); 
  $Compteur=0; 
  $VariableTemp = ""; 
  for ($Ctr=0;$Ctr<strlen($Texte);$Ctr++) 
    { 
    if ($Compteur==strlen($CleDEncryptage))
      $Compteur=0; 
    $VariableTemp.= substr($Texte,$Ctr,1) ^ substr($CleDEncryptage,$Compteur,1); 
    $Compteur++; 
    } 
  return $VariableTemp; 
  }
//----------------------------------------------------------------------------  
function Crypte($Texte) { // crypte les infos de communications des daemons avec la clé
	global $config;
	global $connbdd;
  $Cle = $config['config_security_key'];
  srand((double)microtime()*1000000); 
  $CleDEncryptage = md5(rand(0,32000) ); 
  $Compteur=0; 
  $VariableTemp = ""; 
  for ($Ctr=0;$Ctr<strlen($Texte);$Ctr++) 
    { 
    if ($Compteur==strlen($CleDEncryptage)) 
      $Compteur=0; 
    $VariableTemp.= substr($CleDEncryptage,$Compteur,1).(substr($Texte,$Ctr,1) ^ substr($CleDEncryptage,$Compteur,1) ); 
    $Compteur++;
    } 
  return base64_encode(GenerationCle($VariableTemp,$Cle) );
  }
//----------------------------------------------------------------------------
function Decrypte($Texte) { // decrypte les infos de communications des daemons avec la clé
	global $config;
	global $connbdd;
  $Cle = $config['config_security_key'];
  $Texte = GenerationCle(base64_decode($Texte),$Cle);
  $VariableTemp = ""; 
  for ($Ctr=0;$Ctr<strlen($Texte);$Ctr++) 
    { 
    $md5 = substr($Texte,$Ctr,1); 
    $Ctr++; 
    $VariableTemp.= (substr($Texte,$Ctr,1) ^ $md5); 
    } 
  return $VariableTemp; 
  }
//------------------------------------------------------------------------------------
function client_is_authorize ($mac, $network=1) { // vérifie si la mac est autorisés dans iptables
	global $config;
	global $connbdd;
	$tab_result = myexec ("iptables -t filter -L clients".$network." -n");
	foreach ($tab_result AS $key => $value) {
		preg_match("/^RETURN.*MAC\s+(?P<mac>([0-9A-F]{2}:){5}[0-9A-F]{2}).*$/", $value, $match);
		if ((isset($match['mac'])) AND ($mac ==  $match['mac'])) return TRUE;
	}
	return FALSE;
}
//------------------------------------------------------------------------------------
function client_is_vip_authorize ($mac) { // vérifie si un VIP est autorisé
	global $config;
	global $connbdd;
	$tab_result = myexec ("iptables -t filter -L clientsvip -n");
	foreach ($tab_result AS $key => $value) {
		preg_match("/^ACCEPT.*MAC\s+(?P<mac>([0-9A-F]{2}:){5}[0-9A-F]{2}).*$/", $value, $match);
		if ((isset($match['mac'])) AND ($mac ==  $match['mac'])) return TRUE;
	}
	return FALSE;
}
//------------------------------------------------------------------------------------
function client_is_authorize_nat ($mac, $network=1) { // vérifie si la mac est autorisé dans le NAT de iptables
	global $config;
	global $connbdd;
	$tab_result = myexec ("iptables -t nat -L clients".$network." -n");
	foreach ($tab_result AS $key => $value) {
		preg_match("/^RETURN.*MAC\s+(?P<mac>([0-9A-F]{2}:){5}[0-9A-F]{2}).*$/", $value, $match);
		if ((isset($match['mac'])) AND ($mac ==  $match['mac'])) return TRUE;
	}
	return FALSE;
}
//------------------------------------------------------------------------------------
function authorize_client($mac, $network) {
	global $config;
	global $connbdd;
	$q=msg_get_queue(7001);
	if (isset($mac) AND isset($network)) {
		if (!client_is_authorize ($mac, $network)) {
			myexec ("iptables -t filter -I clients".$network." -m mac --mac-source ".$mac." -j RETURN");
			$message=array();
			$message["order"]="add";
			$message["network"]=$network;
			$message["mac"]=$mac;
			$ret=msg_send($q,8,$message,true,true,$err);
		}
		if (client_is_vip_authorize ($mac)) myexec ("iptables -t filter -D clientsvip -m mac --mac-source ".$mac." -j ACCEPT");
		if (!client_is_authorize_nat ($mac, $network)) myexec ("iptables -t nat -I clients".$network." -m mac --mac-source ".$mac." -j RETURN ");
		if ((client_is_authorize ($mac, $network)) AND (client_is_authorize_nat ($mac, $network)) AND (!client_is_vip_authorize ($mac))) {
			exec_mysql("UPDATE lan_discover SET vip='0', authorize='1' WHERE mac='".$mac."' AND network='".$network."'");
			return TRUE;
		}
		else {
			return FALSE;
		}
	}
	else {
		logme("ERROR : authorize_client paramètre manquant");
		return FALSE;
	}
}
//------------------------------------------------------------------------------------
function unauthorize_client($mac, $network) {
	global $config;
	global $connbdd;
	$q=msg_get_queue(7001);
	if (isset($mac) AND isset($network)) {
		if (client_is_authorize ($mac, $network)) {
			myexec ("iptables -t filter -D clients".$network." -m mac --mac-source $mac -j RETURN");
			$message=array();
			$message["order"]="del";
			$message["network"]=$network;
			$message["mac"]=$mac;
			$ret=msg_send($q,8,$message,true,true,$err);
		}
		if (client_is_vip_authorize ($mac)) myexec ("iptables -t filter -D clientsvip -m mac --mac-source $mac -j ACCEPT");
		if (client_is_authorize_nat ($mac, $network)) myexec ("iptables -t nat -D clients".$network." -m mac --mac-source $mac -j RETURN");
		if ((!client_is_authorize ($mac, $network)) AND (!client_is_authorize_nat ($mac, $network)) AND (!client_is_vip_authorize ($mac))) {
			exec_mysql("UPDATE lan_discover SET vip='0', authorize='0' WHERE mac='".$mac."' AND network='".$network."'");
			exec_mysql("UPDATE session_login SET end_date=NOW() WHERE mac='".$mac."' AND network='".$network."' AND end_date IS NULL");
			$result = exec_mysql("SELECT * FROM lan_discover WHERE mac='".$mac."' AND network='".$network."'");
			$val = mysqli_fetch_array($result);
			$ip = $val['ip'];
			myexec ("conntrack -D -s ".$ip." 2>&1");
			myexec ("conntrack -D -d ".$ip." 2>&1");
			return TRUE;
		}
		else {
			return FALSE;
		}
	}
	else {
		logme("ERROR : unauthorize_client paramètre manquant");
		return FALSE;
	}
}
//------------------------------------------------------------------------------------
function vip_authorize_client($mac) {
	global $config;
	global $connbdd;
	if (client_is_authorize ($mac)) myexec ("iptables -t filter -D clients -m mac --mac-source $mac -j RETURN");
	if (!client_is_vip_authorize ($mac)) myexec ("iptables -t filter -I clientsvip -m mac --mac-source $mac -j ACCEPT");
	if (!client_is_authorize_nat ($mac)) myexec ("iptables -t nat -I clients_vip -m mac --mac-source $mac -j ACCEPT");
	if ((!client_is_authorize ($mac)) AND (client_is_authorize_nat ($mac)) AND (client_is_vip_authorize ($mac))) {
		exec_mysql("UPDATE lan_discover SET vip='1', authorize='0' WHERE mac='$mac'");
		return TRUE;
	}
	else {
		return FALSE;
	}
}
//-------------------------------------------------------------------------------------
function vip_unauthorize_client($mac) {
	global $config;
	global $connbdd;
	if (client_is_authorize ($mac)) myexec ("iptables -t filter -D clients -m mac --mac-source $mac -j RETURN");
	if (client_is_vip_authorize ($mac)) myexec ("iptables -t filter -D clientsvip -m mac --mac-source $mac -j ACCEPT");
	if (client_is_authorize_nat ($mac)) myexec ("iptables -t nat -D clients_vip -m mac --mac-source $mac -j ACCEPT");
	if ((!client_is_authorize ($mac)) AND (!client_is_authorize_nat ($mac)) AND (!client_is_vip_authorize ($mac))) {
		exec_mysql("UPDATE lan_discover SET vip='0', authorize='0' WHERE mac='$mac'");
		return TRUE;
	}
	else {
		return FALSE;
	}
}
//------------------------------------------------------------------------------------
function myexec($commande, $log_error=TRUE) {
	global $config;
	global $connbdd;
	exec ($commande, $result, $return);
	if (($return > 0) && $log_error) logme ("EXEC : ".$commande." -> ".$return);
	return $result;
}
//------------------------------------------------------------------------------------
function ping_host($ip) {
	global $config;
	global $connbdd;
	$data = myexec ("ping -c 1 -i 5 -w 1 $ip");
	foreach ($data AS $key => $value) {
		preg_match("/^64 bytes from.+time=(?P<mac>.+)ms$/", $value, $match);
		if ((isset($match['mac']))) return $match['mac'];
	}
	return 9999;
}
//------------------------------------------------------------------------------------
function check_borne($ip, $interface) {
	global $config;
	global $connbdd;
	$data = myexec ("ping -I ".$interface." -c 1 -i 5 -w 1 ".$ip);
	foreach ($data AS $key => $value) {
		preg_match("/^64 bytes from.+time=(?P<mac>.+)ms$/", $value, $match);
		if ((isset($match['mac']))) return TRUE;
	}
	return FALSE;
}
//------------------------------------------------------------------------------------
function check_borne_is_reset($ipm, $interface) {
	global $config;
	global $connbdd;
	$data = myexec ("ping -I ".$interface." -c 1 -i 5 -w 1 ".$ipm);
	foreach ($data AS $key => $value) {
		preg_match("/^64 bytes from.+time=(?P<mac>.+)ms$/", $value, $match);
		if ((isset($match['mac']))) return TRUE;
	}
	return FALSE;
}
//------------------------------------------------------------------------------------
function ping_host_public($ip) {
	global $config;
	global $connbdd;
	$data = myexec ("ping -I ".$config['bridge_interface'][1]." -c 1 -i 5 -w 1 $ip");
	foreach ($data AS $key => $value) {
		preg_match("/^64 bytes from.+time=(?P<mac>.+)ms$/", $value, $match);
		if ((isset($match['mac']))) return $match['mac'];
	}
	return 0;
}
//--------------------------------------
function logme ($data) {
	syslog ( LOG_DEBUG , "[wprotect] ".$data );
}
//------------------------------------------------------------
function connect_mysql () {
    global $config;
	global $connbdd;
	$connbdd = mysqli_connect ($config['config_mysql_host'], $config['config_mysql_user'], $config['config_mysql_password'], $config['config_mysql_db']);
	if (mysqli_connect_errno())
	{
		logme("Failed to connect to MySQL: " . mysqli_connect_error());
		return FALSE;
	}
    return TRUE;
}
//-----------------------------------------------------------
function verif_mysql () {
    global $config;
	global $connbdd;
	if (!isset($connbdd)) connect_mysql();
	if (!($result = @mysqli_query($connbdd, "SET NAMES 'utf8'"))) {
		logme("Verif MySQL ERROR try to reconnect : " . mysqli_error($connbdd));
		connect_mysql();
		if (!($result = @mysqli_query($connbdd, "SET NAMES 'utf8'"))) {
			logme("Failed to connect to MySQL: " . mysqli_connect_error());
			return FALSE;
		}
		else {
			return TRUE;
		}
	}
    return TRUE;
}
//------------------------------------------------------------
function become_daemon() { 

	$pid = pcntl_fork(); 
	if ($pid == -1) { 
		exit(); 
    }
	elseif ($pid) { 
		exit(); 
    }
	else { 
		posix_setsid(); 
		chdir('/'); 
		umask(0); 
		return posix_getpid(); 
    } 
}
//-----------------------------------------------------------
function sig_handler($sig) { 
	global $thread_task;
	global $proc;
    switch($sig) { 
        case SIGTERM:
			logme ("Shutdown via SIGTERM...");
			foreach ($thread_task AS $key=>$value) {
				$value->stop();
			}
			sleep (1);
			logme ("Shutdown Complete turn OFF...");
			exit(0);
		break;
        case SIGINT:
			logme ("Shutdown via SIGKILL...");
			foreach ($thread_task AS $key=>$value) {
				$value->stop();
			}
			sleep (1);
			logme ("Shutdown Complete turn OFF...");
			exit(0);
        break; 		
    } 
}
//-----------------------------------------------------------
function sig_handler_thread($sig) { 
	global $proc;
    switch($sig) { 
        case SIGTERM:
			logme ("thread received SIGTERM");
			if (is_resource($proc)) {
				proc_terminate($proc, 15);
			}
			exit(0);
		break;
        case SIGINT:
			logme ("thread received SIGINT");
			if (is_resource($proc)) {
				proc_terminate($proc, 15);
			}
			exit(0);
        break; 
    } 
}
//--------------------------------------------------------------------
function get_mac_connected($network) {
global $config;
global $connbdd;
$mac_connected = array();
$result = myexec ("brctl showmacs ".$config['bridge_interface'][$network]);
	if (isset($result[0])) {
		foreach ($result AS $key=>$value) {
			preg_match("/^\s+(2|3|4)\s+(?P<mac>([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2})\s+no.+$/", $value, $match);
			if (isset($match['mac'])) {
				$mac = strtoupper($match['mac']);
				get_config_ap_list();
				if ((!in_array($mac, $config['wifi_access_point_mac'])) AND (!in_array($mac, $config['mac_ignore_list']))) {  //si ce n'est pas un AP wifi et si la mac n'est pas a ignoré
					$mac_connected[] = $mac;
				}
			}
		}
		return $mac_connected;
	}
	else return FALSE;
}
//--------------------------------------------------------------------
function get_mac_from_ip($ip, $network=1) {
	global $config;
	global $connbdd;
	if ((get_option("client_must_dhcp")) == 1) {
		if (($mac = apc_fetch ($network."|".$ip)) == apc_fetch ($network."|dhcp|".$ip)) {
			exec_mysql("INSERT INTO lan_discover SET network='".$network."', mac='".$mac."', ip='".$ip."' ON DUPLICATE KEY UPDATE network='".$network."', ip='".$ip."', mac='".$mac."'");
			return $mac;
		}
		else return "unknow";
	}
	else {
		if (($mac = apc_fetch ($network."|".$ip))) {
			exec_mysql("INSERT INTO lan_discover SET network='".$network."', mac='".$mac."', ip='".$ip."' ON DUPLICATE KEY UPDATE network='".$network."', ip='".$ip."', mac='".$mac."'");
			return $mac;
		}
		else return "unknow";
	}
}
//--------------------------------------------------------------------
function get_host_connected() {
	global $config;
	global $connbdd;
	$mac_connected = array();
	$tab_result=array();
	exec ("exec arp-scan -g -r 3 -b 2 -l -t 500 -i 10 -I ".$config['public_interface'][1], $tab_result);
	unset($tab_final);
	$tab_final=array();
	foreach ($tab_result AS $key=>$val) {
			unset($match);
			preg_match("/^(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(?P<mac>[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2})\s+(?P<info>.+)$/", $val, $match);
			if (isset($match['ip'])) {
				$ip = $match['ip'];
				$mac = strtoupper($match['mac']);
				$info = $match['info'];
				if (!in_array($ip, $config['wifi_access_point_ip'])) {
					$mac_connected[$mac] = $ip;
					myexec("ping -I ".$config['bridge_interface'][1]." -c 1 -w 1 $ip");
				}
			}
		}
	return $mac_connected;
}
//--------------------thread function------------------------------------
function lan_discover() {
	global $proc;
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);	
	while (TRUE) {
		unset ($master_mac_list);
		$master_mac_list = array();
		$result = exec_mysql("SELECT * FROM lan_discover WHERE active='1'");
		while ($val = mysqli_fetch_array($result)) {
			$key = $val['mac'];
			$master_mac_list[$key] = $val['ip'];
		}
		$mac_connected = get_host_connected();
		$result=array_diff_assoc($mac_connected,$master_mac_list); //compare si la list des host connecte a changé
		foreach ($result AS $key => $value) { //opère sur les changements
			if (array_key_exists($key, $master_mac_list)) { //mac existe donc l'ip a changé
				$master_mac_list[$key] = $value;
				logme ($key." nouvelle IP -> ".$value);
				exec_mysql("INSERT INTO lan_discover SET mac='$key', ip='$value', active='1', date=NOW() ON DUPLICATE KEY UPDATE ip='$value', mac='$key', active='1', date=NOW();");
			}
			else { //nouvelle adresse MAC
				$master_mac_list[$key] = $value;
				logme ("nouvelle MAC ".$key." -> ".$value);
				exec_mysql("INSERT INTO lan_discover SET mac='$key', ip='$value', active='1', date=NOW() ON DUPLICATE KEY UPDATE ip='$value', mac='$key', active='1', date=NOW();");
			}
		}
		$result=array_diff_assoc($master_mac_list, $mac_connected); //compare pour trouvé les host deconnecté
		foreach ($result AS $key => $value) { //opère sur les changements
			logme ($key."est déconnecté");
			unset ($master_mac_list[$key]);
			action_if_mac_disconnect($key);
		}
	} // fin while true
}
//--------------------------watch_disconnected_mac-----------------------------
function watch_disconnected_mac($network) {
	global $config;
	global $connbdd;
	connect_mysql();
	proc_nice(19);
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);	
	While (TRUE) {
		unset ($master_mac_list);
		$master_mac_list = array();
		$result = exec_mysql("SELECT * FROM lan_discover WHERE network='".$network."'");
		while ($val = mysqli_fetch_array($result)) {
			$key = $val['mac'];
			$master_mac_list[$key] = $val['active'];
		}
		$mac_connected=get_mac_connected($network);
			foreach ($mac_connected AS $key=>$value) {
				if (((!isset($master_mac_list[$value]))) OR ((isset($master_mac_list[$value])) AND ($master_mac_list[$value]==0))) {  //si une mac existante se reconnect ou une nouvelle mac se connect
					action_if_mac_connect($value, $network);
				}
			}
			foreach ($master_mac_list AS $key=>$value) {
				if ((!in_array($key, $mac_connected)) AND ($value==1)) { //une mac c'est déconnectée
					action_if_mac_disconnect($key, $network);
				}
			}
		sleep(5);
	}
}
//----------------------------------------------------------------------------------
function action_if_mac_disconnect($mac, $network=1) {
	$mac = strtoupper($mac);
	exec_mysql("INSERT INTO lan_discover SET mac='".$mac."', active='0', date=NOW(), network='".$network."' ON DUPLICATE KEY UPDATE network='".$network."', mac='".$mac."', active='0', date=NOW();");
	exec_mysql("UPDATE session_login SET end_date=NOW() WHERE network='".$network."' AND mac='".$mac."' AND end_date IS NULL");
}
//---------------------------------------------------------------------------------
function action_if_mac_connect($mac, $network=1) {
	$mac = strtoupper($mac);
	exec_mysql("INSERT INTO lan_discover SET network='".$network."', mac='".$mac."', active='1', date=NOW() ON DUPLICATE KEY UPDATE network='".$network."', mac='".$mac."', active='1', date=NOW();");
	$result=exec_mysql("SELECT * FROM lan_discover WHERE mac='".$mac."' AND authorize='1' AND network='".$network."'");
	if (($val = mysqli_fetch_array($result)) AND (isset($val['login_id']))) {
		exec_mysql("INSERT INTO session_login SET network='".$network."', start_date=NOW(), mac='".$mac."', id_login='".$val['login_id']."'");
	}
}
//-----------------------------------------------------------------------------
function refresh_cache_id_login_from_mac () {
	global $config;
	global $connbdd;
	if (!isset($config['array_mac_login'])) {
		$config['array_mac_login']=array();
	}
	$query="SELECT mac, login_id FROM lan_discover WHERE login_id > 0";
	$result=exec_mysql($query);
	while ($val = mysqli_fetch_array($result)) {
		$config['array_mac_login'][$val['mac']] = $val['login_id'];
	}
	$config['array_mac_login']['ttl'] = time();
	return TRUE;
}
//-----------------------------------------------------------------------------
function borne_save_config($id) {
	global $config;
	global $connbdd;
	if (isset($id)) {
		$query="SELECT * FROM bornes WHERE id = '".$id."'";
		$result=exec_mysql($query);
		$val = mysqli_fetch_array($result);
		if (isset($val['ip'])) {
			ini_set('default_socket_timeout', 3);
			$connection = @ssh2_connect($val['ip'], 22);
			ini_set('default_socket_timeout', 30);
			if (!$connection) return FALSE;
			else {
				if (@ssh2_auth_password($connection, get_option_from_mysql("bornes_admin_login"), get_option_from_mysql("bornes_admin_password"))) {
					$f = ssh2_exec ($connection, "cat /tmp/running.cfg");
					stream_set_blocking ($f, true);
					$result = stream_get_contents ($f);
					fclose($f);
				}
				else {
					if (@ssh2_auth_password($connection, "root", get_option_from_mysql("bornes_admin_password"))) {
						$f = ssh2_exec ($connection, "uci export");
						stream_set_blocking ($f, true);
						$result = stream_get_contents ($f);
						fclose($f);
					}
					else return FALSE;
				}
				exec_mysql("INSERT INTO bornes_config SET bid='".$id."', config='".mysqli_real_escape_string( $connbdd, stripslashes($result))."'");
				exec_mysql("UPDATE bornes SET last_config_save=NOW() WHERE id='".$id."';");
				return TRUE;
			}
		}
		else return FALSE;
	}
	else return FALSE;
}
//-----------------------------------------------------------------------------
function borne_speedtest($bid) {
	global $config;
	global $connbdd;
	connect_mysql();
	$query="SELECT * FROM bornes WHERE id = '".$bid."'";
	$result=exec_mysql($query);
	$val = mysqli_fetch_array($result);
	if (isset($val['gamme'])) {
		if ($val['gamme']=="AIRMAX") {
			return borne_speedtest_airmax($bid);
		}
		else if ($val['gamme']=="UNIFI") {
			return borne_speedtest_unifi($bid);
		}
		else {
			$return=array();
			$return['code']=1;
			$return['msg']='gamme failed';
			$value="N/A";
			return json_encode($return);
		}
	}
	else {
		$return=array();
		$return['code']=1;
		$return['msg']='erreur inconnu';
		$value="N/A";
		return json_encode($return);
	}
}
//-----------------------------------------------------------------------------
function borne_speedtest_unifi($bid) {
	global $config;
	global $connbdd;
	connect_mysql();
	$return=array();
	$return['code']=1;
	$return['msg']='erreur inconnu';
	$value="N/A";
	if (isset($bid)) {
		$query="SELECT * FROM bornes WHERE id = '".$bid."'";
		$result=exec_mysql($query);
		$val = mysqli_fetch_array($result);
		if (isset($val['ip'])) {
			ini_set('default_socket_timeout', 3);
			$connection = @ssh2_connect($val['ip'], 22);
			ini_set('default_socket_timeout', 30);
			if (!$connection) {
				$return=array();
				$return['code']=1;
				$return['msg']="ERROR -> Echec de la connexion";
				return json_encode($return);
			}
			else {
				if (@ssh2_auth_password($connection, get_option_from_mysql("bornes_admin_login"), get_option_from_mysql("bornes_admin_password"))) {
					$f = ssh2_exec ($connection, "curl http://".$config['public_ip'][$val['network']]."/iperf.bin -w 'speed:%{speed_download}' -o /dev/null");
					stream_set_blocking ($f, true);
					$stream_out = ssh2_fetch_stream($f, SSH2_STREAM_STDIO);
					$result = stream_get_contents ($stream_out);
					fclose($f);
					preg_match("/^speed\:(?P<speed>[0-9]+)\..*$/", $result, $match);
					if (isset($match['speed'])) {
						$value=intval(((($match['speed']*8)/1024)/1024));
						logme("SPEEDTEST : ".$val['name']." : ".$value." Mbit/s");
						exec_mysql("UPDATE bornes SET iperf='".$value."' WHERE id='".$bid."'");
						$return=array();
						$return['code']=0;
						$return['msg']=$val['name']."  ".$value." Mbit/s";
						return json_encode($return);
					}
					else {
						$return=array();
						$return['code']=1;
						$return['msg']="ERROR -> Impossible de lire les données";
						return json_encode($return);
					}
				}
				else {
					$return=array();
					$return['code']=1;
					$return['msg']="ERROR -> Echec de la connexion";
					return json_encode($return);
				}
			}
		}
		$return=array();
		$return['code']=1;
		$return['msg']="ERROR -> IP not find";
		return json_encode($return);
	}
	$return=array();
	$return['code']=1;
	$return['msg']="ERROR -> ID not set";
	return json_encode($return);
}
//------------------------------------------------------------------------
function borne_speedtest_airmax($bid) {
	global $config;
	global $connbdd;
	connect_mysql();
	$return=array();
	$return['code']=1;
	$return['msg']='erreur inconnu';
	if (isset($bid)) {
		$result = exec_mysql("SELECT * FROM bornes WHERE id='".$bid."' LIMIT 1");
		$val = mysqli_fetch_array($result);
		if (isset($val['ip'])) {
			$r=myexec("iperf -c ".$val['ip']." -t 10 -w 256K -y C");
			if (isset($r[0])) {
				$t=explode(",", $r[0]);
				if (isset($t[8])) {
					$value=intval($t[8]/1000000);
					exec_mysql("UPDATE bornes SET iperf='".$value."' WHERE id='".$bid."'");
					$return=array();
					$return['code']=0;
					$return['msg']=$val['name']."  ".$value." Mbit/s";
					return json_encode($return);
				}
				else {
					$return=array();
					$return['code']=1;
					$return['msg']='Speedtest FAILED ! no value';
					return json_encode($return);
				}
			}
			else {
				$return=array();
				$return['code']=1;
				$return['msg']='Speedtest FAILED ! no result';
				return json_encode($return);
			}
		}
		else {
			$return=array();
			$return['code']=1;
			$return['msg']='IP not found';
			return json_encode($return);
		}
	}
	else {
		$return=array();
		$return['code']=1;
		$return['msg']='ID not found';
		return json_encode($return);
	}
}
//-----------------------------------------------------------------------------
function borne_upgrade($id, $file) {
	global $config;
	global $connbdd;
	$serv_ip = $config['public_ip'][1];
	if (isset($id) AND isset($file)) {
		$query="SELECT * FROM bornes WHERE id = '".$id."'";
		$result=exec_mysql($query);
		$val = mysqli_fetch_array($result);
		$connection=FALSE;
		if (isset($val['ip']) OR isset($val['mip'])) {
			logme("FIRMWARE UPGRADE : upgrade ".$val['name']." ".$val['ip']." ".$val['mip']);
			ini_set('default_socket_timeout', 3);
			if (strlen($val['ip']) > 3) $connection = ssh2_connect($val['ip'], 22);
			ini_set('default_socket_timeout', 30);
			if (!is_resource($connection)) {
				logme("FIRMWARE UPGRADE : echec de la connexion sur ip try ip maintenance ...");
				ini_set('default_socket_timeout', 3);
				if (strlen($val['mip']) > 3) $connection = ssh2_connect($val['mip'], 22);
				ini_set('default_socket_timeout', 30);
				if (!is_resource($connection)) {
					logme("FIRMWARE UPGRADE : echec de la connexion sur ip de maintenance ... FAILED");
					return FALSE;
				}
				else {
					$serv_ip = "169.254.1.1";
				}
			}
			logme("FIRMWARE UPGRADE : SSH connected try authentification");
			ini_set('default_socket_timeout', 3);
			if (ssh2_auth_password($connection, "ubnt", "ubnt")) {
				$auth=TRUE;
			}
			elseif (is_resource($connection = ssh2_connect($val['ip'], 22)) AND ssh2_auth_password($connection, get_option_from_mysql("bornes_admin_login"), get_option_from_mysql("bornes_admin_password"))) {
				$auth=TRUE;
			}
			else {
				ini_set('default_socket_timeout', 30);
				logme("FIRMWARE UPGRADE : echec de l'authentification ... failed upgrade");
				return FALSE;
			}
			ini_set('default_socket_timeout', 30);
			logme("FIRMWARE UPGRADE : authentification OK try to upload file ".$file." FROM ".$serv_ip);
			$f = ssh2_exec ($connection, "wget http://".$serv_ip."/firmware/".$file." -O /tmp/fwupdate.bin");
			stream_set_blocking ($f, true);
			logme(stream_get_contents ($f));
			fclose($f);
			logme("FIRMWARE UPGRADE : file uploaded : start UPGRADE");
			$f = ssh2_exec ($connection, "/bin/ubntbox fwupdate.real -m /tmp/fwupdate.bin");
			stream_set_blocking ($f, true);
			logme(stream_get_contents ($f));
			fclose($f);
			return TRUE;
		}
		else {
			logme("FIRMWARE UPGRADE : borne description not found no ip ... failed");
			return FALSE;
		}
	}
	else {
		logme("FIRMWARE UPGRADE : failed ID not valid");
		return FALSE;
	}
}
//-----------------------------------------------------------------------------
function get_id_login_from_mac($mac) {
	global $config;
	global $connbdd;
	if (!isset($config['array_mac_login'])) {
		refresh_cache_id_login_from_mac ();
	}
	if ($config['array_mac_login']['ttl'] + 5 < time()) {
		refresh_cache_id_login_from_mac ();
	}
	if (isset($config['array_mac_login'][$mac])) {
		return $config['array_mac_login'][$mac];
	}
	else {
		return FALSE;
	}
}
//----------------------URL tracking thread------------------------------------
function urltrack($network) {
	global $proc;
	global $config;
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN); 
	$descriptorspec = array(
       0 => array("pipe", "r"),   // stdin
       1 => array("pipe", "w"),  // stdout
       2 => array("pipe", "w")   // stderr
	);
	if ($proc = proc_open("exec tcpdump -l -i ".$config['private_interface'][$network]." -n -e -A -s 0 'tcp dst port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'", $descriptorspec, $pipes, null, null)) {
		while ($proc) {
			$proc_status = proc_get_status ( $proc );
			if (!$proc_status['running']) break;
			$read   = array($pipes[1]);
			$write  = NULL;
			$except = NULL;
			if (@stream_select($read, $write, $except, 0, 100000) > 0) { 
				$line = fgets($pipes[1]);
				preg_match("/^(?P<time>\d{1,2}\:\d{1,2}\:\d{1,2}\.\d{1,6})\s(?P<smac>[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2})\s\>\s.*\,\s.*\,\s.*\:\s(?P<sip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\.(?P<sport>[0-9]{1,5})\s\>\s(?P<dip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\.(?P<dport>[0-9]{1,5})\:\s.*$/", $line, $match);
				if (isset($match['smac'])) {
					$smac = strtoupper($match['smac']);
					$sip = $match['sip'];
					$sport = $match['sport'];
					$dip = $match['dip'];
					$dport = $match['dport'];
				}
				preg_match("/^Host\:\s(?P<host>.+)$/", $line, $match);
				if (isset($match['host'])) {
					$host = rtrim($match['host']);
				}
				preg_match("/^.+GET\s\/(?P<url>.+)\sHTTP.*$/", $line, $match);
				if (isset($match['url'])) {
					$url = rtrim($match['url']);
					if (!isset($host)) $host="";
					syslog ( LOG_DEBUG , "[urltrack".$network."] ".$smac."-".$sip." -> ".$dip.":".$dport." -> ".$host."/".$url );
				}
			}
		}
	}
	echo "Processus terminé\n";
	proc_terminate($proc, 15);
	sleep (1);
}
//-----------------------------------------------------------------------------
function bornes_all_refresh_infos() {
	global $config;
	global $connbdd;
	if ($r=exec_mysql("SELECT * FROM bornes WHERE model!='';")) {
		while ($val = mysqli_fetch_array($r)) {
			if (isset($val['ip'])) {
				$id=$val['id'];
				$s=borne_ip_get_infos ($val['ip'], $val['network']);
				if (!isset($s['security_set'])) $s['security_set']="";
				if (isset($s['ssid']) AND isset($s['firmware']) AND isset($s['model'])) {
					exec_mysql("UPDATE bornes SET last_info=NOW(), gamme='".$s['gamme']."', security_set='".$s['security_set']."', last_ping=NOW(), last_seen=NOW(), ssid='".$s['ssid']."', version='".$s['firmware']."', model='".$s['model']."', status='1' WHERE id='".$id."'");
				}
			}
		}
	}
	else exit();
}
//-----------------------------------------------------------------------------
function borne_id_get_and_store_infos($id){
	global $config;
	global $connbdd;
	if (isset($id)) {
		if ($r=exec_mysql("SELECT ip,network  FROM bornes WHERE id='".$id."' LIMIT 1")) {
			$val = mysqli_fetch_array($r);
			if (isset($val['ip'])) {
				$r=borne_ip_get_infos ($val['ip'], $val['network']);
				if (!isset($r['security_set'])) $r['security_set']="";
				if (isset($r['gamme']) AND isset($r['ssid']) AND isset($r['firmware']) AND isset($r['model'])) {
					exec_mysql("UPDATE bornes SET last_info=NOW(), gamme='".$r['gamme']."', security_set='".$r['security_set']."', last_ping=NOW(), last_seen=NOW(), ssid='".$r['ssid']."', version='".$r['firmware']."', model='".$r['model']."', status='1' WHERE id='".$id."'");
					return TRUE;
				}
				else return FALSE;
			}
			else return FALSE;
		}
		else return FALSE;
	}
	else return FALSE;
}
//-----------------------------------------------------------------------------
function borne_ip_get_infos ($ip, $network=1, $debug=true) {
	global $config;
	global $connbdd;
	logme("GET INFO : ". $ip);
	if (isset($ip)) {
		logme("GET INFO : try ssh connection");
		ini_set('default_socket_timeout', 3);
		$connection = @ssh2_connect($ip, 22);
		ini_set('default_socket_timeout', 3);
		if ($connection) {
			logme("GET INFO : SSH connected, try auth");
			$is_connected = FALSE;
			if (@ssh2_auth_password($connection, get_option_from_mysql("bornes_admin_login"), get_option_from_mysql("bornes_admin_password"))) {
				$is_connected = TRUE;
				if ($debug) logme($ip." GET INFO : ssh connect with normal password");
			}
			elseif (@ssh2_auth_password($connection, "ubnt", "ubnt")) {
				if ($debug) logme($ip." GET INFO : ssh connect with default password");
				$is_connected = TRUE;
			}
			elseif (@ssh2_auth_password($connection, "root", get_option_from_mysql("bornes_admin_password"))) {
				if ($debug) logme($ip." GET INFO : ssh connect with root password for camera");
				$is_connected = TRUE;
			}
			if ($is_connected) { // on test les commandes par model
				logme($ip." GET INFO : check is AirMax device");
				$f = ssh2_exec ($connection, "mca-status"); // ubiquiti airmax
				$err = ssh2_fetch_stream($f, SSH2_STREAM_STDERR);
				stream_set_blocking ($f, true);
				stream_set_blocking ($err, true);
				$output_error = stream_get_contents ($err);
				fclose($err);
				if (!$output_error) {
					$output = stream_get_contents ($f);
					$tmp_code=md5($output);
					if ($debug) logme($ip." GET INFO : recieve airmax data -> check security");
					$model = "airmax";
					if (@ssh2_scp_recv ( $connection , "/etc/persistent/rc.poststart", "/tmp/test-security-".$tmp_code)) {
						$tt=apc_fetch("poststart_b_".$network);
						$ttt=apc_fetch("poststart_p_".$network);
						$tttt=md5(file_get_contents("/tmp/test-security-".$tmp_code));
						if ($tt==$tttt) {
							$security_set="B".$network;
						}
						else if ($ttt==$tttt) {
							$security_set="P".$network;
						}
						else {
							$security_set="";
						}
						unlink("/tmp/test-security-".$tmp_code);
						if ($debug) logme($ip." GET INFO : security ".$security_set);
					}
					fclose($f);
				}
				else {
					
						fclose($f);
						if ($debug) logme($ip." GET INFO : Check is UNIFI device");
						$f = ssh2_exec ($connection, "mca-cli-op info"); // UNIFI
						$err = ssh2_fetch_stream($f, SSH2_STREAM_STDERR);
						stream_set_blocking ($f, true);
						stream_set_blocking ($err, true);
						$output_error = stream_get_contents ($err);
						fclose($err);
						if (!$output_error) {
							$output = stream_get_contents ($f);
							if ($debug) logme($ip." GET INFO : UNIFI device detected -> try to take infos");
							$model = "unifi";
							fclose($f);
						}
						else {
							$output = stream_get_contents ($f);
							fclose($f);
							$model = "error";
							$p['model'] = "ERROR";
							$p['ssid'] = "";
							$p['firmware'] = "";
						}
				}
				switch ($model) {
					case "airmax":
						$a = str_replace(",", "\n", $output);
						$ligne = preg_split("/[\n]+/", $a);
						$b = array();
						foreach( $ligne as $row => $value ) {
							$c=explode ("=", $value);
							if (isset($c[1])) {
								$b[$c[0]]=$c[1];
							}
						}
						if (isset($b['platform'])) {
							$p['model'] = $b['platform'];
						} else $p['model']="";
						if (isset($b['essid'])) {
							$p['ssid'] = $b['essid'];
						} else $p['ssid']="";
						if (isset($b['firmwareVersion'])) {
							$o = explode(".",$b['firmwareVersion']);
							$p['firmware'] = $o[0]." ".$o[2].".".$o[3].".".$o[4];
						} else $p['firmware']="";
						if (isset($security_set)) {
							$p['security_set'] = $security_set;
						}
						else {
							$p['security_set'] = "";
						}
						$p['gamme'] = "AIRMAX";
						return $p;
					break;
					case "openwrt":
						$p['model'] = $output;
						$p['ssid'] = "";
						$p['firmware'] = "";
						$p['gamme'] = "OPENWRT";
						return $p;
					break;
					case "unifi":
						$ligne = preg_split("/[\n]+/", $output);
						$b = array();
						foreach( $ligne as $row => $value ) {
							$c=explode (":", $value);
							if (isset($c[1])) {
								$b[$c[0]]=$c[1];
							}
						}
						if (isset($b['Model'])) {
							$p['model'] = ltrim($b['Model']);
						} else $p['model']="UNIFI";
						if (isset($b['essid'])) {
							$p['ssid'] = $b['essid'];
						} else $p['ssid']="";
						if (isset($b['Version'])) {
							$p['firmware'] = ltrim($b['Version']);
						} else $p['firmware']="";
						if ($debug) logme($ip." GET INFO : UNIFI : model=".$p['model']." ssid=".$p['ssid']." firmware=".$p['firmware']);
						$p['gamme'] = "UNIFI";
						return $p;
					break;
				}
			}
		}
		logme("GET INFO : try snmp");
		// test if tp-link via snmp
		$p=array();
		$t=myexec("snmpwalk -t 2 -v 2c -c remote ".$ip." iso.3.6.1.2.1.1.5.0");
		if (isset($t[0])) {
			foreach ($t AS $k=>$v) {
				preg_match("/^iso\.3\.6\.1\.2\.1\.1\.5\.0\s\=\sSTRING\:\s\"(?P<model>[a-zA-Z0-9\-]+)\".*$/", $v, $match);
				if (isset($match['model'])) {
					$p['model'] = $match['model'];
					$p['gamme'] = "TP-LINK";
					$p['ssid'] = "";
					$p['firmware'] = "";
					return $p;
				}
			}
		}
	}
	logme("GET INFO : no model found");
	return FALSE;
}
//-----------------------------------------------------------------------------
function thread_check_bornes_status () {
	global $proc;
	global $config;
	global $connbdd;
	connect_mysql();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	logme("THREAD : Check bornes status is started ...");
	apc_store("thread_bornes_watcher", getmypid());
	$tosleep=30;
	While (TRUE) {
		if (get_option_from_mysql("poll_bornes_status")==1) {
			$poll_time_calculate_start=time();
			unset ($bornes_mac_list);
			$bornes_mac_list = array();
			$result = exec_mysql("SELECT * FROM bornes WHERE ((UNIX_TIMESTAMP(last_mca) + 40) < UNIX_TIMESTAMP(NOW())) OR status='2';");
			while ($val = mysqli_fetch_array($result)) {
				$tosleep--;
				$bornes_mac_list[$val['mac']]['id'] = $val['id'];
				$bornes_mac_list[$val['mac']]['netid'] = $val['network'];
				$bornes_mac_list[$val['mac']]['ip'] = $val['ip'];
				$bornes_mac_list[$val['mac']]['mip'] = $val['mip'];
				$bornes_mac_list[$val['mac']]['status'] = $val['status'];
				$bornes_mac_list[$val['mac']]['name'] = $val['name'];
			}
			
			foreach ($bornes_mac_list AS $mac=>$v) {
				if (is_debug_mode()) logme("CHECK ".$bornes_mac_list[$mac]['name']." ".$bornes_mac_list[$mac]['ip']);
				if (($bornes_mac_list[$mac]['ip']!="") AND check_borne($bornes_mac_list[$mac]['ip'], $config['bridge_interface'][$v['netid']])) { // check if borne respond
					if (is_debug_mode()) logme($bornes_mac_list[$mac]['name']." ".$bornes_mac_list[$mac]['ip']." PING RESPOND");
					exec_mysql("UPDATE bornes SET last_ping=NOW(), last_seen=NOW(), status='1' WHERE id='".$bornes_mac_list[$mac]['id']."'");
					usleep(250000);
				}
				else { // check if borne respond on maintenance network
					if (is_debug_mode()) logme($bornes_mac_list[$mac]['name']." ".$bornes_mac_list[$mac]['ip']." NO PING RESPOND CHECK M NETWORK");
					if (($bornes_mac_list[$mac]['mip']!="") AND check_borne_is_reset($bornes_mac_list[$mac]['mip'], $config['bridge_interface'][$v['netid']].":0")) { // check if borne respond on maintenance network
						if (is_debug_mode()) logme($bornes_mac_list[$mac]['name']." ".$bornes_mac_list[$mac]['ip']." status 2");
						exec_mysql("UPDATE bornes SET last_ping=NOW(), last_seen=NOW(), status='2' WHERE id='".$bornes_mac_list[$mac]['id']."'");
					}
					else {
						if (is_debug_mode()) logme($bornes_mac_list[$mac]['name']." ".$bornes_mac_list[$mac]['ip']." is OUT status 0");
						exec_mysql("UPDATE bornes SET last_ping=NOW(), status='0' WHERE id='".$bornes_mac_list[$mac]['id']."'");
					}
				}
			}
			$poll_time_calculate_stop=time();
			logme("check_bornes_status : ".($poll_time_calculate_stop-$poll_time_calculate_start). "s");
			if ($tosleep < 2) $tosleep=2;
			sleep($tosleep);
			$tosleep=30;
		}
		else {
			sleep(30);
			$tosleep=30;
		}
	}
}
//----------------------------------GET ALL IP MAC FROM ARP TABLE------------------------------
function thread_get_all_ip_mac_from_arp_table() {
	global $config;
	global $connbdd;
	while(TRUE) {
		foreach ($config['bridge_interface'] AS $net_id => $temp) {
			$r=myexec("arp -a -n | grep ".$temp, FALSE);
			foreach($r AS $k=>$v) {
				preg_match("/^.*\s\((?P<ip>[0-9\.].*)\)\sat\s(?P<mac>[0-9a-f\:]{17})\s.*$/", $v, $match);
				if (isset($match['ip']) AND isset($match['mac'])) {
					apc_store ( $net_id."|".strtoupper($match['mac']) , $match['ip'], 600 );
					apc_store ( $net_id."|".$match['ip'] , strtoupper($match['mac']), 600 );
				}
			}
		}
		sleep(10);
	}
}
//----------------------------------watch IP MAC ------------------------------
function watch_ip_mac($iface) {
	global $proc;
	global $config;
	global $connbdd;
	$ip = $config['iface'][$config['iface'][$iface]['is_bridge_to']]['ip'];
	$network = (substr($config['iface'][$iface]['is_bridge_to'], 2, 1))+1;
	connect_mysql();
	$mac_ip=array();
	$mac_ip[1]=array();
	$mac_ip[2]=array();
	$mac_ip[3]=array();
	$mac_ip[4]=array();
	$cache_ttl=array();
	$cache_ttl[1]=array();
	$cache_ttl[2]=array();
	$cache_ttl[3]=array();
	$cache_ttl[4]=array();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN); 
	$descriptorspec = array(
       0 => array("pipe", "r"),   // stdin
       1 => array("pipe", "w"),  // stdout
       2 => array("pipe", "w")   // stderr
	);
	logme("WATCH CONNECTED MAC : ".$network." ".$iface." -> ".$ip);
	if ($proc = proc_open("exec tcpdump -t -l -i ".$iface." -n -e 'tcp[tcpflags] & (tcp-syn) != 0 and dst host ".$ip." and (tcp dst port 80 or tcp dst port 443)'", $descriptorspec, $pipes, null, null)) {
		while ($proc) {
			$proc_status = proc_get_status ( $proc );
			if (!$proc_status['running']) break;
			$read   = array($pipes[1]);
			$write  = NULL;
			$except = NULL;
			if (@stream_select($read, $write, $except, 0, 100000) > 0) { 
				$line = fgets($pipes[1]);
				preg_match("/^(?P<smac>[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2})\s\>\s.*\,\s.*\,\s.*\:\s(?P<sip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\.(?P<sport>[0-9]{1,5})\s\>\s(?P<dip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\.(?P<dport>[0-9]{1,5})\:\s.*$/", $line, $match);
				if (isset($match['smac'])) {
					$smac = strtoupper($match['smac']);
					$sip = $match['sip'];
					if ((!isset($mac_ip[$network][$smac])) OR ($mac_ip[$network][$smac]!=$sip) OR (($cache_ttl[$network][$smac]+300) < time())) {
						apc_store ( $network."|".$smac , $sip, 600 );
						apc_store ( $network."|".$sip , $smac, 600 );
						//logme("WATCH CONNECTED MAC : ".$network." : STORE CACHE IP ".$sip." has MAC -> ".$smac);
						$cache_ttl[$network][$smac]=time();
						$mac_ip[$network][$smac]=$sip;
					}
					else {
						//logme("WATCH CONNECTED MAC : ".$network." : ALREADY CACHE IP ".$sip." has MAC -> ".$smac);
					}
				}
				else {
					logme("WATCH CONNECTED MAC : ERROR match output failed...");
				}
			}
		}
	}
	echo "Processus terminé\n";
	proc_terminate($proc, 15);
	sleep (1);
}
//------------------------------------------------------------------------------------------------------
function watch_dhcp_ip_mac($iface) {
	global $proc;
	global $config;
	global $connbdd;
	$br=$config['iface'][$iface]['is_bridge_to'];
	$ip = $config['iface'][$config['iface'][$iface]['is_bridge_to']]['ip'];
	$network = (substr($config['iface'][$iface]['is_bridge_to'], 2, 1))+1;
	connect_mysql();
	$mac_ip=array();
	$last_record="";
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN); 
	$descriptorspec = array(
       0 => array("pipe", "r"),   // stdin
       1 => array("pipe", "w"),  // stdout
       2 => array("pipe", "w")   // stderr
	);
	logme("WATCH DHCP MAC IP : ".$network." : bind ".$br." -> ".$ip);
	if ($proc = proc_open("exec tcpdump -v -t -l -i ".$br." -n -e 'src port 67'", $descriptorspec, $pipes, null, null)) {
		$mac="";
		$ip="";
		while ($proc) {
			$proc_status = proc_get_status ( $proc );
			if (!$proc_status['running']) break;
			$read   = array($pipes[1]);
			$write  = NULL;
			$except = NULL;
			if (@stream_select($read, $write, $except, 0, 100000) > 0) { 
				$line = fgets($pipes[1]);
				preg_match("/^(?P<mac>[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2})\s>\s.*$/", $line, $match);
				if (isset($match['mac'])) { //reset trame
					$mac=$match['mac'];
					$ip="";
					$mac="";
				}
				preg_match("/^.*Client\-Ethernet\-Address\s(?P<mac>[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}).*$/", $line, $match);
				if (isset($match['mac'])) {
					$mac=$match['mac'];
				}
				preg_match("/^.*Your\-IP\s(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*$/", $line, $match);
				if (isset($match['ip'])) {
					$ip=$match['ip'];
				}
				if ($ip!="" AND $mac!="" AND $ip!=$last_record) {
					$last_record=$ip;
					$mac = strtoupper($mac);
					logme("DHCP_SNIFFER : ".$network." : new IP : ".$ip." : ".$mac);
					apc_store ( $network."|dhcp|".$ip , $mac, 172800 );
					apc_store ( $network."|dhcp|".$mac , $ip, 172800 );
					$ip="";
					$mac="";
				}
			}
		}
	}
	echo "Processus terminé\n";
	proc_terminate($proc, 15);
	sleep (1);
}
//---------------------------------------------------------------------------------------------------
function server_loop() { //boucle d'attente de nouveaux clients
    GLOBAL $__server_listening;
	GLOBAL $thread_list;
	GLOBAL $config;
	global $connbdd;
	connect_mysql();
	
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
    
	if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) 
    { 
        logme ("failed to create socket: ".socket_strerror($sock)); 
        exit(); 
    } 
	socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
    if(($ret = socket_bind($sock, $config['master_ip'], $config['master_port'])) < 0) 
    { 
        logme ("failed to bind socket: ".socket_strerror($ret)); 
        exit(); 
    } 

    if( ( $ret = socket_listen( $sock, 0 ) ) < 0 ) 
    { 
        logme ("failed to listen to socket: ".socket_strerror($ret)); 
        exit(); 
    } 

    
    
    logme ("waiting for clients to connect"); 

    while ($__server_listening) 
    { 
		//---------------Gestion des Threads par le processus maitre---------------------		
		$oldErrorLevel = error_reporting(0);
		error_reporting( $oldErrorLevel & ~E_WARNING );
		foreach ($thread_list AS $child_key=>$child_pid) {
			if ((pcntl_getpriority($child_pid)) === FALSE) {
				unset ($thread_list[$child_key]);
			}
		}
		error_reporting( $oldErrorLevel);
		//--------------------------------------------------------------------------------
		$write = NULL;
		$except = NULL;
		$tv_sec = 1;
		$sock_tab = array(1 => $sock);
		$ready = @socket_select($sock_tab, $write, $except, $tv_sec);
		if ($ready > 0) {
		$connection = @socket_accept($sock_tab[1]); 
        if ($connection === false) 
        { 
			continue;
        }elseif ($connection > 0) 
        { 
			handle_client($sock_tab[1], $connection); 
        }else 
        { 
            logme ("error: ".socket_strerror($connection)); 
            die; 
        }
		}
    } 
}
//---------------------------------------------------------------------------------------------------
function handle_client($ssock, $csock) { //creation d'une thread pour un nouveau client connecté
    GLOBAL $__server_listening; 
	GLOBAL $thread_list;
	global $config;
	global $connbdd;
	
    $pid = pcntl_fork(); 
    if ($pid == -1) 
    { 
        /* fork failed */ 
        logme ("MASTER SERVER : fork failure! : DIE"); 
        die; 
    }elseif ($pid == 0) 
    { 
        /* child process */
        $__server_listening = false; 
        socket_close($ssock); 
        interact($csock); 
        socket_close($csock);
    }else 
    { 
		array_push($thread_list, $pid);
		socket_close($csock); 
    } 
}
//---------------------------------------------------------------------------------------------------
function is_debug_mode() {
	global $config;
	global $connbdd;
	if (!apc_exists("is_debug_mode_ttl")) {
		apc_store("is_debug_mode_ttl", 0);
	}
	if (apc_fetch("is_debug_mode_ttl")+10 < time()) {
		$result=exec_mysql("SELECT value FROM options WHERE name='debug' LIMIT 1");
		$val=mysqli_fetch_array($result);
		if (isset($val['value'])) {
			apc_store("is_debug_mode", $val['value']);
			apc_store("is_debug_mode_ttl", time());
			return $val['value'];
		}
		else return 0;
	}
	else return apc_fetch("is_debug_mode");
}
//---------------------------------------------------------------------------------------------------
function remove_security_config ($bid) {
	global $config;
	global $connbdd;
	connect_mysql();
	$return=array();
	$return['code']=1;
	$return['msg']='erreur inconnu';
	if (!isset($bid)) {
		$return['code']=1;
		$return['msg']='ID not specified';
		return json_encode($return);
	}
	$result = exec_mysql("SELECT *, UNIX_TIMESTAMP(last_mca) AS last_mca FROM bornes WHERE id='".$bid."' LIMIT 1");
	while ($val = mysqli_fetch_array($result)) {
		if (isset($val['ip']) AND (($val['status']==1) OR ($val['last_mca']+25 > time()))) {
			$ip=$val['ip'];
			$login="admin";
			logme("REMOVE_SECURITY_TO : ".$val['name']." ".$ip);
			$password=get_option_from_mysql("bornes_admin_password");
			ini_set('default_socket_timeout', 3);
			$connection = @ssh2_connect($ip, 22);
			ini_set('default_socket_timeout', 30);
			if (is_resource($connection)) {
				logme("REMOVE_SECURITY_TO : ".$val['name']." Connection ssh OK try to authenticate ...");
				if (ssh2_auth_password($connection, $login, $password)) {
					logme("REMOVE_SECURITY_TO : ".$val['name']." auth OK try to remove files ...");
					if (is_resource($f = ssh2_exec ($connection, "rm /etc/persistent/rc.poststart;rm /etc/persistent/unifi_mca;rm /etc/persistent/unifi_firewall;cfgmtd -w -p /etc/;reboot"))) {
						stream_set_blocking ($f, true);
						fclose($f);
						$return['code']=0;
						$return['msg']=$val['name']." OK";
						logme("REMOVE_SECURITY_TO : ".$return['msg']);
						return json_encode($return);
					}	
					else {
						$return['code']=1;
						$return['msg']=$val['name']." SSH command failed aborted";
						logme("REMOVE_SECURITY_TO : ".$return['msg']." -> FAILED");
						return json_encode($return);
					}
				}
				else {
					$return['code']=1;
					$return['msg']='Echec authentification SSH';
					logme("REMOVE_SECURITY_TO : ".$return['msg']." -> FAILED");
					return json_encode($return);
				}
			}
			else {
				$return['code']=1;
				$return['msg']='Echec de la connexion SSH';
				logme("REMOVE_SECURITY_TO : ".$return['msg']." -> FAILED");
				return json_encode($return);
			}
		}
		else {
			$return['code']=1;
			$return['msg']='Status de la borne incorrect';
			logme("REMOVE_SECURITY_TO : ".$return['msg']." -> FAILED");
			return json_encode($return);
		}
	}
}
//---------------------------------------------------------------------------------------------------
function airmax_load_security_config ($bid, $b_or_p) {
	global $config;
	global $connbdd;
	connect_mysql();
	$return=array();
	$return['code']=1;
	$return['msg']='erreur inconnu';
	if (isset($b_or_p) AND $b_or_p=="b") {
		$file="/opt/wprotect/poststart_b";
	}
	else if (isset($b_or_p) AND $b_or_p=="p") {
		$file="/opt/wprotect/poststart_p";
	}
	else {
		$return['code']=1;
		$return['msg']="Missing argument B or P";
		return json_encode($return);
	}
	if (isset($bid) AND isset($b_or_p)) {
		$result = exec_mysql("SELECT *, UNIX_TIMESTAMP(last_mca) AS last_mca FROM bornes WHERE id='".$bid."' LIMIT 1");
		while ($val = mysqli_fetch_array($result)) {
			if ($val['gamme']=="AIRMAX") {
				if (isset($val['network'])) {
					$file=$file."_".$val['network'];
				}
				if (isset($val['ip']) AND (($val['status']==1) OR ($val['last_mca']+25 > time()))) {
					$ip=$val['ip'];
					$login="admin";
					$password=get_option_from_mysql("bornes_admin_password");
					ini_set('default_socket_timeout', 3);
					$connection = @ssh2_connect($ip, 22);
					ini_set('default_socket_timeout', 30);
					if (is_resource($connection)) {
						logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." Connection ssh OK try to authenticate ...");
						if (ssh2_auth_password($connection, $login, $password)) {
							logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." auth OK try to load config file ...");
							if (file_exists ($file)) {
								
								if (ssh2_scp_send ( $connection , $file , "/etc/persistent/rc.poststart") === FALSE) {
									logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." File transfer failed");
									$return['code']=1;
									$return['msg']=$val['name']." file transfer failed";
									return json_encode($return);
								}
								
								if (is_resource($f = ssh2_exec ($connection, "chmod +x /etc/persistent/rc.poststart"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
							
								if (is_resource($f = ssh2_exec ($connection, "cfgmtd -w -p /etc/"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
							
								if (is_resource($f = ssh2_exec ($connection, "/etc/persistent/rc.poststart"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
							
								if (is_resource($f = ssh2_exec ($connection, "exit"))) {
									stream_set_blocking ($f, false);
									fclose($f);
								}
								else {
									logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." SSH EXIT command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH EXIT command failed aborted";
									return json_encode($return);
								}
							
								borne_id_get_and_store_infos($bid);
								logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." OK");
								$return['code']=0;
								$return['msg']=$val['name']." OK";
								return json_encode($return);
								exit();
							}
							else {
								logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." poststart file not exist ... FAIlED");
								$return['code']=1;
								$return['msg']=$val['name']." poststart file not exist";
								return json_encode($return);
							}
						}
						else {
							logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." Echec authentification SSH");
							$return['code']=1;
							$return['msg']=$val['name']." Echec authentification SSH";
							return json_encode($return);
						}
					}
					else {
						logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." Echec de la connexion SSH");
						$return['code']=1;
						$return['msg']=$val['name']." Echec de la connexion SSH";
						return json_encode($return);
					}
				}
				else {
					logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." is not ready");
					$return['code']=1;
					$return['msg']=$val['name']." Is not READY";
					return json_encode($return);
				}
			}
			if ($val['gamme']=="UNIFI") {
				if (isset($val['ip']) AND (($val['status']==1) OR ($val['last_mca']+25 > time()))) {
					$ip=$val['ip'];
					$login="admin";
					$password=get_option_from_mysql("bornes_admin_password");
					ini_set('default_socket_timeout', 3);
					$connection = @ssh2_connect($ip, 22);
					ini_set('default_socket_timeout', 30);
					$file="/opt/wprotect/unifi_mca_".$val['network'];
					/*//---------generate all network firewall for this UNIFI AP------
					$a=array();
					$a[]=$val['network'];
					if (isset($val['network_add']) AND $val['network_add']!="") {
						logme("secondary network ".$val['network_add']);
						$y=str_split($val['network_add']);
						foreach ($y AS $k=>$v) {
							$a[]=$v;
						}
					}
					$u=array();
					foreach ($a AS $k=>$v) {
						$result2 = exec_mysql("SELECT * FROM network WHERE id='".$v."'");
						while ($val2 = mysqli_fetch_array($result2)) {
							if (!isset($val2['ip_routeur']) OR !isset($val2['mac_routeur']) OR !isset($val2['ip_wprotect']) OR !isset($val2['mac_wprotect']) OR $val2['ip_routeur']=="" OR $val2['mac_routeur']=="" OR $val2['ip_wprotect']=="" OR $val2['mac_wprotect']=="") {
								logme("UNIFI_LOAD_SECURITY_TO : Network protect configuration is not SET");
								$return['code']=1;
								$return['msg']="Network protect configuration is not SET";
								return json_encode($return);
							}
							$u[$v]=array();
							$u[$v]['ip_routeur']=$val2['ip_routeur'];
							$u[$v]['mac_routeur']=$val2['mac_routeur'];
							$u[$v]['ip_wprotect']=$val2['ip_wprotect'];
							$u[$v]['mac_wprotect']=$val2['mac_wprotect'];
							$u[$v]['vlan']=$val2['vlan'];
						}
					}
					system("echo \"\" > /opt/wprotect/tmp/".$val['mac']);
					foreach ($u AS $k=>$v) {
						if ($val["unifi_".$k."_iface"]=="") {
							$return['code']=1;
							$return['msg']="UNIFI interface is not SET please config security first";
							logme("UNIFI_LOAD_SECURITY_TO : ".$return['msg']);
							return json_encode($return);
						}
						$oj=explode(" ", $val["unifi_".$k."_iface"]);
						foreach($oj AS $kk=>$vv) {
							system("cat /opt/wprotect/unifi_firewall.sample >> /opt/wprotect/tmp/".$val['mac']);
							system("sed -i -e \"s/{ROOTER_MAC}/".$v['mac_routeur']."/g\" /opt/wprotect/tmp/".$val['mac']);
							system("sed -i -e \"s/{ROOTER_IP}/".$v['ip_routeur']."/g\" /opt/wprotect/tmp/".$val['mac']);
							system("sed -i -e \"s/{WPROTECT_MAC}/".$v['mac_wprotect']."/g\" /opt/wprotect/tmp/".$val['mac']);
							system("sed -i -e \"s/{WPROTECT_IP}/".$v['ip_wprotect']."/g\" /opt/wprotect/tmp/".$val['mac']);
							system("sed -i -e \"s/{IN_IF}/".$vv."/g\" /opt/wprotect/tmp/".$val['mac']);
							if ( $v['vlan']=="0" OR $v['vlan']=="" ) {
								system("sed -i -e \"s/{OUT_IF}/eth0/g\" /opt/wprotect/tmp/".$val['mac']);
								system("sed -i -e \"s/{BR_IF}/br0/g\" /opt/wprotect/tmp/".$val['mac']);
							}
							else {
								system("sed -i -e \"s/{OUT_IF}/eth0.".$v['vlan']."/g\" /opt/wprotect/tmp/".$val['mac']);
								system("sed -i -e \"s/{BR_IF}/br0.".$v['vlan']."/g\" /opt/wprotect/tmp/".$val['mac']);
							}
						}
					}
					//------END---generate firewall--------------------------*/
					if (is_resource($connection)) {
						logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." Connection ssh OK try to authenticate ...");
						if (ssh2_auth_password($connection, $login, $password)) {
							logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." auth OK try to load config file ...");
							if (file_exists ($file)) {
								
								if (ssh2_scp_send ( $connection , $file , "/etc/persistent/unifi_mca") === FALSE) {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." File MCA transfer failed");
									$return['code']=1;
									$return['msg']=$val['name']." file MCA transfer failed";
									return json_encode($return);
								}
								if (ssh2_scp_send ( $connection , "/opt/wprotect/poststart_unifi" , "/etc/persistent/rc.poststart") === FALSE) {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." File poststart transfer failed");
									$return['code']=1;
									$return['msg']=$val['name']." file poststart transfer failed";
									return json_encode($return);
								}
								/*//------------------firewall transfert----------------------
								if (ssh2_scp_send ( $connection , "/opt/wprotect/tmp/".$val['mac'] , "/etc/persistent/unifi_firewall") === FALSE) {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." File transfer failed");
									$return['code']=1;
									$return['msg']=$val['name']." file transfer failed";
									return json_encode($return);
								}
								if (is_resource($f = ssh2_exec ($connection, "chmod +x /etc/persistent/unifi_firewall"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
								//--------------------------------------------------------*/
								if (is_resource($f = ssh2_exec ($connection, "chmod +x /etc/persistent/unifi_mca"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." SSH +x MCA command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH +x MCA command failed aborted";
									return json_encode($return);
								}
								if (is_resource($f = ssh2_exec ($connection, "chmod +x /etc/persistent/rc.poststart"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
							
								if (is_resource($f = ssh2_exec ($connection, "cfgmtd -w -p /etc/"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
							
								if (is_resource($f = ssh2_exec ($connection, "/etc/persistent/rc.poststart"))) {
									stream_set_blocking ($f, true);
									fclose($f);
								}
								else {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." SSH command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH command failed aborted";
									return json_encode($return);
								}
							
								if (is_resource($f = ssh2_exec ($connection, "exit"))) {
									stream_set_blocking ($f, false);
									fclose($f);
								}
								else {
									logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." SSH EXIT command failed aborted");
									$return['code']=1;
									$return['msg']=$val['name']." SSH EXIT command failed aborted";
									return json_encode($return);
								}
							
								borne_id_get_and_store_infos($bid);
								logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." OK");
								$return['code']=0;
								$return['msg']=$val['name']." OK";
								return json_encode($return);
								exit();
							}
							else {
								logme("UNIFI_LOAD_SECURITY_TO : ".$val['name']." poststart file not exist ... FAIlED");
								$return['code']=1;
								$return['msg']=$val['name']." poststart file not exist";
								return json_encode($return);
							}
						}
						else {
							logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." Echec authentification SSH");
							$return['code']=1;
							$return['msg']=$val['name']." Echec authentification SSH";
							return json_encode($return);
						}
					}
					else {
						logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." Echec de la connexion SSH");
						$return['code']=1;
						$return['msg']=$val['name']." Echec de la connexion SSH";
						return json_encode($return);
					}
				}
				else {
					logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." is not ready");
					$return['code']=1;
					$return['msg']=$val['name']." Is not READY";
					return json_encode($return);
				}
			}
			else {
				logme("AIRMAX_LOAD_SECURITY_TO : ".$val['name']." failed : is not a AIRMAX/UNIFI product");
				$return['code']=1;
				$return['msg']=$val['name']." Is not a AIRMAX/UNIFI product";
				return json_encode($return);
			}
		}
	}
	else {
		return json_encode($return);
	}
}
//---------------------------------------------------------------------------------------------------
function airmax_load_last_config ($bid) {
	global $config;
	global $connbdd;
	connect_mysql();
	if (isset($bid)) {
		$result = exec_mysql("SELECT * FROM bornes_config LEFT JOIN bornes ON bornes_config.bid=bornes.id WHERE bid='".$bid."' ORDER BY date DESC LIMIT 1");
		while ($val = mysqli_fetch_array($result)) {
			if (isset($val['config'])) {
				$config_file = $val['config'];
				if (isset($config_file)) {
					if ($val['status']==2) {
						$bip=$val['mip'];
					}
					else {
						$bip=$val['ip'];
					}
					airmax_load_config_to ($bip, $config_file, "ubnt", "ubnt");
				}
			}
			else {
				return FALSE;
			}
		}
	}
	else {
		return FALSE;
	}
}
//---------------------------------------------------------------------------------------------------
function airmax_load_config_to ($ip, $config_file, $login, $password) {
	global $config;
	$current_tmp_name = microtime(TRUE).".cfg";
	logme("AIRMAX_LOAD_CONFIG_TO : Try to load config to ".$ip);
	if (isset($ip) AND isset($config) AND isset($login) AND isset($password)) {
		ini_set('default_socket_timeout', 3);
		$connection = @ssh2_connect($ip, 22);
		ini_set('default_socket_timeout', 30);
		if ($connection) {
			logme("AIRMAX_LOAD_CONFIG_TO : Connection ssh OK try to authenticate ...");
			if (ssh2_auth_password($connection, $login, $password)) {
				logme("AIRMAX_LOAD_CONFIG_TO : auth OK try to load config file ...");
				file_put_contents ( "/tmp/".$current_tmp_name , $config_file );
				ssh2_scp_send ( $connection , "/tmp/".$current_tmp_name , "/tmp/system.cfg", 0777);
				myexec("rm /tmp/".$current_tmp_name);
				$f = ssh2_exec ($connection, "cfgmtd -f /tmp/system.cfg -w");
				stream_set_blocking ($f, true);
				fclose($f);
				$f = ssh2_exec ($connection, "save");
				stream_set_blocking ($f, true);
				fclose($f);
				sleep(5);
				$f = ssh2_exec ($connection, "reboot");
				stream_set_blocking ($f, true);
				fclose($f);
				logme("AIRMAX_LOAD_CONFIG_TO : OK");
				return TRUE;
			}
			else {
				logme("AIRMAX_LOAD_CONFIG_TO : auth FAILED");
				return FALSE;
			}
		}
		else {
			logme("AIRMAX_LOAD_CONFIG_TO : ssh Connection FAILED");
			return FALSE;
		}
	}
	else {
		logme("AIRMAX_LOAD_CONFIG_TO : Not isset variable ... FAILED");
		return FALSE;
	}
}
//---------------------------------------------------------------------------------------------------
function interact($socket) { //Gestion des commandes des clients
	global $config;
	global $connbdd;
	connect_mysql();
	$count_timeout=0;
	socket_getpeername($socket, $ip);
	socket_write($socket, Crypte("welcome to Wprotect Daemon\n"));
	while ($count_timeout < 10) 
    { 
		$write = NULL;
		$except = NULL;
		$tv_sec = 1;
		$sock_tab[1]=$socket;
		$ready = socket_select($sock_tab, $write, $except, $tv_sec);
		$data = @socket_read($socket, 4096, PHP_NORMAL_READ);
		$data = trim($data);
					$data = Decrypte($data);

					if(!empty($data))
						{
						$command = explode (" ", $data);
						$count_timeout=0;		
							switch ($command[0]) {
							case "get_diag_infos":
								$a=get_queue_size_status();
								$a=json_encode($a);
								socket_write($socket, Crypte($a)."\n");
							break;
							case "backup_is_running":
								$tmp=array();
								$r=is_backup_running();
								if ($r) {
									$tmp["error_code"]=0;
									$tmp["backup_is_running"]=1;
									$tmp["error_msg"]="OK";
								}
								else {
									$tmp["error_code"]=0;
									$tmp["backup_is_running"]=0;
									$tmp["error_msg"]="OK";
								}
								socket_write($socket, Crypte(json_encode($tmp))."\n");
							break;
							case "wan_speedtest":
								socket_write($socket, Crypte(wan_speedtest())."\n");
							break;
							case "qos_reload":
								if (isset($command[1])) {
									$qos_manage_q=msg_get_queue(7001);
									$message=array();
									$message['order']="change";
									$message['network']=$command[1];
									msg_send($qos_manage_q,8,$message,true,false,$err);
									socket_write($socket, Crypte("0")."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "reload_ddos_apache_protection":
								socket_write($socket, Crypte("0")."\n");
								reload_ddos_apache_protection();
							break;
							case "bornes_all_refresh_infos":
								socket_write($socket, Crypte("0")."\n");
								bornes_all_refresh_infos();
							break;
							case "reload_darkstat":
								socket_write($socket, Crypte("0")."\n");
								reload_darkstat();
							break;
							case "generate_poststart":
								socket_write($socket, Crypte("0")."\n");
								generate_poststart();
							break;
							case "borne_get_infos":
								$tmp=array();
								$r=borne_id_get_and_store_infos($command[1]);
								if ($r) {
									$tmp["error_code"]=0;
									$tmp["error_msg"]="OK";
								}
								else {
									$tmp["error_code"]=1;
									$tmp["error_msg"]="erreur inconnu";
								}
								socket_write($socket, Crypte(json_encode($tmp))."\n");
							break;
							case "reload_services_redirect":
								socket_write($socket, Crypte("0")."\n");
								reload_services_redirect();
							break;
							case "clean_data_volume_for_not_existing_mac":
								socket_write($socket, Crypte("0")."\n");
								clean_data_volume_for_not_existing_mac();
							break;
							case "ftp_backup_start":
								socket_write($socket, Crypte("0")."\n");
								backup_to_ftp_start();
							break;
							case "test_ftp_backup_connection":
								$data=array();
								if (ftp_backup_connect()) {
									ftp_close($config['ftp_backup_connection']);
									$data['error_code']=0;
									$data['error_msg']="Connexion au serveur FTP OK !";
								}
								else {
									ftp_close($config['ftp_backup_connection']);
									$data['error_code']=1;
									$data['error_msg']="Impossible de se connecter";
								}
								socket_write($socket, Crypte(json_encode($data))."\n");
							break;
							case "disconnect_client":
								if (isset($command[1])) {
									disconnect_client($command[1]);
									socket_write($socket, Crypte("0")."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "get_pid_list_cpu":
								$r=json_encode(get_pid_list_cpu());
								socket_write($socket, Crypte($r)."\n");
							break;
							case "reboot_service_dns":
								logme("THREAD : Ask from 127.0.0.1 to restart DNS server");
								reload_dns();
								socket_write($socket, Crypte("0")."\n");
							break;
							case "reboot_service_bornes_watcher":
								$pid_to_kill = apc_fetch("thread_bornes_watcher");
								myexec("kill -KILL ".$pid_to_kill);
								logme("THREAD : Ask from 127.0.0.1 to KILL thread_bornes_watcher PID:".$pid_to_kill);
								socket_write($socket, Crypte("0")."\n");
							break;
							case "airmax_load_last_config":
								if (isset($command[1])) {
									socket_write($socket, Crypte("0")."\n");
									airmax_load_last_config($command[1]);
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "configure_security_b":
								if (isset($command[1])) {
									$r=airmax_load_security_config($command[1], "b");
									socket_write($socket, Crypte($r)."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "borne_speedtest":
								if (isset($command[1])) {
									$r=borne_speedtest($command[1]);
									socket_write($socket, Crypte($r)."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "remove_security":
								if (isset($command[1])) {
									$r=remove_security_config($command[1]);
									socket_write($socket, Crypte($r)."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "configure_security_p":
								if (isset($command[1])) {
									$r=airmax_load_security_config($command[1], "p");
									socket_write($socket, Crypte($r)."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							case "reboot_ap_ubiquiti":
								socket_write($socket, Crypte("1")."\n");
								reboot_ap_ubiquiti(-1);
							break;
							case "reboot_one_ap":
								socket_write($socket, Crypte("1")."\n");
								if (isset($command[1])) {
									reboot_ap_ubiquiti($command[1]);
								}
							break;
							case "send_login_by_mail":
								if (isset($command[1])) {
									$thread_mail = new Thread( 'thread_send_login_by_mail' );
									$thread_mail -> start($command[1]);
									socket_write($socket, Crypte("0")."\n");
								}
								else {
									socket_write($socket, Crypte("1")."\n");
								}
							break;
							
							case "ping":
								socket_write($socket, Crypte("pong")."\n");
							break;
							
							case "authorize_mac":
								if (isset($command[1]) AND isset($command[2])) {
									if (authorize_client($command[1], $command[2])) $result="OK"; else $result="NOK";
									socket_write($socket, Crypte("$result")."\n");
									logme ("FROM : " . $ip ." -> ".$data);
								}
								else {
									socket_write($socket, Crypte("NOK")."\n");
									logme ("FROM : " . $ip ." -> ERROR command incomplete : ".$data);
								}
							break;
							
							case "unauthorize_mac":
								if (isset($command[1]) AND isset($command[2])) {
									if (unauthorize_client($command[1], $command[2])) $result="OK"; else $result="NOK";
									socket_write($socket, Crypte("$result")."\n");
									logme ("FROM : " . $ip ." -> ".$data);
								}
								else {
									socket_write($socket, Crypte("NOK")."\n");
									logme ("FROM : " . $ip ." -> ERROR command incomplete : ".$data);
								}
							break;
							
							case "vip_authorize_mac":
								if (vip_authorize_client($command[1])) $result="OK"; else $result="NOK";
								socket_write($socket, Crypte("$result")."\n");
								logme ("FROM : " . $ip ." -> ".$data);
							break;
							
							case "vip_unauthorize_mac":
								if (vip_unauthorize_client($command[1])) $result="OK"; else $result="NOK";
								socket_write($socket, Crypte("$result")."\n");
								logme ("FROM : " . $ip ." -> ".$data);
							break;
							
							case "reload_vip":
								socket_write($socket, Crypte("1")."\n");
								logme ("FROM : " . $ip ." -> Reloading VIP");
								reload_vip();
							break;
							
							case "ping_host":								
								socket_write($socket, Crypte(ping_host($command[1]))."\n");
							break;
							
							case "ping_host_public":								
								socket_write($socket, Crypte(ping_host_public($command[1]))."\n");
							break;
							
							case "mac_from_ip":
								$temp = get_mac_from_ip($command[1], $command[2]);
								socket_write($socket, Crypte($temp)."\n");
							break;
										
							case "set_time_idle_disconnect":
								socket_write($socket, Crypte("ok")."\n");
								set_time_idle_disconnect();
							break;

							case "reload_passthrought_certificat":
								socket_write($socket, Crypte("ok")."\n");
								reload_passthrought_certificat();
							break;

							case "reload_firewall_client":
								socket_write($socket, Crypte("ok")."\n");
								reload_firewall_client();
							break;

							case "firewall_load_ap_passthrought":
								socket_write($socket, Crypte("ok")."\n");
								firewall_load_ap_passthrought();
							break;

							case "create_backup_wprotect":
								socket_write($socket, Crypte("ok")."\n");
								$thread_backup = new Thread( 'create_backup_wprotect' );
								$thread_backup -> start();
							break;
							
							case "restart":
								socket_write($socket, Crypte("ok")."\n");
								myexec ("/etc/init.d/wprotect restart");
								exit(0);
							break;
							
							case "del_backup":
								myexec ("rm /backup/".$command[1]);
								socket_write($socket, Crypte("ok")."\n");
								exit(0);
							break;
							
							case "del_archive":
								myexec ("rm /archive/".$command[1]);
								socket_write($socket, Crypte("ok")."\n");
								exit(0);
							break;
							
							case "borne_save_config":
								if (borne_save_config ($command[1])) socket_write($socket, Crypte("1")."\n");
								else socket_write($socket, Crypte("0")."\n");
								exit(0);
							break;
							
							case "borne_upgrade":
								socket_write($socket, Crypte("1")."\n");
								if (isset($command[1]) AND isset($command[2])) {
									borne_upgrade ($command[1], $command[2]);
								}
								exit(0);
							break;
							case "reload_forbidden_network":
								socket_write($socket, Crypte("1")."\n");
								reload_forbidden_network();
								exit(0);
							break;
							case "reset_wprotect":
								socket_write($socket, Crypte("1")."\n");
								myexec("/etc/init.d/wprotect restart");
								exit(0);
							break;
							case "clean_devices":
								socket_write($socket, Crypte("1")."\n");
								clean_devices();
								exit(0);
							break;
							case "disconnect_all_client":
								socket_write($socket, Crypte("1")."\n");
								disconnect_all_client(1);
								disconnect_all_client(2);
								disconnect_all_client(3);
								disconnect_all_client(4);
								exit(0);
							break;
							case "get_sys_infos":
								$infos = array();
								//---
								$result = exec_mysql("SELECT * FROM thread WHERE name='backup_ftp' AND status='running'");
								$val = mysqli_fetch_assoc($result);
								if (isset($val['pid'])) {
									$infos['ftp_backup_is_running']=1;
								}
								else {
									$infos['ftp_backup_is_running']=0;
								}
								//--
								$infos['sys_info_wan']=apc_fetch("sys_info_wan");
								$infos['sys_info_user_con']=apc_fetch("sys_info_user_con");
								$infos['sys_info_user_auth']=apc_fetch("sys_info_user_auth");
								$infos['sys_info_hdd_percent']=apc_fetch("sys_info_hdd_percent");
								$infos['sys_info_uptime']=apc_fetch("sys_info_uptime");
								$infos['sys_info_load']=apc_fetch("sys_info_load");
								$infos['sys_info_traff_in']=apc_fetch("sys_info_traff_in");
								$infos['sys_info_packet_in']=apc_fetch("sys_info_packet_in");
								$infos['sys_info_session_open']=apc_fetch("sys_info_session_open");
								$infos['sys_info_session_max']=apc_fetch("sys_info_session_max");
								$infos['sys_info_memory_max']=apc_fetch("sys_info_memory_max");
								$infos['sys_info_memory_use']=apc_fetch("sys_info_memory_use");
								$infos['sys_os_name']=$config['sys_os_name'];
								$infos['sys_os_version']=$config['sys_os_version'];
								$infos['sys_os_fullname']=$config['sys_os_fullname'];
								$infos['sys_os_codename']=$config['sys_os_codename'];
								socket_write($socket, Crypte(json_encode($infos))."\n");
								exit(0);
							break;
							default:
								socket_write($socket, Crypte("NOK")."\n");
								logme ("FROM ".$ip." : " . $data . " : Unkonw command Closing connection");
								exit();
							break;
							}
						}
						else {
							$count_timeout++;
						}
	}
exit(0);
}
//----------------------------------------------------------------------------------------------------
function firewall_load_ap_passthrought() {
		global $config;
		global $connbdd;
		get_config_ap_list();
		myexec("iptables -t filter -F ap_passthrought");
		myexec("iptables -t nat -F ap_passthrought");
		myexec ("iptables -t filter -A ap_passthrought -j RETURN");
		if ($config['wifi_access_point_ip']!="") {
			foreach ($config['wifi_access_point_ip'] AS $key=>$value) {
				if ($value!="") {
					logme("Reload AP $value");
					myexec ("iptables -t filter -m physdev --physdev-is-bridged --physdev-in ".$config['public_interface'][$config['wifi_access_point_network'][$key]]." --physdev-out ".$config['private_interface'][$config['wifi_access_point_network'][$key]]." -I ap_passthrought -s ".$value." -j ACCEPT");
					myexec ("iptables -t filter -m physdev --physdev-is-bridged --physdev-in ".$config['private_interface'][$config['wifi_access_point_network'][$key]]." --physdev-out ".$config['public_interface'][$config['wifi_access_point_network'][$key]]." -I ap_passthrought -d ".$value." -j ACCEPT");
					myexec ("iptables -t nat -I ap_passthrought -m mac --mac-source ".$config['wifi_access_point_mac'][$key]." -j ACCEPT");
				}	
			}
		}
}
//----------------------------------------------------------------------------------------------------
function reload_services_redirect() {
	global $config;
	global $connbdd;
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
			if ($k!=0) {
				myexec("iptables -t filter -F services_redirect_".($a+1)." > /dev/null 2>&1");
				myexec("iptables -t filter -N services_redirect_".($a+1)." > /dev/null 2>&1");
				//------------enable or disable firewall_client on network----------------
				$result = exec_mysql("SELECT * FROM network WHERE id='".($a+1)."'");
				$val = mysqli_fetch_array($result);
				if ($val["firewall"] == 1) {
					myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -j firewall_client");
				}
				else {
					myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -j pk_log_accept");
				}
				//--------------------------------------------------------------------------
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -j forbidden_network");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -j clients".($a+1));
				
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p udp --dport 67:68 -j ACCEPT -m comment --comment \"passtrought DHCP request\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p udp --sport 67:68 -j ACCEPT -m comment --comment \"passtrought DHCP request\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp -d ".$config['iface']["br".$a]['ip']." --dport 81 -j ACCEPT -m comment --comment \"passtrought web captive portal\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp -d ".$config['iface']["br".$a]['ip']." --dport 82 -j ACCEPT -m comment --comment \"passtrought web captive portal\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp -d ".$config['iface']["br".$a]['ip']." --dport 444 -j ACCEPT -m comment --comment \"passtrought web captive portal\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp -d ".$config['iface']["br".$a]['ip']." --dport 442 -j ACCEPT -m comment --comment \"passtrought web captive portal\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p udp --dport 5353 -j ACCEPT -m comment --comment \"passtrought DNS request\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p udp --sport 5353 -j ACCEPT -m comment --comment \"passtrought DNS request\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp --dport 5353 -j ACCEPT -m comment --comment \"passtrought DNS request\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p tcp --sport 5353 -j ACCEPT -m comment --comment \"passtrought DNS request\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p udp --dport 123 -j ACCEPT -m comment --comment \"passtrought NTP\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p udp --sport 123 -j ACCEPT -m comment --comment \"passtrought NTP\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp --dport 5001 -j ACCEPT -m comment --comment \"passtrought IPERF\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p tcp --dport 5001 -j ACCEPT -m comment --comment \"passtrought IPERF\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p tcp --dport 18301 -j ACCEPT -m comment --comment \"passtrought ZAP\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p tcp --dport 18301 -j ACCEPT -m comment --comment \"passtrought ZAP\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p udp --dport 5001 -j ACCEPT -m comment --comment \"passtrought IPERF\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p udp --dport 5001 -j ACCEPT -m comment --comment \"passtrought IPERF\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -p udp --dport 18301 -j ACCEPT -m comment --comment \"passtrought ZAP\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -p udp --dport 18301 -j ACCEPT -m comment --comment \"passtrought ZAP\"");
				myexec ("iptables -t filter -I services_redirect_".($a+1)." -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT");
				iptables_add_if_not_exist("iptables -t filter -A FORWARD -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -j services_redirect_".($a+1));
				iptables_add_if_not_exist("iptables -t filter -A FORWARD -m physdev --physdev-is-bridged --physdev-in ".$config['iface']["br".$a]['bridge_ports'][0]." --physdev-out ".$v." -j services_redirect_".($a+1));
			}
		}
	}
}
//----------------------------------------------------------------------------------------------------
function iptables_add_if_not_exist($command) {
	global $config;
	global $connbdd;
	$testcommand=$command;
	$testcommand=str_replace(" -I ", " -C ", $testcommand);
	$testcommand=str_replace(" -A ", " -C ", $testcommand);
	exec ($testcommand, $result, $return);
	if ($return > 0) {
		myexec($command);
	}
}
//----------------------------------------------------------------------------------------------------
function reload_ddos_apache_protection() {
		global $config;
		global $connbdd;
		myexec ("iptables -t filter -F ATTK_CHECK");
		if (get_option_from_mysql("apache_ddos_protection")) {
			myexec ("iptables -t filter -A ATTK_CHECK -m recent --set --name SSH --rsource");
			myexec ("iptables -t filter -A ATTK_CHECK -m recent --update --seconds 1 --hitcount 50 --name SSH --rsource -j REJECT");
		}
		myexec ("iptables -t filter -A ATTK_CHECK -j ACCEPT");
	}		
//----------------------------------------------------------------------------------------------------
function load_firewall() {
	global $config;
	global $connbdd;
	$debug_start=time();
	set_time_idle_disconnect();
	logme ("Loading Firewall...");
	myexec ("echo 1 > /proc/sys/net/ipv4/ip_forward");
	myexec ("iptables -t filter -P INPUT DROP");
	myexec ("iptables -t filter -P FORWARD DROP");
	myexec ("iptables -t filter -P OUTPUT ACCEPT");
	myexec ("iptables -F");
	myexec ("ebtables -F");
	myexec ("iptables -t nat -F");
	myexec ("iptables -X");
	myexec ("ebtables -X");
	myexec ("ebtables -I FORWARD -p IPv6 -j DROP"); // bloc ipv6 forward traffic
	myexec ("ebtables -t broute -F");
	myexec ("ebtables -t broute -A BROUTING -p 802_1Q -j DROP"); // bloc VLAN tagged trafic on Bridge forward
	myexec ("iptables -t nat -X");
	myexec ("iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -i lo -j ACCEPT");
	myexec ("iptables -t filter -A OUTPUT -o lo -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p icmp -j ACCEPT");
	myexec ("iptables -t filter -A OUTPUT -p icmp -j ACCEPT");
	
	//if ($config['private_interface'] == $config['admin_interface']){
	//	$tmp = "-m physdev --physdev-in";
	//}
	//else {
		$tmp = "-i";
	//}
	
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 22 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 443 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 10000 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 80 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p udp --dport 123 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p udp --dport 1812 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p udp --dport 1813 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 661 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 662 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 663 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT ".$tmp." ".$config['admin_interface']." -p tcp --dport 664 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p tcp --dport 5001 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p tcp --dport 18301 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p udp --dport 18301 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p udp --dport 5001 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p udp --dport 514 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p tcp --dport 514 -j ACCEPT");
	
	
	myexec ("iptables -t filter -N ATTK_CHECK");
	myexec ("iptables -t filter -F ATTK_CHECK");
	
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
			if ($k!=0) {
				myexec ("iptables -t filter -A INPUT -m physdev --physdev-in ".$v." -p tcp -m multiport --dports 81,444 -m state --state NEW -j ATTK_CHECK");
				myexec ("iptables -t filter -A INPUT -m physdev --physdev-in ".$v." -p tcp --dport 81 -j ACCEPT");
				myexec ("iptables -t filter -A INPUT -m physdev --physdev-in ".$v." -p tcp --dport 82 -j ACCEPT");
				myexec ("iptables -t filter -A INPUT -m physdev --physdev-in ".$v." -p tcp --dport 444 -j ACCEPT");
				myexec ("iptables -t filter -A INPUT -m physdev --physdev-in ".$v." -p tcp --dport 442 -j ACCEPT");
			}
		}
	}
	
	reload_ddos_apache_protection();
	
	myexec ("iptables -t filter -A INPUT -p tcp --dport 5353 -j ACCEPT");
	myexec ("iptables -t filter -A INPUT -p udp --dport 5353 -j ACCEPT");

	myexec ("iptables -t filter -N pk_log_accept");
	myexec ("iptables -t filter -A pk_log_accept -j ACCEPT");
	myexec ("iptables -t filter -N pk_log_drop");
	myexec ("iptables -t filter -A pk_log_drop -j DROP");
	
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
			if ($k!=0) {
				myexec ("iptables -t filter -I pk_log_accept -p tcp -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -m state --state NEW -j LOG --log-level 4 --log-prefix='[iptrack".($a+1)."] '");
				myexec ("iptables -t filter -I pk_log_accept -p udp -m physdev --physdev-is-bridged --physdev-in ".$v." --physdev-out ".$config['iface']["br".$a]['bridge_ports'][0]." -m state --state NEW -m limit --limit 2/s -j LOG --log-level 4 --log-prefix='[iptrack".($a+1)."] '");
			}
		}	
	}
	
	//---------------------------------------------------------------
	//myexec ("iptables -t filter -N clients");
	//myexec ("iptables -t filter -A clients -j DROP");
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		myexec ("iptables -t filter -N clients".($a+1));
		myexec ("iptables -t filter -A clients".($a+1)." -j DROP");
	}
	myexec ("iptables -t filter -N clientsvip");
	myexec ("iptables -t filter -A clientsvip -j RETURN");
	myexec ("iptables -t filter -N firewall_client");
	myexec ("iptables -t filter -A firewall_client -j pk_log_drop");
	myexec ("iptables -t filter -N forbidden_network");
	myexec ("iptables -t filter -A forbidden_network -j RETURN");
	myexec ("iptables -t nat -N forbidden_network");
	myexec ("iptables -t nat -A forbidden_network -j RETURN");
	//---------activate forbidden_network ---------------
	reload_forbidden_network();
	//-------------FIREWALL CLIENT---------------
	reload_firewall_client();
	//-------------FORWARD SERVICE REDIRECT------
	reload_services_redirect();
	//-------------------------------------------
	
	myexec ("iptables -t filter -I FORWARD -j clientsvip");
	//-------créer une chain pour les certificats passthrought---------
	myexec ("iptables -t filter -N passthrought_certificat");
	myexec ("iptables -t filter -I FORWARD -j passthrought_certificat");
	reload_passthrought_certificat();
	//-------------------------------------------------------
	
	//-------créer une chain pour les ap passtrhgouht---------
	myexec ("iptables -t filter -N ap_passthrought");
	myexec ("iptables -t filter -A ap_passthrought -j RETURN");
	myexec ("iptables -t filter -I FORWARD -j ap_passthrought");
	myexec ("iptables -t filter -I FORWARD -p icmp -d 10.0.0.1 -j ACCEPT");
	//--------------------------------------------------------
	
	myexec ("iptables -t nat -N ap_passthrought");
	myexec ("iptables -t nat -N clients_vip");
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		myexec ("iptables -t nat -N clients".($a+1));
	}
	
	firewall_load_ap_passthrought();
	
	$result = exec_mysql("SELECT * FROM firewall_certificat"); // on laisse passez les ip pour verfiieé des certificats de confiance
	while ($val = mysqli_fetch_array($result)) {
		for ($a = 0; $a < $config['iface']['network_number']; $a++) {
			foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
				if ($k!=0) {
					myexec ("iptables -t nat -A clients".($a+1)." -m physdev --physdev-in ".$v." -d ".$val['ip']." -p tcp --dport 80 -j ACCEPT");
				}
			}
		}
	}
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
			if ($k!=0) {
				if (get_option_from_mysql("nginx_proxy_cache")) {
					myexec ("iptables -t nat -A clients".($a+1)." -m physdev --physdev-in ".$v." -p tcp --dport 80 -j REDIRECT --to-port 82");
					//myexec ("iptables -t nat -A clients".($a+1)." -m physdev --physdev-in ".$v." -p tcp --dport 443 -j REDIRECT --to-port 442");
				}
				else {
					myexec ("iptables -t nat -A clients".($a+1)." -m physdev --physdev-in ".$v." -p tcp --dport 80 -j REDIRECT --to-port 81");
					//myexec ("iptables -t nat -A clients".($a+1)." -m physdev --physdev-in ".$v." -p tcp --dport 443 -j REDIRECT --to-port 444");
				}
			}
		}
	}
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
			if ($k!=0) {
				myexec ("iptables -t nat -A POSTROUTING -o ".$v." -j MASQUERADE");
				myexec ("iptables -t nat -I PREROUTING -j clients".($a+1));
			}
		}
	}
	myexec ("iptables -t nat -I PREROUTING -j ap_passthrought"); // bornes
	myexec ("iptables -t nat -I PREROUTING -j clients_vip"); // VIP
	myexec ("iptables -t nat -I PREROUTING -j forbidden_network");
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		foreach ($config['iface']["br".$a]['bridge_ports'] AS $k => $v) {
			if ($k!=0) {
				if (get_option_from_mysql("nginx_proxy_cache")) {
					myexec ("iptables -t nat -I PREROUTING -m physdev --physdev-in ".$v." -d ".$config['iface']["br".$a]['ip']." -p tcp --dport 80 -j DNAT --to-destination ".$config['iface']["br".$a]['ip'].":82");
					myexec ("iptables -t nat -I PREROUTING -m physdev --physdev-in ".$v." -d ".$config['iface']["br".$a]['ip']." -p tcp --dport 443 -j DNAT --to-destination ".$config['iface']["br".$a]['ip'].":442");
				}
				else {
					myexec ("iptables -t nat -I PREROUTING -m physdev --physdev-in ".$v." -d ".$config['iface']["br".$a]['ip']." -p tcp --dport 80 -j DNAT --to-destination ".$config['iface']["br".$a]['ip'].":81");
					myexec ("iptables -t nat -I PREROUTING -m physdev --physdev-in ".$v." -d ".$config['iface']["br".$a]['ip']." -p tcp --dport 443 -j DNAT --to-destination ".$config['iface']["br".$a]['ip'].":444");
				}
				myexec ("iptables -t nat -I PREROUTING -m physdev --physdev-in ".$v." -p tcp --dport 53 -j DNAT --to-destination ".$config['iface']["br".$a]['ip'].":5353");
				myexec ("iptables -t nat -I PREROUTING -m physdev --physdev-in ".$v." -p udp --dport 53 -j DNAT --to-destination ".$config['iface']["br".$a]['ip'].":5353");
			}
		}
	}
	//-----------QOS QUEUES------------
	logme ("QOS : start to load queues");
	for ($a = 0; $a < $config['iface']['network_number']; $a++) {
		qos_create_queue($a+1);
	}
	logme ("QOS : Queues loaded");
	logme ("FIREWALL : START : start to load authorize clients");
	//-----------------------------------
	foreach ($config['bridge_interface'] AS $k => $v) {
		$result = exec_mysql("SELECT * FROM lan_discover WHERE authorize='1' AND network='".$k."'");
		while ($val = mysqli_fetch_array($result)) {
			authorize_client($val['mac'], $k);
			logme("Authorize : ".$k." : ".$val['mac']);
		}
	}
	logme ("FIREWALL : START : start to load VIP");
	$result = exec_mysql("SELECT * FROM lan_discover WHERE vip='1'");
	while ($val = mysqli_fetch_array($result)) {
		vip_authorize_client($val['mac']);
	}
	//-------------
	$debug_stop=time();
	logme ("Firewall Loaded ! in ".intval($debug_stop-$debug_start)." seconds");
}
//-----------------------------------------------------------------------------------
function exec_mysql($query) {
	global $config;
	global $connbdd;
	if (!is_resource($connbdd)) {
		connect_mysql();
	}
	if (!($result = @mysqli_query($connbdd, $query))) {
		logme("EXEC_MYSQL ERROR (".$query.") : " . @mysqli_error($connbdd));
		if (verif_mysql()) {
			if (!($result = @mysqli_query($connbdd, $query))) {
				logme("EXEC_MYSQL TWICE ERROR (".$query.") : " . @mysqli_error($connbdd));
			}
			else {
				return $result;
			}
		}
		else {
			logme("MYSQL VERIF ERROR : connexion impossible");
			return FALSE;
		}
	}
	else {
		return $result;
	}
}
//-------------------------------------------------------------------
function thread_check_wan_status() {
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	global $config;
	$status=array();
	while(true) {
		sleep(1);
		foreach ($config['net_connection'] AS $k=>$v) {
			if (!isset($status[$k])) {
				$status[$k]=array();
				$status[$k]['pol1']=999;
				$status[$k]['pol2']=999;
				$status[$k]['pol3']=999;
				$status[$k]['name']=$v['name'];
			}
			$status[$k]['pol3']=$status[$k]['pol2'];
			$status[$k]['pol2']=$status[$k]['pol1'];
			$status[$k]['pol1']=intval(ping_host($v['ip']));
			$status[$k]['result']=intval(($status[$k]['pol1']+$status[$k]['pol2']+$status[$k]['pol3'])/3);
		}
		apc_store("sys_info_wan",$status);
	}
}
//-------------------------------------------------------------------
function thread_get_sys_infos() {
	global $config;
	global $connbdd;
	connect_mysql();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	while (TRUE) {
		sleep(2);
		//----
		$result = exec_mysql("select COUNT(*) from lan_discover where active='1'");
		$tmp = mysqli_fetch_array($result);
		apc_store("sys_info_user_con",$tmp[0]);
		//----
		$result = exec_mysql("select COUNT(*) from lan_discover where active='1' AND authorize='1' AND vip='0'");
		$tmp = mysqli_fetch_array($result);
		apc_store("sys_info_user_auth",$tmp[0]);
		//----
		$result = myexec("df /");
		preg_match("/^.+\s+.+\s.+\s+(?P<util>\d+)\s+(?P<percent>\d{1,3})\%.+$/", $result[1], $match);
		if (isset($match['util']) AND isset($match['percent'])) {
			apc_store("sys_info_hdd_percent",$match['percent']);
		}
		//----
		$result = myexec("uptime");
		preg_match("/^\s\d{1,2}\:\d{1,2}\:\d{1,2}\sup\s(?P<uptime>.+)\,\s+.+\,\s+load\saverage\:\s(?P<load1>\d{1,3}[,.]\d{1,2})\,\s(?P<load2>\d{1,3}[,.]\d{1,2})\,\s(?P<load3>\d{1,3}[,.]\d{1,2}).+$/", $result[0], $match);
		if (isset($match['uptime'])) {
			$load=$match['load1'];
			$load = str_replace(",",".",$load);
			$load=floatval($load);
			$load = round($load*100/2);
			if ($load > 99) $load = 100;
			apc_store("sys_info_load",$load);
			apc_store("sys_info_uptime",$match['uptime']);
		}
		//----traffic DL from internet-----
		$r = myexec ("iptables -L -n -v -x | grep RELATED");
		foreach ($config['bridge_interface'] AS $k => $v) {
			if (isset($r[$k])) {
				$tmp = explode (" ", $chaine = ltrim (preg_replace ("/\s\s+/", " ", $r[$k])));
				$p[$k] = $tmp[1];
			}
		}
		$h=0;
		foreach ($p AS $b=>$c) {
			$h = intval($h+$c);
		}
		$v=microtime(TRUE);
		$u=intval(apc_fetch("sys_info_traff_in_current"));
		$d=apc_fetch("sys_info_traff_in_current_time");
		$y=intval((($h-$u)/($v-$d)));
		apc_store("sys_info_traff_in_current", $h);
		apc_store("sys_info_traff_in_current_time", $v );
		apc_store("sys_info_traff_in", round(($y*8)/1000/1000, 1));
		//----
		//----packets DL from internet-----
		$r = myexec ("iptables -L -n -v -x | grep RELATED");
		foreach ($config['bridge_interface'] AS $k => $v) {
			if (isset($r[$k])) {
				$tmp = explode (" ", $chaine = ltrim (preg_replace ("/\s\s+/", " ", $r[$k])));
				$p[$k] = $tmp[0];
			}
		}
		$h=0;
		foreach ($p AS $b=>$c) {
			$h = intval($h+$c);
		}
		$v=microtime(TRUE);
		$u=intval(apc_fetch("sys_info_packet_in_current"));
		$d=apc_fetch("sys_info_packet_in_current_time");
		$y=intval((($h-$u)/($v-$d)));
		apc_store("sys_info_packet_in_current", $h);
		apc_store("sys_info_packet_in_current_time", $v );
		apc_store("sys_info_packet_in", $y);
		//-----sessions
		$r = myexec ("conntrack -C");
		$tmp = explode (" ", $r[0]);
		apc_store("sys_info_session_open", $tmp[0]);
		if (PHP_VERSION_ID < 60000) {
			$r = myexec ("sysctl -n net.ipv4.netfilter.ip_conntrack_max");
		}
		else {
			$r = myexec ("sysctl -n net.netfilter.nf_conntrack_max");
		}
		apc_store("sys_info_session_max", $r[0]);
		//------memory info----------
		$r = myexec ("free | grep Mem");
		$tmp = explode (" ", $chaine = ltrim (preg_replace ("/\s\s+/", " ", $r[0])));
		apc_store("sys_info_memory_max", round($tmp[1]/1000000, 1));
		apc_store("sys_info_memory_use", round($tmp[2]/1000000, 1));
		//-------------
	}
}

//-------------------------------------------------------------------
function check_login_expire() {
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	global $config;
	global $connbdd;
	connect_mysql();
	while (TRUE) {
		sleep (60);
		$network_to_disconnect = array();
		$result = exec_mysql("SELECT id, cp_type FROM network");
		while ($val = mysqli_fetch_array($result)) {
			if (($val['id'] != 0) AND ($val['cp_type'] == 0)) {
				$network_to_disconnect[$val['id']] = true;
			}
		}
		foreach ($network_to_disconnect AS $k=>$v) {
			$query = "SELECT *  FROM login WHERE (UNIX_TIMESTAMP(expire_date)) < (UNIX_TIMESTAMP(NOW())) AND expire_date != '0000-00-00 00:00:00' AND disable='0' AND network='".$k."'";
			$result = exec_mysql($query);
			while ($val = mysqli_fetch_array($result)) {
				if (isset($val['id_login'])) {
					logme ("CHECK LOGIN EXPIRE : disable login : ".$val['login']);
					$query = "SELECT mac, network FROM lan_discover WHERE login_id='".$val['id_login']."' AND network='".$k."'";
					$result2 = exec_mysql($query);
					while ($val2 = mysqli_fetch_array($result2)) {
						unauthorize_client($val2['mac'], $val2['network']);
					}
					exec_mysql("UPDATE login SET disable='1' WHERE id_login='".$val['id_login']."'");
				}
			}
		}
	}
}
//------------------------------------------------------------------
function get_option_from_mysql($name) {
	global $config;
	global $connbdd;
	$query = "SELECT value FROM options WHERE name='".$name."'";
	$result = exec_mysql($query);
	$val = mysqli_fetch_array($result);
	return $val['value'];
}
//--------------------------------------------------------------------
function auto_disconnect_client() {
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	global $config;
	global $connbdd;
	connect_mysql();
	$time_loop = 301;
	while (TRUE) {
		$network_to_disconnect = array();
		$result = exec_mysql("SELECT id, client_auto_disconnect_time FROM network");
		while ($val = mysqli_fetch_array($result)) {
			if (($val['id'] != 0) AND ($val['client_auto_disconnect_time']!="0") AND ($val['client_auto_disconnect_time']!="")) {
				$network_to_disconnect[$val['id']] = $val['client_auto_disconnect_time'];
			}
		}
		foreach ($network_to_disconnect AS $k=>$v) {
			$hier = date("Y-m-d", time()-86400);
			$next_min_save_date = strtotime(date("Y-m-d")." ".$v.":00"); //determine l'heure du prochain event
			$next_max_save_date = $next_min_save_date + $time_loop;
			if ((time() > $next_min_save_date) AND (time() < $next_max_save_date)) { // si c'est l'heure
				logme ("AUTO_DISCONNECT : disconnect all client on network ".$k);
				disconnect_all_client($k); //deconnecter les clients du réseau concerné
			}
		}
	sleep ($time_loop);
	}
}
//--------------------------------------------------------------------
function disconnect_all_client($network) {
	global $config;
	global $connbdd;
	$query="SELECT login.no_auto_disconnect, mac, login_id FROM lan_discover LEFT JOIN login ON lan_discover.login_id=login.id_login WHERE authorize='1' AND lan_discover.network='".$network."' AND (login.no_auto_disconnect!='1' OR login.no_auto_disconnect IS NULL)";
	$result = exec_mysql($query);
	while ($val = mysqli_fetch_array($result)) {
		logme("DISCONNECT_ALL : unauthorize_client ".$val['mac']." ON network ".$network);
		unauthorize_client($val['mac'], $network);
	}
}
//--------------------------------------------------------------------------
function disconnect_client($id) {
	global $config;
	global $connbdd;
	logme("Disconnect : ".$id."");
	$query = "SELECT mac, login.network AS network FROM login LEFT JOIN lan_discover ON lan_discover.login_id=login.id_login WHERE id_login='".$id."'";
	$result = exec_mysql($query);
	while ($val = mysqli_fetch_array($result)) {
		unauthorize_client($val['mac'], $val['network']);
	}
}
//--------------------------------------------------------------------------
function reload_vip() {
	global $config;
	global $connbdd;
	$query = "SELECT mac FROM lan_discover WHERE vip='1'";
	$result = exec_mysql($query);
	myexec ("iptables -t nat -F clients_vip");
	while ($val = mysqli_fetch_array($result)) {
		logme("VIP : add ".$val['mac']." to VIP firewall");
		vip_authorize_client($val['mac']);
	}
}
//--------------------------------------------------------------------------
function device_delete($mac, $network=1) {
	global $config;
	global $connbdd;
	unauthorize_client($mac, $network);
	exec_mysql("DELETE FROM lan_discover WHERE mac='".$mac."' AND network='".$network."' AND vip='0'");
	exec_mysql("DELETE FROM data_volume WHERE mac='".$mac."' AND network='".$network."'");
	exec_mysql("DELETE FROM session_login WHERE mac='".$mac."' AND network='".$network."'");	
}
//--------------------------------------------------------------------------
function login_delete($id) {
	global $config;
	global $connbdd;
	connect_mysql();
	$query = "SELECT * FROM lan_discover WHERE login_id='".$id."' AND no_delete='0'";
	$result = exec_mysql($query);
	while ($val = mysqli_fetch_array($result)) {
		device_delete($val['mac'], $val['network']);
	}
	exec_mysql("DELETE FROM login WHERE id_login='".$id."'");	
}
//--------------------------------------------------------------------------
function clean_data_volume_for_not_existing_mac() {
	global $config;
	global $connbdd;
	connect_mysql();
	logme("CLEANUP data_volume for not existing mac is started...");
 	exec_mysql("DELETE data_volume FROM data_volume LEFT JOIN lan_discover ON lan_discover.mac=data_volume.mac WHERE lan_discover.mac IS NULL");
	//exec_mysql("OPTIMIZE TABLE data_volume");
	logme("CLEANUP data_volume for not existing mac END !");
}
//--------------------------------------------------------------------------
function thread_auto_clean_data_volume_for_not_existing_mac() {
	global $config;
	global $connbdd;
	proc_nice(19);
	$mypid = getmypid();
	while (TRUE) {
		sleep(240);
		$time_to_clean = "02:15";
		$tt_to_clean = strtotime(date("Y-m-d")." ".$time_to_clean);
		if (($tt_to_clean < time()) AND (time() < $tt_to_clean+242)) { //si c l'heure on execute
			clean_data_volume_for_not_existing_mac();
			sleep(240);
		}
	}
}
//-------------------------------------------------------------------------
function clean_devices($since=31449600) { //par default delete since 1 year
	global $config;
	global $connbdd;
	connect_mysql();
	$since = time() - $since;
	logme("CLEAN DEVICES : start ...");
	$query=("SELECT network, mac FROM lan_discover WHERE active='0' AND vip='0' AND authorize='0' AND UNIX_TIMESTAMP(date) < ".$since);
	$result = exec_mysql($query);
	while ($val = mysqli_fetch_array($result)) {
		usleep(250);
		logme("CLEAN DEVICES : delete ".$val['mac']." network ".$val['network']);
		device_delete($val['mac'], $val['network']);
	}
	//exec_mysql("OPTIMIZE TABLE lan_discover");
	$since=31449600;
	$since = time() - $since;
	exec_mysql("DELETE FROM data_volume WHERE UNIX_TIMESTAMP(date) < ".$since);
	exec_mysql("DELETE FROM session_login WHERE UNIX_TIMESTAMP(end_date) < ".$since);
	exec_mysql("DELETE FROM log WHERE UNIX_TIMESTAMP(date) < ".$since);
	logme("CLEAN DEVICES : end !");
}
//--------------------------------------------------------------------------
function clean_discover_useless() {
	global $config;
	global $connbdd;
	connect_mysql();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	while (TRUE) {
		$query = "SELECT value FROM options WHERE name='clean_discover_useless'";
		$result = exec_mysql($query);
		if ($val = mysqli_fetch_array($result)) {
			$clean_discover_useless_wait_time = $val['value'];
			sleep($clean_discover_useless_wait_time/4);
			$query = "DELETE FROM lan_discover WHERE (UNIX_TIMESTAMP(date)+".$clean_discover_useless_wait_time.") < (UNIX_TIMESTAMP(NOW())) AND vip='0' AND active='0' AND authorize='0' AND date_autorize IS NULL";
			$result = exec_mysql($query);
		}
		else { //si erreur mysql
			logme ('ERROR : clean_discover_useless option -> no read value ...');
			sleep(5);
		}
	}
}
//--------------------------------------------------------------------------
function thread_auto_clean_devices() {
	global $config;
	global $connbdd;
	connect_mysql();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	
	while (TRUE) {
		sleep(605);
		clean_devices();
	}
}
//-------------------------------------------------------------------------
function get_and_write_data_volume() {
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	global $config;
	global $connbdd;
	connect_mysql();
	
	$next=strtotime(date("Y-m-d")." ".(date("H")+1).":00");
	while (TRUE) {
		sleep(15);
		if (((time()+1) > $next) AND (get_option("disable_darkstats")==1)) {
			$start_time=time();
			logme("DARKSTAT : load data to mysql starting ...");
			foreach ($config['bridge_interface'] AS $if => $vl) {
				$table = array();
				$current="";
				$level=1;
				if ($dispo = file_get_contents("http://127.0.0.1:66".$if."/hosts/?full=yes&sort=total")) {
					$r = explode ("\n", $dispo);
					foreach ($r AS $k => $v) {
						preg_match("/^\s*\<td\>\<tt\>(?P<mac>([0-9a-f]{2}:){5}[0-9a-f]{2})\<\/tt\>\<\/td\>\s*$/", $v, $m);
						if ((isset($m['mac']))) {
							$current=strtoupper($m['mac']);
							$level=1;
						}
						preg_match("/^\s*\<td class\=\"num\"\>(?P<num>([0-9\,]*))\<\/td\>\s*$/", $v, $m);
						if ((isset($m['num']))) {
							if (isset($table[$current][$level])) {
								$table[$current][$level]=$table[$current][$level] + str_replace(",", "", $m['num']);
								$level++;
							}
							else {
								$table[$current][$level]=0 + str_replace(",", "", $m['num']); // +0 force int number
								$level++;
							}
						}
					}
				}
				
				$tmp=array();
				$result = exec_mysql("SELECT mac, login_id FROM lan_discover WHERE network='".$if."'");
				while ($val = mysqli_fetch_array($result)) {
					$tmp[$val['mac']] = $val['login_id'];
				}
				foreach($table AS $k=>$v) {
					if (isset($tmp[$k])) {
							exec_mysql("INSERT INTO data_volume SET network='".$if."', id_login='".$tmp[$k]."', mac='".$k."', dl='".$table[$k][1]."', ul='".$table[$k][2]."', date='".date ("Y-m-d H:i", $next)."'");
					}
				}
			}
			reload_darkstat(TRUE);
			$next=strtotime(date("Y-m-d")." ".(date("H")+1).":00");
			$duree = time() - $start_time;
			logme("DARKSTAT : data to mysql is loading in ".$duree." seconds END !");
		}
	}
}
//-------------------------------------------------------------------
function is_ubiquiti_mac($mac) {
	$ubiquiti_mac = array();
	$ubiquiti_mac[] = "F0:9F:C2";
	$ubiquiti_mac[] = "DC:9F:DB";
	$ubiquiti_mac[] = "80:2A:A8";
	$ubiquiti_mac[] = "68:72:51";
	$ubiquiti_mac[] = "44:D9:E7";
	$ubiquiti_mac[] = "24:A4:3C";
	$ubiquiti_mac[] = "04:18:D6";
	$ubiquiti_mac[] = "00:27:22";
	$ubiquiti_mac[] = "00:15:6D";
	$ubiquiti_mac[] = "80:2A:A8";
	$ubiquiti_mac[] = "F0:9F:C2";
	$mac_supplier = substr($mac, 0, 8);
	if (in_array($mac_supplier, $ubiquiti_mac)) return TRUE;
	else return FALSE;
}
//--------------------------------------------------------------------------
function is_airmax_mac($mac) {
	$airmax_mac = array();
	$airmax_mac[] = "68:72:51";
	$airmax_mac[] = "24:A4:3C";
	$airmax_mac[] = "04:18:D6";
	$airmax_mac[] = "00:27:22";
	$airmax_mac[] = "00:15:6D";
	$airmax_mac[] = "44:D9:E7";
	$airmax_mac[] = "80:2A:A8";
	$airmax_mac[] = "DC:9F:DB";
	$airmax_mac[] = "F0:9F:C2";
	$mac_supplier = substr($mac, 0, 8);
	if (in_array($mac_supplier, $airmax_mac)) return TRUE;
	else return FALSE;
}
//--------------------------------------------------------------------------
function is_vivotek_mac($mac) {
	$ubiquiti_mac = array();
	$ubiquiti_mac[] = "00:02:D1";
	$mac_supplier = substr($mac, 0, 8);
	if (in_array($mac_supplier, $ubiquiti_mac)) return TRUE;
	else return FALSE;
}
//------------------------------------------------------------------------
function send_broadcast_on_network_maintenance ($netid=1) {  //envoi un broadcast et return un tableau des ip qui ont répondu, false si personne ne répond
	global $config;
	$ip = array();
	$result = myexec("ping -I ".$config['bridge_interface'][$netid].":0 -i 2 -w 2 -c 2 -b 169.254.255.255 2> /dev/null");
	foreach ($result AS $key => $value) {
		preg_match("/^64 bytes from\s(?P<ip>([0-9]{1,3}.){3}.([0-9]{1,3}))\:.*$/", $value, $match);
		if ((isset($match['ip']))) {
			$ip[]=$match['ip'];
		}
	}
	if (isset($ip[0])) return $ip;
	else return false;
}
//------------------------------------------------------------------------
function ping_array_ip($ip) {
	global $config;
	foreach ($ip AS $k=>$v) {
		myexec("ping -I ".$config['bridge_interface'][1].":0 -i 1 -w 2 -c 1 ".$v);
	}
}
//--------------------------------------------------------------------------
function get_bornes_on_maintenance_network() {
	global $config;
	$tmp=array();
	if ($ip = send_broadcast_on_network_maintenance()) {
		ping_array_ip($ip);
		$r = myexec("arp -a -n | grep \"169.254\"");
		foreach ($r AS $k => $v) {
			preg_match("/^\?\s\((?P<ip>([0-9]{1,3}.){3}.([0-9]{1,3}))\)\sat\s(?P<mac>([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))\s.*$/", $v, $match);
			if ((isset($match['ip'])) AND (isset($match['mac']))) {
				$match['mac']=strtoupper($match['mac']);
				if (is_ubiquiti_mac($match['mac'])) {
					$tmp[$match['mac']]=$match['ip'];
				}
			}
		}
	}
	if (!empty($tmp)) return $tmp;
	else return false;
}
//-----------------------------------------------------------------------------
function thread_watch_bornes_on_m_network() {
	global $config;
	global $connbdd;
	connect_mysql();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN);
	proc_nice(19);
	while (TRUE) {
		sleep(5);
		$result = exec_mysql("SELECT * FROM bornes");
		$bornes = array();
		while (($val = mysqli_fetch_array($result))) {
			$bornes[$val['mac']] = $val['ip'];
		}
		if ($r=get_bornes_on_maintenance_network()) {
			foreach ($r AS $k=>$v) { // si des bornes sont en mode maintenance
				if (array_key_exists($k, $bornes)) { //la borne existe en BDD update IP and status
					exec_mysql("UPDATE bornes SET mip='".$v."' WHERE mac='".$k."'");
				}
				else { // la borne existe pas : creation + status
					exec_mysql("INSERT INTO bornes SET mip='".$v."', mac='".$k."'");
				}
			}
		}
	}
}
//--------------------------------------------------------------------
function reload_dns($reload=FALSE) {
	global $config;
	global $connbdd;
	if (!$reload) {
		logme("Restart DNS servers ...");
		myexec("pkill -SIGTERM -f dnsmasq");
		sleep(2);
		myexec("pkill -KILL -f dnsmasq");
		foreach ($config['iface']['bridge_iface'] AS $k => $v) {
			logme("Start DNS servers for network ".($k+1)." : listen ".$config['iface'][$v]['ip']." forward to ".$config['iface'][$v]['dns']);
			file_put_contents("/etc/wprotect/hosts.local.".($k+1), $config['iface'][$v]['ip']." acces-wifi.ovh");
			file_put_contents("/etc/wprotect/dnsmasq.conf.".($k+1), "listen-address=".$config['iface'][$v]['ip']."\nbind-interfaces\nport=5353\naddn-hosts=/etc/wprotect/hosts.perso\naddn-hosts=/etc/wprotect/hosts.local.".($k+1)."\nno-hosts\nserver=".$config['iface'][$v]['dns']."\nno-resolv\ncache-size=4096\nlocal-ttl=60\n"); 
			myexec("dnsmasq --conf-file=/etc/wprotect/dnsmasq.conf.".($k+1));
		}
	}
	else {
		logme("Reload DNS servers configuration ...");
		myexec("pkill -SIGHUP -f dnsmasq");
	}
	logme("DNS servers ready !");
}
//-------------------------------------------------------------------
function reload_darkstat($reset=FALSE) {
	global $config;
	if (get_option("disable_darkstats")==1) {
		if ($reset) {
			logme("DARKSTATS : Reload darkstat with RESET DATA ...");
			myexec("pkill -KILL -f darkstat");
			foreach ($config['bridge_interface'] AS $k => $v) {
				myexec("rm -f /var/lib/darkstat".$k."/darkstat.db");
			}
			$import="";
		}
		else {
			logme("DARKSTATS : Reload darkstat ...");
			myexec("pkill -SIGTERM -f darkstat");
			sleep (3);
			$import="--import darkstat.db";
		}		
		foreach ($config['bridge_interface'] AS $k => $v) {
			if (!file_exists("/var/lib/darkstat".$k)) {
				mkdir("/var/lib/darkstat".$k);
			}
			logme("DARKSTATS : Start listen ".$v." on ".$config['public_network'][$k]);
			myexec("darkstat -i ".$v." --no-dns -p 66".$k." -b 0.0.0.0 -l ".$config['public_network'][$k]."/16 --local-only --chroot /var/lib/darkstat".$k." ".$import." --export darkstat.db");
		}
		logme("Reload darkstat DONE !");
	}
	else {
		myexec("pkill -SIGTERM -f darkstat");
		sleep(1);
		myexec("pkill -KILL -f darkstat");
		logme("DARKSTATS : Reload darkstat DISABLE by settings...");
	}
}
//------------------------------------------------------------------------------
function ftp_backup_connect() {
	global $config;
	$config['ftp_backup_connection'] = ftp_ssl_connect(get_option("ftp_backup_server"), 21, 10);
	if ($config['ftp_backup_connection']!==FALSE) {
		$login_result = ftp_login($config['ftp_backup_connection'], get_option("ftp_backup_user"), get_option("ftp_backup_password"));
	}
	else return FALSE;
	if ($login_result===TRUE) {
		ftp_pasv($config['ftp_backup_connection'], true);
		return TRUE;
	}
	else return FALSE;
}
//-----------------------------------------------------------------------------
function ftp_backup_copy_if_diff($local, $remote) {
	global $config;
	$local_size=filesize($local);
	$remote_size=ftp_size($config['ftp_backup_connection'], $remote);
	if (($local_size!=$remote_size)) {
		if (ftp_put($config['ftp_backup_connection'], $remote, $local, FTP_BINARY)) {
			logme("FTP_BACKUP : copy ".$local." -> ".$remote." : OK");
		}
		else {
			logme("FTP_BACKUP : copy ".$local." -> ".$remote." : ECHEC !!!");
		}
	}
}
//------------------------------------------------------------------------------
function ftp_backup_copy($local, $remote) {
	global $config;
	if (ftp_put($config['ftp_backup_connection'], $remote, $local, FTP_BINARY)) {
		logme("FTP_BACKUP : copy ".$local." -> ".$remote." : OK");
	}
	else {
		logme("FTP_BACKUP : copy ".$local." -> ".$remote." : ECHEC !!!");
	}
}
//------------------------------------------------------------------------------
function ftp_backup_copy_log() {
	global $config;
	$local="/var/log/wprotect/";
	$remote="/wprotect/log/";
	$tmp = array_diff(scandir($local), array('..', '.'));
	$local_files=array();
	foreach ($tmp AS $k=>$v) {
		if (!is_dir($local."/".$v)) {
			if (preg_match("/network/i", $v)) {
				if (preg_match("/.gz/i", $v)) {
					$local_files[]=$v;
				}
			}
		}
	}
	
	foreach ($local_files AS $k=>$v) {
		ftp_backup_copy_if_diff($local.$v, $remote.$v);
	}
}
//------------------------------------------------------------------------------
function ftp_backup_copy_media() {
	global $config;
	$local="/var/www/admin/fileman/Uploads/";
	$remote="/wprotect/";
	$tmp = array_diff(scandir($local."Documents"), array('..', '.'));
	$local_files=array();
	foreach ($tmp AS $k=>$v) {
		if (!is_dir($local."/".$v)) {
			$local_files[]=$v;
		}
	}
	foreach ($local_files AS $k=>$v) {
		ftp_backup_copy_if_diff($local."Documents/".$v, $remote."Documents/".$v);
	}
	$tmp = array_diff(scandir($local."FLV"), array('..', '.'));
	$local_files=array();
	foreach ($tmp AS $k=>$v) {
		if (!is_dir($local."/".$v)) {
			$local_files[]=$v;
		}
	}
	foreach ($local_files AS $k=>$v) {
		ftp_backup_copy_if_diff($local."FLV/".$v, $remote."FLV/".$v);
	}
	$tmp = array_diff(scandir($local."Images"), array('..', '.'));
	$local_files=array();
	foreach ($tmp AS $k=>$v) {
		if (!is_dir($local."/".$v)) {
			$local_files[]=$v;
		}
	}
	foreach ($local_files AS $k=>$v) {
		ftp_backup_copy_if_diff($local."Images/".$v, $remote."Images/".$v);
	}
}
//------------------------------------------------------------------------------
function backup_to_ftp_start() {
	global $config;
	global $connbdd;
	proc_nice(19);
	$mypid = getmypid();
	exec_mysql("INSERT INTO thread SET pid='".$mypid."', name='backup_ftp', status='running'");
	logme("FTP_BACKUP : Start ...");
	if (ftp_backup_connect()) {
		myexec("mkdir /tmp/backup_bdd");
		$result = exec_mysql("SHOW TABLES FROM wprotect");
		while ($val = mysqli_fetch_array($result)) {
			$tablename=$val[0];
			system ("mysqldump -h ".$config['config_mysql_host']." -u ".$config['config_mysql_user']." -p".$config['config_mysql_password']." ".$config['config_mysql_db']." ".$tablename." > /tmp/backup_bdd/".$tablename.".sql");
		}
		$date = date("Y-m-d_h-i");
		system ("cd /tmp/backup_bdd && tar cfj /tmp/wprotect_backup-".$date.".tar.bz2 *");
		@ftp_mkdir($config['ftp_backup_connection'], "wprotect");
		@ftp_chdir($config['ftp_backup_connection'], "/wprotect");
		@ftp_mkdir($config['ftp_backup_connection'], "conf");
		@ftp_mkdir($config['ftp_backup_connection'], "log");
		@ftp_mkdir($config['ftp_backup_connection'], "Documents");
		@ftp_mkdir($config['ftp_backup_connection'], "FLV");
		@ftp_mkdir($config['ftp_backup_connection'], "Images");
		ftp_backup_copy("/etc/network/interfaces", "/wprotect/conf/interfaces");
		ftp_backup_copy("/etc/wprotect/wprotect.conf", "/wprotect/conf/wprotect.conf");
		ftp_backup_copy_log();
		ftp_backup_copy_media();
		ftp_backup_copy("/tmp/wprotect_backup-".$date.".tar.bz2", "/wprotect/conf/wprotect_backup-".$date.".tar.bz2");
		system ("rm -R /tmp/backup_bdd");
		ftp_close($config['ftp_backup_connection']);
	}
	exec_mysql("UPDATE thread SET status='ok' WHERE pid='".$mypid."' AND name='backup_ftp' AND status='running'");
	logme("FTP_BACKUP : End ...");
}
//------------------------------------------------------------------------------
function thread_backup_to_ftp() {
	global $config;
	global $connbdd;
	proc_nice(19);
	$mypid = getmypid();
	while (TRUE) {
		sleep(240);
		$time_to_backup = get_option("ftp_backup_time");
		if ($time_to_backup > 0) { // si backup actif
			$tt_to_backup = strtotime(date("Y-m-d")." ".$time_to_backup);
			if (($tt_to_backup < time()) AND (time() < $tt_to_backup+242)) { //si c l'heure on execute le backup ftp
				backup_to_ftp_start();
				sleep(240);
			}
		}
		else { //si backup non actif on wait
			sleep(3600);
		}
	}
}
//----------------------------------------------------------------------
function get_config_interfaces() {
	global $config;
	global $connbdd;
	$iface=array();
	$iface['network_number']=0;
	$iface['hotspot']=FALSE;
	$handle = @fopen("/etc/network/interfaces", "r");
	if ($handle) {
    while (($buffer = fgets($handle, 4096)) !== false) {
		preg_match("/^\s*auto\s(?P<iface>([0-9a-z.]*))$/", $buffer, $match);
		if (isset($match['iface'])) {
			$iface[$match['iface']]=array();
			$cu_iface = $match['iface'];
		}
		preg_match("/^\s*address\s(?P<ip>([0-9.]*))$/", $buffer, $match);
		if (isset($match['ip'])) {
			$iface[$cu_iface]['ip']=$match['ip'];
		}
		preg_match("/^\s*netmask\s(?P<netmask>([0-9.]*))$/", $buffer, $match);
		if (isset($match['netmask'])) {
			$iface[$cu_iface]['netmask']=$match['netmask'];
		}
		preg_match("/^\s*gateway\s(?P<gateway>([0-9.]*))$/", $buffer, $match);
		if (isset($match['gateway'])) {
			$iface[$cu_iface]['gateway']=$match['gateway'];
		}
		preg_match("/^\s*dns-nameservers\s(?P<dns>([0-9.]*))$/", $buffer, $match);
		if (isset($match['dns'])) {
			$iface[$cu_iface]['dns']=$match['dns'];
		}
		preg_match("/^\s*bridge_ports\s(?P<if>([a-z0-9\s]*))$/", $buffer, $match);
		if (isset($match['if'])) {
			$t=explode(" ", $match['if']);
			if (isset($t[0])) { $iface[$cu_iface]['bridge_ports'][0]=rtrim($t[0],"\n"); $iface[$iface[$cu_iface]['bridge_ports'][0]]['is_bridge_to']=$cu_iface; }
			if (isset($t[1])) { $iface[$cu_iface]['bridge_ports'][1]=rtrim($t[1],"\n"); $iface[$iface[$cu_iface]['bridge_ports'][1]]['is_bridge_to']=$cu_iface; }
			if (isset($t[2])) { $iface[$cu_iface]['bridge_ports'][2]=rtrim($t[2],"\n"); $iface[$iface[$cu_iface]['bridge_ports'][2]]['is_bridge_to']=$cu_iface; }
			if (isset($t[3])) { $iface[$cu_iface]['bridge_ports'][3]=rtrim($t[3],"\n"); $iface[$iface[$cu_iface]['bridge_ports'][3]]['is_bridge_to']=$cu_iface; }
			if ((isset($t[0]) AND ($t[0]=="wlan0")) OR (isset($t[1]) AND ($t[1]=="wlan0")) OR (isset($t[2]) AND ($t[2]=="wlan0")) OR (isset($t[3]) AND ($t[3]=="wlan0"))) {
				LOGME("! MODE HOTSPOT ON !");
				$iface['hotspot']=TRUE;
			}
			$iface['bridge_iface'][] = $cu_iface;
			$iface['network_number']++;
		}
    }
	return $iface;
    if (!feof($handle)) {
        return FALSE;
    }
    fclose($handle);
	}
	return FALSE;
}
//----------------------------------------------------------------------
function thread_ap_ubiquiti_reboot($ip, $password, $name, $sleep_time) {
	global $config;
	global $connbdd;
	proc_nice(19);
	$mypid = getmypid();
	$return=array();
	$return['code']=1;
	$return['msg']='erreur inconnu';
	exec_mysql("INSERT INTO thread SET pid='".$mypid."', name='REBOOT AP ".$name."', status='running'");
	logme("REBOOT AP THREAD ".$mypid." : try ".$name);
	ini_set('default_socket_timeout', 3);
	$connection = ssh2_connect($ip, 22);
	ini_set('default_socket_timeout', 30);
	if (!$connection) {
		logme("REBOOT AP THREAD ".$mypid." : ".$name." Echec de connexion SSH");
		$return['msg']='Echec de connexion SSH';
	}
	else {
		if (ssh2_auth_password($connection, "admin", $password) OR ssh2_auth_password($connection, "ubnt", $password) OR ssh2_auth_password($connection, "root", $password)) {
			if (is_resource($f = ssh2_exec ($connection, "(sleep ".$sleep_time." && reboot) &"))) {
				stream_set_blocking ($f, true);
				fclose($f);
				if (is_resource($f = ssh2_exec ($connection, "exit"))) {
					stream_set_blocking ($f, true);
					fclose($f);
					logme("REBOOT AP THREAD ".$mypid." : ".$name." OK for reboot");
					$return['code']=0;
					$return['msg']='OK';
				}
				else {
					logme("REBOOT AP THREAD ".$mypid." : ".$name." -> Exit command failed");
					$return['msg']='Exit command failed';
				}
			}
			else {
				logme("REBOOT AP THREAD ".$mypid." : ".$name." -> Echec execution command");
				$return['msg']='Echec execution command';
			}
		}
		else {
			logme("REBOOT AP THREAD ".$mypid." : ".$name." -> Echec authentification SSH");
			$return['msg']='Echec authentification SSH';
		}
	}
	if ($return['code']==0) {
		exec_mysql("UPDATE thread SET status='ok', date_end=NOW() WHERE pid='".$mypid."' AND name='REBOOT AP ".$name."' AND date_end='0000-00-00 00:00:00'");
	}
	else {
		exec_mysql("UPDATE thread SET status='".$return['msg']."', date_end=NOW() WHERE pid='".$mypid."' AND name='REBOOT AP ".$name."' AND date_end='0000-00-00 00:00:00'");
	}
	exit();
}
//----------------------------------------------------------------------
function reboot_ap_ubiquiti($bid) {
	global $config;
	global $connbdd;
	$return=array();
	$return['code']=1;
	$return['msg']='erreur inconnu';
	$ubiquiti = array();
	$ubiquiti[] = "NanoStation Loco M5";
	$ubiquiti[] = "NanoStation Loco M2";
	$ubiquiti[] = "Rocket M5";
	$ubiquiti[] = "Rocket M2";
	$ubiquiti[] = "Bullet M2";
	$ubiquiti[] = "NanoStation M5";
	$ubiquiti[] = "NanoStation M2";
	$ubiquiti[] = "UNIFI UAP-AC-LR";
	$ubiquiti[] = "UNIFI UAP-LR";
	if ($bid == -1) {
		logme("REBOOT ALL AP !!");
		$query="SELECT * FROM bornes WHERE status='1' OR (UNIX_TIMESTAMP(last_mca)+42 > UNIX_TIMESTAMP(NOW()))";
		$sleep_time = 15;
	}
	if ($bid > 0) {
		$query="SELECT * FROM bornes WHERE id='".$bid."' AND (status='1' OR (UNIX_TIMESTAMP(last_mca)+42 > UNIX_TIMESTAMP(NOW())))";
		$sleep_time = 3;
	}
	$result=exec_mysql($query);
	$a=0;
	$thread_ubiquiti_reboot=array();
	// START THREAD
	while ($val = mysqli_fetch_array($result)) {
		if (in_array($val['model'], $ubiquiti)) {
			$a++;
			$thread_ubiquiti_reboot[$a] = new Thread( 'thread_ap_ubiquiti_reboot' ); // prepare the thread
			$thread_ubiquiti_reboot[$a]->start($val['ip'], get_option_from_mysql("bornes_admin_password"), $val['name'], $sleep_time); // start the thread with parameters
		}
		else {
			logme("REBOOT AP : ".$val['name']." -> Echec modèle non répertorié");
		}
	}
	// CHECK THREAD
	$u=0;
	while (count($thread_ubiquiti_reboot) > 0) {
		sleep(1);
		$u++;
		foreach ($thread_ubiquiti_reboot AS $k => $v) {
			if (!$thread_ubiquiti_reboot[$k]->isAlive()) {
				unset($thread_ubiquiti_reboot[$k]);
			}
			else if ($u > ($sleep_time+2)) {
				$thread_ubiquiti_reboot[$k]->kill();
				exec_mysql("UPDATE thread SET status='KILL', date_end=NOW() WHERE pid='".$thread_ubiquiti_reboot[$k]->getPid()."' AND date_end='0000-00-00 00:00:00'");
			}
		}
		if ($u > ($sleep_time + 10)) {
			return false;
		}
	}
}
//--------------------------------------------------------------------------------------
function generate_poststart() {
	global $config;
	global $connbdd;
	foreach ($config['bridge_interface'] AS $k => $v) {
		$result = exec_mysql("SELECT * FROM network WHERE id='".$k."'");
		$routeur_mac="";
		$routeur_ip="";
		$wprotect_mac="";
		$wprotect_ip="";
		while ($val = mysqli_fetch_array($result)) {
			$routeur_mac=$val['mac_routeur'];
			$routeur_ip=$val['ip_routeur'];
			$wprotect_mac=$val['mac_wprotect'];
			$wprotect_ip=$val['ip_wprotect'];
		}
		if (($routeur_mac!="") AND ($routeur_ip!="") AND ($wprotect_mac!="") AND ($wprotect_ip!="")) {
			if ($k==1) {
				system("cp /opt/wprotect/poststart_p.sample /opt/wprotect/poststart_p");
				system("cp /opt/wprotect/poststart_b.sample /opt/wprotect/poststart_b");
				system("sed -i -e \"s/{ROOTER_MAC}/".$routeur_mac."/g\" /opt/wprotect/poststart_p");
				system("sed -i -e \"s/{WPROTECT_MAC}/".$wprotect_mac."/g\" /opt/wprotect/poststart_p");
				system("sed -i -e \"s/{ROOTER_IP}/".$routeur_ip."/g\" /opt/wprotect/poststart_p");
				system("sed -i -e \"s/{WPROTECT_IP}/".$wprotect_ip."/g\" /opt/wprotect/poststart_p");
				system("sed -i -e \"s/{ROOTER_MAC}/".$routeur_mac."/g\" /opt/wprotect/poststart_b");
				system("sed -i -e \"s/{WPROTECT_MAC}/".$wprotect_mac."/g\" /opt/wprotect/poststart_b");
				system("sed -i -e \"s/{ROOTER_IP}/".$routeur_ip."/g\" /opt/wprotect/poststart_b");
				system("sed -i -e \"s/{WPROTECT_IP}/".$wprotect_ip."/g\" /opt/wprotect/poststart_b");
			}
			system("cp /opt/wprotect/poststart_p.sample /opt/wprotect/poststart_p_".$k);
			system("cp /opt/wprotect/poststart_b.sample /opt/wprotect/poststart_b_".$k);
			system("sed -i -e \"s/{ROOTER_MAC}/".$routeur_mac."/g\" /opt/wprotect/poststart_p_".$k);
			system("sed -i -e \"s/{WPROTECT_MAC}/".$wprotect_mac."/g\" /opt/wprotect/poststart_p_".$k);
			system("sed -i -e \"s/{ROOTER_IP}/".$routeur_ip."/g\" /opt/wprotect/poststart_p_".$k);
			system("sed -i -e \"s/{WPROTECT_IP}/".$wprotect_ip."/g\" /opt/wprotect/poststart_p_".$k);
			system("sed -i -e \"s/{ROOTER_MAC}/".$routeur_mac."/g\" /opt/wprotect/poststart_b_".$k);
			system("sed -i -e \"s/{WPROTECT_MAC}/".$wprotect_mac."/g\" /opt/wprotect/poststart_b_".$k);
			system("sed -i -e \"s/{ROOTER_IP}/".$routeur_ip."/g\" /opt/wprotect/poststart_b_".$k);
			system("sed -i -e \"s/{WPROTECT_IP}/".$wprotect_ip."/g\" /opt/wprotect/poststart_b_".$k);
			$tmp_b=file_get_contents("/opt/wprotect/poststart_b_".$k);
			$tmp_p=file_get_contents("/opt/wprotect/poststart_p_".$k);
			apc_store("poststart_b_".$k, md5($tmp_b));
			apc_store("poststart_p_".$k, md5($tmp_p));
			//-----generate UNIFI mca---------
				system("cp /opt/wprotect/unifi_mca.sample /opt/wprotect/unifi_mca_".$k);
				system("sed -i -e \"s/{WPROTECT_IP}/".$wprotect_ip."/g\" /opt/wprotect/unifi_mca_".$k);
			//--------------------------------
		}
		else {
			logme("POSTSTART GENERATE files failed for network ".$k."-> PUT empty files");
			if ($k==1) {
				system("touch /opt/wprotect/poststart_p; echo '' > /opt/wprotect/poststart_p");
				system("touch /opt/wprotect/poststart_b; echo '' > /opt/wprotect/poststart_b");
			}
			system("touch /opt/wprotect/poststart_p; echo '' > /opt/wprotect/poststart_p_".$k);
			system("touch /opt/wprotect/poststart_b; echo '' > /opt/wprotect/poststart_b_".$k);
		}
	}
	logme("POSTSTART files REGENERATE");
}
//--------------------------------------------------------------------------------------
function get_pid_list_cpu() {
	global $config;
	$pid=array();
	$pid['get_and_write_data_volume']['pid'] = apc_fetch ("get_and_write_data_volume");
	$pid['server_loop']['pid'] = apc_fetch ("server_loop");
	$pid['check_login_expire']['pid'] = apc_fetch ("check_login_expire");
	$pid['clean_discover_useless']['pid'] = apc_fetch ("clean_discover_useless");
	$pid['thread_auto_clean_devices']['pid'] = apc_fetch ("thread_auto_clean_devices");
	$pid['auto_disconnect_client']['pid'] = apc_fetch ("auto_disconnect_client");
	$pid['thread_bornes_watcher']['pid'] = apc_fetch ("thread_bornes_watcher");
	$pid['thread_watch_bornes_on_m_network']['pid'] = apc_fetch ("thread_watch_bornes_on_m_network");
	$pid['thread_backup_to_ftp']['pid'] = apc_fetch ("thread_backup_to_ftp");
	$pid['thread_get_sys_infos']['pid'] = apc_fetch ("thread_get_sys_infos");
	if ($p=apc_fetch ("watch_disconnected_mac1")) $pid['watch_disconnected_mac1']['pid'] = $p;
	if ($p=apc_fetch ("watch_disconnected_mac2")) $pid['watch_disconnected_mac2']['pid'] = $p;
	if ($p=apc_fetch ("watch_disconnected_mac3")) $pid['watch_disconnected_mac3']['pid'] = $p;
	if ($p=apc_fetch ("watch_disconnected_mac4")) $pid['watch_disconnected_mac4']['pid'] = $p;
	if ($p=apc_fetch ("watch_ip_mac1")) $pid['watch_ip_mac1']['pid'] = $p;
	if ($p=apc_fetch ("watch_ip_mac2")) $pid['watch_ip_mac2']['pid'] = $p;
	if ($p=apc_fetch ("watch_ip_mac3")) $pid['watch_ip_mac3']['pid'] = $p;
	if ($p=apc_fetch ("watch_ip_mac4")) $pid['watch_ip_mac4']['pid'] = $p;
	if ($p=apc_fetch ("watch_dhcp_ip_mac1")) $pid['watch_dhcp_ip_mac1']['pid'] = $p;
	if ($p=apc_fetch ("watch_dhcp_ip_mac2")) $pid['watch_dhcp_ip_mac2']['pid'] = $p;
	if ($p=apc_fetch ("watch_dhcp_ip_mac3")) $pid['watch_dhcp_ip_mac3']['pid'] = $p;
	if ($p=apc_fetch ("watch_dhcp_ip_mac4")) $pid['watch_dhcp_ip_mac4']['pid'] = $p;
	foreach ($pid AS $k=>$v) {
		$pid[$k]['cpu'] = myexec("ps -p ".$v['pid']." -o %cpu | sed \"1 d\"");
	}
	$pid['mysqld']['cpu'] = myexec("ps -C mysqld -o %cpu | sed \"1 d\"");
	$pid['apache2']['cpu'] = myexec("ps -C mysqld -o %cpu | sed \"1 d\"");
	$pid['rsyslogd']['cpu'] = myexec("ps -C rsyslogd -o %cpu | sed \"1 d\"");
	$pid['dnsmasq']['cpu'] = myexec("ps -C dnsmasq -o %cpu | sed \"1 d\"");
	return $pid;
}
//--------------------------------------------------------------------------------------
function seek_routeur($iface) {
	global $proc;
	global $config;
	global $connbdd;
	$br=$config['iface'][$iface]['is_bridge_to'];
	$ip = $config['iface'][$config['iface'][$iface]['is_bridge_to']]['ip'];
	$t=explode(".", $ip);
	$detected=array();
	$cdir_network=$t[0].".".$t[1]."."."64.0/18";
	$network = (substr($config['iface'][$iface]['is_bridge_to'], 2, 1))+1;
	connect_mysql();
	pcntl_signal(SIGTERM, 'sig_handler_thread'); 
	pcntl_signal(SIGINT, 'sig_handler_thread');
	pcntl_signal(SIGCHLD, SIG_IGN); 
	$descriptorspec = array(
       0 => array("pipe", "r"),   // stdin
       1 => array("pipe", "w"),  // stdout
       2 => array("pipe", "w")   // stderr
	);
	logme("SEEK ROUTEUR : ".$cdir_network." : bind ".$br." -> ".$ip);
	if ($proc = proc_open("exec tcpdump -v -t -l -i ".$br." -n -e tcp and src net ".$cdir_network." and '((ip[8]<64 and ip[8]>55) or (ip[8]<128 and ip[8]>120))'", $descriptorspec, $pipes, null, null)) {
		$mac="";
		$ip="";
		while ($proc) {
			$proc_status = proc_get_status ( $proc );
			if (!$proc_status['running']) break;
			$read   = array($pipes[1]);
			$write  = NULL;
			$except = NULL;
			if (@stream_select($read, $write, $except, 0, 100000) > 0) { 
				$line = fgets($pipes[1]);
				preg_match("/^(?P<mac>[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2}\:[0-9a-f]{2})\s>\s.*$/", $line, $match);
				if (isset($match['mac'])) { 
					$mac = strtoupper($match['mac']);
					if (!in_array($mac, $detected)) {
						array_push($detected, $mac);
						logme("WARNING ROUTEUR DETECTED : ".$network." : MAC : ".$mac);
					}
				}
			}
		}
	}
	echo "Processus terminé\n";
	proc_terminate($proc, 15);
	sleep (1);
}
//--------------------------------------------------------------------------------------
function thread_auto_update_certs () {
	global $config;
	global $connbdd;
	$time_loop = 61;
	while (TRUE) {
		$now=time();
		$hier = date("Y-m-d", $now-86400);
		$next_min_save_date = strtotime(date("Y-m-d", $now)." 4:50"); //determine l'heure du prochain event
		$next_max_save_date = $next_min_save_date + $time_loop;
		if ((time() > $next_min_save_date) AND (time() < $next_max_save_date)) { // si c'est l'heure
			update_certs();
		}
		sleep ($time_loop);
	}
}
//--------------------------------------------------------------------------------------
function thread_auto_reboot_ap () {
	global $config;
	global $connbdd;
	$time_loop = 61;
	while (TRUE) {
		$timeset=get_option("auto_reboot_ap_time");
		if ($timeset!="") {
			$now=time();
			$hier = date("Y-m-d", $now-86400);
			$next_min_save_date = strtotime(date("Y-m-d", $now)." ".$timeset); //determine l'heure du prochain event
			$next_max_save_date = $next_min_save_date + $time_loop;
			if ((time() > $next_min_save_date) AND (time() < $next_max_save_date)) { // si c'est l'heure
				reboot_ap_ubiquiti(-1);
			}
		}
		sleep ($time_loop);
	}
}
//--------------------------------------------------------------------------------------
function get_system_version() {
	global $config;
	global $connbdd;
	$r=myexec("lsb_release -da");
	$i=0;
	foreach ($r AS $k=>$v) {
		$v=trim($v);
		$a=explode(":", $v);
		$a[0]=trim($a[0]);
		$a[1]=trim($a[1]);
		$b[$a[0]]=$a[1];
	}
	$config['sys_os_name']=$b['Distributor ID'];
	$config['sys_os_version']=$b['Release'];
	$config['sys_os_fullname']=$b['Description'];
	$config['sys_os_codename']=$b['Codename'];
	exec_mysql("INSERT INTO options SET name='sys_os_name', value='".$config['sys_os_name']."' ON DUPLICATE KEY UPDATE value='".$config['sys_os_name']."'");
	exec_mysql("INSERT INTO options SET name='sys_os_version', value='".$config['sys_os_version']."' ON DUPLICATE KEY UPDATE value='".$config['sys_os_version']."'");
	exec_mysql("INSERT INTO options SET name='sys_os_fullname', value='".$config['sys_os_fullname']."' ON DUPLICATE KEY UPDATE value='".$config['sys_os_fullname']."'");
	exec_mysql("INSERT INTO options SET name='sys_os_codename', value='".$config['sys_os_codename']."' ON DUPLICATE KEY UPDATE value='".$config['sys_os_codename']."'");
}
//--------------------------------------------------------------------------------------------
function qos_create_queue($network) {
	global $config;
	global $connbdd;
	$iface_ul=$config['iface']["br".($network-1)]['bridge_ports'][0];
	$iface_dl=$config['iface']["br".($network-1)]['bridge_ports'][1];
	$ip=$config['iface']["br".($network-1)]['ip'];
	$result = exec_mysql("SELECT * FROM network WHERE id='".$network."' LIMIT 1");
	if ($val = mysqli_fetch_array($result)) {
		if (($val['dl_min'] > 0) AND ($val['ul_min'] > 0)) {
			logme("QOS : ".$network." : DL ".$iface_dl." UL ".$iface_ul);
			apc_store("qos_enable_".$network, 1);
			apc_store("qos_iface_dl_".$network, $iface_dl);
			apc_store("qos_iface_ul_".$network, $iface_ul);
			myexec("tc qdisc del dev ".$iface_dl." root");
			myexec("tc qdisc add dev ".$iface_dl." root handle 1: htb");
			myexec("tc class add dev ".$iface_dl." parent 1: classid 1:1 htb rate 1000mbit");
			myexec("tc qdisc del dev ".$iface_ul." root");
			myexec("tc qdisc add dev ".$iface_ul." root handle 1: htb");
			myexec("tc class add dev ".$iface_ul." parent 1: classid 1:1 htb rate 1000mbit");
			myexec("tc filter add dev ".$iface_dl." parent 1: handle 800::1 protocol ip prio 1 u32 match ip src ".$ip." flowid 1:1");
			for ($id=2;$id<512;$id++) {
				myexec("tc class add dev ".$iface_dl." parent 1:1 classid 1:".$id." htb rate ".$val['dl_min']."kbit ceil ".$val['dl_min']."kbit cburst ".($val['dl_bucket'])." prio 1");
				myexec("tc class add dev ".$iface_ul." parent 1:1 classid 1:".$id." htb rate ".$val['ul_min']."kbit ceil ".$val['ul_min']."kbit cburst ".($val['ul_bucket'])." prio 1");
			}
		}
		else {
			logme("QOS : ".$network." : DISABLE");
			apc_store("qos_enable_".$network, 0);
			apc_store("qos_iface_dl_".$network, $iface_dl);
			apc_store("qos_iface_ul_".$network, $iface_ul);
			myexec("tc qdisc del dev ".$iface_dl." root");
			myexec("tc qdisc del dev ".$iface_ul." root");
		}
	}
}
//--------------------------------------------------------------------------------------------
function qos_change_queue($network) {
	global $config;
	global $connbdd;
	$iface_ul=$config['iface']["br".($network-1)]['bridge_ports'][0];
	$iface_dl=$config['iface']["br".($network-1)]['bridge_ports'][1];
	$result = exec_mysql("SELECT * FROM network WHERE id='".$network."' LIMIT 1");
	if ($val = mysqli_fetch_array($result)) {
		if (($val['dl_min'] > 0) AND ($val['ul_min'] > 0)) {
			logme("QOS : ".$network." : CHANGE DL ".$iface_dl." UL ".$iface_ul);
			$tmp=apc_fetch("qos_enable_".$network);
			if ($tmp==1) {
				apc_store("qos_enable_".$network, 1);
				apc_store("qos_iface_dl_".$network, $iface_dl);
				apc_store("qos_iface_ul_".$network, $iface_ul);
				for ($id=2;$id<512;$id++) {
					myexec("tc class change dev ".$iface_dl." parent 1:1 classid 1:".$id." htb rate ".$val['dl_min']."kbit ceil ".$val['dl_min']."kbit cburst ".($val['dl_bucket'])." prio 2");
					myexec("tc class change dev ".$iface_ul." parent 1:1 classid 1:".$id." htb rate ".$val['ul_min']."kbit ceil ".$val['ul_min']."kbit cburst ".($val['ul_bucket'])." prio 2");
				}
			}
			else {
				logme("QOS : ".$network." : change need it -> Enable QOS");
				qos_create_queue($network);
			}
		}
		else {
			logme("QOS : ".$network." : change need it -> Disable QOS");
			apc_store("qos_enable_".$network, 0);
			apc_store("qos_iface_dl_".$network, $iface_dl);
			apc_store("qos_iface_ul_".$network, $iface_ul);
			myexec("tc qdisc del dev ".$iface_dl." root");
			myexec("tc qdisc del dev ".$iface_ul." root");
		}
	}
}
//--------------------------------------------------------------------------------------------
function qos_add_mac($network, $mac, $id) {
	global $config;
	$is_qos=apc_fetch("qos_enable_".$network);
	if ($is_qos) {
		$iface_dl=apc_fetch("qos_iface_dl_".$network);
		$iface_ul=apc_fetch("qos_iface_ul_".$network);
		logme("QOS : ".$network." : enable for ".$mac);
		$t=explode(":", $mac);
		logme("QOS : ".$network." : add ".$mac." ID ".$id);
		myexec("tc filter add dev ".$iface_dl." parent 1: handle 800::".$id." protocol ip prio 1 u32 match u16 0x0800 0xFFFF at -2 match u32 0x".$t[2].$t[3].$t[4].$t[5]." 0xFFFFFFFF at -12 match u16 0x".$t[0].$t[1]." 0xFFFF at -14 flowid 1:".$id);
		myexec("tc filter add dev ".$iface_ul." parent 1: handle 800::".$id." protocol ip prio 1 u32 match u16 0x0800 0xFFFF at -2 match u16 0x".$t[4].$t[5]." 0xFFFF at -4 match u32 0x".$t[0].$t[1].$t[2].$t[3]." 0xFFFFFFFF at -8 flowid 1:".$id);
	}
}
//--------------------------------------------------------------------------------------------
function qos_del_mac($network, $mac, $id) {
	global $config;
	$is_qos=apc_fetch("qos_enable_".$network);
	if ($is_qos) {
		$iface_dl=apc_fetch("qos_iface_dl_".$network);
		$iface_ul=apc_fetch("qos_iface_ul_".$network);
		logme("QOS : ".$network." : delete qos for ".$mac." ID ".$id);
		$t=explode(":", $mac);
		logme("QOS : ".$network." : del ".$mac." ID ".$id);
		myexec("tc filter del dev ".$iface_dl." parent 1: handle 800::".$id." protocol ip prio 1 u32");
		myexec("tc filter del dev ".$iface_ul." parent 1: handle 800::".$id." protocol ip prio 1 u32");
	}
}
//--------------------------------------------------------------------------------------------
function qos_get_list($network) {
	global $config;
	$return=array();
	$return["dl"]=array();
	$return["ul"]=array();
	$is_qos=apc_fetch("qos_enable_".$network);
	if ($is_qos==1) {
		$iface_dl=apc_fetch("qos_iface_dl_".$network);
		$iface_ul=apc_fetch("qos_iface_ul_".$network);
		$r=myexec("tc filter show dev ".$iface_dl);
		$find_id=false;
		foreach($r AS $k=>$v) {
			preg_match("/^filter\sparent\s1\:\sprotocol\sip\spref\s1\su32\sfh\s.*\sflowid\s1\:(?P<id>[0-9].*)$/", $v, $match);
			if (isset($match['id']) AND ($match['id']>1)) {
				$find_id=$match['id'];
			}
			preg_match("/^\s\smatch\s(?P<mac1>[0-9a-f]{8})\/.*\s\-12$/", $v, $match);
			if (isset($match['mac1'])) {
				$find_mac1=$match['mac1'];
			}
			preg_match("/^\s\smatch\s0000(?P<mac2>[0-9a-f]{4})\/.*\s\-16$/", $v, $match);
			if (isset($match['mac2'])) {
				$find_mac2=$match['mac2'];
			}
			if (isset($find_mac1) AND isset($find_mac2) AND $find_id>1) {
				$a=wordwrap(strtoupper($find_mac2.$find_mac1), 2, ":", true);
				$return["dl"][$find_id]=$a;
				$find_id=false;
				unset($find_mac1);
				unset($find_mac2);
			}
		}
		$r=myexec("tc filter show dev ".$iface_ul);
		$find_id=false;
		foreach($r AS $k=>$v) {
			preg_match("/^filter\sparent\s1\:\sprotocol\sip\spref\s1\su32\sfh\s.*\sflowid\s1\:(?P<id>[0-9].*)$/", $v, $match);
			if (isset($match['id']) AND ($match['id']>1)) {
				$find_id=$match['id'];
			}
			preg_match("/^\s\smatch\s(?P<mac1>[0-9a-f]{4})0800\/.*\sat\s\-4$/", $v, $match);
			if (isset($match['mac1'])) {
				$find_mac1=$match['mac1'];
			}
			preg_match("/^\s\smatch\s(?P<mac2>[0-9a-f]{8})\/.*\sat\s\-8$/", $v, $match);
			if (isset($match['mac2'])) {
				$find_mac2=$match['mac2'];
			}
			if (isset($find_mac1) AND isset($find_mac2) AND $find_id>1) {
				$a=wordwrap(strtoupper($find_mac2.$find_mac1), 2, ":", true);
				$return["ul"][$find_id]=$a;
				$find_id=false;
				unset($find_mac1);
				unset($find_mac2);
			}
		}
		return $return;
	}
	else {
		return $return;
	}
}
//--------------------------------------------------------------------------------------------
function thread_iperf () {
	global $config;
	global $connbdd;
	$time_loop = 2;
	while (TRUE) {
		myexec("pkill -KILL -f iperf");
		logme("IPERF : Start ...");
		myexec("iperf -s");
		sleep ($time_loop);
	}
}
//--------------------------------------------------------------------------------------------
function thread_queue_qos_manage() {
	global $config;
	global $connbdd;
	$q=msg_get_queue(7001);
	$table_id=array();
	$table_id[1]=array();
	$table_id[2]=array();
	$table_id[3]=array();
	$table_id[4]=array();
	while (true) {
		if (msg_receive($q, 0, $msgtype, 8192, $message, true, null, $err)) {
			if (isset($message['order'])) {
				switch($message['order']) {
					case "reload":
						if (isset($message['network'])) {
							qos_create_queue($message['network']);
						}
					break;
					case "change":
						if (isset($message['network'])) {
							qos_change_queue($message['network']);
						}
					break;
					case "add":
						if (isset($message['network']) AND isset($message['mac'])) {
							for ($id=2;$id<512;$id++) {
								if (!isset($table_id[$message['network']][$id])) {
									$id_seek=$id;
									break;
								}
							}
							if (isset($id_seek)) {
								$table_id[$message['network']][$id_seek]=$message['mac'];
								qos_add_mac($message['network'], $message['mac'], $id_seek);
							}
							else {
								logme("QOS : ".$message['network']." : qos table is full");
							}
						}
					break;
					case "del":
						if (isset($message['network']) AND isset($message['mac'])) {
							$id = array_search($message['mac'], $table_id[$message['network']]);
							qos_del_mac($message['network'], $message['mac'], $id);
							unset ($table_id[$message['network']][$id]);
						}
					break;
				}
			}
		}
	}
}
//---------------------------------------------------------------------------------------------------------
function qos_check_filter($network) {
	global $config;
	global $connbdd;
	logme("QOS : CHECK ".$network." : start");
	$start=time();
	$a=qos_get_list($network);
	$result = exec_mysql("SELECT * FROM lan_discover WHERE authorize='1' AND network='".$network."'");
	while ($val = mysqli_fetch_array($result)) {
		if (!in_array($val['mac'], $a['dl']) OR !in_array($val['mac'], $a['ul'])) {
			logme("QOS : CHECK : ".$network." : ".$val['mac']." is not enable -> enable it");
			$q=msg_get_queue(7001);
			$message=array();
			$message["order"]="add";
			$message["network"]=$network;
			$message["mac"]=$val["mac"];
			$ret=msg_send($q,8,$message,true,true,$err);
		}
	}
	logme("QOS : CHECK ".$network." : finish in ".(time()-$start)." seconds");
}
//------------------------------------------------------------------------------------------------------
function thread_qos_check_filter() {
	global $config;
	global $connbdd;
	sleep(3600);
	while (TRUE) {
		foreach ($config['bridge_interface'] AS $k => $v) {
			qos_check_filter($k);	
		}
		sleep(3600);
	}
}
//----------------------------------------------------------------------------------------------------
function get_darkstat_traffic($net_id) {
	global $config;
	$table = array();
	$current="";
	$level=1;
	if ($dispo = file_get_contents("http://127.0.0.1:66".$net_id."/hosts/?full=yes&sort=total")) {
		$r = explode ("\n", $dispo);
		foreach ($r AS $k => $v) {
			preg_match("/^\s*\<td\>\<tt\>(?P<mac>([0-9a-f]{2}:){5}[0-9a-f]{2})\<\/tt\>\<\/td\>\s*$/", $v, $m);
			if ((isset($m['mac']))) {
				$current=strtoupper($m['mac']);
				$level=1;
			}
			preg_match("/^\s*\<td class\=\"num\"\>(?P<num>([0-9\,]*))\<\/td\>\s*$/", $v, $m);
			if ((isset($m['num']))) {
				if (isset($table[$current][$level])) {
					$table[$current][$level]=$table[$current][$level] + str_replace(",", "", $m['num']);
					$level++;
				}
				else {
					$table[$current][$level]=0 + str_replace(",", "", $m['num']); // +0 force int number
					$level++;
				}
			}
		}
	}
	return $table;
}
//----------------------------------------------------------------------------------------------------
function thread_get_actual_traffic() {
	global $config;
	global $connbdd;
	connect_mysql();
	$traff=array();
	while (true) {
		sleep(5);
		if (get_option("beta_test")=="1") {
		foreach ($config['bridge_interface'] AS $net_id => $temp) {
			if (!isset($traff[$net_id])) $traff[$net_id]=array();
			$t=get_darkstat_traffic($net_id);
			$current_time=microtime(TRUE);
			foreach($t AS $k=>$v) {
				if (isset($traff[$net_id][$k])) {
					$total_time=$current_time-$traff[$net_id][$k]['time'];
					$total_traff=($v[3]-$traff[$net_id][$k]['total'])*8; //convert bytes to bits
					$actual_speed=intval($total_traff/$total_time);
					if ($actual_speed >= 0) {
						exec_mysql("UPDATE lan_discover SET traff='".$actual_speed."' WHERE mac='".$k."' AND network='".$net_id."'");
					}
					$traff[$net_id][$k]['time']=$current_time;
					$traff[$net_id][$k]['total']=$v[3];
				}
				else {
					$traff[$net_id][$k]=array();
					$traff[$net_id][$k]['time']=$current_time;
					$traff[$net_id][$k]['total']=$v[3];
				}
			}
		}
		}
	}
}
//----------------------------------------------------------------------------------------------------
function thread_do_something() {
	global $config;
	global $connbdd;
	$current_thread=1;
	$thread_table=array();
	for ($i=1;$i<=$config['num_thread_do_something'];$i++) {
		$thread_table[$i]=msg_get_queue(7500+$i);
	}
	$q=msg_get_queue(7000);
	while (true) {
		if (msg_receive($q, 0, $msgtype, 8192, $message, true, null, $err)) {
			msg_send($thread_table[$current_thread],8,$message,true,false,$err);
			$current_thread++;
			if ($current_thread > $config['num_thread_do_something']) {
				$current_thread=1;
			}
		}
	}
}
//----------------------------------------------------------------------------------------------------
function thread_do_something_thread($id) {
	global $config;
	global $connbdd;
	$q=msg_get_queue(7000);
	while (true) {
		if (msg_receive($q, 0, $msgtype, 8192, $message, true, null, $err)) {
			if (isset($message['order'])) {
				switch($message['order']) {
					case "borne_get_sta_list":
						if (isset($message['borne_ip']) AND isset($message['borne_id'])) {
							$tstartt = time();
							$is_connected = FALSE;
							ini_set('default_socket_timeout', 3);
							$connection = @ssh2_connect($message['borne_ip'], 22);
							if ($connection) {
								if (@ssh2_auth_password($connection, get_option_from_mysql("bornes_admin_login"), get_option_from_mysql("bornes_admin_password"))) {
									$is_connected = TRUE;
								}
								if ($is_connected) {
									$f = ssh2_exec ($connection, "wstalist");
									$err = ssh2_fetch_stream($f, SSH2_STREAM_STDERR);
									stream_set_blocking ($f, true);
									stream_set_blocking ($err, true);
									stream_set_timeout($f, 3);
									stream_set_timeout($err, 3);
									$output_error = stream_get_contents ($err);
									fclose($err);
									if (!$output_error) {
										$output = stream_get_contents ($f);
										$o=json_decode($output, TRUE);
										foreach ($o AS $k => $v) {
											if (isset($v["mac"])) {
												if (isset($v['rssi'])) {
													exec_mysql("UPDATE lan_discover SET `signal`='".$v['rssi']."', bid_connect='".$message['borne_id']."' WHERE network='".$message['network']."' AND mac='".strtoupper($v["mac"])."'");
												}
												else {
													exec_mysql("UPDATE lan_discover SET bid_connect='".$message['borne_id']."' WHERE network='".$message['network']."' AND mac='".strtoupper($v["mac"])."'");
												}
											}
										}
									}
									else {
										logme("REPORT : failed to connect ssh and get sta infos (data error) -> ".$message['borne_ip']);
									}
									fclose($f);
								}
								else {
									logme("REPORT : failed to connect ssh and get sta infos -> ".$message['borne_ip']);
								}
							}
							else {
								logme("REPORT : failed to connect ssh and get sta infos --> ".$message['borne_ip']);
							}
							ini_set('default_socket_timeout', 15);
							$tendt = time();
							if (($tendt - $tstartt) > 3) logme("MCA request took ".($tendt - $tstartt)." sec");
						}
					break;
					case "report_write_to_mysql":
						if (isset($message['deviceId'])) {
							$r=exec_mysql("SELECT * FROM bornes WHERE mac='".$message['deviceId']."' LIMIT 1");
							$val=mysqli_fetch_array($r);
							if (isset($val['name'])) {
								$to_update="SET last_mca=NOW(), last_seen=NOW()";
								if (isset($message['platform'])) {
									$to_update=$to_update.", model='".$message['platform']."'";
								}
								if (isset($message['essid'])) {
									$to_update=$to_update.", ssid='".$message['essid']."'";
								}
								if (isset($message['wlanConnections'])) {
									$to_update=$to_update.", nb_client='".$message['wlanConnections']."'";
								}
								if (isset($message['ccq'])) {
									$to_update=$to_update.", ccq='".($message['ccq']/10)."'";
								}
								if (isset($message['loadavg'])) {
									$to_update=$to_update.", cpu='".$message['loadavg']."'";
								}
								if (isset($message['memTotal']) AND isset($message['memFree'])) {
									$percent = 100 - (($message['memFree'] * 100) / $message['memTotal']);
									$to_update=$to_update.", mem_use='".$percent."'";
								}
								if (isset($message['mem_use'])) {
									$to_update=$to_update.", mem_use='".$message['mem_use']."'";
								}	
								exec_mysql("UPDATE bornes ".$to_update." WHERE mac='".$message['deviceId']."'");
								if (get_option("mca_airmax")=="1") {
									if ($val['gamme']=="AIRMAX" AND ($val['model']=="Bullet M2" OR $val['model']=="Rocket M2")) {
										//logme("REPORT : ask for connections infos");
										$send=array();
										$send['order']="borne_get_sta_list";
										$send['borne_ip']=$val['ip'];
										$send['borne_id']=$val['id'];
										$send['network']=$val['network'];
										$ret=msg_send($q,8,$send,true,false,$err);
									}
								}
								if (isset($message['sta'])) {
									foreach ($message['sta'] AS $mac=>$rssi) {
										exec_mysql("UPDATE lan_discover SET `signal`='".$rssi."', bid_connect='".$val['id']."' WHERE mac='".$mac."'");
									}
								}
							}
							else {
								logme("REPORT : dont find device ".$message['deviceId']." in BDD");
							}
						}
					break;
				}
			}
		}
	}
}
//------------------------------------------------------------------------
function wan_speedtest() {
	global $config;
	$r=myexec("/opt/wprotect/speedtest-cli --json");
	if (substr($r[0], 0, 1)=="{") {
		$a=json_decode($r[0], TRUE);
		if (isset($a['download'])) {
			$v=intval($a['download']/1000000);
			logme("SPEEDTEST : download is ".$v." Mbits");
			return $v;
		}
		else {
			logme("SPEEDTEST : FAILED\n".$a);
			return -1;
		}
	}
	else {
		logme("SPEEDTEST : failed non json output");
		return -1;
	}
}
//-------------------------------------------------------------------------
function thread_get_tplink_infos() {
	global $config;
	global $connbdd;
	$a=new OmadaQuery();
	sleep(15);
	while (true) {
		$name=get_option('omada_name');
		$pass=get_option('omada_pass');
		$ip=get_option('omada_ip');
		if (($name!="") AND ($pass!="") AND ($ip!="")) {
			$a->setName($name);
			$a->setPass($pass);
			$a->setControllerIp($ip);
			$result=$a->getClients();
			if ($a->getLastRequestStatus()===TRUE) {
				$ap_list=array();
				$r=exec_mysql("SELECT id, mac FROM bornes");
				while ($val=mysqli_fetch_array($r)) {
					$ap_list[$val['mac']]=$val['id'];
				}
				foreach ($result["result"]["data"] AS $k=>$v) {
					$v["mac"]=str_replace("-", ":", $v["mac"]);
					$v["apMac"]=str_replace("-", ":", $v["apMac"]);
					exec_mysql("UPDATE lan_discover SET `signal`='".$v["signalLevel"]."', bid_connect='".$ap_list[$v["apMac"]]."' WHERE mac='".$v["mac"]."'");
				}
			}
			else {
				logme("TP-LINK infos getClients : ERROR request failed");
			}
		}
		sleep(15);
	}
}
function get_queue_size_status() {
	global $config;
	$tq=array();
	$result=array();
	$tq[7000]=msg_get_queue(7000);
	$tq[7001]=msg_get_queue(7001);
	//for ($i=1;$i<=$config['num_thread_do_something'];$i++) {
	//	$name=7500+$i;
	//	$tq[$name]=msg_get_queue(7500+$i);
	//}
	foreach ($tq AS $k=>$v) {
		$b=msg_stat_queue($v);
		$result[$k]=$b['msg_qnum'];
	}
	return $result;
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ MAIN PROGRAM §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//----------------------Créer un daemon via fork---------------------
logme("WPROTECT: start ...");
$__parent_pid = become_daemon();
//--------------------readconfig------------------------------------
logme("WPROTECT: Read config ...");
readconfig_master();
generate_poststart();
$config['iface'] = get_config_interfaces();
foreach ($config['public_interface'] AS $k => $v) {
	logme ("Config Wprotect for listen to network from ".$config['public_interface'][$k]." : ".$config['public_ip'][$k]);
}
if( ! Thread::available() ) {
    die( 'Threads not supported' );
}
$a=0;
apc_store("backup_running", 0);
$thread_task_arg = array();
reload_dns();
apc_store("qos_enable_1", 0);
apc_store("qos_enable_2", 0);
apc_store("qos_enable_3", 0);
apc_store("qos_enable_4", 0);
logme("PHP version ".PHP_VERSION_ID);
if (PHP_VERSION_ID > 60000) {
	logme("Load netfilter.conntrack config");
	myexec("sysctl -w net.netfilter.nf_conntrack_generic_timeout=600");
	myexec("sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=7200");
}
myexec("ifconfig ".$config['bridge_interface'][1].":0 169.254.1.1 2> /dev/null");
myexec("ifup ".$config['bridge_interface'][1].":0 2> /dev/null");
myexec("sysctl -w kernel.msgmni=1638400");
myexec("sysctl -w kernel.msgmax=6553600");
myexec("sysctl -w kernel.msgmnb=6553600");
$a++;$thread_task[$a] = new Thread( 'thread_queue_qos_manage' );$thread_task[$a]->start();logme("THREAD $a thread_queue_qos_manage PID : ".$thread_task[$a]->getPid());apc_store("thread_queue_qos_manage", $thread_task[$a]->getPid());
for ($c = 1; $c <= $config['num_thread_do_something']; $c++) {
	$a++;$thread_task[$a] = new Thread( 'thread_do_something_thread' );$thread_task[$a]->start($c);logme("THREAD $a thread_do_something_thread_".$c." PID : ".$thread_task[$a]->getPid());apc_store("thread_do_something_thread_".$c, $thread_task[$a]->getPid());
}
//$a++;$thread_task[$a] = new Thread( 'thread_do_something' );$thread_task[$a]->start();logme("THREAD $a thread_do_something PID : ".$thread_task[$a]->getPid());apc_store("thread_do_something", $thread_task[$a]->getPid());
//----------Load firewall rules and clients---------------------------
load_firewall();
//----lancement des thread------------------------------------------
logme("DARKSTAT : Start");
reload_darkstat();
logme("THREAD : Start");
$a++;$thread_task[$a] = new Thread( 'upgrade_passthrought_dns' );$thread_task[$a]->start();logme("THREAD $a upgrade_passthrought_dns PID : ".$thread_task[$a]->getPid());apc_store("upgrade_passthrought_dns", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_get_all_ip_mac_from_arp_table' );$thread_task[$a]->start();logme("THREAD $a thread_get_all_ip_mac_from_arp_table PID : ".$thread_task[$a]->getPid());apc_store("thread_get_all_ip_mac_from_arp_table", $thread_task[$a]->getPid());
for ($b = 0; $b < $config['iface']['network_number']; $b++) {
	$a++;$thread_task_arg[$a]=$b+1;$thread_task[$a] = new Thread( 'watch_disconnected_mac' );$thread_task[$a]->start($thread_task_arg[$a]);logme("THREAD $a watch_disconnected_mac".($b+1)." PID : ".$thread_task[$a]->getPid());apc_store("watch_disconnected_mac".($b+1), $thread_task[$a]->getPid());
	foreach ($config['iface']["br".$b]['bridge_ports'] AS $k => $v) {
		if ($k!=0) {
			$a++;$thread_task_arg[$a]=$v;$thread_task[$a] = new Thread( 'watch_ip_mac' ); $thread_task[$a]->start($thread_task_arg[$a]);logme("THREAD $a watch_ip_mac".($b+1)." PID : ".$thread_task[$a]->getPid());apc_store("watch_ip_mac".($b+1), $thread_task[$a]->getPid());
			if ((get_option("seek_rooter")) == 1) {
				$a++;$thread_task_arg[$a]=$v;$thread_task[$a] = new Thread( 'seek_routeur' ); $thread_task[$a]->start($thread_task_arg[$a]);logme("THREAD $a seek_routeur".($b+1)." PID : ".$thread_task[$a]->getPid());apc_store("seek_routeur".($b+1), $thread_task[$a]->getPid());
			}
			if ((get_option("client_must_dhcp")) == 1) {
				$a++;$thread_task_arg[$a]=$v;$thread_task[$a] = new Thread( 'watch_dhcp_ip_mac' ); $thread_task[$a]->start($thread_task_arg[$a]);logme("THREAD $a watch_dhcp_ip_mac".($b+1)." PID : ".$thread_task[$a]->getPid());apc_store("watch_dhcp_ip_mac".($b+1), $thread_task[$a]->getPid());
			}
		}
	}
}
$a++;$thread_task[$a] = new Thread( 'thread_check_wan_status' );$thread_task[$a]->start();logme("THREAD $a thread_check_wan_status PID : ".$thread_task[$a]->getPid());apc_store("thread_check_wan_status", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'get_and_write_data_volume' );$thread_task[$a]->start();logme("THREAD $a get_and_write_data_volume PID : ".$thread_task[$a]->getPid());apc_store("get_and_write_data_volume", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'server_loop' );$thread_task[$a]->start();logme("THREAD $a server_loop PID : ".$thread_task[$a]->getPid());apc_store("server_loop", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'check_login_expire' );$thread_task[$a]->start();logme("THREAD $a check_login_expire PID : ".$thread_task[$a]->getPid());apc_store("check_login_expire", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'clean_discover_useless' );$thread_task[$a]->start();logme("THREAD $a clean_discover_useless PID : ".$thread_task[$a]->getPid());apc_store("clean_discover_useless", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_auto_clean_devices' );$thread_task[$a]->start();logme("THREAD $a thread_auto_clean_devices PID : ".$thread_task[$a]->getPid());apc_store("thread_auto_clean_devices", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'auto_disconnect_client' );$thread_task[$a]->start();logme("THREAD $a auto_disconnect_client PID : ".$thread_task[$a]->getPid());apc_store("auto_disconnect_client", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_check_bornes_status' );$thread_task[$a]->start();logme("THREAD $a thread_check_bornes_status PID : ".$thread_task[$a]->getPid());apc_store("thread_bornes_watcher", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_watch_bornes_on_m_network' );$thread_task[$a]->start();logme("THREAD $a thread_watch_bornes_on_m_network PID : ".$thread_task[$a]->getPid());apc_store("thread_watch_bornes_on_m_network", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_backup_to_ftp' );$thread_task[$a]->start();logme("THREAD $a thread_backup_to_ftp PID : ".$thread_task[$a]->getPid());apc_store("thread_backup_to_ftp", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_get_sys_infos' );$thread_task[$a]->start();logme("THREAD $a thread_get_sys_infos PID : ".$thread_task[$a]->getPid());apc_store("thread_get_sys_infos", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_auto_clean_data_volume_for_not_existing_mac' );$thread_task[$a]->start();logme("THREAD $a thread_auto_clean_data_volume_for_not_existing_mac PID : ".$thread_task[$a]->getPid());apc_store("thread_auto_clean_data_volume_for_not_existing_mac", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_auto_update_certs' );$thread_task[$a]->start();logme("THREAD $a thread_auto_update_certs PID : ".$thread_task[$a]->getPid());apc_store("thread_auto_update_certs", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_auto_reboot_ap' );$thread_task[$a]->start();logme("THREAD $a thread_auto_reboot_ap PID : ".$thread_task[$a]->getPid());apc_store("thread_auto_reboot_ap", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_iperf' );$thread_task[$a]->start();logme("THREAD $a thread_iperf PID : ".$thread_task[$a]->getPid());apc_store("thread_iperf", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_qos_check_filter' );$thread_task[$a]->start();logme("THREAD $a thread_qos_check_filter PID : ".$thread_task[$a]->getPid());apc_store("thread_qos_check_filter", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_get_actual_traffic' );$thread_task[$a]->start();logme("THREAD $a thread_get_actual_traffic PID : ".$thread_task[$a]->getPid());apc_store("thread_get_actual_traffic", $thread_task[$a]->getPid());
$a++;$thread_task[$a] = new Thread( 'thread_get_tplink_infos' );$thread_task[$a]->start();logme("THREAD $a thread_get_tplink_infos PID : ".$thread_task[$a]->getPid());apc_store("thread_get_tplink_infos", $thread_task[$a]->getPid());
//--------Gestion des signaux systèmes------------------------
pcntl_signal(SIGTERM, 'sig_handler'); 
pcntl_signal(SIGINT, 'sig_handler');
pcntl_signal(SIGCHLD, SIG_IGN);
//---------------------Debut du programme watchdog------------------------------
logme ("WatchDog activated ... ".count($thread_task)." threads started");
update_certs();
//-------------WATCHDOG--------------------
while (TRUE) {
	sleep (5);
	foreach ($thread_task AS $key => $value) {
		if (!$thread_task[$key]->isAlive()) {
			logme ("WATCHDOG : Task ".$key." Crash, reload task");
			if (isset($thread_task_arg[$key])) {
				$thread_task[$key]->start($thread_task_arg[$key]);
			}
			else {
				$thread_task[$key]->start();
			}
		}
		usleep(500000);
	}
}
?>