mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
add app for getting status of TCP connections for specified services (#8090)
* add the poller for portactivity * add the ability to get monitor ports for portactivity * add the graphs for displaying stuff for the portactivity app * add the portactivity app page * update the docs for Portactivity * remove extra line * minor doc update for Portactivity * add update_application line * convert to use json_app_get * convert curly brackets to square * style fix * remote error, errorString, and version after they stop being important so they are not processed * add alert rule examples * add the poller for portactivity * add the ability to get monitor ports for portactivity * add the graphs for displaying stuff for the portactivity app * add the portactivity app page * update the docs for Portactivity * remove extra line * minor doc update for Portactivity * add update_application line * convert to use json_app_get * convert curly brackets to square * style fix * remote error, errorString, and version after they stop being important so they are not processed * add alert rule examples * remove dump of get_portactivity_ports function added during rebase * update to the current json_app_get * add portactivity snmprec * add the portactivity test data * whoops bad merge when rebasing... fix * minor formatting cleanup and add a missing comma * fix some odditities with what one of the tests is doing * whoops... include the use for the exception * set the response to okay * attempt to make snmpsim array check happy again * the json now lints * more making metric testing happy * one more update to make travis-ci happy * now flattens arrays also add array_flatten * rename array_flatten to data_flatten as pre-commit chokes on it as laravel has something similarly named * go through and properly add all the metrics * tested with the newest one and it works * whoops, clean up json and remove prototype that was used when putting it together * doh! make it happy with laravel now * see if a minor changing in formatting for the numbers makes the polling unit test happy * order them properly * remove a comma * a few more minor fixes
This commit is contained in:
@@ -62,6 +62,7 @@ The unix-agent does not have a discovery module, only a poller module. That poll
|
||||
1. [OS Updates](#os-updates) - SNMP extend
|
||||
1. [PHP-FPM](#php-fpm) - SNMP extend
|
||||
1. [Pi-hole](#pi-hole) - SNMP extend
|
||||
1. [Portactivity](#portactivity) - SNMP extend
|
||||
1. [Postfix](#postfix) - SNMP extend
|
||||
1. [Postgres](#postgres) - SNMP extend
|
||||
1. [PowerDNS](#powerdns) - Agent
|
||||
@@ -772,6 +773,32 @@ extend pi-hole /etc/snmp/pi-hole
|
||||
|
||||
The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under `SNMP Extend` heading top of page.
|
||||
|
||||
### Portactivity
|
||||
#### SNMP Extend
|
||||
|
||||
1. Install the Perl module Parse::Netstat.
|
||||
|
||||
2. Copy the Perl script to the desired host (the host must be added to LibreNMS devices)
|
||||
```
|
||||
wget https://github.com/librenms/librenms-agent/raw/master/snmp/portactivity -O /etc/snmp/portactivity
|
||||
```
|
||||
|
||||
3. Make the script executable. (chmod +x /etc/snmp/portactivity)
|
||||
|
||||
4. Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add:
|
||||
```
|
||||
extend portactivity /etc/snmp/portactivity -p http,ldap,imap
|
||||
```
|
||||
|
||||
Will monitor HTTP, LDAP, and IMAP. The -p switch specifies what ports to use. This is a comma seperated list.
|
||||
|
||||
These must be found in '/etc/services' or where ever NSS is set to fetch it from. If not, it will throw an error.
|
||||
|
||||
If you want to JSON returned by it to be printed in a pretty format use the -P flag.
|
||||
|
||||
5. Restart snmpd on your host.
|
||||
|
||||
Please note that for only TCP[46] services are supported.
|
||||
|
||||
### Postfix
|
||||
#### SNMP Extend
|
||||
|
||||
@@ -1710,6 +1710,31 @@ function get_zfs_pools($device_id)
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ports for a device... just requires the device ID
|
||||
* an empty return means portsactivity is not in use or there are currently no ports
|
||||
* @param $device_id
|
||||
* @return array
|
||||
*/
|
||||
function get_portactivity_ports($device_id)
|
||||
{
|
||||
$options=array(
|
||||
'filter' => array(
|
||||
'type' => array('=', 'portsactivity'),
|
||||
),
|
||||
);
|
||||
|
||||
$component=new LibreNMS\Component();
|
||||
$portsc=$component->getComponents($device_id, $options);
|
||||
|
||||
if (isset($portsc[$device_id])) {
|
||||
$id = $component->getFirstComponentID($portsc, $device_id);
|
||||
return json_decode($portsc[$device_id][$id]['ports']);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sysname of a device with a html line break prepended.
|
||||
* if the device has an empty sysname it will return device's hostname instead
|
||||
|
||||
80
html/includes/graphs/application/portactivity_from.inc.php
Normal file
80
html/includes/graphs/application/portactivity_from.inc.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
$name = 'portactivity';
|
||||
$app_id = $app['app_id'];
|
||||
$unit_text = 'Connections';
|
||||
$colours = 'psychedelic';
|
||||
$dostack = 0;
|
||||
$printtotal = 0;
|
||||
$addarea = 1;
|
||||
$transparency = 15;
|
||||
|
||||
$rrd_filename = rrd_name($device['hostname'], array('app', $name, $app['app_id'], $vars['port']));
|
||||
|
||||
|
||||
$rrd_list=array();
|
||||
if (rrdtool_check_rrd_exists($rrd_filename)) {
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSED',
|
||||
'ds' => 'fromCLOSED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'SYN_SENT',
|
||||
'ds' => 'fromSYN_SENT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'SYN_RECEIVED',
|
||||
'ds' => 'fromSYN_RECEIVED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'ESTABLISHED',
|
||||
'ds' => 'fromESTABLISHED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSE_WAIT',
|
||||
'ds' => 'fromCLOSE_WAIT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'FIN_WAIT_1',
|
||||
'ds' => 'fromFIN_WAIT_1',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSING',
|
||||
'ds' => 'fromCLOSING',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'LAST_ACK',
|
||||
'ds' => 'fromLAST_ACK',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'FIN_WAIT_2',
|
||||
'ds' => 'fromFIN_WAIT_2',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'TIME_WAIT',
|
||||
'ds' => 'fromTIME_WAIT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'UNKNOWN',
|
||||
'ds' => 'fromUNKNOWN',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'other',
|
||||
'ds' => 'fromother',
|
||||
);
|
||||
} else {
|
||||
d_echo('RRD "'.$rrd_filename.'" not found');
|
||||
}
|
||||
|
||||
require 'includes/graphs/generic_multi_line.inc.php';
|
||||
80
html/includes/graphs/application/portactivity_to.inc.php
Normal file
80
html/includes/graphs/application/portactivity_to.inc.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
$name = 'portactivity';
|
||||
$app_id = $app['app_id'];
|
||||
$unit_text = 'Connections';
|
||||
$colours = 'psychedelic';
|
||||
$dostack = 0;
|
||||
$printtotal = 0;
|
||||
$addarea = 1;
|
||||
$transparency = 15;
|
||||
|
||||
$rrd_filename = rrd_name($device['hostname'], array('app', $name, $app['app_id'], $vars['port']));
|
||||
|
||||
|
||||
$rrd_list=array();
|
||||
if (rrdtool_check_rrd_exists($rrd_filename)) {
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSED',
|
||||
'ds' => 'toCLOSED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'SYN_SENT',
|
||||
'ds' => 'toSYN_SENT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'SYN_RECEIVED',
|
||||
'ds' => 'toSYN_RECEIVED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'ESTABLISHED',
|
||||
'ds' => 'toESTABLISHED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSE_WAIT',
|
||||
'ds' => 'toCLOSE_WAIT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'FIN_WAIT_1',
|
||||
'ds' => 'toFIN_WAIT_1',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSING',
|
||||
'ds' => 'toCLOSING',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'LAST_ACK',
|
||||
'ds' => 'toLAST_ACK',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'FIN_WAIT_2',
|
||||
'ds' => 'toFIN_WAIT_2',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'TIME_WAIT',
|
||||
'ds' => 'toTIME_WAIT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'UNKNOWN',
|
||||
'ds' => 'toUNKNOWN',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'other',
|
||||
'ds' => 'toother',
|
||||
);
|
||||
} else {
|
||||
d_echo('RRD "'.$rrd_filename.'" not found');
|
||||
}
|
||||
|
||||
require 'includes/graphs/generic_multi_line.inc.php';
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
$name = 'portactivity';
|
||||
$app_id = $app['app_id'];
|
||||
$unit_text = 'Connections';
|
||||
$colours = 'psychedelic';
|
||||
$dostack = 0;
|
||||
$printtotal = 0;
|
||||
$addarea = 1;
|
||||
$transparency = 15;
|
||||
|
||||
$rrd_filename = rrd_name($device['hostname'], array('app', $name, $app['app_id'], $vars['port']));
|
||||
|
||||
|
||||
$rrd_list=array();
|
||||
if (rrdtool_check_rrd_exists($rrd_filename)) {
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSED',
|
||||
'ds' => 'totalCLOSED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'SYN_SENT',
|
||||
'ds' => 'totalSYN_SENT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'SYN_RECEIVED',
|
||||
'ds' => 'totalSYN_RECEIVED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'ESTABLISHED',
|
||||
'ds' => 'totalESTABLISHED',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSE_WAIT',
|
||||
'ds' => 'totalCLOSE_WAIT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'FIN_WAIT_1',
|
||||
'ds' => 'totalFIN_WAIT_1',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'CLOSING',
|
||||
'ds' => 'totalCLOSING',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'LAST_ACK',
|
||||
'ds' => 'totalLAST_ACK',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'FIN_WAIT_2',
|
||||
'ds' => 'totalFIN_WAIT_2',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'TIME_WAIT',
|
||||
'ds' => 'totalTIME_WAIT',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'UNKNOWN',
|
||||
'ds' => 'totalUNKNOWN',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'other',
|
||||
'ds' => 'totalother',
|
||||
);
|
||||
} else {
|
||||
d_echo('RRD "'.$rrd_filename.'" not found');
|
||||
}
|
||||
|
||||
require 'includes/graphs/generic_multi_line.inc.php';
|
||||
35
html/includes/graphs/application/portactivity_totals.inc.php
Normal file
35
html/includes/graphs/application/portactivity_totals.inc.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
$name = 'portactivity';
|
||||
$app_id = $app['app_id'];
|
||||
$unit_text = 'Connections';
|
||||
$colours = 'psychedelic';
|
||||
$dostack = 0;
|
||||
$printtotal = 0;
|
||||
$addarea = 1;
|
||||
$transparency = 15;
|
||||
|
||||
$rrd_filename = rrd_name($device['hostname'], array('app', $name, $app['app_id'], $vars['port']));
|
||||
|
||||
|
||||
$rrd_list=array();
|
||||
if (rrdtool_check_rrd_exists($rrd_filename)) {
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'Total',
|
||||
'ds' => 'total_conns',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'From',
|
||||
'ds' => 'total_from',
|
||||
);
|
||||
$rrd_list[]=array(
|
||||
'filename' => $rrd_filename,
|
||||
'descr' => 'To',
|
||||
'ds' => 'total_to',
|
||||
);
|
||||
} else {
|
||||
d_echo('RRD "'.$rrd_filename.'" not found');
|
||||
}
|
||||
|
||||
require 'includes/graphs/generic_multi_line.inc.php';
|
||||
78
html/pages/device/apps/portactivity.inc.php
Normal file
78
html/pages/device/apps/portactivity.inc.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
global $config;
|
||||
|
||||
$ports=get_portactivity_ports($device['device_id']);
|
||||
|
||||
sort($ports);
|
||||
|
||||
$link_array = array(
|
||||
'page' => 'device',
|
||||
'device' => $device['device_id'],
|
||||
'tab' => 'apps',
|
||||
'app' => 'portactivity',
|
||||
);
|
||||
|
||||
print_optionbar_start();
|
||||
|
||||
echo 'Ports:';
|
||||
$ports_int=0;
|
||||
while (isset($ports[$ports_int])) {
|
||||
$port=$ports[$ports_int];
|
||||
$label=$ports[$ports_int];
|
||||
|
||||
if ($vars['port'] == $port) {
|
||||
$label='>>'.$port.'<<';
|
||||
}
|
||||
|
||||
$ports_int++;
|
||||
|
||||
$append='';
|
||||
if (isset($ports[$ports_int])) {
|
||||
$append=', ';
|
||||
}
|
||||
|
||||
echo generate_link($label, $link_array, array('port'=>$port)).$append;
|
||||
}
|
||||
|
||||
print_optionbar_end();
|
||||
|
||||
if (!isset($vars['port'])) {
|
||||
echo "Please select a port.\n";
|
||||
|
||||
$graphs = array(
|
||||
# No useful bits to display with out selecting anything.
|
||||
);
|
||||
} else {
|
||||
$graphs = array(
|
||||
'portactivity_totals'=>'Total Connections',
|
||||
'portactivity_total_details'=>'Total Connections Details',
|
||||
'portactivity_to'=>'Connections To Server',
|
||||
'portactivity_from'=>'Connections From Server',
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($graphs as $key => $text) {
|
||||
$graph_type = $key;
|
||||
$graph_array['height'] = '100';
|
||||
$graph_array['width'] = '215';
|
||||
$graph_array['to'] = $config['time']['now'];
|
||||
$graph_array['id'] = $app['app_id'];
|
||||
$graph_array['type'] = 'application_'.$key;
|
||||
|
||||
if (isset($vars['port'])) {
|
||||
$graph_array['port']=$vars['port'];
|
||||
}
|
||||
|
||||
|
||||
echo '<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">'.$text.'</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">';
|
||||
include 'includes/print-graphrow.inc.php';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
159
includes/polling/applications/portactivity.inc.php
Normal file
159
includes/polling/applications/portactivity.inc.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\RRD\RrdDefinition;
|
||||
use LibreNMS\Exceptions\JsonAppException;
|
||||
|
||||
$name = 'portactivity';
|
||||
$app_id = $app['app_id'];
|
||||
|
||||
echo $name;
|
||||
|
||||
try {
|
||||
$returned=json_app_get($device, 'portactivity', 1);
|
||||
} catch (JsonAppException $e) { // Only doing the generic one as this has no non-JSON return
|
||||
echo PHP_EOL . $name . ':' .$e->getCode().':'. $e->getMessage() . PHP_EOL;
|
||||
update_application($app, $e->getCode().':'.$e->getMessage(), []); // Set empty metrics and error message
|
||||
return;
|
||||
}
|
||||
|
||||
$ports=$returned['data'];
|
||||
|
||||
$ports_rrd_def = RrdDefinition::make()
|
||||
->addDataset('total_conns', 'GAUGE', 0)
|
||||
->addDataset('total_to', 'GAUGE', 0)
|
||||
->addDataset('total_from', 'GAUGE', 0)
|
||||
->addDataset('totalLISTEN', 'GAUGE', 0)
|
||||
->addDataset('totalCLOSED', 'GAUGE', 0)
|
||||
->addDataset('totalSYN_SENT', 'GAUGE', 0)
|
||||
->addDataset('totalSYN_RECEIVED', 'GAUGE', 0)
|
||||
->addDataset('totalESTABLISHED', 'GAUGE', 0)
|
||||
->addDataset('totalCLOSE_WAIT', 'GAUGE', 0)
|
||||
->addDataset('totalFIN_WAIT_1', 'GAUGE', 0)
|
||||
->addDataset('totalCLOSING', 'GAUGE', 0)
|
||||
->addDataset('totalLAST_ACK', 'GAUGE', 0)
|
||||
->addDataset('totalFIN_WAIT_2', 'GAUGE', 0)
|
||||
->addDataset('totalTIME_WAIT', 'GAUGE', 0)
|
||||
->addDataset('totalUNKNOWN', 'GAUGE', 0)
|
||||
->addDataset('totalother', 'GAUGE', 0)
|
||||
->addDataset('toLISTEN', 'GAUGE', 0)
|
||||
->addDataset('toCLOSED', 'GAUGE', 0)
|
||||
->addDataset('toSYN_SENT', 'GAUGE', 0)
|
||||
->addDataset('toSYN_RECEIVED', 'GAUGE', 0)
|
||||
->addDataset('toESTABLISHED', 'GAUGE', 0)
|
||||
->addDataset('toCLOSE_WAIT', 'GAUGE', 0)
|
||||
->addDataset('toFIN_WAIT_1', 'GAUGE', 0)
|
||||
->addDataset('toCLOSING', 'GAUGE', 0)
|
||||
->addDataset('toLAST_ACK', 'GAUGE', 0)
|
||||
->addDataset('toFIN_WAIT_2', 'GAUGE', 0)
|
||||
->addDataset('toTIME_WAIT', 'GAUGE', 0)
|
||||
->addDataset('toUNKNOWN', 'GAUGE', 0)
|
||||
->addDataset('toother', 'GAUGE', 0)
|
||||
->addDataset('fromLISTEN', 'GAUGE', 0)
|
||||
->addDataset('fromCLOSED', 'GAUGE', 0)
|
||||
->addDataset('fromSYN_SENT', 'GAUGE', 0)
|
||||
->addDataset('fromSYN_RECEIVED', 'GAUGE', 0)
|
||||
->addDataset('fromESTABLISHED', 'GAUGE', 0)
|
||||
->addDataset('fromCLOSE_WAIT', 'GAUGE', 0)
|
||||
->addDataset('fromFIN_WAIT_1', 'GAUGE', 0)
|
||||
->addDataset('fromCLOSING', 'GAUGE', 0)
|
||||
->addDataset('fromLAST_ACK', 'GAUGE', 0)
|
||||
->addDataset('fromFIN_WAIT_2', 'GAUGE', 0)
|
||||
->addDataset('fromTIME_WAIT', 'GAUGE', 0)
|
||||
->addDataset('fromUNKNOWN', 'GAUGE', 0)
|
||||
->addDataset('fromother', 'GAUGE', 0);
|
||||
|
||||
//
|
||||
// update the RRD files for each port
|
||||
//
|
||||
|
||||
$ports_keys=array_keys($ports);
|
||||
$ports_keys_int=0;
|
||||
while (isset($ports[$ports_keys[$ports_keys_int]])) {
|
||||
$rrd_name = array('app', $name, $app_id, $ports_keys[$ports_keys_int]);
|
||||
$fields = array(
|
||||
'total_conns' => $ports[$ports_keys[$ports_keys_int]]['total_conns'],
|
||||
'total_to' => $ports[$ports_keys[$ports_keys_int]]['total_to'],
|
||||
'total_from' => $ports[$ports_keys[$ports_keys_int]]['total_from'],
|
||||
'totalLISTEN' => $ports[$ports_keys[$ports_keys_int]]['total']['LISTEN'],
|
||||
'totalCLOSED' => $ports[$ports_keys[$ports_keys_int]]['total']['CLOSED'],
|
||||
'totalSYN_SENT' => $ports[$ports_keys[$ports_keys_int]]['total']['SYN_SENT'],
|
||||
'totalSYN_RECEIVED' => $ports[$ports_keys[$ports_keys_int]]['total']['SYN_RECEIVED'],
|
||||
'totalESTABLISHED' => $ports[$ports_keys[$ports_keys_int]]['total']['ESTABLISHED'],
|
||||
'totalCLOSE_WAIT' => $ports[$ports_keys[$ports_keys_int]]['total']['CLOSE_WAIT'],
|
||||
'totalFIN_WAIT_1' => $ports[$ports_keys[$ports_keys_int]]['total']['FIN_WAIT_1'],
|
||||
'totalCLOSING' => $ports[$ports_keys[$ports_keys_int]]['total']['CLOSING'],
|
||||
'totalLAST_ACK' => $ports[$ports_keys[$ports_keys_int]]['total']['LAST_ACK'],
|
||||
'totalFIN_WAIT_2' => $ports[$ports_keys[$ports_keys_int]]['total']['FIN_WAIT_2'],
|
||||
'totalTIME_WAIT' => $ports[$ports_keys[$ports_keys_int]]['total']['TIME_WAIT'],
|
||||
'totalUNKNOWN' => $ports[$ports_keys[$ports_keys_int]]['total']['UNKNOWN'],
|
||||
'totalother' => $ports[$ports_keys[$ports_keys_int]]['total']['other'],
|
||||
'toLISTEN' => $ports[$ports_keys[$ports_keys_int]]['to']['LISTEN'],
|
||||
'toCLOSED' => $ports[$ports_keys[$ports_keys_int]]['to']['CLOSED'],
|
||||
'toSYN_SENT' => $ports[$ports_keys[$ports_keys_int]]['to']['SYN_SENT'],
|
||||
'toSYN_RECEIVED' => $ports[$ports_keys[$ports_keys_int]]['to']['SYN_RECEIVED'],
|
||||
'toESTABLISHED' => $ports[$ports_keys[$ports_keys_int]]['to']['ESTABLISHED'],
|
||||
'toCLOSE_WAIT' => $ports[$ports_keys[$ports_keys_int]]['to']['CLOSE_WAIT'],
|
||||
'toFIN_WAIT_1' => $ports[$ports_keys[$ports_keys_int]]['to']['FIN_WAIT_1'],
|
||||
'toCLOSING' => $ports[$ports_keys[$ports_keys_int]]['to']['CLOSING'],
|
||||
'toLAST_ACK' => $ports[$ports_keys[$ports_keys_int]]['to']['LAST_ACK'],
|
||||
'toFIN_WAIT_2' => $ports[$ports_keys[$ports_keys_int]]['to']['FIN_WAIT_2'],
|
||||
'toTIME_WAIT' => $ports[$ports_keys[$ports_keys_int]]['to']['TIME_WAIT'],
|
||||
'toUNKNOWN' => $ports[$ports_keys[$ports_keys_int]]['to']['UNKNOWN'],
|
||||
'toother' => $ports[$ports_keys[$ports_keys_int]]['to']['other'],
|
||||
'fromLISTEN' => $ports[$ports_keys[$ports_keys_int]]['from']['LISTEN'],
|
||||
'fromCLOSED' => $ports[$ports_keys[$ports_keys_int]]['from']['CLOSED'],
|
||||
'fromSYN_SENT' => $ports[$ports_keys[$ports_keys_int]]['from']['SYN_SENT'],
|
||||
'fromSYN_RECEIVED' => $ports[$ports_keys[$ports_keys_int]]['from']['SYN_RECEIVED'],
|
||||
'fromESTABLISHED' => $ports[$ports_keys[$ports_keys_int]]['from']['ESTABLISHED'],
|
||||
'fromCLOSE_WAIT' => $ports[$ports_keys[$ports_keys_int]]['from']['CLOSE_WAIT'],
|
||||
'fromFIN_WAIT_1' => $ports[$ports_keys[$ports_keys_int]]['from']['FIN_WAIT_1'],
|
||||
'fromCLOSING' => $ports[$ports_keys[$ports_keys_int]]['from']['CLOSING'],
|
||||
'fromLAST_ACK' => $ports[$ports_keys[$ports_keys_int]]['from']['LAST_ACK'],
|
||||
'fromFIN_WAIT_2' => $ports[$ports_keys[$ports_keys_int]]['from']['FIN_WAIT_2'],
|
||||
'fromTIME_WAIT' => $ports[$ports_keys[$ports_keys_int]]['from']['TIME_WAIT'],
|
||||
'fromUNKNOWN' => $ports[$ports_keys[$ports_keys_int]]['from']['UNKNOWN'],
|
||||
'fromother' => $ports[$ports_keys[$ports_keys_int]]['from']['other'],
|
||||
);
|
||||
$tags = array('name' => $name, 'app_id' => $app_id, 'rrd_def' => $ports_rrd_def, 'rrd_name' => $rrd_name);
|
||||
data_update($device, 'app', $tags, $fields);
|
||||
|
||||
$ports_keys_int++;
|
||||
}
|
||||
|
||||
//
|
||||
// component processing for portsactivity
|
||||
//
|
||||
$device_id=$device['device_id'];
|
||||
$options=array(
|
||||
'filter' => array(
|
||||
'device_id' => array('=', $device_id),
|
||||
'type' => array('=', 'portsactivity'),
|
||||
),
|
||||
);
|
||||
|
||||
$component=new LibreNMS\Component();
|
||||
$components=$component->getComponents($device_id, $options);
|
||||
|
||||
//delete portsactivity component if nothing is found
|
||||
if (empty($ports_keys)) {
|
||||
if (isset($components[$device_id])) {
|
||||
foreach ($components[$device_id] as $component_id => $_unused) {
|
||||
$component->deleteComponent($component_id);
|
||||
}
|
||||
}
|
||||
//add portsactivity component if found
|
||||
} else {
|
||||
if (isset($components[$device_id])) {
|
||||
$portsc = $components[$device_id];
|
||||
} else {
|
||||
$portsc = $component->createComponent($device_id, 'portsactivity');
|
||||
}
|
||||
|
||||
$id = $component->getFirstComponentID($portsc);
|
||||
$portsc[$id]['label'] = 'Portsactivity';
|
||||
$portsc[$id]['ports'] = json_encode($ports_keys);
|
||||
|
||||
$component->setComponentPrefs($device_id, $portsc);
|
||||
}
|
||||
|
||||
update_application($app, 'OK', data_flatten($ports));
|
||||
@@ -81,10 +81,10 @@ function poll_sensor($device, $class)
|
||||
} elseif ($class == 'state') {
|
||||
if (!is_numeric($sensor_value)) {
|
||||
$state_value = dbFetchCell(
|
||||
'SELECT `state_value`
|
||||
FROM `state_translations` LEFT JOIN `sensors_to_state_indexes`
|
||||
ON `state_translations`.`state_index_id` = `sensors_to_state_indexes`.`state_index_id`
|
||||
WHERE `sensors_to_state_indexes`.`sensor_id` = ?
|
||||
'SELECT `state_value`
|
||||
FROM `state_translations` LEFT JOIN `sensors_to_state_indexes`
|
||||
ON `state_translations`.`state_index_id` = `sensors_to_state_indexes`.`state_index_id`
|
||||
WHERE `sensors_to_state_indexes`.`sensor_id` = ?
|
||||
AND `state_translations`.`state_descr` LIKE ?',
|
||||
array($sensor['sensor_id'], $sensor_value)
|
||||
);
|
||||
@@ -829,3 +829,38 @@ function json_app_get($device, $extend, $min_version = 1)
|
||||
|
||||
return $parsed_json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some data arrays returned with json_app_get are deeper than
|
||||
* update_application likes. This recurses through the array
|
||||
* and flattens it out so it can nicely be inserted into the
|
||||
* database.
|
||||
*
|
||||
* One argument is taken and that is the array to flatten.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $prefix What to prefix to the name. Defaults to '', nothing.
|
||||
* @param string $joiner The string to join the prefix, if set to something other
|
||||
* than '', and array keys with.
|
||||
*
|
||||
* @return array The flattened array.
|
||||
*/
|
||||
function data_flatten($array, $prefix = '', $joiner = '_')
|
||||
{
|
||||
$return = array();
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
if (strcmp($prefix, '')) {
|
||||
$key=$prefix.$joiner.$key;
|
||||
}
|
||||
$return = array_merge($return, data_flatten($value, $key, $joiner));
|
||||
} else {
|
||||
if (strcmp($prefix, '')) {
|
||||
$key=$prefix.$joiner.$key;
|
||||
}
|
||||
$return[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -363,6 +363,41 @@
|
||||
{
|
||||
"rule": "devices.os = \"Netscaler\" && sensors.sensor_type = \"haCurState\" && sensors.sensor_current ~ \"[2|4|5|7|10|11]\" && macros.device_up = \"1\"",
|
||||
"name": "Netscaler HA node state Critical"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.ssh_total_to>'5'",
|
||||
"name": "SSH Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.http_total_to>'100'",
|
||||
"name": "HTTP Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.https_total_to>'100'",
|
||||
"name": "HTTPS Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.smtp_total_from>'10'",
|
||||
"name": "SMTP Connections From"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.smtp_total_to>'30'",
|
||||
"name": "SMTP Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.ftp_total_to>'5'",
|
||||
"name": "FTP Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.imap_total_to>'20'",
|
||||
"name": "IMAP Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.imaps_total_to>'20'",
|
||||
"name": "IMAPS Connections To"
|
||||
},
|
||||
{
|
||||
"rule": "%applications.app_type='portactivity' && %applications_metrics.imaps_total_from>'0'",
|
||||
"name": "IRCD Connections From"
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
283
tests/data/linux_portactivity-v1.json
Normal file
283
tests/data/linux_portactivity-v1.json
Normal file
@@ -0,0 +1,283 @@
|
||||
{
|
||||
"applications": {
|
||||
"discovery": {
|
||||
"applications": [
|
||||
{
|
||||
"app_type": "portactivity",
|
||||
"app_state": "UNKNOWN",
|
||||
"discovered": "1",
|
||||
"app_state_prev": null,
|
||||
"app_status": "",
|
||||
"app_instance": ""
|
||||
}
|
||||
],
|
||||
"application_metrics": []
|
||||
},
|
||||
"poller": {
|
||||
"applications": [
|
||||
{
|
||||
"app_type": "portactivity",
|
||||
"app_state": "OK",
|
||||
"discovered": "1",
|
||||
"app_state_prev": "UNKNOWN",
|
||||
"app_status": "",
|
||||
"app_instance": ""
|
||||
}
|
||||
],
|
||||
"application_metrics": [
|
||||
{
|
||||
"metric": "ssh_from_CLOSE_WAIT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_CLOSED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_CLOSING",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_ESTABLISHED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_FIN_WAIT_1",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_FIN_WAIT_2",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_LAST_ACK",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_LISTEN",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_other",
|
||||
"value": 0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_SYN_RECEIVED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_SYN_SENT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_TIME_WAIT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_from_UNKNOWN",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_CLOSE_WAIT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_CLOSED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_CLOSING",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_ESTABLISHED",
|
||||
"value": 1.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_FIN_WAIT_1",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_FIN_WAIT_2",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_LAST_ACK",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_LISTEN",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_other",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_SYN_RECEIVED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_SYN_SENT",
|
||||
"value": "0.0",
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_TIME_WAIT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_to_UNKNOWN",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_CLOSE_WAIT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_CLOSED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_CLOSING",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_conns",
|
||||
"value": 1.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_ESTABLISHED",
|
||||
"value": 1.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_FIN_WAIT_1",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_FIN_WAIT_2",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_from",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_LAST_ACK",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_LISTEN",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_other",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_SYN_RECEIVED",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_SYN_SENT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_TIME_WAIT",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_to",
|
||||
"value": 1.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
},
|
||||
{
|
||||
"metric": "ssh_total_UNKNOWN",
|
||||
"value": 0.0,
|
||||
"value_prev": null,
|
||||
"app_type": "portactivity"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
11
tests/snmpsim/linux_portactivity-v1.snmprec
Normal file
11
tests/snmpsim/linux_portactivity-v1.snmprec
Normal file
@@ -0,0 +1,11 @@
|
||||
1.3.6.1.2.1.1.1.0|4|Linux server 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64
|
||||
1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.8072.3.2.10
|
||||
1.3.6.1.2.1.1.3.0|67|77550514
|
||||
1.3.6.1.2.1.1.4.0|4|<private>
|
||||
1.3.6.1.2.1.1.5.0|4|<private>
|
||||
1.3.6.1.2.1.1.6.0|4|<private>
|
||||
1.3.6.1.2.1.25.1.1.0|67|77552962
|
||||
1.3.6.1.4.1.8072.1.3.2.2.1.21.6.100.105.115.116.114.111|2|1
|
||||
1.3.6.1.4.1.8072.1.3.2.2.1.21.12.112.111.114.116.97.99.116.105.118.105.116.121|2|1
|
||||
1.3.6.1.4.1.8072.1.3.2.3.1.2.12.112.111.114.116.97.99.116.105.118.105.116.121|4x|7b0a2020202276657273696f6e22203a20312c0a202020226461746122203a207b0a2020202020202273736822203a207b0a20202020202020202022746f74616c5f746f22203a20312c0a20202020202020202022746f74616c5f636f6e6e7322203a20312c0a2020202020202020202266726f6d22203a207b0a2020202020202020202020202253594e5f524543454956454422203a20302c0a202020202020202020202020224c4153545f41434b22203a20302c0a2020202020202020202020202245535441424c495348454422203a20302c0a20202020202020202020202022554e4b4e4f574e22203a20302c0a2020202020202020202020202254494d455f5741495422203a20302c0a2020202020202020202020202246494e5f574149545f3122203a20302c0a2020202020202020202020202253594e5f53454e5422203a20302c0a20202020202020202020202022434c4f53455f5741495422203a20302c0a202020202020202020202020224c495354454e22203a20302c0a2020202020202020202020202246494e5f574149545f3222203a20302c0a20202020202020202020202022434c4f53454422203a20302c0a20202020202020202020202022434c4f53494e4722203a20302c0a202020202020202020202020226f7468657222203a20300a2020202020202020207d2c0a20202020202020202022746f74616c22203a207b0a2020202020202020202020202245535441424c495348454422203a20312c0a20202020202020202020202022554e4b4e4f574e22203a20302c0a2020202020202020202020202254494d455f5741495422203a20302c0a2020202020202020202020202246494e5f574149545f3122203a20302c0a2020202020202020202020202253594e5f53454e5422203a20302c0a2020202020202020202020202253594e5f524543454956454422203a20302c0a202020202020202020202020224c4153545f41434b22203a20302c0a2020202020202020202020202246494e5f574149545f3222203a20302c0a202020202020202020202020224c495354454e22203a20302c0a20202020202020202020202022434c4f53454422203a20302c0a20202020202020202020202022434c4f53494e4722203a20302c0a202020202020202020202020226f7468657222203a20302c0a20202020202020202020202022434c4f53455f5741495422203a20300a2020202020202020207d2c0a20202020202020202022746f74616c5f66726f6d22203a20302c0a20202020202020202022746f22203a207b0a20202020202020202020202022434c4f53455f5741495422203a20302c0a202020202020202020202020226f7468657222203a20302c0a2020202020202020202020202246494e5f574149545f3222203a20302c0a202020202020202020202020224c495354454e22203a20302c0a20202020202020202020202022434c4f53454422203a20302c0a20202020202020202020202022434c4f53494e4722203a20302c0a2020202020202020202020202253594e5f524543454956454422203a20302c0a202020202020202020202020224c4153545f41434b22203a20302c0a2020202020202020202020202254494d455f5741495422203a20302c0a2020202020202020202020202253594e5f53454e5422203a20302c0a2020202020202020202020202246494e5f574149545f3122203a20302c0a20202020202020202020202022554e4b4e4f574e22203a20302c0a2020202020202020202020202245535441424c495348454422203a20310a2020202020202020207d0a2020202020207d0a2020207d2c0a202020226572726f72537472696e6722203a2022222c0a202020226572726f7222203a202230220a7d0a
|
||||
1.3.6.1.6.3.10.2.1.3.0|2|775505
|
||||
Reference in New Issue
Block a user