0xfffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffe #### const vlanPortIslVlansAllowed = " .1.3.6.1.4.1.9.5.1.9.3.1.5.1.1 " const SNMPGETCMD2 = "f:\usr\bin\snmpget.exe -Ov -v 2c -c " '************************************************************************ 'FUNCTION: * ' enum_AllowedVLAN(strAgent) * 'Purpose: * ' enumerate the vlans configured on the switch. * ' * 'Inputs: * ' strAgent: management IP address of the switch * ' * 'Returns: * ' Array with each element containing a vlan number * ' * 'Calls: * ' SNMPGETCMD2 - constant defining the path to an external * ' program and options used to perform an snmp get operation. * ' fmtBinary - function to left pad a binary number with zeros * ' ToBinary - function to convert an integer to a binary string * ' * 'Comments: * ' CISCO-STACK-MIB is cisco specific. * ' Reference Cisco SNMP Object Navigator viewed at * ' http://tools.cisco.com/Support/SNMP/do/BrowseOID.do? * ' objectInput=vlanPortIslVlansAllowed&translate=Translate& * ' submitValue=SUBMIT&submitClicked=true * ' on 16/11/2006 * '************************************************************************ function enum_AllowedVLAN(strAgent) dim WshShell, oExec dim re 'as regexp dim matches dim match, submatch dim tempstr, stroutput, index, vlans Set WshShell = CreateObject("WScript.Shell") Set oExec = WshShell.Exec(SNMPGETCMD2 & SNMPREAD & " " & _ strAgent & " " & vlanPortIslVlansAllowed) Do while Not oExec.StdOut.AtEndOfStream stroutput = oExec.StdOut.readall Loop Do While oExec.Status <> 1 WScript.Sleep 100 Loop tempstr = "" set re = new regexp re.global = True re.multiline = True 'Pattern to capture the hex digits representing the allowed vlans. re.pattern = "[0-9a-fA-F]{2}" vlans = "" if instr(1,stroutput, "Hex-STRING:") > 0 then set matches = re.execute(stroutput) for each match in matches tempstr = tempstr & fmtBinary(ToBinary(cint("&H" & match)), 8) next tempstr = strreverse(tempstr) index = 1 do index = instr(index, tempstr, "1") if index <> 0 then vlans = vlans & " " & index - 1 index = index + 1 end if loop until index = 0 end if enum_AllowedVLAN = split(trim(vlans)) end function '************************************************************************ 'FUNCTION: * ' fmtBinary(strNumber, intLength) * 'PURPOSE: * ' function to left pad a binary number with zeros * ' * 'INPUTS: * ' strNumber: binary number to left pad with zeros * ' intLength: The desired bit length of the binary number * ' * 'RETURNS: * ' string containing the binary representation of the input. * ' * 'CALLS: * ' Nothing * ' * 'COMMENTS: * '************************************************************************ function fmtBinary(strNumber, intLength) fmtBinary = string(intLength - len(strNumber), "0") & strNumber end function '************************************************************************ 'FUNCTION: * ' ToBinary(intNumber) * ' * 'PURPOSE: * ' convert an integer number to binary. * ' * 'Inputs: * ' intNumber: Number to convert to binary * ' * 'Returns: * ' string containing the binary representation of the input. * ' * 'Calls: * ' Nothing * ' * 'Comments: * ' note the use of \ (integer division operator) rather than / * '************************************************************************ function ToBinary(intNumber) if intNumber > 0 then ToBinary = ToBinary(intNumber\2) & intNumber mod 2 end if end function #### use strict; use Net::SNMP; use Cisco::CopyConfig; my($error,$session,$seed_oid,$oid_root,$community,$hostname,$seed_ip,$found, $htype,$tftpsvr,$line,$key,$value,$sysname,$ssn); my ($osysname,$ochassis,$ossn,$oifdesc,$ovlanallowed);#OID constants my(%done,%devices,%ssndone, %shapes); my(@todo, @lines, @hostinfo); #The sysObjectID OID returns a vendor system identifier OID #Read OIDs and descriptions from file to translate the OIDs open (FH, "c:/CiscoSysObjIDs.csv"); while (){ chomp($_); @lines = split ",", $_; if ($lines[0]){ $devices{$lines[0]} = $lines[1]; } } close FH; #Define OID constants $osysname = "1.3.6.1.2.1.1.5.0"; $ochassis = "1.3.6.1.2.1.1.2.0"; $ossn = "1.3.6.1.2.1.47.1.1.1.1.11.1"; $oifdesc = "1.3.6.1.2.1.2.2.1.2"; #Vlan allowed OID will show only the VLANs not pruned. #Administratively allowed VLANs is 1.3.6.1.4.1.9.5.1.9.3.1.5 $ovlanallowed = "1.3.6.1.4.1.9.9.46.1.6.1.1.4"; $done{"0.0.0.0"}=1; #We need a starting point, get an IP from command line die "usage: $0 seedip" unless ( @ARGV == 1 ); $seed_ip = $ARGV[0]; die "usage: $0 seedip" unless ($seed_ip =~ m{\d+\.\d+\.\d+\.\d+}); $tftpsvr = "xxx.xxx.xxx.xxx"; @todo=($seed_ip); #List of possible targets $oid_root = "1.3.6.1.4.1.9.9.23.1.2.1.1"; $seed_oid = ("$oid_root".".3"); print "Host Name,Host IP,Host Type,Local Interface,Neighbor IP,Neighbor Name,Remote Interface,Neighbor Type,Vlans Allowed to Neighbor\n"; while(@todo){ #Grab a target and go to work $hostname= shift(@todo); $community = "comm1"; unless(exists $done{$hostname}){ #Make sure we haven't done this one yet $done{$hostname}=1; #Remember that we checked this IP #Open SNMP session ($session,$error) = Net::SNMP->session(Hostname => $hostname, Community => $community); return unless($session); $sysname = Get_SNMP_Info($osysname); unless($sysname){ $community = "comm2"; Net::SNMP->session(Hostname => $hostname, Community => $community); $sysname = Get_SNMP_Info($osysname); } unless($sysname){ $community = "comm3"; Net::SNMP->session(Hostname => $hostname, Community => $community); $sysname = Get_SNMP_Info($osysname); } unless($sysname){$sysname = "Unknown device name";} $htype =(Get_SNMP_Info($ochassis)); $htype =~ s/1\.3\.6\.1\.4\.1\.9\.1\.//; if ($htype){ for my $key ( keys %devices ) { if ($htype eq $key) { $htype = $devices{$key} ;last; } } } else{$htype = "Unkown device type";} $ssn = Get_SNMP_Info($ossn); unless ($ssn){$ssn = "UknownSSN$found.$sysname.$hostname"};#Some devices do not support the entPhysical Table $ssndone{$ssn}=1; #Remember that we checked this ssn unless(exists $done{$ssn}){ #Make sure we haven't done this one yet print "$sysname,$hostname,$htype\n"; $found++; Get_Config($hostname,$community,$tftpsvr,$sysname.".cfg"); get_oids($seed_oid);#Get the SNMP info for this target } $session->close; } } print $found."devices found\n"; #---------------------------------------------------------- #This sub finds out how many neighbors the target has #and determines what oids we need to use to get the info that #we want, then calls other subs to get that info #---------------------------------------------------------- sub get_oids{ my($starting_oid , $new_oid , $unique_oid , $result , $crap, $index,$if_oid); my($ip , $name , $port, $type); $starting_oid = $_[0]; $new_oid = $starting_oid ; while(Net::SNMP::oid_context_match($starting_oid,$new_oid)){ $result = $session->get_next_request(($new_oid)); return unless (defined $result); ($new_oid , $crap) = %$result; if (Net::SNMP::oid_context_match($starting_oid,$new_oid)){ $unique_oid = $new_oid; $unique_oid =~ s/$starting_oid//g; $ip = (Convert_IP(Get_SNMP_Info("$oid_root".".4"."$unique_oid"))); $name = (Get_SNMP_Info("$oid_root".".6"."$unique_oid")); $port = (Get_SNMP_Info("$oid_root".".7"."$unique_oid")); $type = (Get_SNMP_Info("$oid_root".".8"."$unique_oid")); $if_oid = $unique_oid; $if_oid =~ s/\.\d+$//; my $ifdescr = Get_SNMP_Info($oifdesc.$if_oid); my $vlanallowed = Get_SNMP_Info($ovlanallowed.$if_oid); if ($vlanallowed){ $vlanallowed = Vlans_Allowed_Format($vlanallowed);} else{$vlanallowed = "Unavailable";} unless (($type=~/phone/i)||($type=~/server/i)||($type=~/ata/i)){@todo=(@todo,$ip)}; #Ignore phones, servers, and ATA devices unless (($type=~/phone/i)||($type=~/server/i)||($type=~/ata/i)){print ",,,$ifdescr,$ip,$name,$port,$type,\"$vlanallowed\"\n"}; get_oids($new_oid); } } } sub Convert_IP{ #This sub converts a hex IP to standard xxx.xxx.xxx.xxx format my($ip , $result , $crap); my($hex1 , $hex2 , $hex3 , $hex4); my($oct1 , $oct2 , $oct3 , $oct4); my($hex_ip) = $_[0] ; if ((substr($hex_ip,0,1) eq "")|| ($hex_ip !~ /0x/)){ $ip = "0.0.0.0"; } else{ $hex_ip =~ s/0x//g; $hex1 = (substr $hex_ip,0,2); $hex2 = (substr $hex_ip,2,2); $hex3 = (substr $hex_ip,4,2); $hex4 = (substr $hex_ip,6,2); $oct1 = hex($hex1); $oct2 = hex($hex2); $oct3 = hex($hex3); $oct4 = hex($hex4); $ip = "$oct1\.$oct2\.$oct3\.$oct4"; } return $ip; } sub Get_SNMP_Info{ #This sub gets the value of an oid my($crap , $value , $result); my($oid) = $_[0]; $result = $session->get_request("$oid"); return unless (defined $result); ($crap , $value) = %$result; return $value; } sub Get_Config{ my ($hostip, $community, $tftp, $cfg_file, $copy); $hostip = shift; $community = shift; $tftp = shift; $cfg_file = shift; unless ($cfg_file) {$cfg_file = $hostip}; $copy = Cisco::CopyConfig->new(Host => $hostip, Comm => $community, Tmout => 15, Retry => 2); $copy->copy($tftp, $cfg_file); if ($copy->error){print "Couldn't get config for $hostip : ".$copy->error."\n"}; } sub Convert_Octet_String{ my $octet_str = shift; my $basePort = 0; my ($index,$octet); my @octet; $octet_str = substr $octet_str, 2; while ($octet_str) { my $octet = hex substr $octet_str, 0, 2, ''; my $index = 0; while ($octet) { next unless $octet & 0x80; push @octet, $basePort + $index; } continue { ++$index; $octet = ($octet << 1) & 0xff; } $basePort += 8; } return @octet; } sub Vlans_Allowed_Format{ my ($vlans,$octets,$bits,$return); $vlans = shift; $octets = From_Hex($vlans); $bits = Reverse_Bit_Order($octets); $return = Range_Format($bits); if($return eq "1-1023"){ $return = "1-4094";#Assume the extended VLANs are allowed as well return $return; } return $return; } sub From_Hex { my ($hex) = @_ ; $hex =~ s/^0x//i ; return pack('H*', $hex) ; } sub Reverse_Bit_Order { my ($octets) = @_ ; return pack('B*', unpack('b*', $octets)) ; } sub Range_Format{ my $bits = shift; my $r = undef; my @s = (); for my $vn (1..length($bits) * 8) { if (vec($bits, $vn, 1)) { if (!defined($r)) { push @s, "$vn" ; $r = 0 ; } else { $r = $vn ; } ; } else { if (defined($r)) { if ($r) { $s[-1] .= "-$r" ; } ; $r = undef ; } ; } } return join(', ',@s); }