#!/usr/bin/perl
# 
#  	iManager Detector 
#  		Program to detect the version of iManager running on remote machine.
#
#       Version  1.0
#       Date     30th Nov 2006
#    
#       Author   Nagareshwar Y Talekar (tnagareshwar@gmail.com)
#
#
##################################################################################################


use LWP::UserAgent;
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 $port=80;
 
#
# Usage: perl iManagerDetector.pl [-d] [-p <port>] { 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] =~ /-p/i )
    {
	$i++;
	if( $i < @ARGV-1 )
	{
		$port = $ARGV[$i];	    
		#print "\n port = " . $port;
	}
	else
	{
	   printUsage();
	   print "\n\n Error : Specify valid port number with -p option\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 port $port";

 
 my @parts = split(/\./, $host);
 if( @parts != 4 )
 {
  	# treat it as single hostname
  	$isSingleHost = 1;
  	$extraTab = "\t"
  	#printUsage();
  	#print "\n\n Error :  Enter proper IP address for the host\n\n";
  	#exit;
 }
  
 
 print "\n\n iManager 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 ". $extraTab . "  Status \t iManager Version \t Platform ";
  print "\n*************************************************************************\n";
  
  if( $isSingleHost )
  {
  	scanHost($host, $disablePing);
  
  }
  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); 
	      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];
     
     if( !$disableCheck )
     {
 	    if( !checkHost($ip) )
 	    {
 		print "$ip \t   Dead \t Unknown \t\t Unknown\n";
 		return;
 	    }
     }    
  
  
  
  # First request
 # print "\n Connecting to http service on host " . $ip;
  
  
  my $ua = new LWP::UserAgent;
  
 
  # wait for 5 seconds before getting response
  # This timeout does not work if the port is not open
  # It works only for http protocol transaction
  $ua->timeout(5);
  
  $ua->agent("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051111 Firefox/1.5");
  my $url = "http://" . $ip . ":$port/nps/version.jsp";
  #print "\n url = $url";
 
  my $request = HTTP::Request->new(GET => $url);
  my $resp = $ua->request($request);
  
  # TODO  : check if there is positive response
  if( $resp->is_info || $resp->is_success )
  {
  
 	 my $version = $resp->content;
 	 
 	 #print "\n response : " . $version;
 	 
 	 if( $version =~ /html/i )
 	 {
 	 	print "$ip \t   Alive \t Not Present \t\t Unknown\n";
 	 	return;
 	 }
 	 
 	 my $server = $resp->header( "Server" );
 
 	 my @fields = split(/ /, $server);
 	 my $serverName = $fields[1];
 	 
 	 if( $serverName =~ /win32/i )
 	 {
 	 	$serverName = "Windows";
 	 }
 	 elsif( $serverName =~ /netware/i )
 	      {
 	       	$serverName = "Netware";
 	      }

 	 #print "\n Server : " . $server ;
 	
 	 my $version = $resp->content;
 	 if( $version =~ /\r/ || $version =~ /\n/ )
 	 { 
 	 	chop $version;
 	 }
 	
 	 if( $version =~ /\r/ || $version =~ /\n/ )
 	 {
 	 	 chop $version;
 	 }
 	 
 	 #print "\n content : " . $version;
 	 
 	 print "$ip \t   Alive \t $version \t\t\t $serverName\n";
 
   }
   else
   {
     print "$ip \t   Alive \t Not Present \t\t Unknown\n";
     #print "\n Failed to get response from server  " . $ip . ", mesg : " . $resp->message;  
  }
  
   
 
 }
 
  
  
  
 
 #****************************************************************************
  
 # 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 iManager Detector v1.0 \n\t\tby Nagareshwar Y Talekar (tnagareshwar\@novell.com)";
    print "\n\n Usage: \n\tperl iManagerDetector.pl [-d] [-p <port>] { 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-p <port>   Use specified <port> for connection instead of default port 80 \n";
    print "\n Example: \n\tperl iManagerDetector.pl -d ldap.myhost.edu\n\tperl iManagerDetector.pl -d -p 8080 192.168.0.100\n\tperl iManagerDetector.pl 192.168.0.1-100\n\n";
    
 }
 
 
  #****************************************************************************

