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 14:12:23 +01:00
* LibreNMS
2012-05-21 16:52:02 +00:00
*
2016-09-08 14:12:23 +01:00
* This file is part of LibreNMS.
2012-05-21 16:52:02 +00:00
*
* @copyright (C) 2006 - 2012 Adam Armstrong
*/
2020-04-17 17:37:56 -05:00
use Illuminate\Support\Str ;
2017-09-21 12:02:01 -05:00
use LibreNMS\Config ;
2023-08-05 12:12:36 -05:00
use LibreNMS\Enum\Severity ;
2016-08-21 08:07:14 -05:00
2018-07-12 15:30:39 -05:00
/**
* Parse cli discovery or poller modules and set config for this run
*
2021-09-08 23:35:56 +02:00
* @param string $type discovery or poller
* @param array $options get_opts array (only m key is checked)
2018-07-12 15:30:39 -05:00
* @return bool
*/
function parse_modules ( $type , $options )
{
$override = false ;
2021-11-17 19:23:55 -06:00
if ( ! empty ( $options [ 'm' ])) {
2018-07-12 15:30:39 -05:00
Config :: set ( " { $type } _modules" , []);
foreach ( explode ( ',' , $options [ 'm' ]) as $module ) {
// parse submodules (only supported by some modules)
2020-04-17 17:37:56 -05:00
if ( Str :: contains ( $module , '/' )) {
2020-05-19 14:35:32 -05:00
[ $module , $submodule ] = explode ( '/' , $module , 2 );
2018-07-12 15:30:39 -05:00
$existing_submodules = Config :: get ( " { $type } _submodules. $module " , []);
$existing_submodules [] = $submodule ;
Config :: set ( " { $type } _submodules. $module " , $existing_submodules );
}
$dir = $type == 'poller' ? 'polling' : $type ;
if ( is_file ( "includes/ $dir / $module .inc.php" )) {
Config :: set ( " { $type } _modules. $module " , 1 );
$override = true ;
}
}
// display selected modules
$modules = array_map ( function ( $module ) use ( $type ) {
$submodules = Config :: get ( " { $type } _submodules. $module " );
2020-09-21 15:40:17 +02:00
2018-07-12 15:30:39 -05:00
return $module . ( $submodules ? '(' . implode ( ',' , $submodules ) . ')' : '' );
}, array_keys ( Config :: get ( " { $type } _modules" , [])));
d_echo ( "Override $type modules: " . implode ( ', ' , $modules ) . PHP_EOL );
}
return $override ;
}
2016-08-28 12:32:58 -05:00
function logfile ( $string )
{
2023-08-19 09:09:00 -05:00
$file = Config :: get ( 'log_file' );
$fd = fopen ( $file , 'a' );
if ( $fd === false ) {
print_error ( "Error: Could not write to log file: $file " );
return ;
}
2016-08-28 12:32:58 -05:00
fputs ( $fd , $string . " \n " );
2011-03-23 09:54:56 +00:00
fclose ( $fd );
2010-11-24 11:32:53 +00:00
}
2016-08-28 12:32:58 -05:00
function percent_colour ( $perc )
{
2011-03-27 10:21:19 +00:00
$r = min ( 255 , 5 * ( $perc - 25 ));
$b = max ( 0 , 255 - ( 5 * ( $perc + 25 )));
return sprintf ( '#%02x%02x%02x' , $r , $b , $b );
2011-03-08 17:12:43 +00:00
}
2007-06-24 14:56:47 +00:00
2017-01-24 16:16:01 -06:00
/**
2023-06-13 13:35:00 +02:00
* @param $device
2017-01-24 16:16:01 -06:00
* @return string the path to the icon image for this device. Close to square.
*/
function getIcon ( $device )
2016-08-28 12:32:58 -05:00
{
2017-01-08 20:32:17 +01:00
return 'images/os/' . getImageName ( $device );
2016-02-23 23:44:51 -06:00
}
2017-01-24 16:16:01 -06:00
/**
2023-06-13 13:35:00 +02:00
* @param $device
2017-01-24 16:16:01 -06:00
* @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 16:16:01 -06:00
return $device [ 'icon' ] ? str_replace ([ '.svg' , '.png' ], '' , $device [ 'icon' ]) : $device [ 'os' ];
}
function getImageName ( $device , $use_database = true , $dir = 'images/os/' )
2016-08-28 12:32:58 -05:00
{
2022-08-30 12:55:37 -05:00
return \LibreNMS\Util\Url :: findOsImage ( $device [ 'os' ], $device [ 'features' ] ?? '' , $use_database ? $device [ 'icon' ] : null , $dir );
2008-11-19 12:12:54 +00:00
}
2016-08-28 12:32:58 -05:00
function renamehost ( $id , $new , $source = 'console' )
{
2018-08-30 14:38:29 -05:00
$host = gethostbyid ( $id );
2023-11-02 06:09:59 +01:00
$new_rrd_dir = Rrd :: dirFromHost ( $new );
2015-07-13 20:10:26 +02:00
2023-11-02 06:09:59 +01:00
if ( is_dir ( $new_rrd_dir )) {
log_event ( "Renaming of $host failed due to existing RRD folder for $new " , $id , 'system' , 5 );
return "Renaming of $host failed due to existing RRD folder for $new \n " ;
}
if ( ! is_dir ( $new_rrd_dir ) && rename ( Rrd :: dirFromHost ( $host ), $new_rrd_dir ) === true ) {
2018-08-30 14:38:29 -05:00
dbUpdate ([ 'hostname' => $new , 'ip' => null ], 'devices' , 'device_id=?' , [ $id ]);
2017-02-13 00:41:05 +02:00
log_event ( "Hostname changed -> $new ( $source )" , $id , 'system' , 3 );
2020-09-21 15:40:17 +02:00
2018-08-30 14:38:29 -05:00
return '' ;
2015-07-13 20:10:26 +02:00
}
2018-08-30 14:38:29 -05:00
log_event ( "Renaming of $host failed" , $id , 'system' , 5 );
2020-09-21 15:40:17 +02:00
2018-08-30 14:38:29 -05:00
return "Renaming of $host failed \n " ;
2007-04-03 14:10:23 +00:00
}
2019-12-08 22:17:27 +01:00
function device_discovery_trigger ( $id )
{
2021-05-13 07:18:54 -05:00
if ( App :: runningInConsole () === false ) {
2019-12-08 22:17:27 +01:00
ignore_user_abort ( true );
set_time_limit ( 0 );
}
2023-10-12 07:15:03 -07:00
$update = dbUpdate ([ 'last_discovered' => null ], 'devices' , '`device_id` = ?' , [ $id ]);
2019-12-08 22:17:27 +01:00
if ( ! empty ( $update ) || $update == '0' ) {
$message = 'Device will be rediscovered' ;
} else {
$message = 'Error rediscovering device' ;
}
2020-09-21 15:40:17 +02:00
2024-01-05 05:39:12 +01:00
return [ 'status' => $update , 'message' => $message ];
2019-12-08 22:17:27 +01:00
}
2016-08-28 12:32:58 -05:00
function delete_device ( $id )
{
2022-01-29 21:09:05 -06:00
$device = DeviceCache :: get ( $id );
if ( ! $device -> exists ) {
return 'No such device.' ;
2015-07-13 20:10:26 +02:00
}
2022-01-29 21:09:05 -06:00
if ( $device -> delete ()) {
return "Removed device $device->hostname \n " ;
2015-07-13 20:10:26 +02:00
}
2022-01-29 21:09:05 -06:00
return "Failed to remove device $device->hostname " ;
2015-07-13 20:10:26 +02:00
}
2016-08-28 12:32:58 -05:00
function isDomainResolves ( $domain )
{
2017-01-24 15:56:51 -06:00
if ( gethostbyname ( $domain ) != $domain ) {
return true ;
}
$records = dns_get_record ( $domain ); // returns array or false
2020-09-21 15:40:17 +02:00
2017-01-24 15:56:51 -06:00
return ! empty ( $records );
2007-04-03 14:10:23 +00:00
}
2016-08-28 12:32:58 -05:00
function match_network ( $nets , $ip , $first = false )
{
2011-03-23 09:54:56 +00:00
$return = false ;
2016-08-28 12:32:58 -05:00
if ( ! is_array ( $nets )) {
$nets = [ $nets ];
}
2011-03-23 09:54:56 +00:00
foreach ( $nets as $net ) {
2016-08-28 12:32:58 -05:00
$rev = ( preg_match ( "/^\!/" , $net )) ? true : false ;
$net = preg_replace ( "/^\!/" , '' , $net );
2011-03-23 09:54:56 +00:00
$ip_arr = explode ( '/' , $net );
$net_long = ip2long ( $ip_arr [ 0 ]);
$x = ip2long ( $ip_arr [ 1 ]);
2021-09-08 03:33:54 +02:00
$mask = long2ip ( $x ) == $ip_arr [ 1 ] ? $x : 0xFFFFFFFF << ( 32 - $ip_arr [ 1 ]);
2011-03-23 09:54:56 +00:00
$ip_long = ip2long ( $ip );
if ( $rev ) {
if (( $ip_long & $mask ) == ( $net_long & $mask )) {
return false ;
2015-07-13 20:10:26 +02:00
}
2016-08-28 12:32:58 -05:00
} else {
2011-03-23 09:54:56 +00:00
if (( $ip_long & $mask ) == ( $net_long & $mask )) {
$return = true ;
2015-07-13 20:10:26 +02:00
}
2011-03-23 09:54:56 +00:00
if ( $first && $return ) {
return true ;
2011-03-11 18:03:49 +00:00
}
2011-03-23 09:54:56 +00:00
}
2015-07-13 20:10:26 +02:00
}
2011-03-23 09:54:56 +00:00
return $return ;
2007-04-03 14:10:23 +00:00
}
2021-04-08 14:57:17 +02:00
// FIXME port to LibreNMS\Util\IPv6 class
function snmp2ipv6 ( $ipv6_snmp )
{
// 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)"
$ipv6 = array_slice ( explode ( '.' , $ipv6_snmp ), - 16 );
$ipv6_2 = [];
for ( $i = 0 ; $i <= 15 ; $i ++ ) {
$ipv6 [ $i ] = zeropad ( dechex ( $ipv6 [ $i ]));
}
for ( $i = 0 ; $i <= 15 ; $i += 2 ) {
$ipv6_2 [] = $ipv6 [ $i ] . $ipv6 [ $i + 1 ];
}
return implode ( ':' , $ipv6_2 );
}
2017-03-12 08:05:31 -05:00
/**
* Log events to the event table
*
2021-09-08 23:35:56 +02:00
* @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-03-12 08:05:31 -05:00
*/
2017-02-13 00:41:05 +02:00
function log_event ( $text , $device = null , $type = null , $severity = 2 , $reference = null )
2016-08-28 12:32:58 -05:00
{
2020-04-11 19:53:25 -05:00
// handle legacy device array
if ( is_array ( $device ) && isset ( $device [ 'device_id' ])) {
$device = $device [ 'device_id' ];
}
2023-08-05 12:12:36 -05:00
\App\Models\Eventlog :: log ( $text , $device , $type , Severity :: tryFrom (( int ) $severity ) ?? Severity :: Info , $reference );
2011-03-08 17:12:43 +00:00
}
2010-02-17 11:02:18 +00:00
2016-08-28 12:32:58 -05:00
function hex2str ( $hex )
{
2011-03-23 09:54:56 +00:00
$string = '' ;
2011-03-11 18:03:49 +00:00
2011-03-26 19:12:24 +00:00
for ( $i = 0 ; $i < strlen ( $hex ) - 1 ; $i += 2 ) {
2017-02-12 07:20:06 -06:00
$string .= chr ( hexdec ( substr ( $hex , $i , 2 )));
2011-03-23 09:54:56 +00:00
}
2011-03-11 18:03:49 +00:00
2011-03-23 09:54:56 +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 12:32:58 -05: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 12:32:58 -05:00
function isHexString ( $str )
{
2017-02-16 02:15:20 -06: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
}
2017-09-21 12:02:01 -05:00
/**
* Check if port is valid to poll.
2020-01-24 19:58:01 +08:00
* Settings: empty_ifdescr, good_if, bad_if, bad_if_regexp, bad_ifname_regexp, bad_ifalias_regexp, bad_iftype, bad_ifoperstatus
2017-09-21 12:02:01 -05:00
*
2021-09-08 23:35:56 +02:00
* @param array $port
* @param array $device
2017-09-21 12:02:01 -05:00
* @return bool
*/
2016-08-28 12:32:58 -05:00
function is_port_valid ( $port , $device )
{
2017-09-21 12:02:01 -05:00
// check empty values first
if ( empty ( $port [ 'ifDescr' ])) {
2017-02-03 19:49:40 +00:00
// If these are all empty, we are just going to show blank names in the ui
2017-09-21 12:02:01 -05:00
if ( empty ( $port [ 'ifAlias' ]) && empty ( $port [ 'ifName' ])) {
2018-08-04 16:10:57 -05:00
d_echo ( "ignored: empty ifDescr, ifAlias and ifName \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2015-07-13 20:10:26 +02:00
}
2017-09-21 12:02:01 -05:00
// ifDescr should not be empty unless it is explicitly allowed
2020-05-19 14:35:32 -05:00
if ( ! Config :: getOsSetting ( $device [ 'os' ], 'empty_ifdescr' , Config :: get ( 'empty_ifdescr' , false ))) {
2018-08-04 16:10:57 -05:00
d_echo ( "ignored: empty ifDescr \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2015-07-13 20:10:26 +02:00
}
2017-09-21 12:02:01 -05:00
}
$ifDescr = $port [ 'ifDescr' ];
2023-08-13 11:43:52 -05:00
$ifName = $port [ 'ifName' ] ?? '' ;
2022-08-21 16:23:43 -05:00
$ifAlias = $port [ 'ifAlias' ] ?? '' ;
2017-09-21 12:02:01 -05:00
$ifType = $port [ 'ifType' ];
2022-08-21 16:23:43 -05:00
$ifOperStatus = $port [ 'ifOperStatus' ] ?? '' ;
2017-09-21 12:02:01 -05:00
2020-05-19 14:35:32 -05:00
if ( str_i_contains ( $ifDescr , Config :: getOsSetting ( $device [ 'os' ], 'good_if' , Config :: get ( 'good_if' )))) {
2017-09-21 12:02:01 -05:00
return true ;
}
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_if' ) as $bi ) {
2018-01-29 15:58:21 -06:00
if ( str_i_contains ( $ifDescr , $bi )) {
2017-09-21 12:02:01 -05:00
d_echo ( "ignored by ifDescr: $ifDescr (matched: $bi ) \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2012-03-29 12:05:45 +00:00
}
2017-09-21 12:02:01 -05:00
}
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_if_regexp' ) as $bir ) {
if ( preg_match ( $bir . 'i' , $ifDescr )) {
d_echo ( "ignored by ifDescr: $ifDescr (matched: $bir ) \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2017-09-17 08:21:28 +01:00
}
2017-09-21 12:02:01 -05:00
}
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_ifname_regexp' ) as $bnr ) {
if ( preg_match ( $bnr . 'i' , $ifName )) {
d_echo ( "ignored by ifName: $ifName (matched: $bnr ) \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2017-09-17 08:21:28 +01:00
}
2017-09-21 12:02:01 -05:00
}
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_ifalias_regexp' ) as $bar ) {
if ( preg_match ( $bar . 'i' , $ifAlias )) {
d_echo ( "ignored by ifName: $ifAlias (matched: $bar ) \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2017-09-17 08:21:28 +01:00
}
2017-09-21 12:02:01 -05:00
}
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_iftype' ) as $bt ) {
2020-04-17 17:37:56 -05:00
if ( Str :: contains ( $ifType , $bt )) {
2017-09-21 12:02:01 -05:00
d_echo ( "ignored by ifType: $ifType (matched: $bt ) \n " );
2020-09-21 15:40:17 +02:00
2017-09-21 12:02:01 -05:00
return false ;
2012-03-29 12:05:45 +00:00
}
}
2011-05-18 23:08:45 +00:00
2020-01-24 19:58:01 +08:00
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_ifoperstatus' ) as $bos ) {
2020-04-17 17:37:56 -05:00
if ( Str :: contains ( $ifOperStatus , $bos )) {
2020-01-24 19:58:01 +08:00
d_echo ( "ignored by ifOperStatus: $ifOperStatus (matched: $bos ) \n " );
2020-09-21 15:40:17 +02:00
2020-01-24 19:58:01 +08:00
return false ;
}
}
2017-09-21 12:02:01 -05:00
return true ;
2011-05-18 23:08:45 +00:00
}
2019-01-19 18:48:30 +01:00
/**
* Try to fill in data for ifDescr, ifName, and ifAlias if devices do not provide them.
* Will not fill ifAlias if the user has overridden it
2022-10-11 19:50:38 +02:00
* Also trims the data
2019-01-19 18:48:30 +01:00
*
2021-09-08 23:35:56 +02:00
* @param array $port
* @param array $device
2019-01-19 18:48:30 +01:00
*/
2022-10-11 19:50:38 +02:00
function port_fill_missing_and_trim ( & $port , $device )
2019-01-19 18:48:30 +01:00
{
2023-08-13 11:43:52 -05:00
$port [ 'ifDescr' ] = isset ( $port [ 'ifDescr' ]) ? trim ( $port [ 'ifDescr' ]) : null ;
$port [ 'ifAlias' ] = isset ( $port [ 'ifAlias' ]) ? trim ( $port [ 'ifAlias' ]) : null ;
$port [ 'ifName' ] = isset ( $port [ 'ifName' ]) ? trim ( $port [ 'ifName' ]) : null ;
2019-01-19 18:48:30 +01:00
// When devices do not provide data, populate with other data if available
2022-08-21 16:23:43 -05:00
if ( ! isset ( $port [ 'ifDescr' ]) || $port [ 'ifDescr' ] == '' ) {
2019-01-19 18:48:30 +01:00
$port [ 'ifDescr' ] = $port [ 'ifName' ];
d_echo ( ' Using ifName as ifDescr' );
}
2023-10-11 18:29:47 -05:00
$attrib = DeviceCache :: get ( $device [ 'device_id' ] ?? null ) -> getAttrib ( 'ifName:' . $port [ 'ifName' ]);
if ( ! empty ( $attrib )) {
2019-01-19 18:48:30 +01:00
// ifAlias overridden by user, don't update it
unset ( $port [ 'ifAlias' ]);
d_echo ( ' ifAlias overriden by user' );
2022-08-21 16:23:43 -05:00
} elseif ( ! isset ( $port [ 'ifAlias' ]) || $port [ 'ifAlias' ] == '' ) {
2019-01-19 18:48:30 +01:00
$port [ 'ifAlias' ] = $port [ 'ifDescr' ];
d_echo ( ' Using ifDescr as ifAlias' );
}
2022-08-21 16:23:43 -05:00
if ( ! isset ( $port [ 'ifName' ]) || $port [ 'ifName' ] == '' ) {
2019-01-19 18:48:30 +01:00
$port [ 'ifName' ] = $port [ 'ifDescr' ];
d_echo ( ' Using ifDescr as ifName' );
}
}
2016-08-28 12:32:58 -05:00
function validate_device_id ( $id )
{
if ( empty ( $id ) || ! is_numeric ( $id )) {
2014-06-26 00:33:00 +01:00
$return = false ;
2016-08-28 12:32:58 -05:00
} else {
2014-06-26 00:33:00 +01:00
$device_id = dbFetchCell ( 'SELECT `device_id` FROM `devices` WHERE `device_id` = ?' , [ $id ]);
2016-08-28 12:32:58 -05:00
if ( $device_id == $id ) {
2014-06-26 00:33:00 +01:00
$return = true ;
2016-08-28 12:32:58 -05:00
} else {
2014-06-26 00:33:00 +01:00
$return = false ;
}
2014-06-24 16:14:42 +01:00
}
2020-09-21 15:40:17 +02:00
2014-06-24 16:14:42 +01:00
return $return ;
}
2014-09-17 21:03:02 +01:00
2016-08-28 12:32:58 -05:00
function convert_delay ( $delay )
{
2021-04-28 15:31:45 -05:00
if ( preg_match ( '/(\d+)([mhd]?)/' , $delay , $matches )) {
$multipliers = [
'm' => 60 ,
'h' => 3600 ,
'd' => 86400 ,
];
$multiplier = $multipliers [ $matches [ 2 ]] ?? 1 ;
return $matches [ 1 ] * $multiplier ;
2014-11-30 17:49:52 +00:00
}
2020-09-21 15:40:17 +02:00
2021-04-28 15:31:45 -05:00
return $delay === '' ? 0 : 300 ;
2014-11-30 17:49:52 +00:00
}
2019-11-17 16:30:43 +01:00
function normalize_snmp_ip_address ( $data )
{
// $data is received from snmpwalk, can be ipv4 xxx.xxx.xxx.xxx or ipv6 xx:xx:...:xx (16 chunks)
// ipv4 is returned unchanged, ipv6 is returned with one ':' removed out of two, like
// xxxx:xxxx:...:xxxx (8 chuncks)
return preg_replace ( '/([0-9a-fA-F]{2}):([0-9a-fA-F]{2})/' , '\1\2' , explode ( '%' , $data , 2 )[ 0 ]);
}
2016-08-28 12:32:58 -05:00
function fix_integer_value ( $value )
{
2015-06-02 17:36:10 +01:00
if ( $value < 0 ) {
$return = 4294967296 + $value ;
2016-08-28 12:32:58 -05:00
} else {
2015-06-02 17:36:10 +01:00
$return = $value ;
}
2020-09-21 15:40:17 +02:00
2015-06-02 17:36:10 +01:00
return $return ;
}
2015-06-11 19:34:11 +01:00
2015-10-22 21:10:33 +00:00
/**
* Checks if the $hostname provided exists in the DB already
*
2021-09-08 23:35:56 +02:00
* @param string $hostname The hostname to check for
* @param string $sysName 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 03:12:31 -06:00
*/
2017-07-16 22:01:07 +01:00
function host_exists ( $hostname , $sysName = null )
2016-08-28 12:32:58 -05:00
{
2017-07-16 22:01:07 +01:00
$query = 'SELECT COUNT(*) FROM `devices` WHERE `hostname`=?' ;
$params = [ $hostname ];
2019-06-23 00:29:12 -05:00
if ( ! empty ( $sysName ) && ! Config :: get ( 'allow_duplicate_sysName' )) {
2017-07-16 22:01:07 +01:00
$query .= ' OR `sysName`=?' ;
$params [] = $sysName ;
2019-06-23 00:29:12 -05:00
if ( ! empty ( Config :: get ( 'mydomain' ))) {
$full_sysname = rtrim ( $sysName , '.' ) . '.' . Config :: get ( 'mydomain' );
2017-07-16 22:01:07 +01:00
$query .= ' OR `sysName`=?' ;
$params [] = $full_sysname ;
2016-05-02 20:20:29 +00:00
}
2015-10-22 21:10:33 +00:00
}
2020-09-21 15:40:17 +02:00
2017-07-16 22:01:07 +01:00
return dbFetchCell ( $query , $params ) > 0 ;
2015-10-22 21:10:33 +00:00
}
2015-11-19 10:20:56 +00:00
2016-01-17 23:59:51 +00:00
/**
* Perform DNS lookup
*
2021-09-08 23:35:56 +02:00
* @param array $device Device array from database
* @param string $type The type of record to lookup
2016-01-17 23:59:51 +00:00
* @return string ip
*
**/
2016-08-28 12:32:58 -05: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 12:32:58 -05: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 12:32:58 -05:00
$record = dns_get_record ( $device [ 'hostname' ], $type );
2020-09-21 15:40:17 +02:00
2022-08-21 16:23:43 -05:00
return $record [ 0 ][ $return ] ?? null ;
2016-01-17 23:59:51 +00:00
} //end dnslookup
2016-02-01 23:29:37 +00:00
2017-09-03 13:58:39 -05:00
/**
* Create a new state index. Update translations if $states is given.
*
* For for backward compatibility:
* Returns null if $states is empty, $state_name already exists, and contains state translations
*
2021-09-08 23:35:56 +02:00
* @param string $state_name the unique name for this state translation
* @param array $states array of states, each must contain keys: descr, graph, value, generic
2017-09-03 13:58:39 -05:00
* @return int|null
*/
function create_state_index ( $state_name , $states = [])
2016-08-28 12:32:58 -05:00
{
2017-04-28 04:33:56 +01:00
$state_index_id = dbFetchCell ( 'SELECT `state_index_id` FROM state_indexes WHERE state_name = ? LIMIT 1' , [ $state_name ]);
if ( ! is_numeric ( $state_index_id )) {
2017-09-03 13:58:39 -05:00
$state_index_id = dbInsert ([ 'state_name' => $state_name ], 'state_indexes' );
// legacy code, return index so states are created
if ( empty ( $states )) {
return $state_index_id ;
}
}
// check or synchronize states
if ( empty ( $states )) {
2017-04-28 04:33:56 +01:00
$translations = dbFetchRows ( 'SELECT * FROM `state_translations` WHERE `state_index_id` = ?' , [ $state_index_id ]);
2017-04-29 16:58:06 +01:00
if ( count ( $translations ) == 0 ) {
2017-04-28 04:33:56 +01:00
// If we don't have any translations something has gone wrong so return the state_index_id so they get created.
return $state_index_id ;
}
2017-09-03 13:58:39 -05:00
} else {
sync_sensor_states ( $state_index_id , $states );
2016-02-27 16:23:58 +01:00
}
2017-09-03 13:58:39 -05:00
return null ;
}
/**
* Synchronize the sensor state translations with the database
*
2021-09-08 23:35:56 +02:00
* @param int $state_index_id index of the state
* @param array $states array of states, each must contain keys: descr, graph, value, generic
2017-09-03 13:58:39 -05:00
*/
function sync_sensor_states ( $state_index_id , $states )
{
$new_translations = array_reduce ( $states , function ( $array , $state ) use ( $state_index_id ) {
$array [ $state [ 'value' ]] = [
'state_index_id' => $state_index_id ,
'state_descr' => $state [ 'descr' ],
'state_draw_graph' => $state [ 'graph' ],
'state_value' => $state [ 'value' ],
'state_generic_value' => $state [ 'generic' ],
];
2020-09-21 15:40:17 +02:00
2017-09-03 13:58:39 -05:00
return $array ;
}, []);
$existing_translations = dbFetchRows (
'SELECT `state_index_id`,`state_descr`,`state_draw_graph`,`state_value`,`state_generic_value` FROM `state_translations` WHERE `state_index_id`=?' ,
[ $state_index_id ]
);
foreach ( $existing_translations as $translation ) {
$value = $translation [ 'state_value' ];
if ( isset ( $new_translations [ $value ])) {
if ( $new_translations [ $value ] != $translation ) {
dbUpdate (
$new_translations [ $value ],
'state_translations' ,
'`state_index_id`=? AND `state_value`=?' ,
[ $state_index_id , $value ]
);
}
// this translation is synchronized, it doesn't need to be inserted
unset ( $new_translations [ $value ]);
} else {
dbDelete ( 'state_translations' , '`state_index_id`=? AND `state_value`=?' , [ $state_index_id , $value ]);
}
}
// insert any new translations
dbBulkInsert ( $new_translations , 'state_translations' );
2016-02-26 23:40:34 +01: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` = ?' , [
'state' ,
$device [ 'device_id' ],
$state_name ,
$index ,
]);
$state_indexes_entry = dbFetchRow ( 'SELECT state_index_id FROM `state_indexes` WHERE `state_name` = ?' , [
$state_name ,
]);
if ( ! empty ( $sensor_entry [ 'sensor_id' ]) && ! empty ( $state_indexes_entry [ 'state_index_id' ])) {
$insert = [
'sensor_id' => $sensor_entry [ 'sensor_id' ],
'state_index_id' => $state_indexes_entry [ 'state_index_id' ],
];
2016-08-28 12:32:58 -05:00
foreach ( $insert as $key => $val_check ) {
2016-02-26 23:40:34 +01:00
if ( ! isset ( $val_check )) {
unset ( $insert [ $key ]);
}
}
2016-02-26 23:56:54 +01:00
dbInsert ( $insert , 'sensors_to_state_indexes' );
2016-02-26 23:40:34 +01:00
}
}
2016-06-15 16:25:14 +00:00
2016-08-28 12:32:58 -05:00
function delta_to_bits ( $delta , $period )
{
2023-03-13 22:32:22 +01:00
return round ( $delta * 8 / $period , 2 );
2016-06-15 16:25:14 +00:00
}
2016-07-07 19:11:13 +01:00
2016-08-28 12:32:58 -05:00
function report_this ( $message )
{
2019-06-23 00:29:12 -05:00
return '<h2>' . $message . ' Please <a href="' . Config :: get ( 'project_issues' ) . '">report this</a> to the ' . Config :: get ( 'project_name' ) . ' developers.</h2>' ;
2016-06-29 00:14:21 +01:00
} //end report_this()
2016-08-23 20:44:45 +02:00
2016-08-28 12:32:58 -05:00
function hytera_h2f ( $number , $nd )
2016-08-23 20:44:45 +02:00
{
2016-08-28 12:32:58 -05:00
if ( strlen ( str_replace ( ' ' , '' , $number )) == 4 ) {
2023-10-26 10:03:03 -05:00
$number = \LibreNMS\Util\StringHelpers :: asciiToHex ( $number , ' ' );
2016-08-23 20:44:45 +02:00
}
$r = '' ;
$y = explode ( ' ' , $number );
foreach ( $y as $z ) {
$r = $z . '' . $r ;
}
$hex = [];
$number = substr ( $r , 0 , - 1 );
//$number = str_replace(" ", "", $number);
for ( $i = 0 ; $i < strlen ( $number ); $i ++ ) {
2016-08-28 12:32:58 -05:00
$hex [] = substr ( $number , $i , 1 );
2016-08-23 20:44:45 +02:00
}
$dec = [];
$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 12:32:58 -05:00
$binfinal .= sprintf ( '%04d' , decbin ( $dec [ $i ]));
2016-08-23 20:44:45 +02:00
}
2016-08-28 12:32:58 -05:00
$sign = substr ( $binfinal , 0 , 1 );
$exp = substr ( $binfinal , 1 , 8 );
2016-08-23 20:44:45 +02:00
$exp = bindec ( $exp );
$exp -= 127 ;
2016-08-28 12:32:58 -05:00
$scibin = substr ( $binfinal , 9 );
$binint = substr ( $scibin , 0 , $exp );
$binpoint = substr ( $scibin , $exp );
2016-08-23 20:44:45 +02:00
$intnumber = bindec ( '1' . $binint );
2019-05-30 09:56:27 -05:00
$tmppoint = [];
2016-08-23 20:44:45 +02:00
for ( $i = 0 ; $i < strlen ( $binpoint ); $i ++ ) {
2016-08-28 12:32:58 -05:00
$tmppoint [] = substr ( $binpoint , $i , 1 );
2016-08-23 20:44:45 +02:00
}
$tmppoint = array_reverse ( $tmppoint );
2022-04-12 08:27:31 -05:00
$tpointnumber = min ( number_format ( $tmppoint [ 0 ] / 2 , strlen ( $binpoint ), '.' , '' ), 1 );
2016-08-23 20:44:45 +02:00
$pointnumber = '' ;
for ( $i = 1 ; $i < strlen ( $binpoint ); $i ++ ) {
2016-08-28 12:32:58 -05:00
$pointnumber = number_format ( $tpointnumber / 2 , strlen ( $binpoint ), '.' , '' );
$tpointnumber = $tmppoint [ $i + 1 ] . substr ( $pointnumber , 1 );
2016-08-23 20:44:45 +02:00
}
$floatfinal = $intnumber + $pointnumber ;
if ( $sign == 1 ) {
$floatfinal = - $floatfinal ;
}
2016-08-28 12:32:58 -05:00
return number_format ( $floatfinal , $nd , '.' , '' );
2016-08-23 20:44:45 +02:00
}
2016-10-06 10:40:37 +10: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 = [];
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` = ?' , [ $entphysical [ $location ][ 'entPhysical_id' ]]);
}
$entPhysicalId = $entphysical [ $location ][ 'entPhysical_id' ];
2020-09-21 15:40:17 +02:00
2016-10-06 10:40:37 +10:00
return [ $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 = [
2024-01-05 05:39:12 +01:00
'device_id' => $device [ 'device_id' ],
'entPhysicalIndex' => $index ,
'entPhysicalClass' => 'container' ,
'entPhysicalVendorType' => $location ,
'entPhysicalName' => $shortlocation ,
'entPhysicalContainedIn' => $parent ,
'entPhysicalParentRelPos' => '-1' ,
2016-10-06 10:40:37 +10:00
];
// Add to the DB and Array.
$id = dbInsert ( $insert , 'entPhysical' );
$entphysical [ $location ] = dbFetchRow ( 'SELECT * FROM entPhysical WHERE entPhysical_id=?' , [ $id ]);
2020-09-21 15:40:17 +02:00
2016-10-06 10:40:37 +10:00
return $index ;
} // end if - Level 1
} // end function
2016-10-11 15:29:06 -06:00
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)
*/
2021-12-01 14:24:35 +01:00
$hex_data = str_replace ([ ' ' , " \n " ], '' , $hex_data );
2021-03-30 15:26:01 -05:00
// we need an even number of digits for hex2bin
if ( strlen ( $hex_data ) % 2 === 1 ) {
$hex_data = '0' . $hex_data ;
}
2016-10-11 15:29:06 -06:00
$value = hex2bin ( $hex_data );
$length = strlen ( $value );
$indices = [];
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 ;
}
}
}
2020-09-21 15:40:17 +02:00
2016-10-11 15:29:06 -06:00
return $indices ;
}
2016-10-14 18:14:18 -05:00
2017-03-22 10:17:13 +00:00
/**
* Function to generate PeeringDB Cache
*/
function cache_peeringdb ()
{
2019-06-23 00:29:12 -05:00
if ( Config :: get ( 'peeringdb.enabled' ) === true ) {
2017-03-22 10:17:13 +00:00
$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 ) {
2017-12-09 17:19:56 +00:00
$rand = rand ( 3 , 30 );
2017-03-22 10:17:13 +00:00
echo "No cached PeeringDB data found, sleeping for $rand seconds" . PHP_EOL ;
sleep ( $rand );
2018-08-26 07:42:21 -05:00
$peer_keep = [];
$ix_keep = [];
2023-10-04 17:07:14 +02:00
// Exclude Private and reserved ASN ranges
// 64512 - 65534 (Private)
// 65535 (Well Known)
// 4200000000 - 4294967294 (Private)
// 4294967295 (Reserved)
2017-03-22 10:17:13 +00:00
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' ];
2023-05-23 09:25:17 -05:00
$get = \LibreNMS\Util\Http :: client () -> get ( $peeringdb_url . '/net?depth=2&asn=' . $asn );
2022-01-26 23:04:26 +01:00
$json_data = $get -> body ();
2017-03-22 10:17:13 +00:00
$data = json_decode ( $json_data );
2020-03-21 15:49:15 -04:00
$ixs = $data -> { 'data' }[ 0 ] -> { 'netixlan_set' };
2022-08-25 10:03:06 +02:00
foreach ( $ixs ?? [] as $ix ) {
2017-03-22 10:17:13 +00:00
$ixid = $ix -> { 'ix_id' };
$tmp_ix = dbFetchRow ( 'SELECT * FROM `pdb_ix` WHERE `ix_id` = ? AND asn = ?' , [ $ixid , $asn ]);
if ( $tmp_ix ) {
$pdb_ix_id = $tmp_ix [ 'pdb_ix_id' ];
$update = [ 'name' => $ix -> { 'name' }, 'timestamp' => time ()];
2017-03-23 10:08:48 +00:00
dbUpdate ( $update , 'pdb_ix' , '`ix_id` = ? AND `asn` = ?' , [ $ixid , $asn ]);
2017-03-22 10:17:13 +00:00
} else {
$insert = [
'ix_id' => $ixid ,
'name' => $ix -> { 'name' },
'asn' => $asn ,
'timestamp' => time (),
];
$pdb_ix_id = dbInsert ( $insert , 'pdb_ix' );
}
2018-08-26 07:42:21 -05:00
$ix_keep [] = $pdb_ix_id ;
2023-05-23 09:25:17 -05:00
$get_ix = \LibreNMS\Util\Http :: client () -> get ( " $peeringdb_url /netixlan?ix_id= $ixid " );
2022-01-26 23:04:26 +01:00
$ix_json = $get_ix -> body ();
2017-03-22 10:17:13 +00:00
$ix_data = json_decode ( $ix_json );
$peers = $ix_data -> { 'data' };
2022-08-30 16:00:12 +02:00
foreach ( $peers ?? [] as $index => $peer ) {
2023-10-04 10:17:34 -05:00
$peer_name = \LibreNMS\Util\AutonomousSystem :: get ( $peer -> { 'asn' }) -> name ();
2017-03-22 10:17:13 +00:00
$tmp_peer = dbFetchRow ( 'SELECT * FROM `pdb_ix_peers` WHERE `peer_id` = ? AND `ix_id` = ?' , [ $peer -> { 'id' }, $ixid ]);
if ( $tmp_peer ) {
$peer_keep [] = $tmp_peer [ 'pdb_ix_peers_id' ];
$update = [
2024-01-05 05:39:12 +01:00
'remote_asn' => $peer -> { 'asn' },
'remote_ipaddr4' => $peer -> { 'ipaddr4' },
2017-03-22 10:17:13 +00:00
'remote_ipaddr6' => $peer -> { 'ipaddr6' },
2024-01-05 05:39:12 +01:00
'name' => $peer_name ,
2017-03-22 10:17:13 +00:00
];
dbUpdate ( $update , 'pdb_ix_peers' , '`pdb_ix_peers_id` = ?' , [ $tmp_peer [ 'pdb_ix_peers_id' ]]);
} else {
$peer_insert = [
2024-01-05 05:39:12 +01:00
'ix_id' => $ixid ,
'peer_id' => $peer -> { 'id' },
'remote_asn' => $peer -> { 'asn' },
2017-03-22 10:17:13 +00:00
'remote_ipaddr4' => $peer -> { 'ipaddr4' },
'remote_ipaddr6' => $peer -> { 'ipaddr6' },
2024-01-05 05:39:12 +01:00
'name' => $peer_name ,
'timestamp' => time (),
2017-03-22 10:17:13 +00:00
];
$peer_keep [] = dbInsert ( $peer_insert , 'pdb_ix_peers' );
}
}
}
2018-08-26 07:42:21 -05:00
}
// cleanup
if ( empty ( $peer_keep )) {
dbDelete ( 'pdb_ix_peers' );
} else {
dbDelete ( 'pdb_ix_peers' , '`pdb_ix_peers_id` NOT IN ' . dbGenPlaceholders ( count ( $peer_keep )), $peer_keep );
}
if ( empty ( $ix_keep )) {
dbDelete ( 'pdb_ix' );
} else {
dbDelete ( 'pdb_ix' , '`pdb_ix_id` NOT IN ' . dbGenPlaceholders ( count ( $ix_keep )), $ix_keep );
2017-03-22 10:17:13 +00:00
}
} else {
echo 'Cached PeeringDB data found.....' . PHP_EOL ;
}
} else {
echo 'Peering DB integration disabled' . PHP_EOL ;
}
}
2017-04-05 09:00:28 +01:00
2017-05-01 23:49:11 -05:00
/**
2023-06-13 13:35:00 +02:00
* @param $device
2017-05-01 23:49:11 -05:00
* @return int|null
*/
function get_device_oid_limit ( $device )
{
2018-11-21 17:25:39 -02:00
// device takes priority
2023-10-11 18:29:47 -05:00
$attrib = DeviceCache :: get ( $device [ 'device_id' ] ?? null ) -> getAttrib ( 'snmp_max_oid' );
if ( $attrib !== null ) {
return $attrib ;
2018-11-21 17:25:39 -02:00
}
2017-05-01 23:49:11 -05:00
2018-11-21 17:25:39 -02:00
// then os
$os_max = Config :: getOsSetting ( $device [ 'os' ], 'snmp_max_oid' , 0 );
if ( $os_max > 0 ) {
return $os_max ;
2017-05-01 23:49:11 -05:00
}
2018-11-21 17:25:39 -02:00
// then global
$global_max = Config :: get ( 'snmp.max_oid' , 10 );
2020-09-21 15:40:17 +02:00
2018-11-21 17:25:39 -02:00
return $global_max > 0 ? $global_max : 10 ;
2017-05-01 23:49:11 -05:00
}
2017-10-17 11:36:49 -05:00
2017-11-24 03:37:52 -06:00
/**
* If Distributed, create a lock, then purge the mysql table
*
2021-09-08 23:35:56 +02:00
* @param string $table
* @param string $sql
2017-11-24 03:37:52 -06:00
* @return int exit code
*/
function lock_and_purge ( $table , $sql )
{
2020-10-07 07:36:35 -05:00
$purge_name = $table . '_purge' ;
$lock = Cache :: lock ( $purge_name , 86000 );
if ( $lock -> get ()) {
2017-11-24 03:37:52 -06:00
$purge_days = Config :: get ( $purge_name );
$name = str_replace ( '_' , ' ' , ucfirst ( $table ));
if ( is_numeric ( $purge_days )) {
if ( dbDelete ( $table , $sql , [ $purge_days ])) {
echo " $name cleared for entries over $purge_days days \n " ;
}
}
2020-10-07 07:36:35 -05:00
$lock -> release ();
2020-09-21 15:40:17 +02:00
2017-11-24 03:37:52 -06:00
return 0 ;
}
2020-10-07 07:36:35 -05:00
return - 1 ;
2017-11-24 03:37:52 -06:00
}
2018-04-22 21:01:37 +08:00
2019-11-05 14:49:09 +01:00
/**
* If Distributed, create a lock, then purge the mysql table according to the sql query
*
2021-09-08 23:35:56 +02:00
* @param string $table
* @param string $sql
* @param string $msg
2019-11-05 14:49:09 +01:00
* @return int exit code
*/
function lock_and_purge_query ( $table , $sql , $msg )
{
$purge_name = $table . '_purge' ;
$purge_duration = Config :: get ( $purge_name );
if ( ! ( is_numeric ( $purge_duration ) && $purge_duration > 0 )) {
return - 2 ;
}
2020-10-07 07:36:35 -05:00
$lock = Cache :: lock ( $purge_name , 86000 );
if ( $lock -> get ()) {
2019-11-05 14:49:09 +01:00
if ( dbQuery ( $sql , [ $purge_duration ])) {
printf ( $msg , $purge_duration );
}
2020-10-07 07:36:35 -05:00
$lock -> release ();
2020-09-21 15:40:17 +02:00
2020-10-07 07:36:35 -05:00
return 0 ;
2019-11-05 14:49:09 +01:00
}
2020-09-21 15:40:17 +02:00
2020-10-07 07:36:35 -05:00
return - 1 ;
2019-11-05 14:49:09 +01:00
}
2018-06-05 09:28:13 +00:00
/**
* Check if disk is valid to poll.
* Settings: bad_disk_regexp
*
2021-09-08 23:35:56 +02:00
* @param array $disk
* @param array $device
2018-06-05 09:28:13 +00:00
* @return bool
*/
function is_disk_valid ( $disk , $device )
{
foreach ( Config :: getCombined ( $device [ 'os' ], 'bad_disk_regexp' ) as $bir ) {
if ( preg_match ( $bir . 'i' , $disk [ 'diskIODevice' ])) {
d_echo ( "Ignored Disk: { $disk [ 'diskIODevice' ] } (matched: $bir ) \n " );
2020-09-21 15:40:17 +02:00
2018-06-05 09:28:13 +00:00
return false ;
}
}
2020-09-21 15:40:17 +02:00
2018-06-05 09:28:13 +00:00
return true ;
}
2018-09-05 02:09:27 +02:00
2020-04-25 05:47:20 +02:00
/**
2022-01-26 23:04:26 +01:00
* Take a BGP error code and subcode to return a string representation of it
*
2020-04-25 05:47:20 +02:00
* @params int code
* @params int subcode
2021-09-10 20:09:53 +02:00
*
2020-04-25 05:47:20 +02:00
* @return string
*/
function describe_bgp_error_code ( $code , $subcode )
{
// https://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-3
$message = 'Unknown' ;
$error_code_key = 'bgp.error_codes.' . $code ;
$error_subcode_key = 'bgp.error_subcodes.' . $code . '.' . $subcode ;
$error_code_message = __ ( $error_code_key );
$error_subcode_message = __ ( $error_subcode_key );
if ( $error_subcode_message != $error_subcode_key ) {
$message = $error_code_message . ' - ' . $error_subcode_message ;
} elseif ( $error_code_message != $error_code_key ) {
$message = $error_code_message ;
}
return $message ;
}