#!/usr/bin/perl
# 
#  	Netware Detector 
#  		Program to detect the netware on remote machine. It displays additional information 
#               such as version, system up time, system name etc.
#                
#
#       Version  1.0
#       Date     29th Dec 2006
#    
#       Author   Nagareshwar Y Talekar (tnagareshwar@gmail.com)
#
#
##################################################################################################



use Net::SNMP;
use Net::Ping;
use Socket; 
use Switch;
use threads; 


use strict;

$|++;                       # force auto flush of output buffer


 my $host;
 my $isSingleHost = 0;
 my $disablePing = 0;
 my $extraTab = "";
 my $communityName = 'public';
 
#
# Usage: perl NetwareDetector.pl [-d] [-c <snmp-communityname>] { host | host-range }
#

#check if any command line parameters specified
if( @ARGV < 1 || @ARGV > 4)
{
	printUsage();
 	exit;
}

my $i=0;
for(; $i < @ARGV-1 ; $i++)
{
    if( $ARGV[$i] =~ /-d/i )
    {
	#print "\n Disabling the ping scan....";
	$disablePing = 1;	    
	next;    
    } 
	
    if( $ARGV[$i] =~ /-c/i )
    {
	$i++;
	if( $i < @ARGV-1 )
	{
		$communityName = $ARGV[$i];	    
		#print "\n port = " . $port;
	}
	else
	{
	   printUsage();
	   print "\n\n Error : Specify the SNMP community name\n\n";
	   exit;
	}

	next;	    
    } 
    
    # Some invalid option specified
    printUsage();
    print "\n\n Error : Invalid options specified \n\n";
    exit;

}
 
 $host = $ARGV[@ARGV-1];

 #print "\n host = $host and community name $communityName";

 
 my @parts = split(/\./, $host);
 if( @parts != 4 )
 {
  	# treat it as single hostname
  	$isSingleHost = 1;
  	$extraTab = "\t"
 }
  
 
 print "\n\n Netware Detector v1.0 \n\t\tby Nagareshwar Y Talekar (tnagareshwar\@novell.com)\n";
 
 
 # check if IP range is specified ?
 our $range1;
 our $range2;
 our @range;
 our $hostCount = 0;
 
  if( $host =~ m/-/ )
  {
    @range = split(/-/, $parts[3] );
    #print "\n ip range is " . $range[0] . "   " . $range[1];
    
    $range1 = $range[0];
    $range2 = $range[1];
    
    print "\n\n Scanning for range of host " . $host . "\n"; 
    
  }
  else
  {
     $isSingleHost = 1;
     print "\n\n Scanning for host " . $host . "\n" ;
  }
  
  # Now scan for each host one by one
 
  print "\n**********************************************************************************************";
  print "\nHost \t\t     Status \tNetware Version      System Name        System UP Time";
  print "\n**********************************************************************************************\n";
  
  if( $isSingleHost )
  {
  	scanHost($host, $disablePing, $communityName);
  
  }
  else
  {
 	  my $baseHost = $parts[0] . "." . $parts[1] . "." . $parts[2]; 

	  my @threadList;
	  my $thr;
	  my $i;

	  for ( $i=$range1; $i <= $range2 ; $i++)
	  {
	      my $hostAddress = $baseHost . "." . $i;
	      $hostCount++;

	      $thr = threads->new( \&scanHost, $hostAddress, $disablePing, $communityName); 
	      push(@threadList, $thr);

	      if( $hostCount % 50 == 0 )
	      {
		 #print "\n\n Waiting for prev threads to terminate..." unless !$verbose;

		 foreach (@threadList) 
		 { 
		     $_->join(); 
		 }

		@threadList  = ();  # make the array empty or $#threadList  = -1;
	      }
	   } 


	 # waiting for all threads to terminate..
	 foreach (@threadList) 
	 { 
	    $_->join(); 
	 }
 
 }
 
 print "\n**********************************************************************************************";
 
 print "\n\n Finished scanning the hosts\n Cleaning up, please wait...\n\n";
 
 
 exit;
 
 
 
 
 
 
 
 
 
 #****************************************************************************
  
 # Scan each host and find out eDir Version
 sub scanHost
 {
 
     my $ip = $_[0];
     my $disableCheck = $_[1];
     my $cname = $_[2];
     
     if( !$disableCheck )
     {
 	    if( !checkHost($ip) )
 	    {
 	    	printf "%-20s %-10s %-20s %-18s %-20s \n",$ip,"Dead", "Unknown", "Unknown", "Unknown";
 		return;
 	    }
     }    
  
  
   
  my ($session, $error) = Net::SNMP->session( -hostname  => $ip,
     					      -community => $cname,
     					      -port      => 161 
  					    );
  
  if (!defined($session)) 
  {
     printf "%-20s %-10s %-20s %-18s %-20s \n",$ip,"Alive", "Unknown", "Unknown", "Unknown";
     #printf("\nFailed to create snmp session to the specified host.\n Error: %s.\n", $error);
     return;
  }
  
  my $sysVersion = '1.3.6.1.2.1.1.1.0';
  my $sysUptime = '1.3.6.1.2.1.1.3.0';
  my $sysName = '1.3.6.1.2.1.1.5.0';
  
  
  my $result = $session->get_request( -varbindlist => [$sysVersion, $sysUptime, ,$sysName]  );
  
  if (!defined($result)) 
  {
     printf "%-20s %-10s %-20s %-18s %-20s \n",$ip,"Alive", "Unknown", "Unknown", "Unknown";
     #printf("Failed to get system information...\nERROR: %s.\n", $session->error);
     $session->close;
     return;
  }
  
  my @version = split(/ /, $result->{$sysVersion} );
  
  if( $result->{$sysVersion} =~ /netware/i )
  {
  	  printf "%-20s %-10s %-20s %-18s %-20s \n",$ip,"Alive",  $version[1] . " " . $version[2] , $result->{$sysName}, $result->{$sysUptime};
  }
  else
  {
      	 printf "%-20s %-10s %-20s %-18s %-20s \n",$ip, "Alive",  "Not Present" , $result->{$sysName}, $result->{$sysUptime};
  }
  
  #printf("sysUpTime for host '%s' is %s, %s\n", $session->hostname, $result->{$sysUptime}, $result->{$sysVersion}  );
  
  $session->close;
    
 
 }
 
  
  
  
 
 #****************************************************************************
  
 # Check if the host is alive 
 sub checkHost
 {
 
   #return 1;
   my $target = $_[0];
   
   #print "\n Checking for host " . $target;
   
   my $p = Net::Ping->new("icmp", 1, 1);
 
   my $result = $p->ping($target);
   
   $p->close();
   
   return $result;
   
 }
 
 
 
 
 
 
 #****************************************************************************
 
 # print the usage  
 sub printUsage
 {
    print "\n\n Netware Detector v1.0 \n\t\tby Nagareshwar Y Talekar (tnagareshwar\@novell.com)";
    print "\n\n Usage: \n\tperl NetwareDetector.pl [-d] [-c <SNMP community name>] { host | host-range } \n\n";
    print "\n Options: \n\t-d         Do not use ping scan to check if the host is alive \n";
    print "\t-c <name>  Specify the snmp community name for the host \n";
    print "\n Example: \n\tperl NetwareDetector.pl -d myhost.novell.com\n\tperl NetwareDetector.pl -d -c public 192.168.0.100\n\tperl NetwareDetector.pl 192.168.0.1-100\n\n";
    
 }
 
 
  #****************************************************************************

