Commit 3b838cd4 authored by Robert Ricci's avatar Robert Ricci
Browse files

Snapshot. This module is not yet fully functional.

parent eb79ba3c
......@@ -3,408 +3,530 @@
# snmpit module for Intel EtherExpress 510T switches
#
package snmpit_intel;
# Special Note:
# Because this code is not urgently needed, and it is unknown if it ever
# will be needed again, it has not been debugged since moving it into
# this module. So don't count on it. It will need to be debugged before
# actually using it for anything useful.
$| = 1; # Turn off line buffering on output
package snmpit_intel;
use strict;
my $debug = 0;
my $block = 0;
my $confirm = 1;
my $verbose = 0;
$| = 1; # Turn off line buffering on output
use English;
use SNMP;
use snmpit_lib;
my $sess; # My snmp session - initialized in new()
#
# These are the commands that can be passed to the portControl function
# below
#
my %cmdOIDs =
(
"enable" => [".1.3.6.1.2.1.2.2.1.7","up"],
"disable"=> [".1.3.6.1.2.1.2.2.1.7","down"],
"100mbit"=> [".1.3.6.1.4.1.343.6.10.2.4.1.10.1.1","speed100Mbit"],
"10mbit" => [".1.3.6.1.4.1.343.6.10.2.4.1.10.1.1","speed10Mbit"],
"full" => [".1.3.6.1.4.1.343.6.10.2.4.1.11.1.1","full"],
"half" => [".1.3.6.1.4.1.343.6.10.2.4.1.11.1.1","half"],
"auto" => [".1.3.6.1.4.1.343.6.10.2.4.1.12.1.1","auto"]
);
#
# Creates a new object.
#
# usage: new($classname,$devicename,$debuglevel)
# returns a new object, blessed into the snmpit_intel class.
#
sub new {
my $ip = shift;
$SNMP::debugging = ($debug - 5) if $debug > 5;
&SNMP::addMibDirs('/usr/local/share/snmp/mibs');
&SNMP::addMibFiles('/usr/local/share/snmp/mibs/INTEL-GEN-MIB.txt',
'/usr/local/share/snmp/mibs/INTEL-S500-MIB.txt',
'/usr/local/share/snmp/mibs/INTEL-VLAN-MIB.txt');
$SNMP::save_descriptions = 1; # must be set prior to mib initialization
SNMP::initMib(); # parses default list of Mib modules
# The next two lines are some voodoo taken from perltoot(1)
my $proto = shift;
my $class = ref($proto) || $proto;
my $name = shift;
my $debugLevel = shift;
#
# Create the actual object
#
my $self = {};
#
# Set the defaults for this object
#
if (defined($debugLevel)) {
$self->{DEBUG} = $debugLevel;
} else {
$self->{DEBUG} = 0;
}
$self->{BLOCK} = 1;
$self->{NAME} = $name;
if ($self->{DEBUG}) {
print "snmpit_cisco module initializing... debug level $self->{DEBUG}\n"
;
}
#
# Set up SNMP module variables, and connect to the device
#
$SNMP::debugging = ($self->{DEBUG} - 2) if $self->{DEBUG} > 2;
my $mibpath = '/usr/local/share/snmp/mibs';
&SNMP::addMibDirs($mibpath);
&SNMP::addMibFiles("$mibpath/INT_GEN.MIB",
"$mibpath/INT_S500.MIB",
"$mibpath/INT_VLAN.MIB");
$SNMP::save_descriptions = 1; # must be set prior to mib initialization
SNMP::initMib(); # parses default list of Mib modules
$SNMP::use_enums = 1; #use enum values instead of only ints
$SNMP::use_enums = 1; #use enum values instead of only ints
warn ("Opening SNMP session to $self->{NAME}...") if ($self->{DEBUG});
print "Opening SNMP session to $ip..." if $debug;
$sess = new SNMP::Session(DestHost => $ip);
print "".(defined $sess ? "Succeeded" : "Failed")."\n" if $debug;
# XXX: SNMP version?
$self->{SESS} = new SNMP::Session(DestHost => $self->{NAME});
my $obj = \$sess;
if (!$self->{SESS}) {
#
# Bomb out if the session could not be established
#
warn "ERROR: Unable to connect via SNMP to $self->{NAME}\n";
return undef;
}
bless($obj);
return $obj;
bless($self,$class);
return $self;
}
my %cmdOIDs =
{
"enable" => (".1.3.6.1.2.1.2.2.1.7","up"),
"disable"=> (".1.3.6.1.2.1.2.2.1.7","down"),
"100mbit"=> (".1.3.6.1.4.1.343.6.10.2.4.1.10.1.1","speed100Mbit"),
"10mbit" => (".1.3.6.1.4.1.343.6.10.2.4.1.10.1.1","speed10Mbit"),
"full" => (".1.3.6.1.4.1.343.6.10.2.4.1.11.1.1","full"),
"half" => (".1.3.6.1.4.1.343.6.10.2.4.1.11.1.1","half"),
"auto" => (".1.3.6.1.4.1.343.6.10.2.4.1.12.1.1","auto")
};
sub portControl {
# returns 0 on success, # of failed ports on failure, -1 for unsupported
my $sess = shift;
$sess = $$sess; # unreference it...
my $cmd = shift;
my @ports = @_;
my @p = map { portnum($_) } @ports;
my @oid = @cmdOIDs{$cmd};
if (defined @oid) {
return &UpdateField(\$oid[0],\$oid[1],\@p);
} else {
print STDERR "Unsupported port control command '$cmd' ignored.\n";
return -1;
}
#
# Set a variable associated with a port. The commands to execute are given
# in the cmdOIs hash above
#
# usage: portControl($self, $command, @ports)
# returns 0 on success.
# returns number of failed ports on failure.
# returns -1 if the operation is unsupported
#
sub portControl($$@) {
my $self = shift;
my $cmd = shift;
my @ports = @_;
$self->debug("portControl: $cmd -> (@ports)\n");
# XXX: portnum
my @p = map { portnum($_) } @ports;
#
# Find the command in the %cmdOIDs hash (defined at the top of this file)
#
my @oid = @{$cmdOIDs{$cmd}};
if (defined @oid) {
return &UpdateField(\$oid[0],\$oid[1],\@p);
} else {
#
# Command not supported
#
print STDERR "Unsupported port control command '$cmd' ignored.\n";
return -1;
}
}
sub vlanLock {
my $sess = shift;
$sess = $$sess; # unreference it...
my $TokenOwner = '.1.3.6.1.4.1.343.6.11.4.5';
my $TokenReq = '.1.3.6.1.4.1.343.6.11.4.6';
my $TokenReqResult = '.1.3.6.1.4.1.343.6.11.4.7';
my $TokenRelease = '.1.3.6.1.4.1.343.6.11.4.8';
my $TokenReleaseResult = '.1.3.6.1.4.1.343.6.11.4.9';
#The zeros and ones are a magic number it needs...
my $Num = pack("C*",0,0,0,0,1,1);
my $RetVal = 0;
my $tries = 0;
while ($RetVal ne "success" && $tries < 10) {
$tries += 1;
$sess->set([[$TokenReq,0,$Num,"OCTETSTR"]]);
$RetVal = $sess->get([[$TokenReqResult,0]]);
while ($RetVal eq "notReady") {
$RetVal = $sess->get([[$TokenReqResult,0]]);
print "*VLAN Token Claim Result is $RetVal\n" if ($verbose);
select (undef, undef, undef, .25); #wait 1/4 second
sub vlanLock($) {
my $self = shift;
my $TokenOwner = '.1.3.6.1.4.1.343.6.11.4.5';
my $TokenReq = '.1.3.6.1.4.1.343.6.11.4.6';
my $TokenReqResult = '.1.3.6.1.4.1.343.6.11.4.7';
my $TokenRelease = '.1.3.6.1.4.1.343.6.11.4.8';
my $TokenReleaseResult = '.1.3.6.1.4.1.343.6.11.4.9';
#
# Some magic needed by the Intel switch
#
my $Num = pack("C*",0,0,0,0,1,1);
#
# Try max_tries times before we give up, in case some other process just
# has it locked.
#
my $tries = 1;
my $max_tries = 20;
while ($tries <= $max_tries) {
#
# Attempt to grab the edit buffer
#
$self->{SESS}->set([[$TokenReq,0,$Num,"OCTETSTR"]]);
my $RetVal = $self->{SESS}->get([[$TokenReqResult,0]]);
while ($RetVal eq "notReady") {
$RetVal = $self->{SESS}->get([[$TokenReqResult,0]]);
$self->debug("*VLAN Token Claim Result is $RetVal\n");
select (undef, undef, undef, .25); #wait 1/4 second
}
$self->debug("VLAN Token Claim Result is $RetVal\n");
if ($RetVal ne 'success') {
#
# Only print this message every five tries
#
if (!($tries % 5)) {
print STDERR "VLAN edit buffer request failed - " .
"try $tries of $max_tries.\n";
}
} else {
last;
}
$tries++;
sleep(1);
}
print "VLAN Token Claim Result is $RetVal\n" if ($verbose);
if ($RetVal ne 'success') {
my $Owner = $sess->get([[$TokenOwner,0]]);
if ($Owner ne "0.0.0.0") {
$tries = 10;
} else {
print STDERR time,
"Try #$tries - Result is $RetVal - Waiting 2 seconds\n" if $debug;
select (undef, undef, undef, 2); #wait 2 seconds
}
if ($tries > $max_tries) {
#
# Admit defeat and exit
#
print STDERR "ERROR: Failed to obtain VLAN edit buffer lock\n";
return 0;
} else {
return 1;
}
}
if ($RetVal ne 'success') {
my $Owner = $sess->get([[$TokenOwner,0]]);
print STDERR "VLAN Token Claim Result is $RetVal\n";
die("Can't edit VLANs: Token taken by $Owner\n");
}
}
sub vlanUnlock {
my $sess = shift;
$sess = $$sess; # unreference it...
my $TokenRelease = '.1.3.6.1.4.1.343.6.11.4.8';
my $TokenReleaseResult = '.1.3.6.1.4.1.343.6.11.4.9';
my $TokenConfirmState = '.1.3.6.1.4.1.343.6.11.1.18';
my $save = ($confirm ? "saveWithConfirmOption" : "save");
print "Releasing Token with $save command\n" if ($verbose);
$sess->set([[$TokenRelease,0,$save,"INTEGER"]]);
my $RetVal = $sess->get([[$TokenReleaseResult,0]]);
print "VLAN Configuration Save Result is $RetVal\n" if ($verbose);
while ($RetVal eq "notReady") {
$RetVal = $sess->get([[$TokenReleaseResult,0]]);
print "VLAN Configuration Save Result is $RetVal\n" if ($verbose);
select (undef, undef, undef, .25); #wait 1/4 second
}
if ($confirm) {
$RetVal = $sess->get([[$TokenConfirmState,0]]);
print "VLAN Configuration Confirm Result is $RetVal\n" if ($verbose);
#
# Release a lock on the VLAN edit buffer. As part of releasing, applies the
# VLAN edit buffer.
#
# usage: vlanUnlock($self)
#
sub vlanUnlock($;$) {
my $self = shift;
my $TokenRelease = '.1.3.6.1.4.1.343.6.11.4.8';
my $TokenReleaseResult = '.1.3.6.1.4.1.343.6.11.4.9';
my $TokenConfirmState = '.1.3.6.1.4.1.343.6.11.1.18';
my $save = ($self->{CONFIRM} ? "saveWithConfirmOption" : "save");
$self->debug("Releasing Token with $save command\n");
$self->{SESS}->set([[$TokenRelease,0,$save,"INTEGER"]]);
my $RetVal = $self->{SESS}->get([[$TokenReleaseResult,0]]);
$self->debug("VLAN Configuration Save Result is $RetVal\n");
while ($RetVal eq "notReady") {
sleep(2);
$RetVal = $sess->get([[$TokenConfirmState,0]]);
print "VLAN Configuration Confirm Result is $RetVal\n" if ($verbose);
}
if ($RetVal eq "ready") {
$RetVal = $sess->set([[$TokenConfirmState,0,"confirm","INTEGER"]]);
print "VLAN Configuration Confirm Result is $RetVal\n" if ($verbose);
$RetVal = $self->{SESS}->get([[$TokenReleaseResult,0]]);
$self->debug("VLAN Configuration Save Result is $RetVal\n");
select (undef, undef, undef, .25); #wait 1/4 second
}
while (!($RetVal =~ /Conf/i)) {
$RetVal = $sess->get([[$TokenConfirmState,0]]);
print "VLAN Configuration Confirm Result is $RetVal\n" if ($verbose);
}
if ($RetVal ne "confirmedNewConf") {
die("VLAN Reconfiguration Failed. No changes saved.\n");
}
} else {
if ($RetVal ne 'success') {
print "VLAN Configuration Save Result is $RetVal\n" if ($verbose);
die("$RetVal VLAN Reconfiguration Failed. No changes saved.\n");
if ($self->{CONFIRM}) {
$RetVal = $self->{SESS}->get([[$TokenConfirmState,0]]);
$self->debug("VLAN Configuration Confirm Result is $RetVal\n");
while ($RetVal eq "notReady") {
sleep(2);
$RetVal = $self->{SESS}->get([[$TokenConfirmState,0]]);
$self->debug("VLAN Configuration Confirm Result is $RetVal\n");
}
if ($RetVal eq "ready") {
$RetVal = $self->{SESS}->set([[$TokenConfirmState,0,"confirm","INTEGER"]]);
$self->debug("VLAN Configuration Confirm Result is $RetVal\n");
} # XXX: Should there be an 'else'?
while (!($RetVal =~ /Conf/i)) {
$RetVal = $self->{SESS}->get([[$TokenConfirmState,0]]);
$self->debug("VLAN Configuration Confirm Result is $RetVal\n");
}
if ($RetVal ne "confirmedNewConf") {
die("VLAN Reconfiguration Failed. No changes saved.\n");
}
} else {
if ($RetVal ne 'success') {
die("VLAN Reconfiguration Failed: $RetVal. No changes saved.\n");
}
}
}
}
sub setupVlan {
# This is to be called ONLY after vlanLock has been called successfully!
my $sess = shift;
$sess = $$sess; # unreference it...
my $name = shift;
my @vlan = @_;
foreach $mac (@vlan) {
my $node = $Interfaces{$mac};
if (! NodeCheck($node)) {
print STDERR "You are not authorized to control $node.\n";
return 1;
# XXX: Changeme!
#sub setupVlan {
# # This is to be called ONLY after vlanLock has been called successfully!
# my $sess = shift;
# $sess = $$sess; # unreference it...
# my $name = shift;
# my @vlan = @_;
# foreach my $mac (@vlan) {
# my $node = $Interfaces{$mac};
# if (! NodeCheck($node)) {
# print STDERR "You are not authorized to control $node.\n";
# return 1;
# }
# }
#
# my $NextVLANId = '.1.3.6.1.4.1.343.6.11.1.6';
# my $Vlan = $sess->get([[$NextVLANId,0]]);
# my $CreateOID = ".1.3.6.1.4.1.343.6.11.1.9.1.3";
# my $RetVal = "Undef.";
# if ( !$name
# #Temporary fix: if its a lX-Y name from assign.tcl, ignore it
# || ($name =~ /^l(\d)+-(\d)+/)
# #End of Temp fix
# ) {
# $name = $Vlan;
# }
# print " Creating VLAN $name as VLAN #$Vlan: @vlan ... ";
# $RetVal = $sess->set([[$CreateOID,$Vlan,$name,"OCTETSTR"]]);
# print "",($RetVal? "Succeeded":"Failed"),".\n";
# if (! defined ($RetVal) ) {
# &vlanUnlock(*sess,$verbose,1);
# die("VLAN name \"$name\" not unique.\n");
# }
# my @x;
# my $n=0;
# while (@vlan != 0 && $n < @vlan) {
# my $i=0;
# while ($i < 6 ) {
# $x[$i] = hex ("0x".substr($vlan[$n],2*$i,2) );
# $i++;
# }
# my $MacObjOID = ".1.3.6.1.4.1.343.6.11.1.10.1.3.$Vlan." .
# "$x[0].$x[1].$x[2].$x[3].$x[4].$x[5]";
# print " Adding MAC Address $vlan[$n] ".
# "($Vlan.$x[0].$x[1].$x[2].$x[3].$x[4].$x[5])... ";
# $RetVal = $sess->set([[$MacObjOID,0,$vlan[$n],"OCTETSTR"]]);
# print "",($RetVal? "Succeeded":"Failed"), ".\n";
# $n++;
# }
#}
#
# Remove the given VLAN from this switch. This presupposes that all of its
# ports have already been removed with removePortsFromVlan(). The VLAN is
# given as a VLAN identifier from the database.
#
# usage: removeVlan(self,int vlan)
# returns 1 on success
# returns 0 on failure
#
#
sub removeVlan($$) {
my $self = shift;
my $vlan_id = shift;
#
# Find the real VLAN number from the passed VLAN ID
#
my $vlan_number = $self->findVlan($vlan_id);
if (!defined($vlan_number)) {
print STDERR "ERROR: VLAN with identifier $vlan_id does not exist\n";
return 0;
}
}
$self->debug("Found VLAN with ID $vlan_id: $vlan_number\n");
my $NextVLANId = '.1.3.6.1.4.1.343.6.11.1.6';
my $Vlan = $sess->get([[$NextVLANId,0]]);
my $CreateOID = ".1.3.6.1.4.1.343.6.11.1.9.1.3";
my $RetVal = "Undef.";
if ( !$name
#Temporary fix: if its a lX-Y name from assign.tcl, ignore it
|| ($name =~ /^l(\d)+-(\d)+/)
#End of Temp fix
) {
$name = $Vlan;
}
print " Creating VLAN $name as VLAN #$Vlan: @vlan ... ";
$RetVal = $sess->set([[$CreateOID,$Vlan,$name,"OCTETSTR"]]);
print "",($RetVal? "Succeeded":"Failed"),".\n";
if (! defined ($RetVal) ) {
&vlanUnlock(*sess,$verbose,1);
die("VLAN name \"$name\" not unique.\n");
}
my @x;
my $n=0;
while (@vlan != 0 && $n < @vlan) {
my $i=0;
while ($i < 6 ) {
$x[$i] = hex ("0x".substr($vlan[$n],2*$i,2) );
$i++;
#
# Need to lock the VLAN edit buffer
#
if (!$self->vlanLock()) {
return 0;
}
my $MacObjOID = ".1.3.6.1.4.1.343.6.11.1.10.1.3.$Vlan." .
"$x[0].$x[1].$x[2].$x[3].$x[4].$x[5]";
print " Adding MAC Address $vlan[$n] ".
"($Vlan.$x[0].$x[1].$x[2].$x[3].$x[4].$x[5])... ";
$RetVal = $sess->set([[$MacObjOID,0,$vlan[$n],"OCTETSTR"]]);
print "",($RetVal? "Succeeded":"Failed"), ".\n";
$n++;
}
}
sub removeVlan {
my $sess = shift;
$sess = $$sess; # unreference it...
my $r = shift;
my $DeleteOID = ".1.3.6.1.4.1.343.6.11.1.9.1.4";
my $RetVal = "Undef.";
print " Removing VLAN #$r ... ";
if ($r == 24) {
print STDERR "VLAN #$r is the Control VLAN, and cannot be removed.\n";
} else {
$RetVal = $sess->set([[$DeleteOID,$r,"delete","INTEGER"]]);
#
# Perform the actual removal
#
my $DeleteOID = ".1.3.6.1.4.1.343.6.11.1.9.1.4";
my $RetVal = "Undef.";
print " Removing VLAN #$vlan_number ... ";
$RetVal = $self->{SESS}->set([[$DeleteOID,$vlan_number,"delete","INTEGER"]]);
print "",($RetVal? "Succeeded":"Failed"),".\n";
if (! defined ($RetVal) ) {
print STDERR "VLAN #$r does not exist on this switch.\n";
#
# Unlock whether successful or not
#
$self->vlanUnlock();
if (! defined $RetVal) {
print STDERR "VLAN #$vlan_number does not exist on this switch.\n";
return 0;
} else {
$self->vlanUnlock();
return 1;
}
}
}
#
# SUB UpdateField----------------------
# XXX: Major cleanup
#
sub UpdateField($$$@) {
my $self = shift;
my ($OID,$val,@ports)= @_;
my $Status = 0;
my $err = 0;
$self->debug("UpdateField: '@_'\n");
sub UpdateField {
# returns 0 on success, # of failed ports on failure
my $sess = shift;
$sess = $$sess; # unreference it...
local(*OID,*val,*ports)= @_;
my $Status = 0;
my $retval;
my $i = $sess->{DestHost};
foreach my $port (@ports) {
my $trans = $ifIndex{$port};
if (defined $trans) {
if (defined ($Ports{"$i:$trans"})) {
$trans = "$trans,".$Ports{"$i:$trans"};
} else {
$trans = "$trans,".$Ports{"$i:$port"};
}
} else { $trans = "???"; }
print "Checking port $port ($trans) for $val..." if $verbose;
$Status = $sess->get([[$OID,$port]]);
if (!defined $Status) {
print STDERR "Port $port ($trans), change to $val: No answer from device\n";
return 1; # Return error
} else {
print "Okay.\nPort $port was $Status\n" if $verbose;
if ($Status ne $val) {
print "Setting $port to $val..." if $verbose;
# The empty sub {} is there to force it into async mode
$sess->set([[$OID,$port,$val,"INTEGER"]],sub {});
if ($block) {
while ($Status ne $val) {
$Status=$sess->get([[$OID,$port]]);
print "Value for $port was ",$Status,"\n" if ($verbose);
}
print "Okay.\n";
} else { print "\n"; }
}
}
}
if ( (!$block) && $confirm ) {
my $loops=0;
my $max_loops=10;
my %notdone=();
my @done=();
foreach my $port (@ports) {
$Status=$sess->get([[$OID,$port]]);
print "Value for $port was ",$Status,"\n" if ($verbose);
if ($Status ne $val) { $notdone{$port}=1; }
}
while ( %notdone && $loops < $max_loops ) {
if ($loops > 5) {
sleep($loops-5);
}
foreach my $port (sort num keys(%notdone)) {
$Status=$sess->get([[$OID,$port]]);
print "Value for $port was ",$Status,"\n" <