Свичи 3COM, port security

Вот скрипт, позволяющий управлять всеми (почти) возможностями port security.

#!/usr/bin/perl
#sets up port security modes on 3com SSII switches
#v.1.0.7 added --reset option
#v.1.0.6 can delete secure MACs
#v.1.0.5 can add secure MACs
#v.1.0.4 not needs MIB, uses numeric OIDs
#v.1.0.3 changed displayed names (PortMode -> securePortMode)
#v.1.0.2 can show stored MACs
#v.1.0.1 can set ifAdminStatus
#v.1.0.0 can set securePortMode, secureIntrusionAction, secureNumberAddresses only
#(c) Denis Nelubin, 2005
#(c) OmskTeleCom, Ltd., 2005

use SNMP;
use Getopt::Long;

#parameters names
@portmode_is = ('', 'noRestrictions', 'continuousLearning', 'autoLearn', 'secure');
%portmode_si = ('noRestrictions'=>1, 'continuousLearning'=>2, 'autoLearn'=>3, 'secure'=>4);
@ntkmode_is = ('', 'notAvailable', 'disabled', 'needToKnowOnly',
               'needToKnowWithBroadcastsAllowed', 'needToKnowWithMulticastsAllowed',
               'permanentNeedToKnowOnly', 'permanentNeedToKnowWithBroadcastsAllowed',
               'permanentNeedToKnowWithMulticastsAllowed');
%ntkmode_si = ('notAvailable'=>1, 'disabled'=>2, 'needToKnowOnly'=>3,
               'needToKnowWithBroadcastsAllowed'=>4, 'needToKnowWithMulticastsAllowed'=>5,
               'permanentNeedToKnowOnly'=>6, 'permanentNeedToKnowWithBroadcastsAllowed'=>7,
               'permanentNeedToKnowWithMulticastsAllowed'=>8);
@intact_is = ('', 'notAvailable', 'noAction', 'disablePort', 'disablePortTemporarily');
%intact_si = ('notAvailable'=>1, 'noAction'=>2, 'disablePort'=>3, 'disablePortTemporarily'=>4);
@admst_is = ('', 'enabled', 'disabled', 'testing');

GetOptions('u|unit|slot:i'=>\$unit,
           'n|num-addr:i'=>\$numaddr,
           'm|mode:s'=>\$portmode,
           'a|action:s'=>\$intact,
           'set:i'=>\$autoset,
           'v|verbose'=>\$verbose,
           'c|community:s'=>\$community,
           't|timeout:i'=>\$timeout,
           'r|retries:i'=>\$retries,
           'e|enable'=>\$enable,
           'd|disable'=>\$disable,
           'add-mac:s'=>\@addmac,
           'del-mac:s'=>\@delmac,
           'reset'=>\$autoreset) or usage();

usage() if($#ARGV<1);

$host = $ARGV[0];
$port = $ARGV[1];

#convert port to unit and port
if($port<100)
{
 $unit = 1 unless($unit);
}
else
{
 $unit = int($port/100);
 $port = $port%100;
}

usage() if(!$unit or !$port);

#default values
$community = 'private' unless($community);
$timeout = 3000000 unless($timeout);
$retries = 3 unless($retries);

$adminstatus = 2 if(defined $disable);
$adminstatus = 1 if(defined $enable);

if(defined $autoset)
{
 $portmode = 3 unless(defined $portmode);
 $numaddr = ($autoset?$autoset:1) unless(defined $numaddr);
 $intact = 4 unless(defined $intact);
 $adminstatus = 1 unless(defined $adminstatus);
}
if(defined $autoreset)
{
 $portmode = 1 unless(defined $portmode);
 $numaddr = 0 unless(defined $numaddr);
 $intact = 2 unless(defined $intact);
 $adminstatus = 1 unless(defined $adminstatis);
}

#convert from strings to numbers
$portmode = $portmode_si{$portmode} unless($portmode=~/^\d/);
$intact = $intact_si{$intact} unless($intact=~/^\d/);

if($verbose)
{
 print "host:\t$host\n" if(defined $host);
 print "unit:\t$unit\n" if(defined $unit);
 print "port:\t$port\n" if(defined $port);
 print "community:\t$community\n" if(defined $community);
 print "timeout:\t$timeout\n" if(defined $timeout);
 print "retries:\t$retries\n" if(defined $retries);
 print "mode:\t$portmode ($portmode_is[$portmode])\n" if(defined $portmode);
 print "action:\t$intact ($intact_is[$intact])\n" if(defined $intact);
 print "num-addr:\t$numaddr\n" if(defined $numaddr);
 print "adminstatus:\t$adminstatus ($admst_is[$adminstatus])\n" if(defined $adminstatus);
 foreach $mac (@addmac)
 {
  print "add-mac:\t$mac\n";
 }
 foreach $mac (@delmac)
 {
  print "del-mac:\t$mac\n";
 }
}

#SNMP::addMibDirs('/usr/share/snmp/mibs');#!!!!!!?????
#SNMP::loadModules('A3COM0021-PORT-SECURITY');

$sess = SNMP::Session->new( DestHost=>$host,
                            Community=>$community,
                            Timeout=>$timeout,
                            Retries=>$retries);
die("SNMP session: ".$sess->{ErrorStr}."\n") if($sess->{ErrorNum});

#set values
@vars;
#push(@vars,['secureNumberAddresses',"$unit.$port",$numaddr]) if(defined $numaddr);
push(@vars,['.1.3.6.1.4.1.43.10.22.1.1.6',"$unit.$port",$numaddr,'INTEGER']) if(defined $numaddr);
#push(@vars,['securePortMode',"$unit.$port",$portmode]) if(defined $portmode);
push(@vars,['.1.3.6.1.4.1.43.10.22.1.1.3',"$unit.$port",$portmode,'INTEGER']) if(defined $portmode);
#push(@vars,['secureIntrusionAction',"$unit.$port",$intact]) if(defined $intact);
push(@vars,['.1.3.6.1.4.1.43.10.22.1.1.5',"$unit.$port",$intact,'INTEGER']) if(defined $intact);
#push(@vars,['ifAdminStatus',$unit*100+$port,$adminstatus]) if(defined $adminstatus);
push(@vars,['.1.3.6.1.2.1.2.2.1.7',$unit*100+$port,$adminstatus,'INTEGER']) if(defined $adminstatus);
foreach $mac (@addmac)
{
 #push(@vars,['secureAddrRowStatus',"$unit.$port".oidmac($mac),4]); #4: createAndGo
 push(@vars,['.1.3.6.1.4.1.43.10.22.2.1.4',"$unit.$port".oidmac($mac),4,'INTEGER']);
}
foreach $mac (@delmac)
{
 #push(@vars,['secureAddrRowStatus',"$unit.$port".oidmac($mac),6]); #6: destroy
 push(@vars,['.1.3.6.1.4.1.43.10.22.2.1.4',"$unit.$port".oidmac($mac),6,'INTEGER']);
}

if($#vars>=0)
{
 $sess->set(\@vars);
 die("SNMP set: ".$sess->{ErrorStr}."\n") if($sess->{ErrorNum});
}

#get values
($secslot, $secport, $portmode, $ntkmode, $intact, $numaddr, $numaddrstor, $adminstatus)
 = $sess->get([
#               ['secureSlotIndex',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.1',"$unit.$port"],
#               ['securePortIndex',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.2',"$unit.$port"],
#               ['securePortMode',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.3',"$unit.$port"],
#               ['secureNeedToKnowMode',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.4',"$unit.$port"],
#               ['secureIntrusionAction',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.5',"$unit.$port"],
#               ['secureNumberAddresses',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.6',"$unit.$port"],
#               ['secureNumberAddressesStored',"$unit.$port"],
               ['.1.3.6.1.4.1.43.10.22.1.1.7',"$unit.$port"],
#               ['ifAdminStatus',$unit*100+$port]
               ['.1.3.6.1.2.1.2.2.1.7',$unit*100+$port]
              ]);
die("SNMP get: ".$sess->{ErrorStr}."\n") if($sess->{ErrorNum});
print "secureSlotIndex\t$secslot\n";
print "securePortIndex\t$secport\n";
print "securePortMode\t$portmode ($portmode_is[$portmode])\n";
#print "secureNeedToKnowMode\t$ntkmode ($ntkmode_is[$ntkmode])\n";
print "secureIntrusionAction\t$intact ($intact_is[$intact])\n";
print "secureNumberAddresses\t$numaddr\n";
print "secureNumberAddressesStored\t$numaddrstor\n";
print "ifAdminStatus\t$adminstatus ($admst_is[$adminstatus])\n";

#get macs
#$vars = new SNMP::Varbind(['secureAddrMAC',"$unit.$port"]);
$vars = new SNMP::Varbind(['.1.3.6.1.4.1.43.10.22.2.1.3',"$unit.$port"]);
for($i=0; $i<$numaddrstor; $i++)
{
 $mac = $sess->getnext($vars);
 die("SNMP getnext: ".$sess->{ErrorStr}."\n") if($sess->{ErrorNum});
 $mac = strmac($mac);
 print "secureAddrMAC\t$mac\n" unless($sess->{ErrorStr});
}

exit 0;

sub usage
{
 print "Usage:\n";
 print "$0 <opts> host port\n";
 print "-u|--unit|--slot <num> - Unit or slot number (default 1)\n";
 print "-m|--mode (1-4".join('|',@portmode_is).") - Port security mode\n";
 print "-a|--action (1-4".join('|',@intact_is).") - Action on intrusion\n";
 print "-n|--num-addr <num> - Number of secure macs to store\n";
 print "-e|--enable - Enable port\n";
 print "-d|--disable - Disable port\n";
 print "--set [<num>] - Equal to '-e -m autoLearn -a disablePortTemporarily -n <num>' (default num=1)\n";
 print "--reset - Equal to '-e -m noRestrictions -a noAction -n 0'\n";
 print "--add-mac <mac> - Adds new secured MAC (--num-addr must be set to hold enough macs)\n";
 print "--del-mac <mac> - Deletes secured MAC (--mode $portmode_is[3] deletes all macs)\n";
 print "-c|--community <str> - Community string (default 'private')\n";
 print "-t|--timeout <num> - SNMP timeout in microsecs (default 3000000)\n";
 print "-r|--retries <num> - number of SNMP retries (default 3)\n";
 print "-v|--verbose - show parsed input parameters\n";
 exit 0;
}

sub strmac
{
 my $mac = shift;
 $mac = unpack('H*',$mac);
 $mac =~ s/(.{2})/$1:/g;
 $mac =~ s/:$//;
 return $mac;
}

sub oidmac
{ #taken from http://forum.nag.ru/viewtopic.php?p=78192
 my $mac = shift;
 my @a_mac = split(/:|-/, $mac);
 my $oid = '';
 foreach my $t (@a_mac)
 {
  $oid .= '.'.hex($t);
 }
 return $oid;
}