2012-05-16 16:26:19 +00:00
< ? php
2014-12-15 11:10:26 +00:00
/* Copyright ( C ) 2014 Daniel Preussker < f0o @ devilcode . org >
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2015-07-13 20:10:26 +02:00
*
2014-12-15 11:10:26 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2015-07-13 20:10:26 +02:00
*
2014-12-15 11:10:26 +00:00
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />. */
2012-05-16 16:26:19 +00:00
2015-07-13 20:10:26 +02:00
/*
2014-12-15 11:10:26 +00:00
* Alerts Tracking
* @ author Daniel Preussker < f0o @ devilcode . org >
* @ copyright 2014 f0o , LibreNMS
* @ license GPL
* @ package LibreNMS
* @ subpackage Alerts
2012-05-16 16:26:19 +00:00
*/
2016-06-22 08:42:48 +00:00
include_once ( $config [ 'install_dir' ] . '/includes/common.inc.php' );
2015-04-08 09:23:33 +00:00
include_once ( $config [ 'install_dir' ] . '/includes/device-groups.inc.php' );
include_once ( $config [ 'install_dir' ] . '/html/includes/authentication/' . $config [ 'auth_mechanism' ] . '.inc.php' );
2015-04-03 18:22:29 +00:00
2012-05-16 16:26:19 +00:00
/**
2014-12-15 11:10:26 +00:00
* Generate SQL from Rule
* @ param string $rule Rule to generate SQL for
2015-04-25 11:10:37 +00:00
* @ return string | boolean
2014-12-15 11:10:26 +00:00
*/
2016-08-28 12:32:58 -05:00
function GenSQL ( $rule )
{
2015-07-13 20:10:26 +02:00
$rule = RunMacros ( $rule );
2016-08-28 12:32:58 -05:00
if ( empty ( $rule )) {
2015-07-13 20:10:26 +02:00
//Cannot resolve Macros due to recursion. Rule is invalid.
return false ;
}
//Pretty-print rule to dissect easier
2016-03-02 17:08:45 +00:00
$pretty = array ( '*' => '*' , '(' => ' ( ' , ')' => ' ) ' , '/' => '/' , '&&' => ' && ' , '||' => ' || ' , 'DATE_SUB ( NOW ( )' => 'DATE_SUB( NOW()' );
2016-08-28 12:32:58 -05:00
$rule = str_replace ( array_keys ( $pretty ), $pretty , $rule );
$tmp = explode ( " " , $rule );
2015-07-13 20:10:26 +02:00
$tables = array ();
2016-08-28 12:32:58 -05:00
foreach ( $tmp as $opt ) {
if ( strstr ( $opt , '%' ) && strstr ( $opt , '.' )) {
$tmpp = explode ( " . " , $opt , 2 );
$tmpp [ 0 ] = str_replace ( " % " , " " , $tmpp [ 0 ]);
$tables [] = mres ( str_replace ( " ( " , " " , $tmpp [ 0 ]));
$rule = str_replace ( $opt , $tmpp [ 0 ] . '.' . $tmpp [ 1 ], $rule );
2015-07-13 20:10:26 +02:00
}
}
$tables = array_keys ( array_flip ( $tables ));
2016-08-28 12:32:58 -05:00
if ( dbFetchCell ( 'SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME = ?' , array ( $tables [ 0 ], 'device_id' )) != 1 ) {
2015-07-13 20:10:26 +02:00
//Our first table has no valid glue, append the 'devices' table to it!
array_unshift ( $tables , 'devices' );
}
$x = sizeof ( $tables ) - 1 ;
$i = 0 ;
$join = " " ;
2016-08-28 12:32:58 -05:00
while ( $i < $x ) {
if ( isset ( $tables [ $i + 1 ])) {
$gtmp = ResolveGlues ( array ( $tables [ $i + 1 ]), 'device_id' );
if ( $gtmp === false ) {
2015-11-30 19:13:32 +00:00
//Cannot resolve glue-chain. Rule is invalid.
return false ;
2015-07-13 20:10:26 +02:00
}
2015-11-30 19:13:32 +00:00
$last = " " ;
$qry = " " ;
2016-08-28 12:32:58 -05:00
foreach ( $gtmp as $glue ) {
if ( empty ( $last )) {
list ( $tmp , $last ) = explode ( '.' , $glue );
2015-11-30 19:13:32 +00:00
$qry .= $glue . ' = ' ;
2016-08-28 12:32:58 -05:00
} else {
list ( $tmp , $new ) = explode ( '.' , $glue );
2015-11-30 19:13:32 +00:00
$qry .= $tmp . '.' . $last . ' && ' . $tmp . '.' . $new . ' = ' ;
$last = $new ;
}
2016-08-28 12:32:58 -05:00
if ( ! in_array ( $tmp , $tables )) {
2015-11-30 19:13:32 +00:00
$tables [] = $tmp ;
2015-07-13 20:10:26 +02:00
}
}
2015-11-30 19:13:32 +00:00
$join .= " ( " . $qry . $tables [ 0 ] . " .device_id ) && " ;
2015-07-13 20:10:26 +02:00
}
$i ++ ;
}
2016-08-28 12:32:58 -05:00
$sql = " SELECT * FROM " . implode ( " , " , $tables ) . " WHERE ( " . $join . " " . str_replace ( " ( " , " " , $tables [ 0 ]) . " .device_id = ?) && ( " . str_replace ( array ( " % " , " @ " , " !~ " , " ~ " ), array ( " " , " .* " , " NOT REGEXP " , " REGEXP " ), $rule ) . " ) " ;
2015-07-13 20:10:26 +02:00
return $sql ;
2012-05-16 16:26:19 +00:00
}
2015-04-24 19:05:55 +00:00
/**
* Process Macros
* @ param string $rule Rule to process
2015-05-07 14:09:41 +00:00
* @ param int $x Recursion - Anchor
2015-04-25 11:10:37 +00:00
* @ return string | boolean
2015-04-24 19:05:55 +00:00
*/
2016-08-28 12:32:58 -05:00
function RunMacros ( $rule , $x = 1 )
{
2015-07-13 20:10:26 +02:00
global $config ;
krsort ( $config [ 'alert' ][ 'macros' ][ 'rule' ]);
2016-08-28 12:32:58 -05:00
foreach ( $config [ 'alert' ][ 'macros' ][ 'rule' ] as $macro => $value ) {
if ( ! strstr ( $macro , " " )) {
$rule = str_replace ( '%macros.' . $macro , '(' . $value . ')' , $rule );
2015-07-13 20:10:26 +02:00
}
}
2016-08-28 12:32:58 -05:00
if ( strstr ( $rule , " %macros " )) {
if ( ++ $x < 30 ) {
$rule = RunMacros ( $rule , $x );
} else {
2015-07-13 20:10:26 +02:00
return false ;
}
}
return $rule ;
2015-04-24 19:05:55 +00:00
}
2015-04-03 18:22:29 +00:00
/**
* Get Alert - Rules for Devices
* @ param int $device Device - ID
* @ return array
*/
2016-08-28 12:32:58 -05:00
function GetRules ( $device )
{
2015-07-13 20:10:26 +02:00
$groups = GetGroupsFromDevice ( $device );
$params = array ( $device , $device );
$where = " " ;
2016-08-28 12:32:58 -05:00
foreach ( $groups as $group ) {
2015-07-13 20:10:26 +02:00
$where .= " || alert_map.target = ? " ;
$params [] = 'g' . $group ;
}
2016-08-28 12:32:58 -05:00
return dbFetchRows ( 'SELECT alert_rules.* FROM alert_rules LEFT JOIN alert_map ON alert_rules.id=alert_map.rule WHERE alert_rules.disabled = 0 && ( (alert_rules.device_id = -1 || alert_rules.device_id = ? ) || alert_map.target = ? ' . $where . ' )' , $params );
2015-04-03 18:22:29 +00:00
}
2012-05-16 16:26:19 +00:00
2015-04-20 16:39:55 +00:00
/**
* Check if device is under maintenance
* @ param int $device Device - ID
2015-04-20 18:18:22 +00:00
* @ return int
2015-04-20 16:39:55 +00:00
*/
2016-08-28 12:32:58 -05:00
function IsMaintenance ( $device )
{
2015-07-13 20:10:26 +02:00
$groups = GetGroupsFromDevice ( $device );
$params = array ( $device );
$where = " " ;
2016-08-28 12:32:58 -05:00
foreach ( $groups as $group ) {
2015-07-13 20:10:26 +02:00
$where .= " || alert_schedule_items.target = ? " ;
$params [] = 'g' . $group ;
}
2016-08-28 12:32:58 -05:00
return dbFetchCell ( 'SELECT alert_schedule.schedule_id FROM alert_schedule LEFT JOIN alert_schedule_items ON alert_schedule.schedule_id=alert_schedule_items.schedule_id WHERE ( alert_schedule_items.target = ?' . $where . ' ) && NOW() BETWEEN alert_schedule.start AND alert_schedule.end LIMIT 1' , $params );
2015-04-20 16:39:55 +00:00
}
2012-05-16 16:26:19 +00:00
/**
2014-12-15 11:10:26 +00:00
* Run all rules for a device
* @ param int $device Device - ID
* @ return void
*/
2016-08-28 12:32:58 -05:00
function RunRules ( $device )
{
if ( IsMaintenance ( $device ) > 0 ) {
2015-07-13 20:10:26 +02:00
echo " Under Maintenance, Skipping alerts. \r \n " ;
return false ;
}
2016-08-28 12:32:58 -05:00
foreach ( GetRules ( $device ) as $rule ) {
2015-07-13 20:10:26 +02:00
echo " # " . $rule [ 'id' ] . " : " ;
2016-08-28 12:32:58 -05:00
$inv = json_decode ( $rule [ 'extra' ], true );
if ( isset ( $inv [ 'invert' ])) {
2015-07-13 20:10:26 +02:00
$inv = ( bool ) $inv [ 'invert' ];
2016-08-28 12:32:58 -05:00
} else {
2015-07-13 20:10:26 +02:00
$inv = false ;
}
$chk = dbFetchRow ( " SELECT state FROM alerts WHERE rule_id = ? && device_id = ? ORDER BY id DESC LIMIT 1 " , array ( $rule [ 'id' ], $device ));
$sql = GenSQL ( $rule [ 'rule' ]);
2016-08-28 12:32:58 -05:00
$qry = dbFetchRows ( $sql , array ( $device ));
2016-02-27 11:51:31 +00:00
if ( isset ( $qry [ 0 ][ 'ip' ])) {
$qry [ 0 ][ 'ip' ] = inet6_ntop ( $qry [ 0 ][ 'ip' ]);
}
2015-07-13 20:10:26 +02:00
$s = sizeof ( $qry );
2016-08-28 12:32:58 -05:00
if ( $s == 0 && $inv === false ) {
2015-07-13 20:10:26 +02:00
$doalert = false ;
2016-08-28 12:32:58 -05:00
} elseif ( $s > 0 && $inv === false ) {
2015-07-13 20:10:26 +02:00
$doalert = true ;
2016-08-28 12:32:58 -05:00
} elseif ( $s == 0 && $inv === true ) {
2015-07-13 20:10:26 +02:00
$doalert = true ;
2016-08-28 12:32:58 -05:00
} else { //( $s > 0 && $inv == false ) {
2015-07-13 20:10:26 +02:00
$doalert = false ;
}
2016-08-28 12:32:58 -05:00
if ( $doalert ) {
if ( $chk [ 'state' ] === " 2 " ) {
2015-07-13 20:10:26 +02:00
echo " SKIP " ;
2016-08-28 12:32:58 -05:00
} elseif ( $chk [ 'state' ] >= " 1 " ) {
2015-07-13 20:10:26 +02:00
echo " NOCHG " ;
2016-08-28 12:32:58 -05:00
} else {
$extra = gzcompress ( json_encode ( array ( 'contacts' => GetContacts ( $qry ), 'rule' => $qry )), 9 );
if ( dbInsert ( array ( 'state' => 1 , 'device_id' => $device , 'rule_id' => $rule [ 'id' ], 'details' => $extra ), 'alert_log' )) {
if ( ! dbUpdate ( array ( 'state' => 1 , 'open' => 1 ), 'alerts' , 'device_id = ? && rule_id = ?' , array ( $device , $rule [ 'id' ]))) {
dbInsert ( array ( 'state' => 1 , 'device_id' => $device , 'rule_id' => $rule [ 'id' ], 'open' => 1 , 'alerted' => 0 ), 'alerts' );
2015-07-13 20:10:26 +02:00
}
echo " ALERT " ;
}
}
2016-08-28 12:32:58 -05:00
} else {
if ( $chk [ 'state' ] === " 0 " ) {
2015-07-13 20:10:26 +02:00
echo " NOCHG " ;
2016-08-28 12:32:58 -05:00
} else {
if ( dbInsert ( array ( 'state' => 0 , 'device_id' => $device , 'rule_id' => $rule [ 'id' ]), 'alert_log' )) {
if ( ! dbUpdate ( array ( 'state' => 0 , 'open' => 1 ), 'alerts' , 'device_id = ? && rule_id = ?' , array ( $device , $rule [ 'id' ]))) {
dbInsert ( array ( 'state' => 0 , 'device_id' => $device , 'rule_id' => $rule [ 'id' ], 'open' => 1 , 'alerted' => 0 ), 'alerts' );
2015-07-13 20:10:26 +02:00
}
echo " OK " ;
}
}
}
}
2012-05-16 16:26:19 +00:00
}
/**
2014-12-15 11:10:26 +00:00
* Find contacts for alert
* @ param array $results Rule - Result
* @ return array
*/
2016-08-28 12:32:58 -05:00
function GetContacts ( $results )
{
2015-07-13 20:10:26 +02:00
global $config ;
2016-08-28 12:32:58 -05:00
if ( sizeof ( $results ) == 0 ) {
2015-07-13 20:10:26 +02:00
return array ();
}
2016-08-28 12:32:58 -05:00
if ( $config [ 'alert' ][ 'default_only' ] == true || $config [ 'alerts' ][ 'email' ][ 'default_only' ] == true ) {
2015-07-13 20:10:26 +02:00
return array ( '' . ( $config [ 'alert' ][ 'default_mail' ] ? $config [ 'alert' ][ 'default_mail' ] : $config [ 'alerts' ][ 'email' ][ 'default' ]) => 'NOC' );
}
$users = get_userlist ();
$contacts = array ();
$uids = array ();
2016-08-28 12:32:58 -05:00
foreach ( $results as $result ) {
$tmp = null ;
if ( is_numeric ( $result [ " bill_id " ])) {
$tmpa = dbFetchRows ( " SELECT user_id FROM bill_perms WHERE bill_id = ? " , array ( $result [ " bill_id " ]));
foreach ( $tmpa as $tmp ) {
2015-07-13 20:10:26 +02:00
$uids [ $tmp [ 'user_id' ]] = $tmp [ 'user_id' ];
}
}
2016-08-28 12:32:58 -05:00
if ( is_numeric ( $result [ " port_id " ])) {
$tmpa = dbFetchRows ( " SELECT user_id FROM ports_perms WHERE access_level >= 0 AND port_id = ? " , array ( $result [ " port_id " ]));
foreach ( $tmpa as $tmp ) {
2015-07-13 20:10:26 +02:00
$uids [ $tmp [ 'user_id' ]] = $tmp [ 'user_id' ];
}
}
2016-08-28 12:32:58 -05:00
if ( is_numeric ( $result [ " device_id " ])) {
if ( $config [ 'alert' ][ 'syscontact' ] == true ) {
if ( dbFetchCell ( " SELECT attrib_value FROM devices_attribs WHERE attrib_type = 'override_sysContact_bool' AND device_id = ? " , array ( $result [ " device_id " ])) === " 1 " ) {
$tmpa = dbFetchCell ( " SELECT attrib_value FROM devices_attribs WHERE attrib_type = 'override_sysContact_string' AND device_id = ? " , array ( $result [ " device_id " ]));
} else {
$tmpa = dbFetchCell ( " SELECT sysContact FROM devices WHERE device_id = ? " , array ( $result [ " device_id " ]));
2015-07-13 20:10:26 +02:00
}
$contacts [ $tmpa ] = " NOC " ;
}
$tmpa = dbFetchRows ( " SELECT user_id FROM devices_perms WHERE access_level >= 0 AND device_id = ? " , array ( $result [ " device_id " ]));
2016-08-28 12:32:58 -05:00
foreach ( $tmpa as $tmp ) {
2015-07-13 20:10:26 +02:00
$uids [ $tmp [ 'user_id' ]] = $tmp [ 'user_id' ];
}
}
}
2016-08-28 12:32:58 -05:00
foreach ( $users as $user ) {
if ( empty ( $user [ 'email' ])) {
2015-07-13 20:10:26 +02:00
continue ;
2016-08-28 12:32:58 -05:00
} elseif ( empty ( $user [ 'realname' ])) {
2015-07-13 20:10:26 +02:00
$user [ 'realname' ] = $user [ 'username' ];
}
$user [ 'level' ] = get_userlevel ( $user [ 'username' ]);
2016-08-28 12:32:58 -05:00
if ( $config [ " alert " ][ " globals " ] && ( $user [ 'level' ] >= 5 && $user [ 'level' ] < 10 )) {
2015-07-13 20:10:26 +02:00
$contacts [ $user [ 'email' ]] = $user [ 'realname' ];
2016-08-28 12:32:58 -05:00
} elseif ( $config [ " alert " ][ " admins " ] && $user [ 'level' ] == 10 ) {
2015-07-13 20:10:26 +02:00
$contacts [ $user [ 'email' ]] = $user [ 'realname' ];
2016-08-28 12:32:58 -05:00
} elseif ( in_array ( $user [ 'user_id' ], $uids )) {
2015-07-13 20:10:26 +02:00
$contacts [ $user [ 'email' ]] = $user [ 'realname' ];
}
}
2016-07-26 22:29:04 +01:00
$tmp_contacts = array ();
foreach ( $contacts as $email => $name ) {
if ( strstr ( $email , ',' )) {
$split_contacts = preg_split ( " /[, \ s]+/ " , $email );
foreach ( $split_contacts as $split_email ) {
2016-08-28 12:32:58 -05:00
if ( ! empty ( $split_email )) {
2016-07-28 20:28:23 +01:00
$tmp_contacts [ $split_email ] = $name ;
}
2016-07-26 22:29:04 +01:00
}
} else {
$tmp_contacts [ $email ] = $name ;
}
}
return $tmp_contacts ;
2012-05-16 16:26:19 +00:00
}