mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-30 00:26:50 +09:00
486 lines
15 KiB
PHP
486 lines
15 KiB
PHP
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2017 The Cacti Group |
|
|
| |
|
|
| This program is free software; you can redistribute it and/or |
|
|
| modify it under the terms of the GNU General Public License |
|
|
| as published by the Free Software Foundation; either version 2 |
|
|
| of the License, or (at your option) any later version. |
|
|
| |
|
|
| This program is snmpagent in the hope that it will be useful, |
|
|
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
| GNU General Public License for more details. |
|
|
+-------------------------------------------------------------------------+
|
|
| Cacti: The Complete RRDTool-based Graphing Solution |
|
|
+-------------------------------------------------------------------------+
|
|
| This code is designed, written, and maintained by the Cacti Group. See |
|
|
| about.php and/or the AUTHORS file for specific developer information. |
|
|
+-------------------------------------------------------------------------+
|
|
| http://www.cacti.net/ |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
/* This mib parser bases on the PHP mib_compiler script of David Eder for
|
|
phpsnmp which bases itself on libsnmp. Both scripts are licensed under the
|
|
GNU Lesser General Public License.
|
|
|
|
/**
|
|
* phpsnmp - a PHP SNMP library
|
|
* Copyright (C) 2004 David Eder <david@eder,us>
|
|
*
|
|
* Based on snmp - a Python SNMP library
|
|
* Copyright (C) 2003 Unicity Pty Ltd <libsnmp@unicity.com.au>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
class MibParser extends MibCache {
|
|
|
|
protected $parsed = array();
|
|
protected $oids = array();
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
function __construct(){
|
|
set_time_limit(0);
|
|
ini_set('memory_limit', '256M');
|
|
error_reporting(E_ALL);
|
|
}
|
|
|
|
function add_mib($filename, $mib_name){
|
|
MibParser::parse_mib(file_get_contents($filename), $mib_name, true);
|
|
}
|
|
|
|
/**
|
|
* Get Tokens
|
|
*
|
|
* @param string $text
|
|
* @return array
|
|
*/
|
|
function get_tokens($text)
|
|
{
|
|
$in_quote = false;
|
|
$in_comment = false;
|
|
$token = '';
|
|
$tokens = array();
|
|
$length = strlen($text);
|
|
for($i = 0; $i < $length; $i++)
|
|
{
|
|
if($in_quote)
|
|
{
|
|
if($text{$i} == '"')
|
|
{
|
|
$in_quote = false;
|
|
if($token != '')
|
|
{
|
|
/* strip whitespaces from the end of the beginning of every object description row */
|
|
$lines = preg_split( '/\r\n|\r|\n/', $token);
|
|
$token = '';
|
|
foreach($lines as $line) {
|
|
$token .= trim($line) . "\r\n";
|
|
}
|
|
$tokens[] = $token;
|
|
$token = '';
|
|
}
|
|
}
|
|
else
|
|
$token .= $text{$i};
|
|
}
|
|
elseif($in_comment)
|
|
{
|
|
if($text{$i} == "\n" || $text{$i} == "\r")
|
|
$in_comment = false;
|
|
}
|
|
else
|
|
{
|
|
switch($text{$i})
|
|
{
|
|
case ':':
|
|
if($text{$i+1} == ':' && $text{$i+2} == '=')
|
|
{
|
|
if($token != '')
|
|
{
|
|
$tokens[] = $token;
|
|
$token = '';
|
|
}
|
|
$tokens[] = '::=';
|
|
$i += 2;
|
|
}
|
|
else
|
|
$token .= $text{$i};
|
|
break;
|
|
case '.':
|
|
if($text{$i+1} == '.')
|
|
{
|
|
if($token != '')
|
|
{
|
|
$tokens[] = $token;
|
|
$token = '';
|
|
}
|
|
$tokens[] = '..';
|
|
$i++;
|
|
}
|
|
else
|
|
$token .= $text{$i};
|
|
break;
|
|
case ',':
|
|
case ';':
|
|
case '{':
|
|
case '}':
|
|
case '(':
|
|
case ')':
|
|
case '|':
|
|
if($token != '')
|
|
{
|
|
$tokens[] = $token;
|
|
$token = '';
|
|
}
|
|
$tokens[] = $text{$i};
|
|
break;
|
|
case ' ':
|
|
case "\t":
|
|
case "\n":
|
|
case "\r":
|
|
if($token != '')
|
|
{
|
|
$tokens[] = $token;
|
|
$token = '';
|
|
}
|
|
break;
|
|
case '-':
|
|
if($text{$i+1} == '-')
|
|
$in_comment = true;
|
|
else
|
|
$token .= $text{$i};
|
|
break;
|
|
case '"';
|
|
$in_quote = true;
|
|
break;
|
|
default:
|
|
$token .= $text{$i};
|
|
}
|
|
}
|
|
}
|
|
if($token != '')
|
|
$tokens[] = $token;
|
|
return $tokens;
|
|
}
|
|
|
|
/**
|
|
* Parse simple token
|
|
*
|
|
* @param array $tokens
|
|
* @param integer $index
|
|
* @param array $allowed
|
|
* @return array
|
|
*/
|
|
function parse_simple_token($tokens, &$index, $allowed=NULL)
|
|
{
|
|
$index++;
|
|
|
|
if(is_array($allowed))
|
|
{
|
|
if(in_array(strtolower($tokens[$index]), $allowed))
|
|
return $tokens[$index];
|
|
}
|
|
elseif(is_null($allowed))
|
|
{
|
|
if($tokens[$index] == '{')
|
|
return MibParser::parse_bracket_token($tokens, $index, '{', '}');
|
|
else
|
|
return $tokens[$index];
|
|
}
|
|
trigger_error("unknown token {$tokens[$index]} {$tokens[$index]}", E_USER_ERROR);
|
|
return $tokens[$index];
|
|
}
|
|
|
|
/**
|
|
* Parse SYNTAX token
|
|
*
|
|
* @param array $tokens
|
|
* @param integer $index
|
|
* @return array
|
|
*/
|
|
function parse_SYNTAX_token($tokens, &$index)
|
|
{
|
|
$ret = NULL;
|
|
switch($tokens[$index+1])
|
|
{
|
|
case 'SEQUENCE':
|
|
if($tokens[$index+2] == 'OF')
|
|
{
|
|
$index += 3;
|
|
if($tokens[$index] == '{')
|
|
$ret = array('SEQUENCE OF'=>MibParser::parse_bracket_token($tokens, $index, '{', '}'));
|
|
else
|
|
$ret = array('SEQUENCE OF'=>$tokens[$index]);
|
|
}
|
|
break;
|
|
case 'OCTET':
|
|
if($tokens[$index+2] == 'STRING')
|
|
{
|
|
$index += 3;
|
|
if($tokens[$index] == '{')
|
|
$ret = array('OCTET STRING'=>MibParser::parse_bracket_token($tokens, $index, '{', '}'));
|
|
elseif($tokens[$index] == '(')
|
|
$ret = array('OCTET STRING'=>MibParser::parse_bracket_token($tokens, $index, '(', ')'));
|
|
else
|
|
$ret = 'OCTET STRING';
|
|
}
|
|
break;
|
|
case 'OBJECT':
|
|
if($tokens[$index+2] == 'IDENTIFIER') {
|
|
$index++;
|
|
$ret = $tokens[$index] . ' ' . $tokens[$index+1];
|
|
$index++;
|
|
}else {
|
|
trigger_error("unknown token {$tokens[$index+1]} {$tokens[$index+2]}", E_USER_ERROR);
|
|
}
|
|
break;
|
|
case 'INTEGER':
|
|
case 'Counter':
|
|
case 'Counter32':
|
|
case 'Counter64':
|
|
case 'Integer32':
|
|
case 'Gauge':
|
|
case 'Gauge32':
|
|
case 'TimeStamp':
|
|
case 'TimeTicks':
|
|
case 'PhysAddress':
|
|
case 'IpAddress':
|
|
case 'DateAndTime':
|
|
case 'TimeInterval':
|
|
case 'Unsigned32':
|
|
case 'DisplayString':
|
|
$index++;
|
|
$ret = $tokens[$index];
|
|
if($tokens[$index+1] == '{') {
|
|
$index++;
|
|
$ret = array($ret=>MibParser::parse_bracket_token($tokens, $index, '{', '}'));
|
|
} elseif($tokens[$index+1] == '(') {
|
|
$index++;
|
|
$ret = array($ret=>MibParser::parse_bracket_token($tokens, $index, '(', ')'));
|
|
}
|
|
break;
|
|
default:
|
|
$index++;
|
|
$ret = $tokens[$index];
|
|
if($tokens[$index+1] == '{') {
|
|
$index++;
|
|
$ret = array($ret=>MibParser::parse_bracket_token($tokens, $index, '{', '}'));
|
|
} elseif($tokens[$index+1] == '(') {
|
|
$index++;
|
|
$ret = array($ret=>MibParser::parse_bracket_token($tokens, $index, '(', ')'));
|
|
}
|
|
break;
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Parse bracket token
|
|
*
|
|
* @param array $tokens
|
|
* @param integer $index
|
|
* @param integer $start
|
|
* @param integer $end
|
|
* @return array
|
|
*/
|
|
function parse_bracket_token($tokens, &$index, $start, $end)
|
|
{
|
|
$begin = $index + 1;
|
|
while($index + 1 < count($tokens) && $tokens[$index] != $end)
|
|
{
|
|
$index++;
|
|
if($tokens[$index] == $start)
|
|
{
|
|
MibParser::parse_bracket_token($tokens, $index, $start, $end);
|
|
$index++;
|
|
}
|
|
}
|
|
return array_slice($tokens, $begin, $index - $begin);
|
|
}
|
|
|
|
/**
|
|
* Parse a MIB file
|
|
*
|
|
* @param string $mibtext
|
|
* @param boolean $full
|
|
*/
|
|
function parse_mib($mibtext, $mib_name, $full=false)
|
|
{
|
|
$tokens = MibParser::get_tokens($mibtext);
|
|
$cnt = count($tokens);
|
|
$rec = array();
|
|
|
|
for($index = 0; $index < $cnt; $index++)
|
|
{
|
|
|
|
if($tokens[$index] == 'DEFINITIONS' && $tokens[$index+1] == "::=" && $tokens[$index+2] == "BEGIN"){
|
|
$mib_name = $tokens[$index-1];
|
|
$this->mib = $mib_name;
|
|
}
|
|
else if(in_array($tokens[$index], array('OBJECT-IDENTITY', 'OBJECT-TYPE', 'OBJECT-GROUP', 'NOTIFICATION-GROUP', 'MODULE-IDENTITY', 'NOTIFICATION-TYPE')) )
|
|
{
|
|
if($tokens[$index-1] != ',' && $tokens[$index+1] != 'FROM' && $tokens[$index+1] != 'MACRO')
|
|
{
|
|
if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
|
|
$rec = array('NAME'=>$tokens[$index-1], 'MIB'=>$mib_name , 'TYPE' => $tokens[$index]);
|
|
}
|
|
}
|
|
elseif( $tokens[$index] == "TEXTUAL-CONVENTION")
|
|
{
|
|
if($tokens[$index-1] == '::=') {
|
|
if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
|
|
$rec = array('NAME'=>$tokens[$index-2], 'MIB'=>$mib_name, 'TYPE' => $tokens[$index], 'VALUE' => "TEXTUAL-CONVENTION");
|
|
}
|
|
}
|
|
elseif($tokens[$index] == 'OBJECT')
|
|
{
|
|
if($tokens[$index+1] == 'IDENTIFIER' && $tokens[$index-1] != '(' && $tokens[$index-1] != '::=' && $tokens[$index-1] != 'SYNTAX' && $tokens[$index-2] != '(')
|
|
{
|
|
if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
|
|
$rec = array('NAME'=>$tokens[$index-1], 'MIB'=>$mib_name, 'TYPE' => $tokens[$index]);
|
|
}
|
|
}
|
|
elseif($tokens[$index] == '{')
|
|
MibParser::parse_bracket_token($tokens, $index, '{', '}');
|
|
elseif(isset($rec['NAME']))
|
|
{
|
|
if($tokens[$index] == '::=' && $tokens[$index+1] != "TEXTUAL-CONVENTION")
|
|
{
|
|
$rec['VALUE'] = MibParser::parse_simple_token($tokens, $index);
|
|
$this->parsed[] = $rec;
|
|
$rec = array();
|
|
}
|
|
elseif($full)
|
|
{
|
|
if($tokens[$index] == 'ACCESS')
|
|
$rec['ACCESS'] = MibParser::parse_simple_token($tokens, $index, array('read-only', 'not-accessible', 'read-write'));
|
|
elseif($tokens[$index] == 'OBJECTS')
|
|
$rec['OBJECTS'] = MibParser::parse_simple_token($tokens, $index);
|
|
elseif($tokens[$index] == 'NOTIFICATIONS')
|
|
$rec['NOTIFICATIONS'] = MibParser::parse_simple_token($tokens, $index);
|
|
elseif($tokens[$index] == 'DEFVAL')
|
|
$rec['DEFVAL'] = MibParser::parse_simple_token($tokens, $index);
|
|
elseif($tokens[$index] == 'DESCRIPTION')
|
|
{
|
|
$rec['DESCRIPTION'] = MibParser::parse_simple_token($tokens, $index);
|
|
} elseif($tokens[$index] == 'INDEX')
|
|
$rec['INDEX'] = MibParser::parse_simple_token($tokens, $index);
|
|
elseif($tokens[$index] == 'MAX-ACCESS')
|
|
$rec['MAX-ACCESS'] = MibParser::parse_simple_token($tokens, $index, array('read-only', 'not-accessible', 'read-write', 'read-create', 'accessible-for-notify'));
|
|
elseif($tokens[$index] == 'REFERENCE')
|
|
$rec['REFERENCE'] = MibParser::parse_simple_token($tokens, $index);
|
|
elseif($tokens[$index] == 'STATUS')
|
|
$rec['STATUS'] = MibParser::parse_simple_token($tokens, $index, array('current', 'deprecated', 'obsolete', 'mandatory'));
|
|
elseif($tokens[$index] == 'SYNTAX')
|
|
$rec['SYNTAX'] = MibParser::parse_SYNTAX_token($tokens, $index);
|
|
elseif($tokens[$index] == 'UNITS')
|
|
$rec['UNITS'] = MibParser::parse_simple_token($tokens, $index);
|
|
}
|
|
}
|
|
}
|
|
if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
|
|
}
|
|
|
|
function generate(){
|
|
$this->oids['enterprises'] = array('oid' => '.1.3.6.1.4.1');
|
|
|
|
foreach($this->parsed as $object) {
|
|
if(isset($object['VALUE'][0]) && !is_numeric($object['VALUE'][0])) {
|
|
if(isset($object['VALUE'][1]) && is_numeric($object['VALUE'][1])) {
|
|
if(isset($this->oids[$object['VALUE'][0]]['oid'])) {
|
|
$oid = $this->oids[$object['VALUE'][0]]['oid'] . "." . $object['VALUE'][1];
|
|
}else {
|
|
$oid = db_fetch_cell("SELECT `oid` FROM snmpagent_cache WHERE name = '" . $object['VALUE'][0] . "' LIMIT 1");
|
|
$oid .= "." . $object['VALUE'][1];
|
|
}
|
|
|
|
$syntax = NULL;
|
|
if(isset($object['SYNTAX'])) {
|
|
$syntax = is_array($object['SYNTAX']) ? key($object['SYNTAX']) : $object['SYNTAX'];
|
|
}
|
|
|
|
$parent_otype = strtoupper(substr($object['VALUE'][0], -5));
|
|
$otype = $object['TYPE'];
|
|
|
|
if($otype == "OBJECT-TYPE" && $syntax !== NULL && !in_array(strtoupper(substr($object['NAME'], -5)), array("TABLE", "ENTRY")) && !in_array($parent_otype, array("TABLE", "ENTRY")) ) {
|
|
$oid .= ".0";
|
|
$otype = "DATA";
|
|
}
|
|
|
|
$kind ="unknown";
|
|
if(in_array($otype, array("MODULE-IDENTITY", "OBJECT-IDENTITY"))) {
|
|
$kind = "Node";
|
|
}else if(in_array($otype, array("NOTIFICATION-GROUP", "OBJECT-GROUP"))) {
|
|
$kind = "Group";
|
|
}else if($otype == "OBJECT-TYPE" && strtoupper(substr($object['NAME'], -5)) == "TABLE" && $syntax == "SEQUENCE OF") {
|
|
$kind = "Table";
|
|
}else if($otype == "OBJECT-TYPE" && strtoupper(substr($object['NAME'], -5)) == "ENTRY" && $parent_otype == "TABLE") {
|
|
$kind = "Row";
|
|
}else if($otype == "OBJECT-TYPE" && $parent_otype == "ENTRY") {
|
|
$kind = "Column";
|
|
}else if($otype == "DATA") {
|
|
$kind = "Scalar";
|
|
}else if($otype == "NOTIFICATION-TYPE") {
|
|
$kind = "Notification";
|
|
}
|
|
|
|
$this->oids[$object['NAME']] = array(
|
|
'oid' => $oid,
|
|
'max-access' => (isset($object['MAX-ACCESS'])? $object['MAX-ACCESS'] : 'not-accessible'),
|
|
'syntax' => $syntax,
|
|
'otype' => $otype,
|
|
'kind' => $kind,
|
|
'mib' => $object['MIB'],
|
|
'description' => $object['DESCRIPTION']
|
|
);
|
|
|
|
if($otype == "OBJECT-GROUP" && isset($object['OBJECTS'])) {
|
|
$this->oids[$object['NAME']]['objects'] = array_diff($object['OBJECTS'], array(','));
|
|
} elseif($otype == "NOTIFICATION-GROUP" && isset($object['NOTIFICATIONS'])) {
|
|
$this->oids[$object['NAME']]['notifications'] = array_diff($object['NOTIFICATIONS'], array(','));
|
|
} elseif($otype == "NOTIFICATION-TYPE" && isset($object['OBJECTS'])) {
|
|
$this->oids[$object['NAME']]['objects'] = array_diff($object['OBJECTS'], array(','));
|
|
}
|
|
} elseif($object["VALUE"] == "TEXTUAL-CONVENTION") {
|
|
$syntax = NULL;
|
|
if(isset($object['SYNTAX'])) {
|
|
$syntax = is_array($object['SYNTAX']) ? key($object['SYNTAX']) : $object['SYNTAX'];
|
|
}
|
|
$kind = "Textual-Convention";
|
|
$otype = "TEXTUAL-CONVENTION";
|
|
$this->oids[$object['NAME']] = array(
|
|
'oid' => "",
|
|
'max-access' => "",
|
|
'syntax' => $syntax,
|
|
'otype' => $otype,
|
|
'kind' => $kind,
|
|
'mib' => $object['MIB'],
|
|
'description' => $object['DESCRIPTION']
|
|
);
|
|
}
|
|
}
|
|
}
|
|
unset($this->oids['enterprises']);
|
|
unset($this->parsed);
|
|
}
|
|
|
|
}
|