View Issue Details

IDProjectCategoryView StatusLast Update
379RackTablesSNMPpublic2010-11-29 13:49
Reporteruser143Assigned Toinfrastation  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Product Version0.18.5 
Target Version0.19.0Fixed in Version0.19.0 
Summary379: Support for SNMPv3
DescriptionPolicy says: new devices only get snmpv3 ;)

-> so I've implemented snmpv3 support for RackTables

The interface could be prettier but it works.
TagsNo tags attached.

Activities

infrastation

infrastation

2010-11-19 04:53

administrator   ~0000175

I have looked through. Will commit after a couple of runs on the real hardware.
infrastation

infrastation

2010-11-20 17:54

administrator   ~0000178

The patch fails to apply properly (tried with trunk):

$ patch -p1 < /tmp/snmpv3.patch
patching file inc/interface.php
Hunk #1 succeeded at 5013 (offset 721 lines).
patching file inc/ophandlers.php
Hunk #1 succeeded at 1955 (offset 118 lines).
patching file inc/snmp.php
Hunk #1 succeeded at 940 (offset 40 lines).
Hunk #2 succeeded at 950 (offset 40 lines).
Hunk #3 succeeded at 1000 (offset 40 lines).
Hunk #4 succeeded at 1069 (offset 41 lines).
Hunk #5 FAILED at 1038.
Hunk #6 succeeded at 1096 (offset 47 lines).
patch: **** malformed patch at line 197: @@ -1113,6 +1140,8 @@

Could you check, that the revision you have sumbitted is correct?

2010-11-20 19:48

 

snmpv3-new.patch (15,542 bytes)   
diff -ur RackTables-0.18.5/inc/interface.php RackTables-0.18.5-snmpv3/inc/interface.php
--- RackTables-0.18.5/inc/interface.php	2010-10-19 20:48:07.000000000 +0200
+++ RackTables-0.18.5-snmpv3/inc/interface.php	2010-11-20 20:16:06.360887000 +0100
@@ -4292,10 +4292,50 @@
 			$snmpcomm = 'public';
 
 		echo "<p align=center>
-This object has no ports listed, that's why you see this form. If you supply a SNMP community,
-I can try to automatically harvest the data. As soon as at least one port is added,
-this tab will not be seen any more. Good luck.<br>\n";
-		echo "<input type=text name=community value='" . $snmpcomm . "'>\n";
+This object has no ports listed, that's why you see this form. I can try to automatically harvest the data.
+As soon as at least one port is added, this tab will not be seen any more. Good luck.
+<br />
+You may enter just the snmp community and use SNMPv3 (leave community empty and fill the other fields)
+<br />\n";
+
+		echo "<input type=text name=community value='" . $snmpcomm . "'><br /><br />\n";
+
+		echo '
+		<label for="sec_name">Security User</label>
+		<input type="text" id="sec_name" name="sec_name"><br />
+
+		
+		<label for="sec_level">Security Level</label>
+		<select id="sec_level" name="sec_level"> 
+			<option value="noAuthNoPriv" selected="selected">noAuth and no Priv</option>
+			<option value="authNoPriv" >auth without Priv</option>
+			<option value="authPriv" >auth with Priv</option>
+		</select>
+		<br />
+
+		<label for="auth_protocol_1">Auth Type</label>
+		<input id="auth_protocol_1" name="auth_protocol" type="radio" value="md5" />
+		<label for="auth_protocol_1">MD5</label>
+		<input id="auth_protocol_2" name="auth_protocol" type="radio" value="sha" />
+		<label for="auth_protocol_2">SHA</label>
+		<br />
+
+		<label for="auth_passphrase">Auth Key</label>
+		<input type="text" id="auth_passphrase" name="auth_passphrase">
+		<br />
+
+		<label for="priv_protocol_1">Priv Type</label>
+		<input id="priv_protocol_1" name="priv_protocol" type="radio" value="DES" />
+		<label for="priv_protocol_1">DES</label>
+		<input id="priv_protocol_2" name="priv_protocol" type="radio" value="AES" />
+		<label for="priv_protocol_2">AES</label>
+		<br />
+
+		<label for="priv_passphrase">Priv Key</label>
+		<input type="text" id="priv_passphrase" name="priv_passphrase">
+		<br />';
+		
+
 		echo "<input type=submit name='do_scan' value='Go!'> \n";
 		echo "</form></p>\n";
 	}
diff -ur RackTables-0.18.5/inc/ophandlers.php RackTables-0.18.5-snmpv3/inc/ophandlers.php
--- RackTables-0.18.5/inc/ophandlers.php	2010-10-18 19:23:19.000000000 +0200
+++ RackTables-0.18.5-snmpv3/inc/ophandlers.php	2010-11-20 20:16:06.370887000 +0100
@@ -1837,8 +1837,30 @@
 function querySNMPData ()
 {
 	assertUIntArg ('object_id');
-	assertStringArg ('community');
-	return doSNMPmining ($_REQUEST['object_id'], $_REQUEST['community']);
+	assertStringArg ('community', TRUE);
+
+	$snmpsetup = array ();
+	if ( strlen($_REQUEST['community']) == 0 ) {
+		assertStringArg ('sec_name');
+		assertStringArg ('sec_level');
+		assertStringArg ('auth_protocol');
+		assertStringArg ('auth_passphrase', TRUE);
+		assertStringArg ('priv_protocol');
+		assertStringArg ('priv_passphrase', TRUE);
+
+		$snmpsetup['sec_name'] = $_REQUEST['sec_name'];
+		$snmpsetup['sec_level'] = $_REQUEST['sec_level'];
+		$snmpsetup['auth_protocol'] = $_REQUEST['auth_protocol'];
+		$snmpsetup['auth_passphrase'] = $_REQUEST['auth_passphrase'];
+		$snmpsetup['priv_protocol'] = $_REQUEST['priv_protocol'];
+		$snmpsetup['priv_passphrase'] = $_REQUEST['priv_passphrase'];
+	}
+	else {
+		$snmpsetup['community'] = $_REQUEST['community'];
+	}
+
+
+	return doSNMPmining ($_REQUEST['object_id'], $snmpsetup);
 }
 
 $msgcode['addFileWithoutLink']['OK'] = 69;
diff -ur RackTables-0.18.5/inc/snmp.php RackTables-0.18.5-snmpv3/inc/snmp.php
--- RackTables-0.18.5/inc/snmp.php	2010-10-19 19:51:54.000000000 +0200
+++ RackTables-0.18.5-snmpv3/inc/snmp.php	2010-11-20 20:16:06.370887000 +0100
@@ -900,7 +900,7 @@
 $msgcode['doSNMPmining']['ERR1'] = 161;
 $msgcode['doSNMPmining']['ERR2'] = 162;
 $msgcode['doSNMPmining']['OK'] = 81;
-function doSNMPmining ($object_id, $community)
+function doSNMPmining ($object_id, $snmpsetup)
 {
 	$objectInfo = spotEntity ('object', $object_id);
 	$objectInfo['attrs'] = getAttrValues ($object_id);
@@ -910,28 +910,30 @@
 	if (count ($endpoints) > 1)
 		return buildRedirectURL (__FUNCTION__, 'ERR2'); // can't pick an address
 
+	$device = new SNMPDevice($endpoints[0], $snmpsetup);
+
 	switch ($objectInfo['objtype_id'])
 	{
 	case 7:
 	case 8:
-		return doSwitchSNMPmining ($objectInfo, $endpoints[0], $community);
+		return doSwitchSNMPmining ($objectInfo, $device);
 	case 2:
-		return doPDUSNMPmining ($objectInfo, $endpoints[0], $community);
+		return doPDUSNMPmining ($objectInfo, $device);
 	}	
 }
 
 $msgcode['doSwitchSNMPmining']['ERR3'] = 188;
 $msgcode['doSwitchSNMPmining']['ERR4'] = 189;
-function doSwitchSNMPmining ($objectInfo, $hostname, $community)
+function doSwitchSNMPmining ($objectInfo, $device)
 {
 	$log = emptyLog();
 	global $known_switches, $iftable_processors;
 	
-	if (FALSE === ($sysObjectID = @snmpget ($hostname, $community, 'sysObjectID.0')))
+	if (FALSE === ($sysObjectID = $device->snmpget ('sysObjectID.0')))
 		return buildRedirectURL (__FUNCTION__, 'ERR3'); // // fatal SNMP failure
 	$sysObjectID = preg_replace ('/^.*(enterprises\.)([\.[:digit:]]+)$/', '\\2', $sysObjectID);
-	$sysName = substr (@snmpget ($hostname, $community, 'sysName.0'), strlen ('STRING: '));
-	$sysDescr = substr (@snmpget ($hostname, $community, 'sysDescr.0'), strlen ('STRING: '));
+	$sysName = substr ($device->snmpget ('sysName.0'), strlen ('STRING: '));
+	$sysDescr = substr ($device->snmpget ('sysDescr.0'), strlen ('STRING: '));
 	$sysDescr = str_replace (array ("\n", "\r"), " ", $sysDescr);  // Make it one line
 	if (!isset ($known_switches[$sysObjectID]))
 		return buildRedirectURL (__FUNCTION__, 'ERR4', array ($sysObjectID)); // unknown OID
@@ -958,7 +960,7 @@
 		updateStickerForCell ($objectInfo, 5, $exact_release);
 		if (array_key_exists ($major_line, $ios_codes))
 			updateStickerForCell ($objectInfo, 4, $ios_codes[$major_line]);
-		$sysChassi = @snmpget ($hostname, $community, '1.3.6.1.4.1.9.3.6.3.0');
+		$sysChassi = $device->snmpget ('1.3.6.1.4.1.9.3.6.3.0');
 		if ($sysChassi !== FALSE or $sysChassi !== NULL)
 			updateStickerForCell ($objectInfo, 1, str_replace ('"', '', substr ($sysChassi, strlen ('STRING: '))));
 		checkPIC ('1-29');
@@ -1026,7 +1028,7 @@
 		$exact_release = preg_replace ('/^.*, IronWare Version ([^ ]+) .*$/', '\\1', $sysDescr);
 		updateStickerForCell ($objectInfo, 5, $exact_release);
 		# FOUNDRY-SN-AGENT-MIB::snChasSerNum.0
-		$sysChassi = @snmpget ($hostname, $community, 'enterprises.1991.1.1.1.1.2.0');
+		$sysChassi = $device->snmpget ('enterprises.1991.1.1.1.1.2.0');
 		if ($sysChassi !== FALSE or $sysChassi !== NULL)
 			updateStickerForCell ($objectInfo, 1, str_replace ('"', '', substr ($sysChassi, strlen ('STRING: '))));
 
@@ -1036,7 +1038,7 @@
 		# FGS-1XG1XGC (one fixed CX4 port)
 		# FGS-2XGC (two fixed CX4 ports)
 		# FGS-2XG (two XFP slots)
-		foreach (@snmpwalkoid ($hostname, $community, 'enterprises.1991.1.1.2.2.1.1.2') as $module_raw)
+		foreach ($device->snmpwalkoid ('enterprises.1991.1.1.2.2.1.1.2') as $module_raw)
 			if (preg_match ('/^STRING: "(FGS-1XG1XGC|FGS-2XGC) /i', $module_raw))
 			{
 				$iftable_processors['fgs-uplinks']['dict_key'] = '1-40'; // CX4
@@ -1047,7 +1049,7 @@
 		# table: FOUNDRY-SN-AGENT-MIB::snChasPwrSupplyDescription
 		# "Power supply 1 "
 		# "Power supply 2 "
-		foreach (@snmpwalkoid ($hostname, $community, 'enterprises.1991.1.1.1.2.1.1.2') as $PSU_raw)
+		foreach ($device->snmpwalkoid ('enterprises.1991.1.1.1.2.1.1.2') as $PSU_raw)
 		{
 			$count = 0;
 			$PSU_cooked = trim (preg_replace ('/^string: "(.+)"$/i', '\\1', $PSU_raw, 1, $count));
@@ -1083,14 +1085,14 @@
 	}
 	$ifInfo = array();
 	$tablename = 'ifDescr';
-	foreach (snmpwalkoid ($hostname, $community, $tablename) as $oid => $value)
+	foreach ($device->snmpwalkoid ($tablename) as $oid => $value)
 	{
 		$randomindex = preg_replace ("/^.*${tablename}\.(.+)\$/", '\\1', $oid);
 		$value = trim (preg_replace ('/^.+: (.+)$/', '\\1', $value), '"');
 		$ifInfo[$randomindex][$tablename] = $value;
 	}
 	$tablename = 'ifPhysAddress';
-	foreach (snmpwalkoid ($hostname, $community, $tablename) as $oid => $value)
+	foreach ($device->snmpwalkoid ($tablename) as $oid => $value)
 	{
 		$randomindex = preg_replace ("/^.*${tablename}\.(.+)\$/", '\\1', $oid);
 		$value = trim ($value);
@@ -1127,7 +1129,10 @@
 				continue; // try next processor on current port
 			$newlabel = preg_replace ($iftable_processors[$processor_name]['pattern'], $iftable_processors[$processor_name]['label'], $iface['ifDescr'], 1, $count);
 			checkPIC ($iftable_processors[$processor_name]['dict_key']);
-			commitAddPort ($objectInfo['id'], $newname, $iftable_processors[$processor_name]['dict_key'], $newlabel, $iface['ifPhysAddress']);
+			$msg = commitAddPort ($objectInfo['id'], $newname, $iftable_processors[$processor_name]['dict_key'], $newlabel, $iface['ifPhysAddress']);
+			if (!empty($msg)) {
+				$log = mergeLogs($log, oneLiner(100, array("Error adding port " . $iface['ifDescr'] . ": $processor_name: $msg")));
+			}
 			if (!$iftable_processors[$processor_name]['try_next_proc']) // done with this port
 				continue 2;
 		}
@@ -1138,11 +1143,11 @@
 }
 
 $msgcode['doPDUSNMPmining']['OK'] = 0;
-function doPDUSNMPmining ($objectInfo, $hostname, $community)
+function doPDUSNMPmining ($objectInfo, $hostname, $snmpsetup)
 {
 	$log = emptyLog();
 	global $known_APC_SKUs;
-	$switch = new APCPowerSwitch ($hostname, $community);
+	$switch = new APCPowerSwitch ($hostname, $snmpsetup);
 	if (FALSE !== ($dict_key = array_search ($switch->getHWModel(), $known_APC_SKUs)))
 		updateStickerForCell ($objectInfo, 2, $dict_key);
 	updateStickerForCell ($objectInfo, 1, $switch->getHWSerial());
@@ -1168,12 +1173,16 @@
 define('APC_STATUS_REBOOT', 3);
 
 class SNMPDevice {
-    protected $hostname;
-    protected $community;
+    protected $snmp;
+
+    function __construct($hostname, $snmpsetup) {
+	if( isset($snmpsetup['community']) ) {
+	    $this->snmp = new SNMPv2($hostname, $snmpsetup);
+	}
+	else {
+	    $this->snmp = new SNMPv3($hostname, $snmpsetup);
+	}
 
-    function __construct($hostname, $community) {
-        $this->hostname = $hostname;
-        $this->community = $community;
     }
 
     function getName() {
@@ -1183,13 +1192,63 @@
     function getDescription() {
 	return $this->getString('sysDescr.0');
     }
+    
+    function snmpget($oid) {
+	return $this->snmp->snmpget($oid);
+    }
+    
+    function snmpwalkoid($oid) {
+	return $this->snmp->snmpwalkoid($oid);
+    }
 
     protected function snmpSet($oid, $type, $value) {
-        return snmpset($this->hostname, $this->community, $oid, $type, $value);
+        return $this->snmp->snmpset($oid, $type, $value);
     }
 
     protected function getString($oid) {
-	return trim(str_replace('STRING: ', '', snmpget($this->hostname, $this->community, $oid)), '"');
+	return trim(str_replace('STRING: ', '', $this->snmp->snmpget($oid)), '"');
+    }
+}
+
+abstract class SNMP {
+    protected $hostname;
+    protected $snmpsetup;
+
+    function __construct($hostname, $snmpsetup) {
+	$this->hostname = $hostname;
+	$this->snmpsetup = $snmpsetup;
+    }
+    
+    abstract function snmpget($oid);
+    abstract function snmpset($oid, $type, $value);
+    abstract function snmpwalkoid($oid);
+}
+
+class SNMPv2 extends SNMP {
+    function snmpget($oid) {
+	return snmpget($this->hostname, $this->snmpsetup['community'], $oid);
+    }
+
+    function snmpset($oid, $type, $value) {
+	return snmpset($this->hostname, $this->snmpsetup['community'], $oid, $type, $value);
+    }
+    
+    function snmpwalkoid($oid) {
+	return snmpwalkoid($this->hostname, $this->snmpsetup['community'], $oid);
+    }
+}
+
+class SNMPv3 extends SNMP {
+    function snmpget($oid) {
+	return snmp3_get($this->hostname, $this->snmpsetup['sec_name'], $this->snmpsetup['sec_level'], $this->snmpsetup['auth_protocol'], $this->snmpsetup['auth_passphrase'], $this->snmpsetup['priv_protocol'], $this->snmpsetup['priv_passphrase'], $oid);
+    }
+
+    function snmpset($oid, $type, $value) {
+	return snmp3_set($this->hostname, $this->snmpsetup['sec_name'], $this->snmpsetup['sec_level'], $this->snmpsetup['auth_protocol'], $this->snmpsetup['auth_passphrase'], $this->snmpsetup['priv_protocol'], $this->snmpsetup['priv_passphrase'], $oid, $type, $value);
+    }
+    
+    function snmpwalkoid($oid) {
+	return snmp3_real_walk($this->hostname, $this->snmpsetup['sec_name'], $this->snmpsetup['sec_level'], $this->snmpsetup['auth_protocol'], $this->snmpsetup['auth_passphrase'], $this->snmpsetup['priv_protocol'], $this->snmpsetup['priv_passphrase'], $oid);
     }
 }
 
@@ -1197,8 +1256,8 @@
     protected $snmpMib = 'SNMPv2-SMI::enterprises.318';
 
     function getPorts() {
-        $data = snmpwalk($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.2");
-        $status = snmpwalk($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.4");
+        $data = $this->snmpwalk("{$this->snmpMib}.1.1.12.3.3.1.1.2");
+        $status = $this->snmpwalk("{$this->snmpMib}.1.1.12.3.3.1.1.4");
         $out = array();
         foreach ($data as $id => $d) {
             $out[$id + 1] = array(trim(str_replace('STRING: ', '', $d), '"'), str_replace('INTEGER: ', '', $status[$id]));
@@ -1207,15 +1266,15 @@
     }
     
     function getPortStatus($id) {
-        return trim(snmpget($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.4.$id"), 'INTEGER: ');
+        return trim($this->snmpget("{$this->snmpMib}.1.1.12.3.3.1.1.4.$id"), 'INTEGER: ');
     }
 
     function getPortName($id) {
-        return trim(str_replace('STRING: ', '', snmpget($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.3.3.1.1.2.$id")), '"');
+        return trim(str_replace('STRING: ', '', $this->snmpget("{$this->snmpMib}.1.1.12.3.3.1.1.2.$id")), '"');
     }
 
     function setPortName($id, $name) {
-        return snmpset($this->hostname, $this->community, "{$this->snmpMib}.1.1.4.5.2.1.3.$id", 's', $name);
+        return $this->snmpset("{$this->snmpMib}.1.1.4.5.2.1.3.$id", 's', $name);
     }
 
     function portOff($id) {
@@ -1232,17 +1291,17 @@
 	// rPDUIdentFirmwareRev.0 == .1.3.6.1.4.1.318.1.1.12.1.3.0 = STRING: "vN.N.N"
 	function getFWRev()
 	{
-		return preg_replace ('/^STRING: "(.+)"$/', '\\1', snmpget ($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.1.3.0"));
+		return preg_replace ('/^STRING: "(.+)"$/', '\\1', $this->snmpget ("{$this->snmpMib}.1.1.12.1.3.0"));
 	}
 	// rPDUIdentSerialNumber.0 == .1.3.6.1.4.1.318.1.1.12.1.6.0 = STRING: "XXXXXXXXXXX"
 	function getHWSerial()
 	{
-		return preg_replace ('/^STRING: "(.+)"$/', '\\1', snmpget ($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.1.6.0"));
+		return preg_replace ('/^STRING: "(.+)"$/', '\\1', $this->snmpget ("{$this->snmpMib}.1.1.12.1.6.0"));
 	}
 	// rPDUIdentModelNumber.0 == .1.3.6.1.4.1.318.1.1.12.1.5.0 = STRING: "APnnnn"
 	function getHWModel()
 	{
-		return preg_replace ('/^STRING: "(.*)"$/', '\\1', snmpget ($this->hostname, $this->community, "{$this->snmpMib}.1.1.12.1.5.0"));
+		return preg_replace ('/^STRING: "(.*)"$/', '\\1', $this->snmpget ("{$this->snmpMib}.1.1.12.1.5.0"));
 	}
 }
 
snmpv3-new.patch (15,542 bytes)   

user143

2010-11-20 19:49

  ~0000186

Oh, I'm sorry - I've attached the working version..
infrastation

infrastation

2010-11-22 12:11

administrator   ~0000193

I have committed the patch to trunk for the means of testing. If that shows itself to work well for everyone, this change will be available in 0.19.0 release.
infrastation

infrastation

2010-11-29 13:49

administrator   ~0000196

Tested to leave SNMPv1 working, at least. Will be available in 0.19.0 release.

Issue History

Date Modified Username Field Change
2010-11-15 17:13 user143 New Issue
2010-11-15 17:13 user143 File Added: snmpv3.patch
2010-11-19 04:52 infrastation Status new => assigned
2010-11-19 04:52 infrastation Assigned To => infrastation
2010-11-19 04:53 infrastation Note Added: 0000175
2010-11-19 04:56 infrastation Target Version => 0.19.0
2010-11-20 17:54 infrastation Note Added: 0000178
2010-11-20 17:55 infrastation Status assigned => feedback
2010-11-20 19:48 user143 File Added: snmpv3-new.patch
2010-11-20 19:49 user143 Note Added: 0000186
2010-11-21 10:24 infrastation File Deleted: snmpv3.patch
2010-11-21 10:24 infrastation Status feedback => assigned
2010-11-22 12:11 infrastation Note Added: 0000193
2010-11-29 13:49 infrastation Note Added: 0000196
2010-11-29 13:49 infrastation Status assigned => closed
2010-11-29 13:49 infrastation Resolution open => fixed
2010-11-29 13:49 infrastation Fixed in Version => 0.19.0