2009-09-07 11:07:59 +00:00
< ? php
2007-04-03 14:10:23 +00:00
2012-05-21 16:52:02 +00:00
/**
2016-09-08 13:12:23 +00:00
* LibreNMS
2012-05-21 16:52:02 +00:00
*
2016-09-08 13:12:23 +00:00
* This file is part of LibreNMS .
2012-05-21 16:52:02 +00:00
*
2016-09-08 13:12:23 +00:00
* @ package LibreNMS
2012-05-21 16:52:02 +00:00
* @ subpackage functions
* @ copyright ( C ) 2006 - 2012 Adam Armstrong
*
*/
2016-08-21 13:07:14 +00:00
use LibreNMS\Exceptions\HostExistsException ;
use LibreNMS\Exceptions\HostIpExistsException ;
use LibreNMS\Exceptions\HostUnreachableException ;
use LibreNMS\Exceptions\HostUnreachablePingException ;
use LibreNMS\Exceptions\InvalidPortAssocModeException ;
use LibreNMS\Exceptions\SnmpVersionUnsupportedException ;
2016-09-07 17:42:49 +00:00
function set_debug ( $debug )
{
if ( isset ( $debug )) {
ini_set ( 'display_errors' , 1 );
ini_set ( 'display_startup_errors' , 0 );
ini_set ( 'log_errors' , 0 );
ini_set ( 'allow_url_fopen' , 0 );
ini_set ( 'error_reporting' , E_ALL );
}
} //end set_debug()
2016-08-28 17:32:58 +00:00
function array_sort ( $array , $on , $order = SORT_ASC )
{
2012-05-25 10:34:01 +00:00
$new_array = array ();
$sortable_array = array ();
if ( count ( $array ) > 0 ) {
foreach ( $array as $k => $v ) {
if ( is_array ( $v )) {
foreach ( $v as $k2 => $v2 ) {
if ( $k2 == $on ) {
$sortable_array [ $k ] = $v2 ;
}
}
2016-08-28 17:32:58 +00:00
} else {
2012-05-25 10:34:01 +00:00
$sortable_array [ $k ] = $v ;
}
}
switch ( $order ) {
2016-08-28 17:32:58 +00:00
case SORT_ASC :
asort ( $sortable_array );
break ;
case SORT_DESC :
arsort ( $sortable_array );
break ;
2012-05-25 10:34:01 +00:00
}
foreach ( $sortable_array as $k => $v ) {
$new_array [ $k ] = $array [ $k ];
}
}
return $new_array ;
2012-04-08 16:21:52 +00:00
}
2016-08-28 17:32:58 +00:00
function mac_clean_to_readable ( $mac )
{
2017-02-12 13:20:06 +00:00
return rtrim ( chunk_split ( $mac , 2 , ':' ), ':' );
2009-05-03 22:32:01 +00:00
}
2016-08-28 17:32:58 +00:00
function only_alphanumeric ( $string )
{
2015-07-13 18:10:26 +00:00
return preg_replace ( '/[^a-zA-Z0-9]/' , '' , $string );
2009-04-23 21:13:56 +00:00
}
2016-08-28 17:32:58 +00:00
function logfile ( $string )
{
2015-07-13 18:10:26 +00:00
global $config ;
2011-09-16 10:31:48 +00:00
2016-08-28 17:32:58 +00:00
$fd = fopen ( $config [ 'log_file' ], 'a' );
fputs ( $fd , $string . " \n " );
2015-07-13 18:10:26 +00:00
fclose ( $fd );
2010-11-24 11:32:53 +00:00
}
2017-01-12 17:01:34 +00:00
/**
* Detect the os of the given device .
*
* @ param array $device device to check
* @ return string the name of the os
*/
2016-08-28 17:32:58 +00:00
function getHostOS ( $device )
{
2015-08-20 14:06:44 +00:00
global $config ;
2011-03-08 17:12:43 +00:00
2016-08-28 17:32:58 +00:00
$sysDescr = snmp_get ( $device , " SNMPv2-MIB::sysDescr.0 " , " -Ovq " );
$sysObjectId = snmp_get ( $device , " SNMPv2-MIB::sysObjectID.0 " , " -Ovqn " );
2010-08-11 00:40:07 +00:00
2016-09-13 21:16:02 +00:00
d_echo ( " | $sysDescr | $sysObjectId | \n " );
2010-07-11 20:12:24 +00:00
2017-01-11 22:22:16 +00:00
// check yaml files
2017-01-03 20:04:18 +00:00
$pattern = $config [ 'install_dir' ] . '/includes/definitions/*.yaml' ;
foreach ( glob ( $pattern ) as $file ) {
$tmp = Symfony\Component\Yaml\Yaml :: parse (
file_get_contents ( $file )
);
if ( isset ( $tmp [ 'discovery' ]) && is_array ( $tmp [ 'discovery' ])) {
foreach ( $tmp [ 'discovery' ] as $item ) {
2017-01-12 17:01:34 +00:00
// check each item individually, if all the conditions in that item are true, we have a match
if ( checkDiscovery ( $item , $sysObjectId , $sysDescr )) {
2017-01-03 20:04:18 +00:00
return $tmp [ 'os' ];
}
}
}
}
2017-01-11 22:22:16 +00:00
// check include files
$os = null ;
$pattern = $config [ 'install_dir' ] . '/includes/discovery/os/*.inc.php' ;
foreach ( glob ( $pattern ) as $file ) {
include $file ;
if ( isset ( $os )) {
return $os ;
}
}
2017-01-03 20:04:18 +00:00
return 'generic' ;
}
2011-03-08 17:12:43 +00:00
2017-01-12 17:01:34 +00:00
/**
* Check an array of conditions if all match , return true
* sysObjectId if sysObjectId starts with any of the values under this item
* sysDescr if sysDescr contains any of the values under this item
* sysDescr_regex if sysDescr matches any of the regexes under this item
*
* @ param array $array Array of items , keys should be sysObjectId , sysDescr , or sysDescr_regex
* @ param string $sysObjectId The sysObjectId to check against
* @ param string $sysDescr the sysDesr to check against
* @ return bool the result ( all items passed return true )
*/
function checkDiscovery ( $array , $sysObjectId , $sysDescr )
{
// all items must be true
foreach ( $array as $key => $value ) {
if ( $key == 'sysObjectId' ) {
if ( ! starts_with ( $sysObjectId , $value )) {
return false ;
}
} elseif ( $key == 'sysDescr' ) {
if ( ! str_contains ( $sysDescr , $value )) {
return false ;
}
} elseif ( $key == 'sysDescr_regex' ) {
if ( ! preg_match_any ( $sysDescr , $value )) {
return false ;
}
2017-02-04 10:02:05 +00:00
} elseif ( $key == 'sysObjectId_regex' ) {
if ( ! preg_match_any ( $sysObjectId , $value )) {
return false ;
}
2017-01-12 17:01:34 +00:00
}
}
return true ;
}
/**
* Check an array of regexes against a subject if any match , return true
*
* @ param string $subject the string to match against
* @ param array | string $regexes an array of regexes or single regex to check
* @ return bool if any of the regexes matched , return true
*/
2017-01-03 20:04:18 +00:00
function preg_match_any ( $subject , $regexes )
{
foreach (( array ) $regexes as $regex ) {
if ( preg_match ( $regex , $subject )) {
return true ;
}
}
return false ;
2008-03-12 11:15:58 +00:00
}
2016-08-28 17:32:58 +00:00
function percent_colour ( $perc )
{
2015-07-13 18:10:26 +00:00
$r = min ( 255 , 5 * ( $perc - 25 ));
$b = max ( 0 , 255 - ( 5 * ( $perc + 25 )));
2011-03-27 10:21:19 +00:00
2015-07-13 18:10:26 +00:00
return sprintf ( '#%02x%02x%02x' , $r , $b , $b );
2011-03-08 17:12:43 +00:00
}
2007-06-24 14:56:47 +00:00
2015-07-13 18:10:26 +00:00
// Returns the last in/out errors value in RRD
2016-08-28 17:32:58 +00:00
function interface_errors ( $rrd_file , $period = '-1d' )
{
2015-07-13 18:10:26 +00:00
global $config ;
$errors = array ();
$cmd = $config [ 'rrdtool' ] . " fetch -s $period -e -300s $rrd_file AVERAGE | grep : | cut -d \" \" -f 4,5 " ;
$data = trim ( shell_exec ( $cmd ));
$in_errors = 0 ;
$out_errors = 0 ;
foreach ( explode ( " \n " , $data ) as $entry ) {
list ( $in , $out ) = explode ( " " , $entry );
$in_errors += ( $in * 300 );
$out_errors += ( $out * 300 );
}
$errors [ 'in' ] = round ( $in_errors );
$errors [ 'out' ] = round ( $out_errors );
2007-04-03 14:10:23 +00:00
2015-07-13 18:10:26 +00:00
return $errors ;
2007-04-03 14:10:23 +00:00
}
2017-01-24 22:16:01 +00:00
/**
* @ param $device
* @ return string the logo image path for this device . Images are often wide , not square .
*/
function getLogo ( $device )
{
$img = getImageName ( $device , true , 'images/logos/' );
if ( ! starts_with ( $img , 'generic' )) {
return 'images/logos/' . $img ;
}
return getIcon ( $device );
}
/**
2017-02-24 09:59:30 +00:00
* @ param array $device
* @ param string $class to apply to the image tag
2017-01-24 22:16:01 +00:00
* @ return string an image tag with the logo for this device . Images are often wide , not square .
*/
2017-02-24 09:59:30 +00:00
function getLogoTag ( $device , $class = null )
2016-08-28 17:32:58 +00:00
{
2017-02-24 09:59:30 +00:00
$tag = '<img src="' . getLogo ( $device ) . '" title="' . getImageTitle ( $device ) . '"' ;
if ( isset ( $class )) {
$tag .= " class= \" $class\ " " ;
}
$tag .= ' />' ;
return $tag ;
2014-01-13 10:05:19 +00:00
}
2017-01-24 22:16:01 +00:00
/**
* @ param $device
* @ return string the path to the icon image for this device . Close to square .
*/
function getIcon ( $device )
2016-08-28 17:32:58 +00:00
{
2017-01-08 19:32:17 +00:00
return 'images/os/' . getImageName ( $device );
2016-02-24 05:44:51 +00:00
}
2017-01-24 22:16:01 +00:00
/**
* @ param $device
* @ return string an image tag with the icon for this device . Close to square .
*/
function getIconTag ( $device )
{
return '<img src="' . getIcon ( $device ) . '" title="' . getImageTitle ( $device ) . '"/>' ;
}
2017-01-24 23:36:33 +00:00
function getImageTitle ( $device )
{
2017-01-24 22:16:01 +00:00
return $device [ 'icon' ] ? str_replace ( array ( '.svg' , '.png' ), '' , $device [ 'icon' ]) : $device [ 'os' ];
}
function getImageName ( $device , $use_database = true , $dir = 'images/os/' )
2016-08-28 17:32:58 +00:00
{
2015-07-13 18:10:26 +00:00
global $config ;
2017-01-24 22:16:01 +00:00
$os = strtolower ( $device [ 'os' ]);
2015-07-13 18:10:26 +00:00
2016-02-24 05:44:51 +00:00
// fetch from the database
2017-01-24 22:16:01 +00:00
if ( $use_database && is_file ( $config [ 'html_dir' ] . " / $dir " . $device [ 'icon' ])) {
2016-02-24 05:44:51 +00:00
return $device [ 'icon' ];
2015-07-13 18:10:26 +00:00
}
2016-02-24 05:44:51 +00:00
// linux specific handling, distro icons
2017-01-08 19:32:17 +00:00
$distro = null ;
2017-01-24 22:16:01 +00:00
if ( $os == " linux " ) {
2016-02-24 05:44:51 +00:00
$features = strtolower ( trim ( $device [ 'features' ]));
list ( $distro ) = explode ( " " , $features );
2015-07-13 18:10:26 +00:00
}
2017-01-08 19:32:17 +00:00
$possibilities = array (
$distro ,
2017-01-24 22:16:01 +00:00
$config [ 'os' ][ $os ][ 'icon' ],
$os ,
2017-01-08 19:32:17 +00:00
);
foreach ( $possibilities as $basename ) {
2017-01-14 22:14:33 +00:00
foreach ( array ( '.svg' , '.png' ) as $ext ) {
$name = $basename . $ext ;
2017-01-24 22:16:01 +00:00
if ( is_file ( $config [ 'html_dir' ] . " / $dir " . $name )) {
2017-01-08 19:32:17 +00:00
return $name ;
}
}
2016-02-24 05:44:51 +00:00
}
// fallback to the generic icon
2017-01-28 10:13:55 +00:00
return 'generic.svg' ;
2008-11-19 12:12:54 +00:00
}
2016-08-28 17:32:58 +00:00
function renamehost ( $id , $new , $source = 'console' )
{
2015-07-13 18:10:26 +00:00
global $config ;
$host = dbFetchCell ( " SELECT `hostname` FROM `devices` WHERE `device_id` = ? " , array ( $id ));
2016-08-28 17:32:58 +00:00
if ( ! is_dir ( $config [ 'rrd_dir' ] . " / $new " ) && rename ( $config [ 'rrd_dir' ] . " / $host " , $config [ 'rrd_dir' ] . " / $new " ) === true ) {
2015-07-13 18:10:26 +00:00
dbUpdate ( array ( 'hostname' => $new ), 'devices' , 'device_id=?' , array ( $id ));
2017-02-12 22:41:05 +00:00
log_event ( " Hostname changed -> $new ( $source ) " , $id , 'system' , 3 );
2016-07-07 06:33:43 +00:00
} else {
2017-02-12 22:41:05 +00:00
log_event ( " Renaming of $host failed " , $id , 'system' , 5 );
2016-11-13 00:19:22 +00:00
if ( __FILE__ === $_SERVER [ 'SCRIPT_FILE_NAME' ]) {
echo " Renaming of $host failed \n " ;
} else {
return " Renaming of $host failed \n " ;
}
2015-07-13 18:10:26 +00:00
}
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function delete_device ( $id )
{
2015-07-13 18:10:26 +00:00
global $config , $debug ;
2017-02-01 20:17:35 +00:00
if ( isCli () === false ) {
ignore_user_abort ( true );
set_time_limit ( 0 );
}
2015-07-13 18:10:26 +00:00
$ret = '' ;
$host = dbFetchCell ( " SELECT hostname FROM devices WHERE device_id = ? " , array ( $id ));
2016-08-28 17:32:58 +00:00
if ( empty ( $host )) {
2015-07-13 18:10:26 +00:00
return " No such host. " ;
}
// Remove IPv4/IPv6 addresses before removing ports as they depend on port_id
2016-08-28 17:32:58 +00:00
dbQuery ( " DELETE `ipv4_addresses` FROM `ipv4_addresses` INNER JOIN `ports` ON `ports`.`port_id`=`ipv4_addresses`.`port_id` WHERE `device_id`=? " , array ( $id ));
dbQuery ( " DELETE `ipv6_addresses` FROM `ipv6_addresses` INNER JOIN `ports` ON `ports`.`port_id`=`ipv6_addresses`.`port_id` WHERE `device_id`=? " , array ( $id ));
2015-07-13 18:10:26 +00:00
foreach ( dbFetch ( " SELECT * FROM `ports` WHERE `device_id` = ? " , array ( $id )) as $int_data ) {
$int_if = $int_data [ 'ifDescr' ];
$int_id = $int_data [ 'port_id' ];
delete_port ( $int_id );
$ret .= " Removed interface $int_id ( $int_if ) \n " ;
}
2017-02-23 23:03:07 +00:00
// Remove sensors manually due to constraints
foreach ( dbFetchRows ( " SELECT * FROM `sensors` WHERE `device_id` = ? " , array ( $id )) as $sensor ) {
$sensor_id = $sensor [ 'sensor_id' ];
dbDelete ( 'sensors_to_state_indexes' , " `sensor_id` = ? " , array ( $sensor ));
}
2015-07-13 18:10:26 +00:00
$fields = array ( 'device_id' , 'host' );
2016-08-28 17:32:58 +00:00
foreach ( $fields as $field ) {
foreach ( dbFetch ( " SELECT table_name FROM information_schema.columns WHERE table_schema = ? AND column_name = ? " , array ( $config [ 'db_name' ], $field )) as $table ) {
2015-07-13 18:10:26 +00:00
$table = $table [ 'table_name' ];
$entries = ( int ) dbDelete ( $table , " ` $field ` = ? " , array ( $id ));
2016-08-28 17:32:58 +00:00
if ( $entries > 0 && $debug === true ) {
2015-07-13 18:10:26 +00:00
$ret .= " $field @ $table = # $entries\n " ;
2012-05-20 23:19:28 +00:00
}
2012-05-09 16:18:23 +00:00
}
2015-07-13 18:10:26 +00:00
}
$ex = shell_exec ( " bash -c '( [ ! -d " . trim ( $config [ 'rrd_dir' ]) . " / " . $host . " ] || rm -vrf " . trim ( $config [ 'rrd_dir' ]) . " / " . $host . " 2>&1 ) && echo -n OK' " );
2016-08-28 17:32:58 +00:00
$tmp = explode ( " \n " , $ex );
if ( $tmp [ sizeof ( $tmp ) - 1 ] != " OK " ) {
2015-07-13 18:10:26 +00:00
$ret .= " Could not remove files: \n $ex\n " ;
}
$ret .= " Removed device $host\n " ;
2017-02-12 22:41:05 +00:00
log_event ( " Device $host has been removed " , 0 , 'system' , 3 );
2015-07-13 18:10:26 +00:00
return $ret ;
}
2016-08-02 03:01:01 +00:00
/**
* Add a device to LibreNMS
*
* @ param string $host dns name or ip address
* @ param string $snmp_version If this is empty , try v2c , v3 , v1 . Otherwise , use this specific version .
* @ param string $port the port to connect to for snmp
* @ param string $transport udp or tcp
* @ param string $poller_group the poller group this device will belong to
2016-08-09 20:00:12 +00:00
* @ param boolean $force_add add even if the device isn ' t reachable
2016-08-02 03:01:01 +00:00
* @ param string $port_assoc_mode snmp field to use to determine unique ports
2016-08-07 17:16:40 +00:00
*
* @ return int returns the device_id of the added device
*
* @ throws HostExistsException This hostname already exists
* @ throws HostIpExistsException We already have a host with this IP
* @ throws HostUnreachableException We could not reach this device is some way
* @ throws HostUnreachablePingException We could not ping the device
* @ throws InvalidPortAssocModeException The given port association mode was invalid
* @ throws SnmpVersionUnsupportedException The given snmp version was invalid
2016-08-02 03:01:01 +00:00
*/
2016-08-28 17:32:58 +00:00
function addHost ( $host , $snmp_version = '' , $port = '161' , $transport = 'udp' , $poller_group = '0' , $force_add = false , $port_assoc_mode = 'ifIndex' )
{
2015-07-13 18:10:26 +00:00
global $config ;
2012-05-09 16:18:23 +00:00
2015-07-13 18:10:26 +00:00
// Test Database Exists
2016-08-02 03:01:01 +00:00
if ( host_exists ( $host ) === true ) {
2016-08-07 17:16:40 +00:00
throw new HostExistsException ( " Already have host $host " );
2016-08-02 03:01:01 +00:00
}
2016-01-21 21:05:11 +00:00
2016-08-02 03:01:01 +00:00
// Valid port assoc mode
if ( ! is_valid_port_assoc_mode ( $port_assoc_mode )) {
2016-08-07 17:16:40 +00:00
throw new InvalidPortAssocModeException ( " Invalid port association_mode ' $port_assoc_mode '. Valid modes are: " . join ( ', ' , get_port_assoc_modes ()));
2016-08-02 03:01:01 +00:00
}
2015-07-13 18:10:26 +00:00
2016-08-02 03:01:01 +00:00
// check if we have the host by IP
if ( $config [ 'addhost_alwayscheckip' ] === true ) {
$ip = gethostbyname ( $host );
} else {
$ip = $host ;
}
2016-10-13 21:21:02 +00:00
if ( $force_add !== true && ip_exists ( $ip )) {
2016-08-07 17:16:40 +00:00
throw new HostIpExistsException ( " Already have host with this IP $host " );
2016-08-02 03:01:01 +00:00
}
// Test reachability
2016-08-09 20:00:12 +00:00
if ( ! $force_add ) {
$address_family = snmpTransportToAddressFamily ( $transport );
$ping_result = isPingable ( $host , $address_family );
if ( ! $ping_result [ 'result' ]) {
throw new HostUnreachablePingException ( " Could not ping $host " );
}
2016-08-02 03:01:01 +00:00
}
2015-07-13 18:10:26 +00:00
2016-08-02 03:01:01 +00:00
// if $snmpver isn't set, try each version of snmp
if ( empty ( $snmp_version )) {
$snmpvers = array ( 'v2c' , 'v3' , 'v1' );
} else {
$snmpvers = array ( $snmp_version );
}
2016-08-07 17:16:40 +00:00
$host_unreachable_exception = new HostUnreachableException ( " Could not connect, please check the snmp details and snmp reachability " );
2016-08-02 03:01:01 +00:00
// try different snmp variables to add the device
foreach ( $snmpvers as $snmpver ) {
if ( $snmpver === " v3 " ) {
// Try each set of parameters from config
foreach ( $config [ 'snmp' ][ 'v3' ] as $v3 ) {
$device = deviceArray ( $host , null , $snmpver , $port , $transport , $v3 , $port_assoc_mode );
2016-09-16 08:40:00 +00:00
if ( $force_add === true || isSNMPable ( $device )) {
if ( $force_add !== true ) {
$snmphost = snmp_get ( $device , " sysName.0 " , " -Oqv " , " SNMPv2-MIB " );
}
$result = createHost ( $host , null , $snmpver , $port , $transport , $v3 , $poller_group , $port_assoc_mode , $snmphost , $force_add );
2016-08-02 03:01:01 +00:00
if ( $result !== false ) {
return $result ;
2015-07-13 18:10:26 +00:00
}
2016-08-02 03:01:01 +00:00
} else {
2016-08-07 17:16:40 +00:00
$host_unreachable_exception -> addReason ( " SNMP $snmpver : No reply with credentials " . $v3 [ 'authname' ] . " / " . $v3 [ 'authlevel' ]);
2015-07-13 18:10:26 +00:00
}
2011-09-08 12:24:18 +00:00
}
2016-08-02 03:01:01 +00:00
} elseif ( $snmpver === " v2c " || $snmpver === " v1 " ) {
// try each community from config
foreach ( $config [ 'snmp' ][ 'community' ] as $community ) {
$device = deviceArray ( $host , $community , $snmpver , $port , $transport , null , $port_assoc_mode );
2016-08-07 17:16:40 +00:00
2016-09-16 08:40:00 +00:00
if ( $force_add === true || isSNMPable ( $device )) {
if ( $force_add !== true ) {
$snmphost = snmp_get ( $device , " sysName.0 " , " -Oqv " , " SNMPv2-MIB " );
}
$result = createHost ( $host , $community , $snmpver , $port , $transport , array (), $poller_group , $port_assoc_mode , $snmphost , $force_add );
2016-08-02 03:01:01 +00:00
if ( $result !== false ) {
return $result ;
}
} else {
2016-08-07 17:16:40 +00:00
$host_unreachable_exception -> addReason ( " SNMP $snmpver : No reply with community $community " );
2015-07-13 18:10:26 +00:00
}
2012-05-09 16:18:23 +00:00
}
2016-08-02 03:01:01 +00:00
} else {
2016-08-07 17:16:40 +00:00
throw new SnmpVersionUnsupportedException ( " Unsupported SNMP Version \" $snmpver\ " , must be v1 , v2c , or v3 " );
2015-06-11 18:34:11 +00:00
}
}
2012-05-20 23:19:28 +00:00
2016-08-07 17:16:40 +00:00
throw $host_unreachable_exception ;
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function deviceArray ( $host , $community , $snmpver , $port = 161 , $transport = 'udp' , $v3 = array (), $port_assoc_mode = 'ifIndex' )
{
2015-07-13 18:10:26 +00:00
$device = array ();
$device [ 'hostname' ] = $host ;
$device [ 'port' ] = $port ;
$device [ 'transport' ] = $transport ;
2016-01-21 21:05:11 +00:00
/* Get port_assoc_mode id if neccessary
* We can work with names of IDs here */
2016-08-28 17:32:58 +00:00
if ( ! is_int ( $port_assoc_mode )) {
$port_assoc_mode = get_port_assoc_mode_id ( $port_assoc_mode );
}
2016-01-21 21:05:11 +00:00
$device [ 'port_association_mode' ] = $port_assoc_mode ;
2015-07-13 18:10:26 +00:00
$device [ 'snmpver' ] = $snmpver ;
if ( $snmpver === " v2c " or $snmpver === " v1 " ) {
$device [ 'community' ] = $community ;
2016-08-28 17:32:58 +00:00
} elseif ( $snmpver === " v3 " ) {
2015-07-13 18:10:26 +00:00
$device [ 'authlevel' ] = $v3 [ 'authlevel' ];
$device [ 'authname' ] = $v3 [ 'authname' ];
$device [ 'authpass' ] = $v3 [ 'authpass' ];
$device [ 'authalgo' ] = $v3 [ 'authalgo' ];
$device [ 'cryptopass' ] = $v3 [ 'cryptopass' ];
$device [ 'cryptoalgo' ] = $v3 [ 'cryptoalgo' ];
}
return $device ;
2011-03-15 16:12:44 +00:00
}
2016-08-28 17:32:58 +00:00
function netmask2cidr ( $netmask )
{
2015-07-13 18:10:26 +00:00
$addr = Net_IPv4 :: parseAddress ( " 1.2.3.4/ $netmask " );
return $addr -> bitmask ;
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function cidr2netmask ( $netmask )
{
2015-07-13 18:10:26 +00:00
return ( long2ip ( ip2long ( " 255.255.255.255 " ) << ( 32 - $netmask )));
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function formatUptime ( $diff , $format = " long " )
{
2015-07-13 18:10:26 +00:00
$yearsDiff = floor ( $diff / 31536000 );
$diff -= $yearsDiff * 31536000 ;
$daysDiff = floor ( $diff / 86400 );
$diff -= $daysDiff * 86400 ;
$hrsDiff = floor ( $diff / 60 / 60 );
$diff -= $hrsDiff * 60 * 60 ;
$minsDiff = floor ( $diff / 60 );
$diff -= $minsDiff * 60 ;
$secsDiff = $diff ;
$uptime = " " ;
if ( $format == " short " ) {
if ( $yearsDiff > '0' ) {
$uptime .= $yearsDiff . " y " ;
}
if ( $daysDiff > '0' ) {
$uptime .= $daysDiff . " d " ;
}
if ( $hrsDiff > '0' ) {
$uptime .= $hrsDiff . " h " ;
}
if ( $minsDiff > '0' ) {
$uptime .= $minsDiff . " m " ;
}
if ( $secsDiff > '0' ) {
$uptime .= $secsDiff . " s " ;
}
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
if ( $yearsDiff > '0' ) {
$uptime .= $yearsDiff . " years, " ;
}
if ( $daysDiff > '0' ) {
$uptime .= $daysDiff . " day " . ( $daysDiff != 1 ? 's' : '' ) . " , " ;
}
if ( $hrsDiff > '0' ) {
$uptime .= $hrsDiff . " h " ;
}
if ( $minsDiff > '0' ) {
$uptime .= $minsDiff . " m " ;
}
if ( $secsDiff > '0' ) {
$uptime .= $secsDiff . " s " ;
}
}
return trim ( $uptime );
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function isSNMPable ( $device )
{
2015-07-13 18:10:26 +00:00
global $config ;
2017-02-23 22:47:18 +00:00
$pos = snmp_check ( $device );
if ( $pos === true ) {
2015-07-13 18:10:26 +00:00
return true ;
2017-02-23 22:47:18 +00:00
} else {
$pos = snmp_get ( $device , " sysObjectID.0 " , " -Oqv " , " SNMPv2-MIB " );
if ( $pos === '' || $pos === false ) {
return false ;
} else {
return true ;
}
2015-07-13 18:10:26 +00:00
}
2007-04-03 14:10:23 +00:00
}
2015-09-24 00:07:15 +00:00
/**
* Check if the given host responds to ICMP echo requests ( " pings " ) .
*
* @ param string $hostname The hostname or IP address to send ping requests to .
* @ param int $address_family The address family ( AF_INET for IPv4 or AF_INET6 for IPv6 ) to use . Defaults to IPv4 . Will * not * be autodetected for IP addresses , so it has to be set to AF_INET6 when pinging an IPv6 address or an IPv6 - only host .
2015-10-17 19:11:21 +00:00
* @ param array $attribs The device attributes
2015-09-24 00:07:15 +00:00
*
2016-08-02 03:01:01 +00:00
* @ return array 'result' => bool pingable , 'last_ping_timetaken' => int time for last ping , 'db' => fping results
2015-09-24 00:07:15 +00:00
*/
2016-08-28 17:32:58 +00:00
function isPingable ( $hostname , $address_family = AF_INET , $attribs = array ())
{
2015-07-13 18:10:26 +00:00
global $config ;
2015-10-13 22:46:36 +00:00
$response = array ();
2015-10-17 18:49:01 +00:00
if ( can_ping_device ( $attribs ) === true ) {
2015-10-07 21:19:27 +00:00
$fping_params = '' ;
2016-08-28 17:32:58 +00:00
if ( is_numeric ( $config [ 'fping_options' ][ 'retries' ]) || $config [ 'fping_options' ][ 'retries' ] > 1 ) {
2015-10-07 21:19:27 +00:00
$fping_params .= ' -r ' . $config [ 'fping_options' ][ 'retries' ];
}
2016-08-28 17:32:58 +00:00
if ( is_numeric ( $config [ 'fping_options' ][ 'timeout' ]) || $config [ 'fping_options' ][ 'timeout' ] > 1 ) {
2015-10-07 21:19:27 +00:00
$fping_params .= ' -t ' . $config [ 'fping_options' ][ 'timeout' ];
}
2016-08-28 17:32:58 +00:00
if ( is_numeric ( $config [ 'fping_options' ][ 'count' ]) || $config [ 'fping_options' ][ 'count' ] > 0 ) {
2015-10-07 21:19:27 +00:00
$fping_params .= ' -c ' . $config [ 'fping_options' ][ 'count' ];
}
2016-08-28 17:32:58 +00:00
if ( is_numeric ( $config [ 'fping_options' ][ 'millisec' ]) || $config [ 'fping_options' ][ 'millisec' ] > 0 ) {
2015-10-07 21:19:27 +00:00
$fping_params .= ' -p ' . $config [ 'fping_options' ][ 'millisec' ];
}
2016-08-28 17:32:58 +00:00
$status = fping ( $hostname , $fping_params , $address_family );
2015-10-07 21:19:27 +00:00
if ( $status [ 'loss' ] == 100 ) {
2016-08-28 17:32:58 +00:00
$response [ 'result' ] = false ;
} else {
$response [ 'result' ] = true ;
2015-10-07 21:19:27 +00:00
}
if ( is_numeric ( $status [ 'avg' ])) {
$response [ 'last_ping_timetaken' ] = $status [ 'avg' ];
}
$response [ 'db' ] = $status ;
2016-08-28 17:32:58 +00:00
} else {
2015-10-07 21:19:27 +00:00
$response [ 'result' ] = true ;
$response [ 'last_ping_timetaken' ] = 0 ;
2015-07-13 18:10:26 +00:00
}
return ( $response );
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function getpollergroup ( $poller_group = '0' )
{
2015-07-13 18:10:26 +00:00
//Is poller group an integer
if ( is_int ( $poller_group ) || ctype_digit ( $poller_group )) {
return $poller_group ;
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
//Check if it contains a comma
2016-08-28 17:32:58 +00:00
if ( strpos ( $poller_group , ',' ) !== false ) {
2015-07-13 18:10:26 +00:00
//If it has a comma use the first element as the poller group
2016-08-28 17:32:58 +00:00
$poller_group_array = explode ( ',' , $poller_group );
2015-07-13 18:10:26 +00:00
return getpollergroup ( $poller_group_array [ 0 ]);
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
if ( $config [ 'distributed_poller_group' ]) {
//If not use the poller's group from the config
return getpollergroup ( $config [ 'distributed_poller_group' ]);
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
//If all else fails use default
return '0' ;
}
}
}
2015-06-22 10:37:00 +00:00
}
2017-02-22 09:12:31 +00:00
/**
* Add a host to the database
*
* @ param string $host The IP or hostname to add
* @ param string $community The snmp community
* @ param string $snmpver snmp version : v1 | v2c | v3
* @ param int $port SNMP port number
* @ param string $transport SNMP transport : udp | udp6 | udp | tcp6
* @ param array $v3 SNMPv3 settings required array keys : authlevel , authname , authpass , authalgo , cryptopass , cryptoalgo
* @ param int $poller_group distributed poller group to assign this host to
* @ param string $port_assoc_mode field to use to identify ports : ifIndex , ifName , ifDescr , ifAlias
* @ param string $snmphost device sysName to check for duplicates
* @ param bool $force_add Do not detect the host os
* @ return int the id of the added host
* @ throws HostExistsException Throws this exception if the host already exists
* @ throws Exception Throws this exception if insertion into the database fails
*/
function createHost (
$host ,
$community ,
$snmpver ,
$port = 161 ,
$transport = 'udp' ,
$v3 = array (),
$poller_group = 0 ,
$port_assoc_mode = 'ifIndex' ,
$snmphost = '' ,
$force_add = false
) {
2015-07-13 18:10:26 +00:00
$host = trim ( strtolower ( $host ));
$poller_group = getpollergroup ( $poller_group );
2016-08-02 03:01:01 +00:00
/* Get port_assoc_mode id if necessary
2016-02-26 14:04:38 +00:00
* We can work with names of IDs here */
2016-08-28 17:32:58 +00:00
if ( ! is_int ( $port_assoc_mode )) {
$port_assoc_mode = get_port_assoc_mode_id ( $port_assoc_mode );
}
2016-02-26 14:04:38 +00:00
2017-02-22 09:12:31 +00:00
$device = array (
'hostname' => $host ,
2015-07-13 18:10:26 +00:00
'sysName' => $host ,
2017-02-22 09:12:31 +00:00
'os' => 'generic' ,
2015-07-13 18:10:26 +00:00
'community' => $community ,
'port' => $port ,
'transport' => $transport ,
'status' => '1' ,
'snmpver' => $snmpver ,
2015-08-11 11:38:05 +00:00
'poller_group' => $poller_group ,
'status_reason' => '' ,
2016-01-21 21:05:11 +00:00
'port_association_mode' => $port_assoc_mode ,
2015-07-13 18:10:26 +00:00
);
2012-05-09 16:18:23 +00:00
2017-02-22 09:12:31 +00:00
$device = array_merge ( $device , $v3 ); // merge v3 settings
2011-09-14 17:26:59 +00:00
2016-09-16 08:40:00 +00:00
if ( $force_add !== true ) {
$device [ 'os' ] = getHostOS ( $device );
}
2011-03-15 16:12:44 +00:00
2017-02-22 09:12:31 +00:00
if ( host_exists ( $host , $snmphost )) {
throw new HostExistsException ( " Already have host $host ( $snmphost ) " );
2010-02-07 22:39:02 +00:00
}
2016-08-02 03:01:01 +00:00
2017-02-22 09:12:31 +00:00
$device_id = dbInsert ( $device , 'devices' );
if ( $device_id ) {
oxidized_reload_nodes ();
return $device_id ;
}
throw new \Exception ( " Failed to add host to the database, please run ./validate.php " );
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function isDomainResolves ( $domain )
{
2017-01-24 21:56:51 +00:00
if ( gethostbyname ( $domain ) != $domain ) {
return true ;
}
$records = dns_get_record ( $domain ); // returns array or false
return ! empty ( $records );
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function hoststatus ( $id )
{
2015-07-13 18:10:26 +00:00
return dbFetchCell ( " SELECT `status` FROM `devices` WHERE `device_id` = ? " , array ( $id ));
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function match_network ( $nets , $ip , $first = false )
{
2015-07-13 18:10:26 +00:00
$return = false ;
2016-08-28 17:32:58 +00:00
if ( ! is_array ( $nets )) {
$nets = array ( $nets );
}
2015-07-13 18:10:26 +00:00
foreach ( $nets as $net ) {
2016-08-28 17:32:58 +00:00
$rev = ( preg_match ( " /^ \ !/ " , $net )) ? true : false ;
$net = preg_replace ( " /^ \ !/ " , " " , $net );
2015-07-13 18:10:26 +00:00
$ip_arr = explode ( '/' , $net );
$net_long = ip2long ( $ip_arr [ 0 ]);
$x = ip2long ( $ip_arr [ 1 ]);
$mask = long2ip ( $x ) == $ip_arr [ 1 ] ? $x : 0xffffffff << ( 32 - $ip_arr [ 1 ]);
$ip_long = ip2long ( $ip );
if ( $rev ) {
if (( $ip_long & $mask ) == ( $net_long & $mask )) {
return false ;
}
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
if (( $ip_long & $mask ) == ( $net_long & $mask )) {
$return = true ;
}
if ( $first && $return ) {
return true ;
}
}
}
return $return ;
2007-04-03 14:10:23 +00:00
}
2016-08-28 17:32:58 +00:00
function snmp2ipv6 ( $ipv6_snmp )
{
$ipv6 = explode ( '.' , $ipv6_snmp );
2015-07-13 18:10:26 +00:00
$ipv6_2 = array ();
2011-04-21 17:11:58 +00:00
2015-07-13 18:10:26 +00:00
# Workaround stupid Microsoft bug in Windows 2008 -- this is fixed length!
# < fenestro> "because whoever implemented this mib for Microsoft was ignorant of RFC 2578 section 7.7 (2)"
if ( count ( $ipv6 ) == 17 && $ipv6 [ 0 ] == 16 ) {
array_shift ( $ipv6 );
}
2011-04-21 17:11:58 +00:00
2016-08-28 17:32:58 +00:00
for ( $i = 0 ; $i <= 15 ; $i ++ ) {
2015-07-13 18:10:26 +00:00
$ipv6 [ $i ] = zeropad ( dechex ( $ipv6 [ $i ]));
}
2016-08-28 17:32:58 +00:00
for ( $i = 0 ; $i <= 15 ; $i += 2 ) {
2015-07-13 18:10:26 +00:00
$ipv6_2 [] = $ipv6 [ $i ] . $ipv6 [ $i + 1 ];
}
2011-03-08 17:12:43 +00:00
2016-08-28 17:32:58 +00:00
return implode ( ':' , $ipv6_2 );
2010-01-01 14:09:57 +00:00
}
2016-08-28 17:32:58 +00:00
function ipv62snmp ( $ipv6 )
{
2015-07-13 18:10:26 +00:00
$ipv6_split = array ();
2016-08-28 17:32:58 +00:00
$ipv6_ex = explode ( ':' , Net_IPv6 :: uncompress ( $ipv6 ));
for ( $i = 0 ; $i < 8 ; $i ++ ) {
$ipv6_ex [ $i ] = zeropad ( $ipv6_ex [ $i ], 4 );
}
$ipv6_ip = implode ( '' , $ipv6_ex );
for ( $i = 0 ; $i < 32 ;
$i += 2 ) {
$ipv6_split [] = hexdec ( substr ( $ipv6_ip , $i , 2 ));
2015-07-13 18:10:26 +00:00
}
2011-03-08 17:12:43 +00:00
2016-08-28 17:32:58 +00:00
return implode ( '.' , $ipv6_split );
2010-01-01 14:09:57 +00:00
}
2016-08-28 17:32:58 +00:00
function get_astext ( $asn )
{
2015-07-13 18:10:26 +00:00
global $config , $cache ;
if ( isset ( $config [ 'astext' ][ $asn ])) {
return $config [ 'astext' ][ $asn ];
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
if ( isset ( $cache [ 'astext' ][ $asn ])) {
return $cache [ 'astext' ][ $asn ];
2016-08-28 17:32:58 +00:00
} else {
$result = dns_get_record ( " AS $asn .asn.cymru.com " , DNS_TXT );
$txt = explode ( '|' , $result [ 0 ][ 'txt' ]);
2015-07-13 18:10:26 +00:00
$result = trim ( str_replace ( '"' , '' , $txt [ 4 ]));
$cache [ 'astext' ][ $asn ] = $result ;
return $result ;
}
}
2010-01-03 20:13:10 +00:00
}
2010-01-07 16:50:52 +00:00
2017-03-12 13:05:31 +00:00
/**
* Log events to the event table
*
* @ param string $text message describing the event
* @ param array | int $device device array or device_id
* @ param string $type brief category for this event . Examples : sensor , state , stp , system , temperature , interface
* @ param int $severity 1 : ok , 2 : info , 3 : notice , 4 : warning , 5 : critical , 0 : unknown
* @ param int $reference the id of the referenced entity . Supported types : interface
*/
2017-02-12 22:41:05 +00:00
function log_event ( $text , $device = null , $type = null , $severity = 2 , $reference = null )
2016-08-28 17:32:58 +00:00
{
2015-07-13 18:10:26 +00:00
if ( ! is_array ( $device )) {
$device = device_by_id_cache ( $device );
}
2010-06-20 21:37:05 +00:00
2017-03-12 13:05:31 +00:00
$insert = array ( 'host' => ( $device [ 'device_id' ] ? : 0 ),
'device_id' => ( $device [ 'device_id' ] ? : 0 ),
'reference' => ( $reference ? : " NULL " ),
'type' => ( $type ? : " NULL " ),
'datetime' => array ( " NOW() " ),
'severity' => $severity ,
'message' => $text ,
'username' => $_SESSION [ 'username' ] ? : '' ,
);
2011-05-12 17:59:00 +00:00
2015-07-13 18:10:26 +00:00
dbInsert ( $insert , 'eventlog' );
2011-03-08 17:12:43 +00:00
}
2010-02-17 11:02:18 +00:00
2012-04-26 12:11:03 +00:00
// Parse string with emails. Return array with email (as key) and name (as value)
2016-08-28 17:32:58 +00:00
function parse_email ( $emails )
{
2015-07-13 18:10:26 +00:00
$result = array ();
$regex = '/^[\"\']?([^\"\']+)[\"\']?\s{0,}<([^@]+@[^>]+)>$/' ;
if ( is_string ( $emails )) {
$emails = preg_split ( '/[,;]\s{0,}/' , $emails );
foreach ( $emails as $email ) {
if ( preg_match ( $regex , $email , $out , PREG_OFFSET_CAPTURE )) {
$result [ $out [ 2 ][ 0 ]] = $out [ 1 ][ 0 ];
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
if ( strpos ( $email , " @ " )) {
2016-08-28 17:32:58 +00:00
$result [ $email ] = null ;
2015-07-13 18:10:26 +00:00
}
}
}
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
// Return FALSE if input not string
2016-08-28 17:32:58 +00:00
return false ;
2015-07-13 18:10:26 +00:00
}
return $result ;
2012-04-26 12:11:03 +00:00
}
2016-08-28 17:32:58 +00:00
function send_mail ( $emails , $subject , $message , $html = false )
{
2015-07-13 18:10:26 +00:00
global $config ;
2016-08-28 17:32:58 +00:00
if ( is_array ( $emails ) || ( $emails = parse_email ( $emails ))) {
2015-07-13 18:10:26 +00:00
$mail = new PHPMailer ();
$mail -> Hostname = php_uname ( 'n' );
2017-03-03 18:22:33 +00:00
2016-08-28 17:32:58 +00:00
foreach ( parse_email ( $config [ 'email_from' ]) as $from => $from_name ) {
2015-07-13 18:10:26 +00:00
$mail -> setFrom ( $from , $from_name );
2016-08-28 17:32:58 +00:00
}
foreach ( $emails as $email => $email_name ) {
2015-07-13 18:10:26 +00:00
$mail -> addAddress ( $email , $email_name );
2016-08-28 17:32:58 +00:00
}
2015-07-13 18:10:26 +00:00
$mail -> Subject = $subject ;
$mail -> XMailer = $config [ 'project_name_version' ];
$mail -> CharSet = 'utf-8' ;
$mail -> WordWrap = 76 ;
$mail -> Body = $message ;
2016-08-28 17:32:58 +00:00
if ( $html ) {
2015-07-13 18:10:26 +00:00
$mail -> isHTML ( true );
2016-08-28 17:32:58 +00:00
}
2015-07-13 18:10:26 +00:00
switch ( strtolower ( trim ( $config [ 'email_backend' ]))) {
2016-08-28 17:32:58 +00:00
case 'sendmail' :
$mail -> Mailer = 'sendmail' ;
$mail -> Sendmail = $config [ 'email_sendmail_path' ];
break ;
case 'smtp' :
$mail -> isSMTP ();
$mail -> Host = $config [ 'email_smtp_host' ];
$mail -> Timeout = $config [ 'email_smtp_timeout' ];
$mail -> SMTPAuth = $config [ 'email_smtp_auth' ];
$mail -> SMTPSecure = $config [ 'email_smtp_secure' ];
$mail -> Port = $config [ 'email_smtp_port' ];
$mail -> Username = $config [ 'email_smtp_username' ];
$mail -> Password = $config [ 'email_smtp_password' ];
2017-01-10 10:03:47 +00:00
$mail -> SMTPAutoTLS = $config [ 'email_auto_tls' ];
2016-08-28 17:32:58 +00:00
$mail -> SMTPDebug = false ;
break ;
default :
$mail -> Mailer = 'mail' ;
break ;
2015-07-13 18:10:26 +00:00
}
return $mail -> send () ? true : $mail -> ErrorInfo ;
}
2014-03-07 21:30:07 +00:00
}
2016-08-28 17:32:58 +00:00
function formatCiscoHardware ( & $device , $short = false )
{
2015-07-13 18:10:26 +00:00
if ( $device [ 'os' ] == " ios " ) {
if ( $device [ 'hardware' ]) {
2016-12-16 23:04:37 +00:00
if ( preg_match ( " /^WS-C([A-Za-z0-9]+)/ " , $device [ 'hardware' ], $matches )) {
2015-07-13 18:10:26 +00:00
if ( ! $short ) {
2016-12-16 23:04:37 +00:00
$device [ 'hardware' ] = " Catalyst " . $matches [ 1 ] . " ( " . $device [ 'hardware' ] . " ) " ;
} else {
$device [ 'hardware' ] = " Catalyst " . $matches [ 1 ];
}
} elseif ( preg_match ( " /^CISCO([0-9]+)(.*)/ " , $device [ 'hardware' ], $matches )) {
if ( ! $short && $matches [ 2 ]) {
2015-07-13 18:10:26 +00:00
$device [ 'hardware' ] = " Cisco " . $matches [ 1 ] . " ( " . $device [ 'hardware' ] . " ) " ;
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
$device [ 'hardware' ] = " Cisco " . $matches [ 1 ];
}
}
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
if ( preg_match ( " /Cisco IOS Software, C([A-Za-z0-9]+) Software.*/ " , $device [ 'sysDescr' ], $matches )) {
2016-12-16 23:04:37 +00:00
$device [ 'hardware' ] = " Catalyst " . $matches [ 1 ];
2016-08-28 17:32:58 +00:00
} elseif ( preg_match ( " /Cisco IOS Software, ([0-9]+) Software.*/ " , $device [ 'sysDescr' ], $matches )) {
2015-07-13 18:10:26 +00:00
$device [ 'hardware' ] = " Cisco " . $matches [ 1 ];
}
2010-02-21 17:02:20 +00:00
}
2015-07-13 18:10:26 +00:00
}
2010-02-21 17:02:20 +00:00
}
2010-06-18 16:38:41 +00:00
2016-08-28 17:32:58 +00:00
function hex2str ( $hex )
{
2015-07-13 18:10:26 +00:00
$string = '' ;
2011-03-11 18:03:49 +00:00
2015-07-13 18:10:26 +00:00
for ( $i = 0 ; $i < strlen ( $hex ) - 1 ; $i += 2 ) {
2017-02-12 13:20:06 +00:00
$string .= chr ( hexdec ( substr ( $hex , $i , 2 )));
2015-07-13 18:10:26 +00:00
}
2011-03-11 18:03:49 +00:00
2015-07-13 18:10:26 +00:00
return $string ;
2010-06-18 16:38:41 +00:00
}
2010-07-05 15:27:01 +00:00
2010-07-07 13:58:11 +00:00
# Convert an SNMP hex string to regular string
2016-08-28 17:32:58 +00:00
function snmp_hexstring ( $hex )
{
return hex2str ( str_replace ( ' ' , '' , str_replace ( ' 00' , '' , $hex )));
2010-07-05 15:27:01 +00:00
}
2010-07-07 13:58:11 +00:00
# Check if the supplied string is an SNMP hex string
2016-08-28 17:32:58 +00:00
function isHexString ( $str )
{
2017-02-16 08:15:20 +00:00
return ( bool ) preg_match ( " /^[a-f0-9][a-f0-9]( [a-f0-9][a-f0-9])* $ /is " , trim ( $str ));
2010-07-05 15:27:01 +00:00
}
2010-07-09 22:38:46 +00:00
# Include all .inc.php files in $dir
2016-08-28 17:32:58 +00:00
function include_dir ( $dir , $regex = " " )
{
2015-08-20 14:06:44 +00:00
global $device , $config , $valid ;
2011-09-16 10:31:48 +00:00
2015-07-13 18:10:26 +00:00
if ( $regex == " " ) {
$regex = " / \ .inc \ .php $ / " ;
}
2011-03-23 09:54:56 +00:00
2015-07-13 18:10:26 +00:00
if ( $handle = opendir ( $config [ 'install_dir' ] . '/' . $dir )) {
while ( false !== ( $file = readdir ( $handle ))) {
if ( filetype ( $config [ 'install_dir' ] . '/' . $dir . '/' . $file ) == 'file' && preg_match ( $regex , $file )) {
2015-08-20 14:06:44 +00:00
d_echo ( " Including: " . $config [ 'install_dir' ] . '/' . $dir . '/' . $file . " \n " );
2012-04-05 16:44:58 +00:00
2015-07-13 18:10:26 +00:00
include ( $config [ 'install_dir' ] . '/' . $dir . '/' . $file );
}
}
2010-07-09 22:38:46 +00:00
2015-07-13 18:10:26 +00:00
closedir ( $handle );
}
2010-07-09 22:38:46 +00:00
}
2016-08-28 17:32:58 +00:00
function is_port_valid ( $port , $device )
{
2015-07-13 18:10:26 +00:00
2015-08-20 14:06:44 +00:00
global $config ;
2015-07-13 18:10:26 +00:00
2017-02-03 19:49:40 +00:00
if ( empty ( $port [ 'ifDescr' ]) && empty ( $port [ 'ifAlias' ]) && empty ( $port [ 'ifName' ])) {
// If these are all empty, we are just going to show blank names in the ui
$valid = 0 ;
} elseif ( strstr ( $port [ 'ifDescr' ], " irtual " ) && strpos ( $port [ 'ifDescr' ], " Virtual Services Platform " ) === false ) {
2011-05-18 23:08:45 +00:00
$valid = 0 ;
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
$valid = 1 ;
$if = strtolower ( $port [ 'ifDescr' ]);
2016-04-30 00:43:28 +00:00
$ifname = strtolower ( $port [ 'ifName' ]);
$ifalias = strtolower ( $port [ 'ifAlias' ]);
2015-07-13 18:10:26 +00:00
$fringe = $config [ 'bad_if' ];
2016-08-28 17:32:58 +00:00
if ( is_array ( $config [ 'os' ][ $device [ 'os' ]][ 'bad_if' ])) {
$fringe = array_merge ( $config [ 'bad_if' ], $config [ 'os' ][ $device [ 'os' ]][ 'bad_if' ]);
2015-07-13 18:10:26 +00:00
}
foreach ( $fringe as $bi ) {
2016-07-30 14:50:44 +00:00
if ( stristr ( $if , $bi )) {
2015-07-13 18:10:26 +00:00
$valid = 0 ;
2015-08-20 14:06:44 +00:00
d_echo ( " ignored : $bi : $if " );
2015-07-13 18:10:26 +00:00
}
2011-05-18 23:08:45 +00:00
}
2015-07-13 18:10:26 +00:00
if ( is_array ( $config [ 'bad_if_regexp' ])) {
$fringe = $config [ 'bad_if_regexp' ];
2016-08-28 17:32:58 +00:00
if ( is_array ( $config [ 'os' ][ $device [ 'os' ]][ 'bad_if_regexp' ])) {
$fringe = array_merge ( $config [ 'bad_if_regexp' ], $config [ 'os' ][ $device [ 'os' ]][ 'bad_if_regexp' ]);
2015-07-13 18:10:26 +00:00
}
foreach ( $fringe as $bi ) {
if ( preg_match ( $bi . " i " , $if )) {
$valid = 0 ;
2015-08-20 14:06:44 +00:00
d_echo ( " ignored : $bi : " . $if );
2015-07-13 18:10:26 +00:00
}
}
2016-04-28 22:36:13 +00:00
}
2016-04-30 00:43:28 +00:00
if ( is_array ( $config [ 'bad_ifname_regexp' ])) {
2016-04-28 22:36:13 +00:00
$fringe = $config [ 'bad_ifname_regexp' ];
2016-08-28 17:32:58 +00:00
if ( is_array ( $config [ 'os' ][ $device [ 'os' ]][ 'bad_ifname_regexp' ])) {
$fringe = array_merge ( $config [ 'bad_ifname_regexp' ], $config [ 'os' ][ $device [ 'os' ]][ 'bad_ifname_regexp' ]);
2016-04-28 22:36:13 +00:00
}
foreach ( $fringe as $bi ) {
if ( preg_match ( $bi . " i " , $ifname )) {
$valid = 0 ;
d_echo ( " ignored : $bi : " . $ifname );
}
}
}
2016-04-30 00:43:28 +00:00
if ( is_array ( $config [ 'bad_ifalias_regexp' ])) {
2016-04-28 22:36:13 +00:00
$fringe = $config [ 'bad_ifalias_regexp' ];
2016-08-28 17:32:58 +00:00
if ( is_array ( $config [ 'os' ][ $device [ 'os' ]][ 'bad_ifalias_regexp' ])) {
$fringe = array_merge ( $config [ 'bad_ifalias_regexp' ], $config [ 'os' ][ $device [ 'os' ]][ 'bad_ifalias_regexp' ]);
2016-04-28 22:36:13 +00:00
}
foreach ( $fringe as $bi ) {
if ( preg_match ( $bi . " i " , $ifalias )) {
$valid = 0 ;
d_echo ( " ignored : $bi : " . $ifalias );
}
}
2015-07-13 18:10:26 +00:00
}
if ( is_array ( $config [ 'bad_iftype' ])) {
$fringe = $config [ 'bad_iftype' ];
2016-08-28 17:32:58 +00:00
if ( is_array ( $config [ 'os' ][ $device [ 'os' ]][ 'bad_iftype' ])) {
$fringe = array_merge ( $config [ 'bad_iftype' ], $config [ 'os' ][ $device [ 'os' ]][ 'bad_iftype' ]);
2015-07-13 18:10:26 +00:00
}
foreach ( $fringe as $bi ) {
2016-07-30 14:50:44 +00:00
if ( stristr ( $port [ 'ifType' ], $bi )) {
2015-07-13 18:10:26 +00:00
$valid = 0 ;
2015-08-20 14:06:44 +00:00
d_echo ( " ignored ifType : " . $port [ 'ifType' ] . " (matched: " . $bi . " ) " );
2015-07-13 18:10:26 +00:00
}
}
}
2016-02-08 19:58:03 +00:00
if ( empty ( $port [ 'ifDescr' ]) && ! $config [ 'os' ][ $device [ 'os' ]][ 'empty_ifdescr' ]) {
2015-07-13 18:10:26 +00:00
$valid = 0 ;
}
if ( $device [ 'os' ] == " catos " && strstr ( $if , " vlan " )) {
$valid = 0 ;
}
if ( $device [ 'os' ] == " dlink " ) {
$valid = 1 ;
2012-03-29 12:05:45 +00:00
}
}
2011-05-18 23:08:45 +00:00
2015-07-13 18:10:26 +00:00
return $valid ;
2011-05-18 23:08:45 +00:00
}
2016-08-28 17:32:58 +00:00
function scan_new_plugins ()
{
2015-07-13 18:10:26 +00:00
2015-08-20 14:06:44 +00:00
global $config ;
2015-07-13 18:10:26 +00:00
$installed = 0 ; // Track how many plugins we install.
2016-08-28 17:32:58 +00:00
if ( file_exists ( $config [ 'plugin_dir' ])) {
2015-07-13 18:10:26 +00:00
$plugin_files = scandir ( $config [ 'plugin_dir' ]);
2016-08-28 17:32:58 +00:00
foreach ( $plugin_files as $name ) {
if ( is_dir ( $config [ 'plugin_dir' ] . '/' . $name )) {
if ( $name != '.' && $name != '..' ) {
if ( is_file ( $config [ 'plugin_dir' ] . '/' . $name . '/' . $name . '.php' ) && is_file ( $config [ 'plugin_dir' ] . '/' . $name . '/' . $name . '.inc.php' )) {
2015-07-13 18:10:26 +00:00
$plugin_id = dbFetchRow ( " SELECT `plugin_id` FROM `plugins` WHERE `plugin_name` = ' $name ' " );
2016-08-28 17:32:58 +00:00
if ( empty ( $plugin_id )) {
if ( dbInsert ( array ( 'plugin_name' => $name , 'plugin_active' => '0' ), 'plugins' )) {
2015-07-13 18:10:26 +00:00
$installed ++ ;
}
}
}
}
2014-02-25 12:51:07 +00:00
}
}
}
2015-07-13 18:10:26 +00:00
return ( $installed );
2014-02-25 12:51:07 +00:00
}
2016-08-28 17:32:58 +00:00
function validate_device_id ( $id )
{
2014-06-24 15:14:42 +00:00
2015-07-13 18:10:26 +00:00
global $config ;
2016-08-28 17:32:58 +00:00
if ( empty ( $id ) || ! is_numeric ( $id )) {
2015-07-13 18:10:26 +00:00
$return = false ;
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
$device_id = dbFetchCell ( " SELECT `device_id` FROM `devices` WHERE `device_id` = ? " , array ( $id ));
2016-08-28 17:32:58 +00:00
if ( $device_id == $id ) {
2015-07-13 18:10:26 +00:00
$return = true ;
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
$return = false ;
}
}
return ( $return );
2014-06-24 15:14:42 +00:00
}
2014-09-17 20:03:02 +00:00
2014-10-07 10:29:54 +00:00
// The original source of this code is from Stackoverflow (www.stackoverflow.com).
// http://stackoverflow.com/questions/6054033/pretty-printing-json-with-php
// Answer provided by stewe (http://stackoverflow.com/users/3202187/ulk200
2016-08-28 17:32:58 +00:00
if ( ! defined ( 'JSON_UNESCAPED_SLASHES' )) {
2014-10-02 19:17:45 +00:00
define ( 'JSON_UNESCAPED_SLASHES' , 64 );
2016-08-28 17:32:58 +00:00
}
if ( ! defined ( 'JSON_PRETTY_PRINT' )) {
2014-10-02 19:17:45 +00:00
define ( 'JSON_PRETTY_PRINT' , 128 );
2016-08-28 17:32:58 +00:00
}
if ( ! defined ( 'JSON_UNESCAPED_UNICODE' )) {
2014-10-02 19:17:45 +00:00
define ( 'JSON_UNESCAPED_UNICODE' , 256 );
2016-08-28 17:32:58 +00:00
}
2014-10-02 19:17:45 +00:00
2016-08-28 17:32:58 +00:00
function _json_encode ( $data , $options = 448 )
{
2014-10-24 23:16:07 +00:00
if ( version_compare ( PHP_VERSION , '5.4' , '>=' )) {
2014-10-02 19:17:45 +00:00
return json_encode ( $data , $options );
2016-08-28 17:32:58 +00:00
} else {
2015-07-13 18:10:26 +00:00
return _json_format ( json_encode ( $data ), $options );
2014-10-24 23:16:07 +00:00
}
2014-10-02 19:17:45 +00:00
}
2016-08-28 17:32:58 +00:00
function _json_format ( $json , $options = 448 )
{
2014-10-02 19:17:45 +00:00
$prettyPrint = ( bool ) ( $options & JSON_PRETTY_PRINT );
$unescapeUnicode = ( bool ) ( $options & JSON_UNESCAPED_UNICODE );
$unescapeSlashes = ( bool ) ( $options & JSON_UNESCAPED_SLASHES );
2015-07-13 18:10:26 +00:00
if ( ! $prettyPrint && ! $unescapeUnicode && ! $unescapeSlashes ) {
2014-10-02 19:17:45 +00:00
return $json ;
}
$result = '' ;
$pos = 0 ;
$strLen = strlen ( $json );
$indentStr = ' ' ;
$newLine = " \n " ;
$outOfQuotes = true ;
$buffer = '' ;
$noescape = true ;
2015-07-13 18:10:26 +00:00
for ( $i = 0 ; $i < $strLen ; $i ++ ) {
2014-10-02 19:17:45 +00:00
// Grab the next character in the string
$char = substr ( $json , $i , 1 );
// Are we inside a quoted string?
2015-07-13 18:10:26 +00:00
if ( '"' === $char && $noescape ) {
2014-10-02 19:17:45 +00:00
$outOfQuotes = ! $outOfQuotes ;
}
2015-07-13 18:10:26 +00:00
if ( ! $outOfQuotes ) {
2014-10-02 19:17:45 +00:00
$buffer .= $char ;
$noescape = '\\' === $char ? ! $noescape : true ;
continue ;
2016-08-28 17:32:58 +00:00
} elseif ( '' !== $buffer ) {
2015-07-13 18:10:26 +00:00
if ( $unescapeSlashes ) {
2014-10-02 19:17:45 +00:00
$buffer = str_replace ( '\\/' , '/' , $buffer );
}
2015-07-13 18:10:26 +00:00
if ( $unescapeUnicode && function_exists ( 'mb_convert_encoding' )) {
2014-10-02 19:17:45 +00:00
// http://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
2016-08-28 17:32:58 +00:00
$buffer = preg_replace_callback (
'/\\\\u([0-9a-f]{4})/i' ,
2015-07-13 18:10:26 +00:00
function ( $match ) {
2014-10-02 19:17:45 +00:00
return mb_convert_encoding ( pack ( 'H*' , $match [ 1 ]), 'UTF-8' , 'UCS-2BE' );
2016-08-28 17:32:58 +00:00
},
$buffer
);
2014-10-02 19:17:45 +00:00
}
$result .= $buffer . $char ;
$buffer = '' ;
continue ;
2016-08-28 17:32:58 +00:00
} elseif ( false !== strpos ( " \t \r \n " , $char )) {
2014-10-02 19:17:45 +00:00
continue ;
}
2015-07-13 18:10:26 +00:00
if ( ':' === $char ) {
2014-10-02 19:17:45 +00:00
// Add a space after the : character
$char .= ' ' ;
2016-08-28 17:32:58 +00:00
} elseif (( '}' === $char || ']' === $char )) {
2014-10-02 19:17:45 +00:00
$pos -- ;
$prevChar = substr ( $json , $i - 1 , 1 );
2015-07-13 18:10:26 +00:00
if ( '{' !== $prevChar && '[' !== $prevChar ) {
2014-10-02 19:17:45 +00:00
// If this character is the end of an element,
// output a new line and indent the next line
$result .= $newLine ;
2015-07-13 18:10:26 +00:00
for ( $j = 0 ; $j < $pos ; $j ++ ) {
2014-10-02 19:17:45 +00:00
$result .= $indentStr ;
}
2016-08-28 17:32:58 +00:00
} else {
2014-10-02 19:17:45 +00:00
// Collapse empty {} and []
$result = rtrim ( $result ) . " \n \n " . $indentStr ;
}
}
$result .= $char ;
// If the last character was the beginning of an element,
// output a new line and indent the next line
2015-07-13 18:10:26 +00:00
if ( ',' === $char || '{' === $char || '[' === $char ) {
2014-10-02 19:17:45 +00:00
$result .= $newLine ;
2015-07-13 18:10:26 +00:00
if ( '{' === $char || '[' === $char ) {
2014-10-02 19:17:45 +00:00
$pos ++ ;
}
2015-07-13 18:10:26 +00:00
for ( $j = 0 ; $j < $pos ; $j ++ ) {
2014-10-02 19:17:45 +00:00
$result .= $indentStr ;
}
}
}
// If buffer not empty after formating we have an unclosed quote
2015-07-13 18:10:26 +00:00
if ( strlen ( $buffer ) > 0 ) {
2014-10-02 19:17:45 +00:00
//json is incorrectly formatted
$result = false ;
}
return $result ;
}
2014-11-30 17:49:52 +00:00
2016-08-28 17:32:58 +00:00
function convert_delay ( $delay )
{
$delay = preg_replace ( '/\s/' , '' , $delay );
if ( strstr ( $delay , 'm' , true )) {
2014-11-30 17:49:52 +00:00
$delay_sec = $delay * 60 ;
2016-08-28 17:32:58 +00:00
} elseif ( strstr ( $delay , 'h' , true )) {
2014-11-30 17:49:52 +00:00
$delay_sec = $delay * 3600 ;
2016-08-28 17:32:58 +00:00
} elseif ( strstr ( $delay , 'd' , true )) {
2014-11-30 17:49:52 +00:00
$delay_sec = $delay * 86400 ;
2016-08-28 17:32:58 +00:00
} elseif ( is_numeric ( $delay )) {
2014-11-30 17:49:52 +00:00
$delay_sec = $delay ;
2016-08-28 17:32:58 +00:00
} else {
2015-02-26 01:25:25 +00:00
$delay_sec = 300 ;
2014-11-30 17:49:52 +00:00
}
return ( $delay_sec );
}
2016-08-28 17:32:58 +00:00
function guidv4 ( $data )
{
2015-04-10 16:00:32 +00:00
// http://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid#15875555
// From: Jack http://stackoverflow.com/users/1338292/ja%CD%A2ck
assert ( strlen ( $data ) == 16 );
$data [ 6 ] = chr ( ord ( $data [ 6 ]) & 0x0f | 0x40 ); // set version to 0100
$data [ 8 ] = chr ( ord ( $data [ 8 ]) & 0x3f | 0x80 ); // set bits 6-7 to 10
return vsprintf ( '%s%s-%s-%s-%s-%s%s%s' , str_split ( bin2hex ( $data ), 4 ));
}
2016-10-14 01:07:07 +00:00
/**
* @ param $curl
*/
function set_curl_proxy ( $curl )
2016-08-28 17:32:58 +00:00
{
2017-03-22 10:17:13 +00:00
$proxy = get_proxy ();
2016-10-14 01:07:07 +00:00
$tmp = rtrim ( $proxy , " / " );
$proxy = str_replace ( array ( " http:// " , " https:// " ), " " , $tmp );
if ( ! empty ( $proxy )) {
curl_setopt ( $curl , CURLOPT_PROXY , $proxy );
2015-04-13 09:51:16 +00:00
}
}
2015-04-19 19:23:34 +00:00
2017-03-22 10:17:13 +00:00
/**
* Return the proxy url
*
* @ return array | bool | false | string
*/
function get_proxy ()
{
2017-03-23 06:48:10 +00:00
global $config ;
2017-03-22 10:17:13 +00:00
if ( getenv ( 'http_proxy' )) {
return getenv ( 'http_proxy' );
} elseif ( getenv ( 'https_proxy' )) {
return getenv ( 'https_proxy' );
} elseif ( isset ( $config [ 'callback_proxy' ])) {
return $config [ 'callback_proxy' ];
} elseif ( isset ( $config [ 'http_proxy' ])) {
return $config [ 'http_proxy' ];
}
return false ;
}
2016-08-28 17:32:58 +00:00
function target_to_id ( $target )
{
if ( $target [ 0 ] . $target [ 1 ] == " g: " ) {
$target = " g " . dbFetchCell ( 'SELECT id FROM device_groups WHERE name = ?' , array ( substr ( $target , 2 )));
} else {
$target = dbFetchCell ( 'SELECT device_id FROM devices WHERE hostname = ?' , array ( $target ));
2015-04-19 19:23:34 +00:00
}
return $target ;
}
2016-08-28 17:32:58 +00:00
function id_to_target ( $id )
{
if ( $id [ 0 ] == " g " ) {
$id = 'g:' . dbFetchCell ( " SELECT name FROM device_groups WHERE id = ? " , array ( substr ( $id , 1 )));
} else {
$id = dbFetchCell ( " SELECT hostname FROM devices WHERE device_id = ? " , array ( $id ));
2015-04-19 19:23:34 +00:00
}
return $id ;
}
2015-05-26 13:58:29 +00:00
2016-08-28 17:32:58 +00:00
function first_oid_match ( $device , $list )
{
2015-05-26 13:58:29 +00:00
foreach ( $list as $item ) {
2015-07-13 18:10:26 +00:00
$tmp = trim ( snmp_get ( $device , $item , " -Ovq " ), '" ' );
if ( ! empty ( $tmp )) {
return $tmp ;
}
2015-05-26 13:58:29 +00:00
}
}
2015-06-02 16:36:10 +00:00
2016-08-28 17:32:58 +00:00
function hex_to_ip ( $hex )
{
2015-06-03 14:41:10 +00:00
$return = " " ;
2016-08-28 17:32:58 +00:00
if ( filter_var ( $hex , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ) === false && filter_var ( $hex , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ) === false ) {
2015-06-03 14:41:10 +00:00
$hex_exp = explode ( ' ' , $hex );
foreach ( $hex_exp as $item ) {
if ( ! empty ( $item ) && $item != " \" " ) {
$return .= hexdec ( $item ) . '.' ;
}
}
$return = substr ( $return , 0 , - 1 );
2016-08-28 17:32:58 +00:00
} else {
2015-06-09 14:19:06 +00:00
$return = $hex ;
2015-06-03 14:41:10 +00:00
}
return $return ;
}
2016-08-28 17:32:58 +00:00
function fix_integer_value ( $value )
{
2015-06-02 16:36:10 +00:00
if ( $value < 0 ) {
$return = 4294967296 + $value ;
2016-08-28 17:32:58 +00:00
} else {
2015-06-02 16:36:10 +00:00
$return = $value ;
}
return $return ;
}
2015-06-11 18:34:11 +00:00
2016-08-02 03:01:01 +00:00
function ip_exists ( $ip )
{
2015-06-11 18:34:11 +00:00
// Function to check if an IP exists in the DB already
2016-08-02 03:01:01 +00:00
if ( filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ) !== false ) {
$dbresult = dbFetchRow ( " SELECT `ipv6_address_id` FROM `ipv6_addresses` WHERE `ipv6_address` = ? OR `ipv6_compressed` = ? " , array ( $ip , $ip ));
return ! empty ( $dbresult );
} elseif ( filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ) !== false ) {
$dbresult = dbFetchRow ( " SELECT `ipv4_address_id` FROM `ipv4_addresses` WHERE `ipv4_address` = ? " , array ( $ip ));
return ! empty ( $dbresult );
2015-07-13 18:10:26 +00:00
}
2016-08-02 03:01:01 +00:00
// not an ipv4 or ipv6 address...
return false ;
2015-06-11 18:34:11 +00:00
}
2015-06-22 20:55:31 +00:00
2016-08-28 17:32:58 +00:00
function fping ( $host , $params , $address_family = AF_INET )
{
2015-06-22 20:55:31 +00:00
global $config ;
2015-06-22 22:02:11 +00:00
$descriptorspec = array (
0 => array ( " pipe " , " r " ),
1 => array ( " pipe " , " w " ),
2 => array ( " pipe " , " w " )
);
2015-06-22 20:55:31 +00:00
2015-09-22 00:25:35 +00:00
// Default to AF_INET (IPv4)
$fping_path = $config [ 'fping' ];
if ( $address_family == AF_INET6 ) {
$fping_path = $config [ 'fping6' ];
}
$process = proc_open ( $fping_path . ' -e -q ' . $params . ' ' . $host . ' 2>&1' , $descriptorspec , $pipes );
2015-06-22 22:02:11 +00:00
$read = '' ;
2015-06-22 20:55:31 +00:00
2015-06-22 22:02:11 +00:00
if ( is_resource ( $process )) {
2015-07-13 18:10:26 +00:00
fclose ( $pipes [ 0 ]);
2015-06-22 20:55:31 +00:00
2015-07-13 18:10:26 +00:00
while ( ! feof ( $pipes [ 1 ])) {
$read .= fgets ( $pipes [ 1 ], 1024 );
}
fclose ( $pipes [ 1 ]);
proc_close ( $process );
2015-06-22 22:02:11 +00:00
}
2015-06-22 20:55:31 +00:00
preg_match ( '/[0-9]+\/[0-9]+\/[0-9]+%/' , $read , $loss_tmp );
preg_match ( '/[0-9\.]+\/[0-9\.]+\/[0-9\.]*$/' , $read , $latency );
2016-08-28 17:32:58 +00:00
$loss = preg_replace ( " /%/ " , " " , $loss_tmp [ 0 ]);
2015-06-22 20:55:31 +00:00
list ( $xmt , $rcv , $loss ) = preg_split ( " / \ // " , $loss );
2015-06-23 08:48:36 +00:00
list ( $min , $avg , $max ) = preg_split ( " / \ // " , $latency [ 0 ]);
2015-06-22 20:55:31 +00:00
if ( $loss < 0 ) {
$xmt = 1 ;
$rcv = 1 ;
$loss = 100 ;
}
2017-01-13 12:47:16 +00:00
$xmt = set_numeric ( $xmt );
$rcv = set_numeric ( $rcv );
$loss = set_numeric ( $loss );
$min = set_numeric ( $min );
$max = set_numeric ( $max );
$avg = set_numeric ( $avg );
2015-06-22 20:55:31 +00:00
$response = array ( 'xmt' => $xmt , 'rcv' => $rcv , 'loss' => $loss , 'min' => $min , 'max' => $max , 'avg' => $avg );
return $response ;
}
2015-07-20 14:10:56 +00:00
2016-08-28 17:32:58 +00:00
function function_check ( $function )
{
2015-07-20 14:10:56 +00:00
return function_exists ( $function );
}
2015-08-25 08:40:20 +00:00
2016-08-28 17:32:58 +00:00
function force_influx_data ( $data )
{
2016-04-12 09:01:20 +00:00
/*
* It is not trivial to detect if something is a float or an integer , and
* therefore may cause breakages on inserts .
* Just setting every number to a float gets around this , but may introduce
* inefficiencies .
* I ' ve left the detection statement in there for a possible change in future ,
* but currently everything just gets set to a float .
*/
if ( is_numeric ( $data )) {
// If it is an Integer
if ( ctype_digit ( $data )) {
return floatval ( $data );
// Else it is a float
2016-08-28 17:32:58 +00:00
} else {
2016-04-12 09:01:20 +00:00
return floatval ( $data );
}
2016-08-28 17:32:58 +00:00
} else {
2016-04-12 09:01:20 +00:00
return $data ;
2015-08-17 14:31:21 +00:00
}
} // end force_influx_data
2015-10-26 11:08:19 +00:00
2015-09-25 17:03:58 +00:00
/**
* Try to determine the address family ( IPv4 or IPv6 ) associated with an SNMP
* transport specifier ( like " udp " , " udp6 " , etc . ) .
*
* @ param string $transport The SNMP transport specifier , for example " udp " ,
* " udp6 " , " tcp " , or " tcp6 " . See `man snmpcmd` ,
* section " Agent Specification " for a full list .
*
* @ return int The address family associated with the given transport
* specifier : AF_INET for IPv4 ( or local connections not associated
* with an IP stack ), AF_INET6 for IPv6 .
*/
2016-08-28 17:32:58 +00:00
function snmpTransportToAddressFamily ( $transport )
{
2015-09-22 00:25:35 +00:00
if ( ! isset ( $transport )) {
$transport = 'udp' ;
}
2015-09-25 17:03:47 +00:00
$ipv6_snmp_transport_specifiers = array ( 'udp6' , 'udpv6' , 'udpipv6' , 'tcp6' , 'tcpv6' , 'tcpipv6' );
if ( in_array ( $transport , $ipv6_snmp_transport_specifiers )) {
2015-09-22 00:25:35 +00:00
return AF_INET6 ;
2016-08-28 17:32:58 +00:00
} else {
2015-09-22 00:25:35 +00:00
return AF_INET ;
}
}
2015-10-22 21:10:33 +00:00
/**
* Checks if the $hostname provided exists in the DB already
*
* @ param string $hostname The hostname to check for
2017-02-22 09:12:31 +00:00
* @ param string $snmphost The sysName to check
2015-10-22 21:10:33 +00:00
* @ return bool true if hostname already exists
* false if hostname doesn ' t exist
2017-02-22 09:12:31 +00:00
*/
2016-08-28 17:32:58 +00:00
function host_exists ( $hostname , $snmphost = '' )
{
2016-05-02 20:20:29 +00:00
global $config ;
2015-10-22 21:10:33 +00:00
$count = dbFetchCell ( " SELECT COUNT(*) FROM `devices` WHERE `hostname` = ? " , array ( $hostname ));
if ( $count > 0 ) {
return true ;
2016-08-28 17:32:58 +00:00
} else {
2016-05-02 20:20:29 +00:00
if ( $config [ 'allow_duplicate_sysName' ] === false && ! empty ( $snmphost )) {
2017-03-03 14:27:56 +00:00
if ( ! empty ( $config [ 'mydomain' ])) {
$full_host = rtrim ( $snmphost , '.' ) . '.' . $config [ 'mydomain' ];
$count = dbFetchCell ( " SELECT COUNT(*) FROM `devices` WHERE `sysName` = ? or `sysName` = ? " , array ( $snmphost , $full_host ));
} else {
$count = dbFetchCell ( " SELECT COUNT(*) FROM `devices` WHERE `sysName` = ? " , array ( $snmphost ));
}
2016-05-02 20:20:29 +00:00
if ( $count > 0 ) {
return true ;
2016-08-28 17:32:58 +00:00
} else {
2016-05-02 20:20:29 +00:00
return false ;
}
}
2015-10-22 21:10:33 +00:00
return false ;
}
}
2015-11-19 10:20:56 +00:00
/**
* Check the innodb buffer size
*
* @ return array including the current set size and the currently used buffer
**/
2016-08-28 17:32:58 +00:00
function innodb_buffer_check ()
{
2015-11-19 10:20:56 +00:00
$pool [ 'size' ] = dbFetchCell ( 'SELECT @@innodb_buffer_pool_size' );
// The following query is from the excellent mysqltuner.pl by Major Hayden https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
$pool [ 'used' ] = dbFetchCell ( 'SELECT SUM(DATA_LENGTH+INDEX_LENGTH) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ("information_schema", "performance_schema", "mysql") AND ENGINE = "InnoDB" GROUP BY ENGINE ORDER BY ENGINE ASC' );
return $pool ;
}
/**
* Print warning about InnoDB buffer size
*
* @ param array $innodb_buffer An array that contains the used and current size
*
* @ return string $output
**/
2016-08-28 17:32:58 +00:00
function warn_innodb_buffer ( $innodb_buffer )
{
2015-11-19 10:20:56 +00:00
$output = 'InnoDB Buffersize too small.' . PHP_EOL ;
$output .= 'Current size: ' . ( $innodb_buffer [ 'size' ] / 1024 / 1024 ) . ' MiB' . PHP_EOL ;
$output .= 'Minimum Required: ' . ( $innodb_buffer [ 'used' ] / 1024 / 1024 ) . ' MiB' . PHP_EOL ;
$output .= 'To ensure integrity, we\'re not going to pull any updates until the buffersize has been adjusted.' . PHP_EOL ;
2016-08-28 17:32:58 +00:00
$output .= 'Config proposal: "innodb_buffer_pool_size = ' . pow ( 2 , ceil ( log (( $innodb_buffer [ 'used' ] / 1024 / 1024 ), 2 ))) . 'M"' . PHP_EOL ;
2015-11-19 10:20:56 +00:00
return $output ;
}
2016-01-17 16:47:26 +00:00
2016-08-28 17:32:58 +00:00
function oxidized_reload_nodes ()
{
2016-01-17 16:47:26 +00:00
global $config ;
2016-08-28 17:32:58 +00:00
if ( $config [ 'oxidized' ][ 'enabled' ] === true && $config [ 'oxidized' ][ 'reload_nodes' ] === true && isset ( $config [ 'oxidized' ][ 'url' ])) {
2016-02-05 22:29:42 +00:00
$oxidized_reload_url = $config [ 'oxidized' ][ 'url' ] . '/reload?format=json' ;
2016-01-17 16:47:26 +00:00
$ch = curl_init ( $oxidized_reload_url );
curl_setopt ( $ch , CURLOPT_TIMEOUT , 5 );
2017-02-03 14:12:42 +00:00
curl_setopt ( $ch , CURLOPT_TIMEOUT_MS , 5000 );
2016-01-17 16:47:26 +00:00
curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 5 );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_HEADER , 1 );
curl_exec ( $ch );
curl_close ( $ch );
}
}
2016-01-17 23:59:51 +00:00
/**
* Perform DNS lookup
*
* @ param array $device Device array from database
* @ param string $type The type of record to lookup
*
* @ return string ip
*
**/
2016-08-28 17:32:58 +00:00
function dnslookup ( $device , $type = false , $return = false )
{
2016-12-30 00:13:12 +00:00
if ( filter_var ( $device [ 'hostname' ], FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ) == true || filter_var ( $device [ 'hostname' ], FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ) == true ) {
2017-01-28 00:02:39 +00:00
return false ;
2016-01-18 00:04:30 +00:00
}
2016-01-17 23:59:51 +00:00
if ( empty ( $type )) {
// We are going to use the transport to work out the record type
if ( $device [ 'transport' ] == 'udp6' || $device [ 'transport' ] == 'tcp6' ) {
$type = DNS_AAAA ;
$return = 'ipv6' ;
2016-08-28 17:32:58 +00:00
} else {
2016-01-17 23:59:51 +00:00
$type = DNS_A ;
$return = 'ip' ;
}
}
2016-01-18 12:54:25 +00:00
if ( empty ( $return )) {
2017-01-28 00:02:39 +00:00
return false ;
2016-01-18 12:54:25 +00:00
}
2016-08-28 17:32:58 +00:00
$record = dns_get_record ( $device [ 'hostname' ], $type );
2016-01-17 23:59:51 +00:00
return $record [ 0 ][ $return ];
} //end dnslookup
2016-02-01 23:29:37 +00:00
2016-02-02 01:05:29 +00:00
2016-02-01 23:29:37 +00:00
/**
* Run rrdtool info on a file path
*
* @ param string $path Path to pass to rrdtool info
* @ param string $stdOutput Variable to recieve the output of STDOUT
* @ param string $stdError Variable to recieve the output of STDERR
*
* @ return int exit code
*
**/
2016-08-28 17:32:58 +00:00
function rrdtest ( $path , & $stdOutput , & $stdError )
{
2016-02-01 23:46:28 +00:00
global $config ;
2016-02-01 23:29:37 +00:00
//rrdtool info <escaped rrd path>
$command = $config [ 'rrdtool' ] . ' info ' . escapeshellarg ( $path );
$process = proc_open (
$command ,
array (
0 => array ( 'pipe' , 'r' ),
1 => array ( 'pipe' , 'w' ),
2 => array ( 'pipe' , 'w' ),
),
$pipes
);
if ( ! is_resource ( $process )) {
throw new \RuntimeException ( 'Could not create a valid process' );
}
$status = proc_get_status ( $process );
2016-08-28 17:32:58 +00:00
while ( $status [ 'running' ]) {
2016-02-02 11:36:49 +00:00
usleep ( 2000 ); // Sleep 2000 microseconds or 2 milliseconds
2016-02-01 23:29:37 +00:00
$status = proc_get_status ( $process );
}
$stdOutput = stream_get_contents ( $pipes [ 1 ]);
$stdError = stream_get_contents ( $pipes [ 2 ]);
proc_close ( $process );
return $status [ 'exitcode' ];
}
2016-02-26 22:40:34 +00:00
2016-08-28 17:32:58 +00:00
function create_state_index ( $state_name )
{
2017-01-07 17:32:38 +00:00
if ( dbFetchRow ( 'SELECT * FROM state_indexes WHERE state_name = ?' , array ( $state_name )) != true ) {
2016-02-27 15:23:58 +00:00
$insert = array ( 'state_name' => $state_name );
return dbInsert ( $insert , 'state_indexes' );
}
2016-02-26 22:40:34 +00:00
}
function create_sensor_to_state_index ( $device , $state_name , $index )
{
$sensor_entry = dbFetchRow ( 'SELECT sensor_id FROM `sensors` WHERE `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?' , array (
'state' ,
$device [ 'device_id' ],
$state_name ,
$index
));
$state_indexes_entry = dbFetchRow ( 'SELECT state_index_id FROM `state_indexes` WHERE `state_name` = ?' , array (
$state_name
));
if ( ! empty ( $sensor_entry [ 'sensor_id' ]) && ! empty ( $state_indexes_entry [ 'state_index_id' ])) {
$insert = array (
'sensor_id' => $sensor_entry [ 'sensor_id' ],
'state_index_id' => $state_indexes_entry [ 'state_index_id' ],
);
2016-08-28 17:32:58 +00:00
foreach ( $insert as $key => $val_check ) {
2016-02-26 22:40:34 +00:00
if ( ! isset ( $val_check )) {
unset ( $insert [ $key ]);
}
}
2016-02-26 22:56:54 +00:00
dbInsert ( $insert , 'sensors_to_state_indexes' );
2016-02-26 22:40:34 +00:00
}
}
2016-06-15 16:25:14 +00:00
2016-08-28 17:32:58 +00:00
function delta_to_bits ( $delta , $period )
{
2016-07-07 18:10:37 +00:00
return round (( $delta * 8 / $period ), 2 );
2016-06-15 16:25:14 +00:00
}
2016-07-07 18:11:13 +00:00
2016-08-28 17:32:58 +00:00
function report_this ( $message )
{
2016-06-28 23:14:21 +00:00
global $config ;
return '<h2>' . $message . ' Please <a href="' . $config [ 'project_issues' ] . '">report this</a> to the ' . $config [ 'project_name' ] . ' developers.</h2>' ;
} //end report_this()
2016-08-23 18:44:45 +00:00
2016-08-28 17:32:58 +00:00
function hytera_h2f ( $number , $nd )
2016-08-23 18:44:45 +00:00
{
2016-08-28 17:32:58 +00:00
if ( strlen ( str_replace ( " " , " " , $number )) == 4 ) {
2016-08-23 18:44:45 +00:00
$hex = '' ;
for ( $i = 0 ; $i < strlen ( $number ); $i ++ ) {
$byte = strtoupper ( dechex ( ord ( $number { $i })));
$byte = str_repeat ( '0' , 2 - strlen ( $byte )) . $byte ;
$hex .= $byte . " " ;
}
$number = $hex ;
unset ( $hex );
}
$r = '' ;
$y = explode ( ' ' , $number );
foreach ( $y as $z ) {
$r = $z . '' . $r ;
}
$hex = array ();
$number = substr ( $r , 0 , - 1 );
//$number = str_replace(" ", "", $number);
for ( $i = 0 ; $i < strlen ( $number ); $i ++ ) {
2016-08-28 17:32:58 +00:00
$hex [] = substr ( $number , $i , 1 );
2016-08-23 18:44:45 +00:00
}
$dec = array ();
$hexCount = count ( $hex );
for ( $i = 0 ; $i < $hexCount ; $i ++ ) {
$dec [] = hexdec ( $hex [ $i ]);
}
$binfinal = " " ;
$decCount = count ( $dec );
for ( $i = 0 ; $i < $decCount ; $i ++ ) {
2016-08-28 17:32:58 +00:00
$binfinal .= sprintf ( " %04d " , decbin ( $dec [ $i ]));
2016-08-23 18:44:45 +00:00
}
2016-08-28 17:32:58 +00:00
$sign = substr ( $binfinal , 0 , 1 );
$exp = substr ( $binfinal , 1 , 8 );
2016-08-23 18:44:45 +00:00
$exp = bindec ( $exp );
$exp -= 127 ;
2016-08-28 17:32:58 +00:00
$scibin = substr ( $binfinal , 9 );
$binint = substr ( $scibin , 0 , $exp );
$binpoint = substr ( $scibin , $exp );
2016-08-23 18:44:45 +00:00
$intnumber = bindec ( " 1 " . $binint );
$tmppoint = " " ;
for ( $i = 0 ; $i < strlen ( $binpoint ); $i ++ ) {
2016-08-28 17:32:58 +00:00
$tmppoint [] = substr ( $binpoint , $i , 1 );
2016-08-23 18:44:45 +00:00
}
$tmppoint = array_reverse ( $tmppoint );
2016-08-28 17:32:58 +00:00
$tpointnumber = number_format ( $tmppoint [ 0 ] / 2 , strlen ( $binpoint ), '.' , '' );
2016-08-23 18:44:45 +00:00
$pointnumber = " " ;
for ( $i = 1 ; $i < strlen ( $binpoint ); $i ++ ) {
2016-08-28 17:32:58 +00:00
$pointnumber = number_format ( $tpointnumber / 2 , strlen ( $binpoint ), '.' , '' );
$tpointnumber = $tmppoint [ $i + 1 ] . substr ( $pointnumber , 1 );
2016-08-23 18:44:45 +00:00
}
$floatfinal = $intnumber + $pointnumber ;
if ( $sign == 1 ) {
$floatfinal =- $floatfinal ;
}
2016-08-28 17:32:58 +00:00
return number_format ( $floatfinal , $nd , '.' , '' );
2016-08-23 18:44:45 +00:00
}
2016-10-06 00:40:37 +00:00
/*
* Cisco CIMC functions
*/
// Create an entry in the entPhysical table if it doesnt already exist.
function setCIMCentPhysical ( $location , $data , & $entphysical , & $index )
{
// Go get the location, this will create it if it doesnt exist.
$entPhysicalIndex = getCIMCentPhysical ( $location , $entphysical , $index );
// See if we need to update
$update = array ();
foreach ( $data as $key => $value ) {
// Is the Array(DB) value different to the supplied data
if ( $entphysical [ $location ][ $key ] != $value ) {
$update [ $key ] = $value ;
$entphysical [ $location ][ $key ] = $value ;
} // End if
} // end foreach
// Do we need to update
if ( count ( $update ) > 0 ) {
dbUpdate ( $update , 'entPhysical' , '`entPhysical_id` = ?' , array ( $entphysical [ $location ][ 'entPhysical_id' ]));
}
$entPhysicalId = $entphysical [ $location ][ 'entPhysical_id' ];
return array ( $entPhysicalId , $entPhysicalIndex );
}
function getCIMCentPhysical ( $location , & $entphysical , & $index )
{
global $device ;
// Level 1 - Does the location exist
if ( isset ( $entphysical [ $location ])) {
// Yes, return the entPhysicalIndex.
return $entphysical [ $location ][ 'entPhysicalIndex' ];
} else {
/*
* No , the entry doesnt exist .
* Find its parent so we can create it .
*/
// Pull apart the location
$parts = explode ( '/' , $location );
// Level 2 - Are we at the root
if ( count ( $parts ) == 1 ) {
// Level 2 - Yes. We are the root, there is no parent
d_echo ( " ROOT - " . $location . " \n " );
$shortlocation = $location ;
$parent = 0 ;
} else {
// Level 2 - No. Need to go deeper.
d_echo ( " NON-ROOT - " . $location . " \n " );
$shortlocation = array_pop ( $parts );
$parentlocation = implode ( '/' , $parts );
d_echo ( " Decend - parent location: " . $parentlocation . " \n " );
$parent = getCIMCentPhysical ( $parentlocation , $entphysical , $index );
} // end if - Level 2
d_echo ( " Parent: " . $parent . " \n " );
// Now we have an ID, create the entry.
$index ++ ;
$insert = array (
'device_id' => $device [ 'device_id' ],
'entPhysicalIndex' => $index ,
'entPhysicalClass' => 'container' ,
'entPhysicalVendorType' => $location ,
'entPhysicalName' => $shortlocation ,
'entPhysicalContainedIn' => $parent ,
'entPhysicalParentRelPos' => '-1' ,
);
// Add to the DB and Array.
$id = dbInsert ( $insert , 'entPhysical' );
$entphysical [ $location ] = dbFetchRow ( 'SELECT * FROM entPhysical WHERE entPhysical_id=?' , array ( $id ));
return $index ;
} // end if - Level 1
} // end function
2016-10-11 21:29:06 +00:00
/* idea from http://php.net/manual/en/function.hex2bin.php comments */
function hex2bin_compat ( $str )
{
if ( strlen ( $str ) % 2 !== 0 ) {
trigger_error ( __FUNCTION__ . '(): Hexadecimal input string must have an even length' , E_USER_WARNING );
}
return pack ( " H* " , $str );
}
if ( ! function_exists ( 'hex2bin' )) {
// This is only a hack
function hex2bin ( $str )
{
return hex2bin_compat ( $str );
}
}
function q_bridge_bits2indices ( $hex_data )
{
/* convert hex string to an array of 1 - based indices of the nonzero bits
* ie . '9a00' -> '100110100000' -> array ( 1 , 4 , 5 , 7 )
*/
$hex_data = str_replace ( ' ' , '' , $hex_data );
$value = hex2bin ( $hex_data );
$length = strlen ( $value );
$indices = array ();
for ( $i = 0 ; $i < $length ; $i ++ ) {
$byte = ord ( $value [ $i ]);
for ( $j = 7 ; $j >= 0 ; $j -- ) {
if ( $byte & ( 1 << $j )) {
$indices [] = 8 * $i + 8 - $j ;
}
}
}
return $indices ;
}
2016-10-14 23:14:18 +00:00
/**
* @ param array $device
* @ param int | string $raw_value The value returned from snmp
* @ param int $capacity the normalized capacity
* @ return int the toner level as a percentage
*/
function get_toner_levels ( $device , $raw_value , $capacity )
{
// -3 means some toner is left
if ( $raw_value == '-3' ) {
return 50 ;
}
2017-01-31 08:07:50 +00:00
// -2 means unknown
if ( $raw_value == '-2' ) {
return false ;
}
// -1 mean no restrictions
if ( $raw_value == '-1' ) {
2016-10-14 23:14:18 +00:00
return 0 ; // FIXME: is 0 what we should return?
}
// Non-standard snmp values
if ( $device [ 'os' ] == 'ricoh' || $device [ 'os' ] == 'nrg' || $device [ 'os' ] == 'lanier' ) {
if ( $raw_value == '-100' ) {
return 0 ;
}
} elseif ( $device [ 'os' ] == 'brother' ) {
if ( ! str_contains ( $device [ 'hardware' ], 'MFC-L8850' )) {
switch ( $raw_value ) {
case '0' :
return 100 ;
case '1' :
return 5 ;
case '2' :
return 0 ;
case '3' :
return 1 ;
}
}
}
return round ( $raw_value / $capacity * 100 );
}
2016-10-18 03:06:03 +00:00
/**
* check if we should skip this device from discovery
* @ param $needles
* @ param $haystack
* @ param $name
* @ return bool
*/
function can_skip_discovery ( $needles , $haystack , $name )
{
foreach (( array ) $needles as $needle ) {
if ( preg_match ( $needle . " i " , $haystack )) {
d_echo ( " { $name } - regexp ' { $needle } ' matches ' { $haystack } ' - skipping device discovery \n " );
return true ;
}
}
return false ;
}
2016-11-23 06:57:19 +00:00
/**
* Intialize global stat arrays
*/
function initStats ()
{
global $snmp_stats , $db_stats ;
if ( ! isset ( $snmp_stats )) {
$snmp_stats = array (
'snmpget' => 0 ,
'snmpget_sec' => 0.0 ,
'snmpwalk' => 0 ,
'snmpwalk_sec' => 0.0 ,
);
}
if ( ! isset ( $db_stats )) {
$db_stats = array (
'insert' => 0 ,
'insert_sec' => 0.0 ,
'update' => 0 ,
'update_sec' => 0.0 ,
'fetchcell' => 0 ,
'fetchcell_sec' => 0.0 ,
'fetchcol' => 0 ,
'fetchcol_sec' => 0.0 ,
'fetchrow' => 0 ,
'fetchrow_sec' => 0.0 ,
'fetchrows' => 0 ,
'fetchrows_sec' => 0.0 ,
);
}
}
/**
* Print global stat arrays
*/
function printStats ()
{
global $snmp_stats , $db_stats ;
printf (
" SNMP: Get[%d/%.2fs] Walk [%d/%.2fs] \n " ,
$snmp_stats [ 'snmpget' ],
$snmp_stats [ 'snmpget_sec' ],
$snmp_stats [ 'snmpwalk' ],
$snmp_stats [ 'snmpwalk_sec' ]
);
printf (
" MySQL: Cell[%d/%.2fs] Row[%d/%.2fs] Rows[%d/%.2fs] Column[%d/%.2fs] Update[%d/%.2fs] Insert[%d/%.2fs] Delete[%d/%.2fs] \n " ,
$db_stats [ 'fetchcell' ],
$db_stats [ 'fetchcell_sec' ],
$db_stats [ 'fetchrow' ],
$db_stats [ 'fetchrow_sec' ],
$db_stats [ 'fetchrows' ],
$db_stats [ 'fetchrows_sec' ],
$db_stats [ 'fetchcolumn' ],
$db_stats [ 'fetchcolumn_sec' ],
$db_stats [ 'update' ],
$db_stats [ 'update_sec' ],
$db_stats [ 'insert' ],
$db_stats [ 'insert_sec' ],
$db_stats [ 'delete' ],
$db_stats [ 'delete_sec' ]
);
}
/**
* Update statistics for db operations
*
* @ param string $stat fetchcell , fetchrow , fetchrows , fetchcolumn , update , insert , delete
* @ param float $start_time The time the operation started with 'microtime(true)'
* @ return float The calculated run time
*/
function recordDbStatistic ( $stat , $start_time )
{
global $db_stats ;
initStats ();
$runtime = microtime ( true ) - $start_time ;
$db_stats [ $stat ] ++ ;
$db_stats [ " ${ stat } _sec " ] += $runtime ;
//double accounting corrections
if ( $stat == 'fetchcolumn' ) {
$db_stats [ 'fetchrows' ] -- ;
$db_stats [ 'fetchrows_sec' ] -= $runtime ;
}
if ( $stat == 'fetchcell' ) {
$db_stats [ 'fetchrow' ] -- ;
$db_stats [ 'fetchrow_sec' ] -= $runtime ;
}
return $runtime ;
}
/**
* @ param string $stat snmpget , snmpwalk
* @ param float $start_time The time the operation started with 'microtime(true)'
* @ return float The calculated run time
*/
function recordSnmpStatistic ( $stat , $start_time )
{
global $snmp_stats ;
initStats ();
$runtime = microtime ( true ) - $start_time ;
$snmp_stats [ $stat ] ++ ;
$snmp_stats [ " ${ stat } _sec " ] += $runtime ;
return $runtime ;
}
2017-02-14 12:56:16 +00:00
2017-02-15 15:22:09 +00:00
/**
* @ param $device
* @ param bool $record_perf
* @ return array
*/
function device_is_up ( $device , $record_perf = false )
{
$address_family = snmpTransportToAddressFamily ( $device [ 'transport' ]);
$ping_response = isPingable ( $device [ 'hostname' ], $address_family , $device [ 'attribs' ]);
$device_perf = $ping_response [ 'db' ];
$device_perf [ 'device_id' ] = $device [ 'device_id' ];
$device_perf [ 'timestamp' ] = array ( 'NOW()' );
if ( $record_perf === true && can_ping_device ( $device [ 'attribs' ]) === true ) {
dbInsert ( $device_perf , 'device_perf' );
}
$response = array ();
$response [ 'ping_time' ] = $ping_response [ 'last_ping_timetaken' ];
if ( $ping_response [ 'result' ]) {
if ( isSNMPable ( $device )) {
$response [ 'status' ] = '1' ;
$response [ 'status_reason' ] = '' ;
} else {
echo 'SNMP Unreachable' ;
$response [ 'status' ] = '0' ;
$response [ 'status_reason' ] = 'snmp' ;
}
} else {
echo 'Unpingable' ;
$response [ 'status' ] = '0' ;
$response [ 'status_reason' ] = 'icmp' ;
}
if ( $device [ 'status' ] != $response [ 'status' ]) {
dbUpdate ( array ( 'status' => $response [ 'status' ], 'status_reason' => $response [ 'status_reason' ]), 'devices' , 'device_id=?' , array ( $device [ 'device_id' ]));
log_event ( 'Device status changed to ' . ( $response [ 'status' ] == '1' ? 'Up' : 'Down' ) . ' from ' . $response [ 'status_reason' ] . ' check.' , $device , ( $response [ 'status' ] == '1' ? 'up' : 'down' ));
}
return $response ;
}
2017-02-14 23:04:55 +00:00
function update_device_logo ( & $device )
2017-02-14 12:56:16 +00:00
{
$icon = getImageName ( $device , false );
if ( $icon != $device [ 'icon' ]) {
log_event ( 'Device Icon changed ' . $device [ 'icon' ] . " => $icon " , $device , 'system' , 3 );
$device [ 'icon' ] = $icon ;
2017-02-14 23:04:55 +00:00
dbUpdate ( array ( 'icon' => $icon ), 'devices' , 'device_id=?' , array ( $device [ 'device_id' ]));
2017-02-14 12:56:16 +00:00
echo " Changed Icon! : $icon\n " ;
}
}
2017-03-22 10:17:13 +00:00
/**
* Function to generate PeeringDB Cache
*/
function cache_peeringdb ()
{
global $config ;
if ( $config [ 'peeringdb' ][ 'enabled' ] === true ) {
$peeringdb_url = 'https://peeringdb.com/api' ;
// We cache for 71 hours
$cached = dbFetchCell ( " SELECT count(*) FROM `pdb_ix` WHERE (UNIX_TIMESTAMP() - timestamp) < 255600 " );
if ( $cached == 0 ) {
$rand = rand ( 30 , 600 );
echo " No cached PeeringDB data found, sleeping for $rand seconds " . PHP_EOL ;
sleep ( $rand );
foreach ( dbFetchRows ( " SELECT `bgpLocalAs` FROM `devices` WHERE `disabled` = 0 AND `ignore` = 0 AND `bgpLocalAs` > 0 AND (`bgpLocalAs` < 64512 OR `bgpLocalAs` > 65535) AND `bgpLocalAs` < 4200000000 GROUP BY `bgpLocalAs` " ) as $as ) {
$asn = $as [ 'bgpLocalAs' ];
$get = Requests :: get ( $peeringdb_url . '/net?depth=2&asn=' . $asn , array (), array ( 'proxy' => get_proxy ()));
$json_data = $get -> body ;
$data = json_decode ( $json_data );
$ixs = $data -> { 'data' }{ 0 } -> { 'netixlan_set' };
foreach ( $ixs as $ix ) {
$ixid = $ix -> { 'ix_id' };
$tmp_ix = dbFetchRow ( " SELECT * FROM `pdb_ix` WHERE `ix_id` = ? AND asn = ? " , array ( $ixid , $asn ));
if ( $tmp_ix ) {
$pdb_ix_id = $tmp_ix [ 'pdb_ix_id' ];
$update = array ( 'name' => $ix -> { 'name' }, 'timestamp' => time ());
2017-03-23 10:08:48 +00:00
dbUpdate ( $update , 'pdb_ix' , '`ix_id` = ? AND `asn` = ?' , array ( $ixid , $asn ));
2017-03-22 10:17:13 +00:00
} else {
$insert = array (
'ix_id' => $ixid ,
'name' => $ix -> { 'name' },
'asn' => $asn ,
'timestamp' => time ()
);
$pdb_ix_id = dbInsert ( $insert , 'pdb_ix' );
}
$keep = $pdb_ix_id ;
$get_ix = Requests :: get ( " $peeringdb_url /netixlan?ix_id= $ixid " , array (), array ( 'proxy' => get_proxy ()));
$ix_json = $get_ix -> body ;
$ix_data = json_decode ( $ix_json );
$peers = $ix_data -> { 'data' };
foreach ( $peers as $index => $peer ) {
$peer_name = get_astext ( $peer -> { 'asn' });
$tmp_peer = dbFetchRow ( " SELECT * FROM `pdb_ix_peers` WHERE `peer_id` = ? AND `ix_id` = ? " , array ( $peer -> { 'id' }, $ixid ));
if ( $tmp_peer ) {
$peer_keep [] = $tmp_peer [ 'pdb_ix_peers_id' ];
$update = array (
'remote_asn' => $peer -> { 'asn' },
'remote_ipaddr4' => $peer -> { 'ipaddr4' },
'remote_ipaddr6' => $peer -> { 'ipaddr6' },
'name' => $peer_name ,
);
dbUpdate ( $update , 'pdb_ix_peers' , '`pdb_ix_peers_id` = ?' , array ( $tmp_peer [ 'pdb_ix_peers_id' ]));
} else {
$peer_insert = array (
'ix_id' => $ixid ,
'peer_id' => $peer -> { 'id' },
'remote_asn' => $peer -> { 'asn' },
'remote_ipaddr4' => $peer -> { 'ipaddr4' },
'remote_ipaddr6' => $peer -> { 'ipaddr6' },
'name' => $peer_name ,
'timestamp' => time ()
);
$peer_keep [] = dbInsert ( $peer_insert , 'pdb_ix_peers' );
}
}
$pdb_ix_peers_ids = implode ( ',' , $peer_keep );
dbDelete ( 'pdb_ix_peers' , " `pdb_ix_peers_id` NOT IN ( $pdb_ix_peers_ids ) " );
}
$pdb_ix_ids = implode ( ',' , $keep );
dbDelete ( 'pdb_ix' , " `pdb_ix_id` NOT IN ( $pdb_ix_ids ) " );
}
} else {
echo " Cached PeeringDB data found..... " . PHP_EOL ;
}
} else {
echo 'Peering DB integration disabled' . PHP_EOL ;
}
}
2017-04-05 08:00:28 +00:00
/**
* Dump the database schema to an array .
* The top level will be a list of tables
* Each table contains the keys Columns and Indexes .
*
* Each entry in the Columns array contains these keys : Field , Type , Null , Default , Extra
* Each entry in the Indexes array contains these keys : Name , Columns ( array ), Unique
*
* @ return array
*/
function dump_db_schema ()
{
global $config ;
$output = array ();
foreach ( dbFetchRows ( " SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ' { $config [ 'db_name' ] } ' ORDER BY TABLE_NAME; " ) as $table ) {
$table = $table [ 'TABLE_NAME' ];
foreach ( dbFetchRows ( " SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ' { $config [ 'db_name' ] } ' AND TABLE_NAME=' $table ' ORDER BY COLUMN_NAME " ) as $data ) {
$column = $data [ 'COLUMN_NAME' ];
$output [ $table ][ 'Columns' ][ $column ] = array (
'Field' => $data [ 'COLUMN_NAME' ],
'Type' => $data [ 'COLUMN_TYPE' ],
'Null' => $data [ 'IS_NULLABLE' ] === 'YES' ,
'Default' => $data [ 'COLUMN_DEFAULT' ],
'Extra' => $data [ 'EXTRA' ],
);
}
foreach ( dbFetchRows ( " SHOW INDEX FROM ` $table ` " ) as $key ) {
$key_name = $key [ 'Key_name' ];
if ( isset ( $output [ $table ][ 'Indexes' ][ $key_name ])) {
$output [ $table ][ 'Indexes' ][ $key_name ][ 'Columns' ][] = $key [ 'Column_name' ];
} else {
$output [ $table ][ 'Indexes' ][ $key_name ] = array (
'Name' => $key [ 'Key_name' ],
'Columns' => array ( $key [ 'Column_name' ]),
'Unique' => ! $key [ 'Non_unique' ],
'Type' => $key [ 'Index_type' ],
);
}
}
}
return $output ;
}
/**
* Generate an SQL segment to create the column based on data from dump_db_schema ()
*
* @ param array $column_data The array of data for the column
* @ return string sql fragment , for example : " `ix_id` int(10) unsigned NOT NULL "
*/
function column_schema_to_sql ( $column_data )
{
$null = $column_data [ 'Null' ] ? 'NULL' : 'NOT NULL' ;
$default = $column_data [ 'Default' ] == '' ? '' : " DEFAULT ' { $column_data [ 'Default' ] } ' " ;
if ( str_contains ( $default , 'CURRENT_TIMESTAMP' )) {
$default = str_replace ( " ' " , " " , $default );
}
return trim ( " ` { $column_data [ 'Field' ] } ` { $column_data [ 'Type' ] } $null $default { $column_data [ 'Extra' ] } " );
}
/**
* Generate an SQL segment to create the index based on data from dump_db_schema ()
*
* @ param array $index_data The array of data for the index
* @ return string sql fragment , for example : " PRIMARY KEY (`device_id`) "
*/
function index_schema_to_sql ( $index_data )
{
if ( $index_data [ 'Name' ] == 'PRIMARY' ) {
2017-04-05 15:20:14 +00:00
$index = 'PRIMARY KEY (%s)' ;
2017-04-05 08:00:28 +00:00
} elseif ( $index_data [ 'Unique' ]) {
2017-04-05 15:20:14 +00:00
$index = " UNIQUE ` { $index_data [ 'Name' ] } ` (%s) " ;
2017-04-05 08:00:28 +00:00
} else {
2017-04-05 15:20:14 +00:00
$index = " INDEX ` { $index_data [ 'Name' ] } ` (%s) " ;
2017-04-05 08:00:28 +00:00
}
$columns = implode ( ',' , array_map ( function ( $col ) {
return " ` $col ` " ;
}, $index_data [ 'Columns' ]));
2017-04-05 15:20:14 +00:00
return sprintf ( $index , $columns );
2017-04-05 08:00:28 +00:00
}
2017-04-13 09:18:12 +00:00
/**
* Get an array of the schema files .
* schema_version => full_file_name
*
* @ return mixed
*/
function get_schema_list ()
{
global $config ;
// glob returns an array sorted by filename
$files = glob ( $config [ 'install_dir' ] . '/sql-schema/*.sql' );
// set the keys to the db schema version
return array_reduce ( $files , function ( $array , $file ) {
$array [ basename ( $file , '.sql' )] = $file ;
return $array ;
}, array ());
}
/**
* Get the current database schema , will return 0 if there is no schema .
*
* @ return int
*/
function get_db_schema ()
{
return ( int ) @ dbFetchCell ( 'SELECT version FROM `dbSchema` ORDER BY version DESC LIMIT 1' );
}
/**
* Check if the database schema is up to date .
*
* @ return bool
*/
function db_schema_is_current ()
{
$current = get_db_schema ();
$schemas = get_schema_list ();
end ( $schemas );
$latest = key ( $schemas );
return $current >= $latest ;
}