#!/usr/bin/perl
# 
#  	NSL iManager Snapins Detector 
#  		Program to detect the NSL snapins installed on iManager remotely.
#
#       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;
 


#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 NSL iManager Snapins 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 \t SSO Snapin \tpcProx Snapin \tSW Snapin ";
  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];
     my $ssoFound = "No";
     my $pcproxFound = "No";
     my $swFound = "No";
     
     
     if( !$disableCheck )
     {
 	    if( !checkHost($ip) )
 	    {
 	        printf "%-15s", $ip;
 		print "   Dead \t\t Unknown \t Unknown\tUnknown \tUnknown\n";
 		return;
 	    }
     }    
  
    #check if iManager present
    if( CheckSnapin($ip, $port, "nps/iManager.html") == 0)
    {
 	printf "%-15s", $ip;
	print "   Alive \t Not Present \t No\t\tNo\t\tNo\n";	
	return;    	
    }
  
  
  
    #now check if any of these snapins are present
    if( CheckSnapin($ip, $port, "nps/packages/sso.npm") )
    {
    	$ssoFound = "Yes";
    }
    	
    if(	CheckSnapin($ip, $port, "nps/packages/pcprox.npm") )
    {
        $pcproxFound = "Yes";
    }    
    
    
    if(	CheckSnapin($ip, $port, "nps/packages/sw.npm") )
    {
        $swFound = "Yes";
    }    
    
    printf "%-15s", $ip;
    printf "   Alive \t Present \t $ssoFound\t\t$pcproxFound\t\t$swFound\n";
  
  }
  
  
  
  
  
  
  
  sub CheckSnapin
  {
    my $ip = $_[0];
    my $port = $_[1];
    my $snapin = $_[2];
    
 
	  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/" . $snapin;
	  #print "\n url = $url";

	  my $request = HTTP::Request->new(HEAD => $url);
	  my $resp = $ua->request($request);

	  if( $resp->is_info || $resp->is_success )
	  {
	  	if( $snapin =~ /npm/i )
	  	{
	  	     if( $resp->content_type =~ /plain/ && $resp->content_length > 1000 )
	  	     {
	  	     	return 1;
	  	     }
	  		
	  	     return 0;
	  	}
	  	
  		if( $resp->server =~ /apache/i )
  		{
  		    return 1;
  		}
 	 		
		#print "\n response " . $resp->content_type;
		#print "\n length   " . $resp->content_length;
		#print "\n title   " . $resp->server;
		
		return 0;
	  }
	  else
	  {
		return 0;
	  }
  
   
 	  return 0;
 }
 
  
  
  
 
 #****************************************************************************
  
 # 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 NSL iManager Snapins Detector v1.0 \n\t\tby Nagareshwar Y Talekar (tnagareshwar\@novell.com)";
    print "\n\n Usage: \n\tperl NSLSnapinsDetector.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> instead of default port 80 \n";
    print "\n Example: \n\tperl NSLSnapinsDetector.pl -d ldap.myhost.edu\n\tperl NSLSnapinsDetector.pl -d -p 8080 192.168.0.100\n\tperl NSLSnapinsDetector.pl 192.168.0.1-100\n\n";
    
 }
 
 
  #****************************************************************************

