<?xml version="1.0" encoding="windows-1252"?>
<node id="98175" title="switchcheck.pl" created="2001-07-19 18:13:02" updated="2005-08-11 05:54:27">
<type id="1748">
sourcecode</type>
<author id="79338">
fingers</author>
<data>
<field name="doctext">
&lt;CODE&gt;
#!/usr/bin/perl -w
# switchcheck.pl
use strict;
use Net::SNMP;
my($error,$session,$seed_oid,$oid_root,$csvname,$community,$hostname,$seed_ip,$serial,$option,$logdir);
my(@unique,@hostname);
my($ifMIB) = "1.3.6.1.2.1.31.1.1.1";
my(%option)=(
	verbose =&gt; 0,
	csv =&gt; 0,
	log =&gt; 0,
	batch =&gt; 0,
	help =&gt; 0,
	hostname =&gt; 0,
	read =&gt; 0
	);
die "\nusage: $0 option ip\n Use $0 -h for list of options\n" unless ( @ARGV &gt;= 1 ); 
$logdir="/var/log/sc";


#Begin processing command line arguments
#***************************************************************
while(@ARGV){
	$option = $ARGV[0];
	if($option eq "-v"){
		$option{'verbose'} = 1;
		$option{'log'} = 0;
		$option{'read'} = 0;
	
	}
	elsif($option eq "-l"){
		$option{'log'} = 1;
		$option{'verbose'} = 0;
		$option{'read'} = 0;
	}
	elsif($option eq "-r"){
		$option{'read'} = 1;
		$option{'verbose'} = 0;
		$option{'log'} = 0;
	}
	elsif($option eq "-b"){
		$option{'batch'} = 1;
		$community = $ARGV[1];
		shift @ARGV;
	}
	elsif($option eq "-h"){
		$option{'help'} = 1;
		die "\n\n usage: $0 options ip ... \n\n
		-h		This help message
		-l		Logging
		-v		Verbose
		-c filename 	Send output to filename.csv
		-b community	Batch, community is the snmp community name
		-r ip ...	Display results from log files for specified IPs\n\n\n";
	
	}
	elsif($option eq "-c"){
		$option{'csv'} = 1;
		$option{'read'} = 0;
		$option{'log'} = 0;
		$csvname = ("$ARGV[1]".".csv");
		shift @ARGV;
	}
	else{
		die "usage: $0 ip\n" unless ($option =~ m{\d+\.\d+\.\d+\.\d+});
		push @hostname , $option;
		$option{'hostname'} = 1;
	}
	shift @ARGV;
}
die "You need to give at least one IP address as an option\n" unless($option{'hostname'});	

#End argument processing
#*************************************************************

#Prompt for SNMP community string
unless($option{'batch'}){
	print "community: ";
	chomp($community = &lt;STDIN&gt;);
}
$oid_root = "1.3.6.1.2.1.2.2.1";
$seed_oid = ("$oid_root".".1");

unless($option{'csv'}){
foreach(@hostname){
	undef @unique;
	$hostname=$_;
	#Open SNMP session
	($session,$error) = Net::SNMP-&gt;session(Hostname =&gt; $hostname, Community =&gt; $community);
	die "$error\n" unless($session);
	get_oids($seed_oid); #Get the SNMP info for this target
		
		
		if($option{'verbose'}){
			print "Port  Speed			Errors/Data In 		              Errors/Data Out 		         Uptime \n";
			print "-----------------------------------------------------------------------------------------------------------------------------\n";		
			
			SNMP_Grocery_List();
		}

		elsif($option{'log'}){
			SNMP_Logging();
		}
		elsif($option{'read'}){
			Read_Log();
		}
		else{
			SNMP_Light();
		}
	$session-&gt;close;
	
	}
}
	if($option{'csv'}){
		open(CSV,"&gt;$csvname")|| die "Can't open $csvname\n";
		
		if($option{'verbose'}){
			print CSV "Name,Speed,Errors_In,Data_in,Errors_out,Data_out,Uptime,Switch_IP\n";
			foreach(@hostname){
				undef @unique;
				$hostname=$_;
				#Open SNMP session
				($session,$error) = Net::SNMP-&gt;session(Hostname =&gt; $hostname, Community =&gt; $community);
				die "$error\n" unless($session);
				get_oids($seed_oid); #Get the SNMP info for this target
				Make_CSV_Verbose();
			}
			$session-&gt;close;
			
		}
		else{
		print CSV "Switch_IP,Name,Total_Ports,Up,Down,Admin_Down\n";
			foreach(@hostname){
				undef @unique;
				$hostname=$_;
				#Open SNMP session
				($session,$error) = Net::SNMP-&gt;session(Hostname =&gt; $hostname, Community =&gt; $community);
				die "$error\n" unless($session);
				get_oids($seed_oid); #Get the SNMP info for this target
				Make_CSV();
				$session-&gt;close;
			}
		}
		close(CSV) || die "Can't close $csvname\n";	
	}
	


#Subs below here
#***************************************************************************	

#This sub is what walks through and enumerates an oid tree
#***************************************************************************	
	sub get_oids{
		my($starting_oid , $new_oid , $unique_oid , $result , $crap);
		$starting_oid = $_[0];
		$new_oid = $starting_oid ;
		
		while(Net::SNMP::oid_context_match($starting_oid,$new_oid)){
			$result = $session-&gt;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;
				push @unique , $unique_oid ;
				get_oids($new_oid);
			
			}
		
		}

#This is the sub for -v option
#***************************************************************************	
	
	sub SNMP_Grocery_List{		
		my($unique , $oper , $admin , $name , $uptime , $speed , $datain , $dataout , $errorsin , $errorsout);
		my(%tally);
		%tally=(
			total =&gt; 0,
			up =&gt; 0,
			down =&gt; 0,
			admin =&gt; 0
			);
		foreach(@unique){
			$unique = $_ ;
			$tally{'total'}++;
			$oper = (Get_SNMP_Info("$oid_root".".8"."$unique"));
			if($oper == 1){	
				$tally{'up'}++;
				$name = (Get_SNMP_Info("$ifMIB".".1"."$unique"));
				$uptime = (Get_SNMP_Info("$oid_root".".9"."$unique"));
				$speed = (Get_SNMP_Info("$ifMIB".".15"."$unique"));
				$datain = (Get_SNMP_Info("$oid_root".".10"."$unique"));
				$dataout = (Get_SNMP_Info("$oid_root".".16"."$unique"));
				$errorsin = (Get_SNMP_Info("$oid_root".".14"."$unique"));
				$errorsout = (Get_SNMP_Info("$oid_root".".20"."$unique"));
				
				$~="GROCERY";
				write;
			}
			else {
				$tally{'down'}++;
				$admin = (Get_SNMP_Info("$oid_root".".7"."$unique"));
				if($admin == 2){
					$tally{'admin'}++;
				}
			}
		}
		print "\nSummary: $hostname \n Total Ports: $tally{'total'} \n Ports Up: $tally{'up'} \n Ports Down: $tally{'down'} \n Admin Down $tally{'admin'} \n";
			
format GROCERY =
@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; @&lt;&lt;&lt;&lt;&lt;&lt; @&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;/@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;   @&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;/@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;		@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
$name,$speed,$errorsin,$datain,$errorsout,$dataout,$uptime
.
			
	}
# Sub for -l option
#***************************************************************************	
	sub SNMP_Logging{
		my($unique , $oper , $dbm);
		my(%log);
		$dbm=("$logdir"."sc"."$hostname");
		dbmopen(%log, $dbm, 0644);
		foreach(@unique){
			$unique = $_ ;
			$oper = (Get_SNMP_Info("$oid_root".".8"."$unique"));
			if($oper == 1){	
				$log{$unique}++;
			}
		}
		dbmclose(%log);
	}

#Sub for -r option
#***************************************************************************	

	sub Read_Log{
		my($dbm,$name,$uptime,$unique,$counter);
		my(%log);
		$dbm=("$logdir"."sc"."$hostname");
		dbmopen(%log, $dbm, 0644);
		print "\n\n Switch Check Log for $hostname\n";
		print "---------------------------------------------------\n";
		while (($unique, $counter) = each(%log)) {
			$name = (Get_SNMP_Info("$ifMIB".".1"."$unique"));
			$uptime = (Get_SNMP_Info("$oid_root".".9"."$unique"));
			$~="READ_LOG";
			write;
		}
		dbmclose(%log);
format READ_LOG =
@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; @&lt;&lt;&lt;&lt;&lt;&lt; @&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
$name,$counter,$uptime
.


}
				
		

#sub for default operation
#***************************************************************************	
	sub SNMP_Light{		
		my($unique , $oper , $admin);
		my(%tally);
		%tally=(
			total =&gt; 0,
			up =&gt; 0,
			down =&gt; 0,
			admin =&gt; 0
			);
		foreach(@unique){
			$unique = $_ ;
			$tally{'total'}++;
			$oper = (Get_SNMP_Info("$oid_root".".8"."$unique"));
			if($oper == 1){	
				$tally{'up'}++;
			}
			else {
				$tally{'down'}++;
				$admin = (Get_SNMP_Info("$oid_root".".7"."$unique"));
				if($admin == 2){
					$tally{'admin'}++;
				}
			}
		}
		print "\nSummary: $hostname \n Total Ports: $tally{'total'} \n Ports Up: $tally{'up'} \n Ports Down: $tally{'down'} \n Admin Down $tally{'admin'} \n";
			
	}

#Sub that acually gets the value for a oid
#***************************************************************************	

		sub Get_SNMP_Info{ #This sub gets the value of an oid
		
			my($crap , $value , $result);
			my($oid) = $_[0];
			$result = $session-&gt;get_request("$oid");
			return unless (defined $result);
			($crap , $value) = %$result;
			return $value;

		}


#sub for -c and -v
#***************************************************************************	
		
		sub Make_CSV_Verbose{
		my($unique , $oper , $admin , $name , $uptime , $speed , $datain , $dataout , $errorsin , $errorsout);
		foreach(@unique){
			$unique = $_ ;
			$oper = (Get_SNMP_Info("$oid_root".".8"."$unique"));
			$name = (Get_SNMP_Info("$ifMIB".".1"."$unique"));
			$uptime = (Get_SNMP_Info("$oid_root".".9"."$unique"));
			$speed = (Get_SNMP_Info("$ifMIB".".15"."$unique"));
			$datain = (Get_SNMP_Info("$oid_root".".10"."$unique"));
			$dataout = (Get_SNMP_Info("$oid_root".".16"."$unique"));
			$errorsin = (Get_SNMP_Info("$oid_root".".14"."$unique"));
			$errorsout = (Get_SNMP_Info("$oid_root".".20"."$unique"));
			print CSV "$name,$speed,$errorsin,$datain,$errorsout,$dataout,$uptime,$hostname\n";
				
			
		}
			
	}
#sub for -c			
#***************************************************************************	
		sub Make_CSV{
		my($unique, $sysname , $oper , $admin);
		my(%tally);
		%tally=(
			total =&gt; 0,
			up =&gt; 0,
			down =&gt; 0,
			admin =&gt; 0
			);
			$sysname = (Get_SNMP_Info("1.3.6.1.2.1.1.5.0"));
		foreach(@unique){
			$unique = $_ ;
			$tally{'total'}++;
			$oper = (Get_SNMP_Info("$oid_root".".8"."$unique"));
			if($oper == 1){	
				$tally{'up'}++;
			}
			else {
				$tally{'down'}++;
				$admin = (Get_SNMP_Info("$oid_root".".7"."$unique"));
				if($admin == 2){
					$tally{'admin'}++;
				}
			}
		}
		print CSV "$hostname,$sysname,$tally{'total'},$tally{'up'},$tally{'down'},$tally{'admin'}\n";
			
	}


#***************************************************************************	



}

=head1 Name

 switchcheck.pl

=head1 Summary

 Usage: switchcheck.pl options ip { ip ip ... }
 
 Designed to get an overview or collect statisics on switchports usage using SNMP.

 -b option allows you to specify community name on the command line to allow being called in a cron job

 -l logs basic port usage stats to a dbm file

 -r is used to read files created by -l

 -v gives more detailed stats on ports that are up

 -c generates a csv file, can be used in conjunction with -v

 Some options are mutually exclusive. The later option takes precedence.
 

=head1 Tested

 with:
   Perl 5.6.1
   RedHat 7.1
 against:
   Cisco 6509,2924XL,3508XL,3512XL,3524XL,3548XL switches

=head1 Author

 fingers

=head1 Credits
 Thanks to ybic for answering dumb perl questions and appreciating poorly written code

=head1 Caveats

 When looking at the port counts it is important to keep in mind that vlans and other "interfaces" show up in this count. 
 Look at the output from -v for each type of switch you are using to get an idea how many non-port interfaces each switch has.

=head1 Todos

  Add in -i option to add a polling interval, to spread out the bandwidth impacts of running against remote equipment.

  Accept multiple RO strings for use in enviroments where switches may have different community names.

  Add in VLAN and MAC information to the -v reports. So far I haven't been able to identify the oids to use for these.
  
  Add in support to log to a real database instead of dbm.

=head1 Updates

 2001-07-19 Post to perlmonks


 =cut

&lt;/CODE&gt;

</field>
<field name="codedescription">
Usage: switchcheck.pl options ip { ip ip ... } &lt;br&gt;
 
 Designed to get an overview or collect statisics on switchports usage using SNMP. &lt;br&gt;

 -b option allows you to specify community name on the command line to allow being called in a cron job

 -l logs basic port usage stats to a dbm file &lt;br&gt;

 -r is used to read files created by -l &lt;br&gt;

 -v gives more detailed stats on ports that are up &lt;br&gt;

 -c generates a csv file, can be used in conjunction with -v  &lt;br&gt;

 Some options are mutually exclusive. The later option takes precedence. &lt;br&gt;
 
Tested  &lt;br&gt;
 with: &lt;br&gt;
   Perl 5.6.1 &lt;br&gt;
   RedHat 7.1 &lt;br&gt;
 against: &lt;br&gt;
   Cisco 6509,2924XL,3508XL,3512XL,3524XL,3548XL switches &lt;br&gt;

I realize it may be a little sloppy and amateur, I definately would appreciate any constructive criticism anyone has about my code. &lt;br&gt; 
</field>
<field name="codecategory">
Networking Code</field>
<field name="codeauthor">
fingers

</field>
</data>
</node>
