Cacti / cacti

Cacti ™
http://www.cacti.net
GNU General Public License v2.0
1.63k stars 404 forks source link

cacti_snmp_walk returns OID and value as strings, mac-addresses are expected #2647

Closed vKnmnn closed 5 years ago

vKnmnn commented 5 years ago

I'm having trouble with the Cisco WLC APs script, or rather the output it creates. On the new machine I'm moving to, there's cacti 1.2.3, spine 1.2.3, php 7.2, net-snmp 5.7.3

The WLC script calls cacti_snmp_walk( hostname, comunity, oid, snmp_ver, "", "", "", ""; ""; "", 161, 1000, 1). This works on the old machine (cacti 0.8.8b, spin3 0.8.8b, php5.5.9, net-snmp 5.7.2) Here, however, the output gets all garbled up, because the values get converted from hex to ascii. Part of the var_dump:

array(169) {
  [0]=>
  array(2) {
    ["oid"]=>
    string(44) "1.3.6.1.4.1.14179.2.2.1.1.1.0.53.26.188.58.0"
    ["value"]=>
    string(6) "5:"
 }....

old machine:

array(169) {
  [0]=>
  array(2) {
    ["oid"]=>
    string(44) "enterprises.14179.2.2.1.1.1.0.53.26.188.58.0"
    ["value"]=>
    string(17) "AA:AA:AA:AA:AA:AA" (redacted)
  }

There is an artifact in the returned values with plain linux snmpwalk, where one specific mac-address gets returned as type STRING instead of HEX-STRING, similar to this case on cisco bug-tracker

I'm guessing this messes up cacti's guesswork on which data-type to return.

output of snmpwalk:

.1.3.6.1.4.1.14179.2.2.1.1.1.120.114.93.62.41.0 = Hex-STRING: 78 72 5D 3E 29 00
.1.3.6.1.4.1.14179.2.2.1.1.1.120.114.93.94.71.96 = STRING: "xr]^G`"
.1.3.6.1.4.1.14179.2.2.1.1.1.120.114.93.139.212.0 = Hex-STRING: 78 72 5D 8B D4 00

Do you have any idea, how to get around this, as it probably isn't a bug in cacti?

below is the Cisco_WLC_APs_Assoc.php script.

<?php
#ini_set('display_errors', 'On');
#error_reporting(E_ALL);
/* do NOT run this script through a web browser */
if (!isset($_SERVER["argv"][0]) || isset($_SERVER['REQUEST_METHOD'])  || isset($_SERVER['REMOTE_ADDR'])) {
   die("<br><strong>This script is only meant to run at the command line.</strong>");
}

$no_http_headers = true;

if (file_exists(dirname(__FILE__) . "/../include/global.php")) {
        include(dirname(__FILE__) . "/../include/global.php");
}
include(dirname(__FILE__) . "/../include/config.php");
include(dirname(__FILE__) . "/../lib/snmp.php");

$oids = array(
        "index" => ".1.3.6.1.4.1.14179.2.2.1.1.1",
        "bsnAPName" => ".1.3.6.1.4.1.14179.2.2.1.1.3",
        "bsnApIpAddress" => ".1.3.6.1.4.1.14179.2.2.1.1.19",
        "bsnAPSerialNumber" => ".1.3.6.1.4.1.14179.2.2.1.1.17"
        );

$hostname = $_SERVER["argv"][1];
$snmp_community = $_SERVER["argv"][2];
$snmp_version = $_SERVER["argv"][3];
$cmd = $_SERVER["argv"][4];

function snmp_walk($hostname, $snmp_community, $oid, $snmp_version, $cacti_version) {
        if ($cacti_version) {
                $value = cacti_snmp_walk($hostname, $snmp_community, $oid, $snmp_version, "", "", "", "", "", "", 161, 1000, 1);
                                var_dump($value);
        } else {
                $value = cacti_snmp_walk($hostname, $snmp_community, $oid, $snmp_version, "", "", 161, 1000);
        }
        return $value;
}
if ($cmd == "index") {
        $return_arr = reindex(snmp_walk($hostname, $snmp_community, $oids["index"], $snmp_version, $config["cacti_version"]));

        for ($i=0;($i<sizeof($return_arr));$i++) {
                print $return_arr[$i] . "\n";
        }
}elseif ($cmd == "query") {
        $arg = $_SERVER["argv"][5];

        $arr_index = reindex(snmp_walk($hostname, $snmp_community, $oids["index"], $snmp_version, $config["cacti_version"]));
        $arr = reindex(snmp_walk($hostname, $snmp_community, $oids[$arg], $snmp_version, $config["cacti_version"]));

        for ($i=0;($i<sizeof($arr_index));$i++) {
                print $arr_index[$i] . "!" . $arr[$i] . "\n";
        }

}elseif ($cmd == "get") {
        $arg = $_SERVER["argv"][5];
        $index = $_SERVER["argv"][6];

        if (($arg == "apassoc")){
                $test=str_replace("HEX-00:","",$index);
                $bsnMobileStationAPMacAddr = ".1.3.6.1.4.1.14179.2.1.4.1.4";
                $stations = snmp_walk($hostname, $snmp_community, $bsnMobileStationAPMacAddr, $snmp_version, $config["cacti_version"]);
                $assoc = 0;
                for ($i=0;($i<sizeof($stations));$i++) {
                        if ($stations[$i]["value"] == "$test") {$assoc++;}
                }
                print $assoc;
        }
}

function reindex($arr) {
        $return_arr = array();

        for ($i=0;($i<sizeof($arr));$i++) {
                $return_arr[$i] = $arr[$i]["value"];
        }

        return $return_arr;
}

?>
cigamit commented 5 years ago

Please review the latest lib/snmp.php, there is a new value_output_format option to the walk command. I think it's SNMP_STRING_OUTPUT_HEX. Just use that. Feel free to publish your entire template here if you choose.

vKnmnn commented 5 years ago

Thanks for the help, @cigamit. I've altered the appropriate line to: $value = cacti_snmp_walk($hostname, $snmp_community, $oid, $snmp_version, "", "", "", "", "", "", 161, 1000, 1, 100, SNMP_POLLER, "", SNMP_STRING_OUTPUT_HEX);

Now the command fails with sh: 1: -O not found. There seem to be a couple things wrong here. var_dump($path_snmpwalk);on line 553 prints a NULL, which it probably shouldnt, when the value is set. Do i need to run php in a special way to be able to acces the db?

note, that calling cacti_snmp_walk with 17 arguments, the 17th being SNMP_STRING_OUTPUT_HEX, or any other value, causes this behaviour for me, calling with 16 arguments gives me the garbled output again.

vKnmnn commented 5 years ago

I hardcoded the path to snmpwalk binary in lib/snmp.php, and all works as it should, even with 17 arguments.

netniV commented 5 years ago

If you are running from the command line, you should probably include_once() the include/cli_check.php file at the top of the script. If the script is being run by the poller or script server, that will already have been done so it won’t do it twice. If running via the command line directly the script, it will include all the appropriate items needed to gain access to the DB.

vKnmnn commented 5 years ago

Ok, so including cli_check makes it work too, but then i get a few Notices that are messing up the indexing of the output. A few notices about previously defined constants and an undefined index in functions.php

netniV commented 5 years ago

What are they ? Did yo7 make sure to use the _once?

vKnmnn commented 5 years ago

yes, i used include_once:

include_once(dirname(__FILE__) . "/../include/cli_check.php"

and ran the script as sudo -u www-data -g www-data php $cactipath/scripts/Cisco_WLC_APs_Assoc.php "$devip" "$snmpcomm" "2" "index"

the notices are:

Notice: Constant CACTI_VERSION already defined in /usr/share/cacti/site/include/global.php on line 47

Notice: Constant CACTI_CLI already defined in /usr/share/cacti/site/include/global.php on line 51

Notice: Constant CACTI_DOCUMENTATION_TOC already defined in /usr/share/cacti/site/include/global.php on line 57

Notice: Undefined index: base_path in /usr/share/cacti/site/lib/functions.php on line 4075

Notice: Undefined index: base_path in /usr/share/cacti/site/lib/functions.php on line 4075

Notice: Undefined index: base_path in /usr/share/cacti/site/lib/functions.php on line 4075

Notice: Constant URL_PATH already defined in /usr/share/cacti/site/include/global.php on line 208

Notice: Constant CACTI_DATE_TIME_FORMAT already defined in /usr/share/cacti/site/include/global.php on line 431
vKnmnn commented 5 years ago

it only works, if i include AFTER all other includes. (e.g. on line 16). If i include the cli_check first, i only get the notices and no other output.

netniV commented 5 years ago

Hmm, in that case then it looks like it was already included. If you want to be really sure add a check for one of the constants used is_defined() and then only include once if the cli constant isn’t already there.

vKnmnn commented 5 years ago

I'm not sure i understand. If i check whether the constants are already defined and only include if they aren't, that doesn't really do anything, since we're including global and config.php already.

I ran the script via the browser too, selecting the data query from the host settings and running it verbosely with the yellow button and even then, snmp.php fails to read the config.

netniV commented 5 years ago

On for command line scripts only the cli_check.php should be included not global. That then includes global itself. But, if you have duplicate CACTI_CLI constants then it is getting cli_check.php included more than once.

If (!is_defined(‘CACTI_CLI’)) {
    Include_once(‘include/cli_check.php’);
}
vKnmnn commented 5 years ago

ah, i see. It still doesnt fix anything though. read_config_option('path_snmpwalk') returns NULL when calling cacti_snmp_walk.

netniV commented 5 years ago

And that is definitely set in the database?

SELECT * FROM settings where name = 'path_snmpwalk';
vKnmnn commented 5 years ago

yes

mysql> SELECT * FROM cacti.settings where name = 'path_snmpwalk';
+---------------+-------------------+
| name          | value             |
+---------------+-------------------+
| path_snmpwalk | /usr/bin/snmpwalk |
+---------------+-------------------+

I have to let this issue sit for the next two weeks, because i'll not be at work.

TheWitness commented 5 years ago

SeLinux, suhosin or mod_security?

cigamit commented 5 years ago

Closing as this is a dead issue.

vKnmnn commented 4 years ago

I've finally gotten around to fix this. I'm posting the fix here in case someone has the same problem:

--- /usr/share/cacti/cacti-1.2.7/scripts/Cisco_WLC_APs_Assoc.php        2019-10-17 16:18:24.105191191 +0200
+++ /usr/share/cacti/site/scripts/Cisco_WLC_APs_Assoc.php       2019-10-18 10:15:30.492002006 +0200
@@ -38,6 +38,9 @@
        $return_arr = reindex(snmp_walk($hostname, $snmp_community, $oids["index"], $snmp_version, $config["cacti_version"]));

        for ($i=0;($i<sizeof($return_arr));$i++) {
+               if ( strlen($return_arr[$i]) != 17 ){
+                       $return_arr[$i] =  preg_replace('~(..)(?!$)\.?~','\1:',bin2hex($return_arr[$i]));
+               }
                print $return_arr[$i] . "\n";
        }
 }elseif ($cmd == "query") {
@@ -48,6 +51,12 @@
        $arr = reindex(snmp_walk($hostname, $snmp_community, $oids[$arg], $snmp_version, $config["cacti_version"]));

        for ($i=0;($i<sizeof($arr_index));$i++) {
+               if ( strlen($arr_index[$i]) != 17 ){
+                       $arr_index[$i] =  preg_replace('~(..)(?!$)\.?~','\1:',bin2hex($arr_index[$i]));
+               }
+               if ( strlen($arr[$i]) != 17 ){
+                       $arr[$i] =  preg_replace('~(..)(?!$)\.?~','\1:',bin2hex($arr[$i]));
+               }
                print $arr_index[$i] . "!" . $arr[$i] . "\n";
        }
vKnmnn commented 4 years ago

I uploaded a gist containing the template HERE