#!/usr/local/bin/perl

# Author : Karthik

#This calculates the subnet mask and also number of subnets based on
#the number of hosts needed by the user provided his base IP address

print "\nEnter the Base Network Address \n";
$base_addr = <STDIN>;
chomp($base_addr);

print "\nEnter the desired number of hosts\n";
$num_of_hosts = <STDIN>;
chomp($num_of_hosts);

@dummy = split(/\./,$base_addr);

# checking the validity of IP address ..

$length = @dummy;

if($length == 4)
  {

    $class_type = &validity($dummy[0],$num_of_hosts);

    if($class_type > 0)
      {
	$host_bits = &calc_host_bits($num_of_hosts);
	print "\nHost Number Bits are : $host_bits \n";
	$network_prefix = 32 - $host_bits;
	$possible_ips = 2 ** $host_bits;
	print "The Number of possible IP addresses are : $possible_ips \n\n";
	
	@smask = &calc_submask($network_prefix);

	for($m=0;$m<4;$m++)
	  {
	    $temporary = pop @smask;
	    $smaskstr = $smaskstr . $temporary . ".";
	  }
	chop($smaskstr);
	
	print "\nThe Subnet Mask is [in IP Format] : $smaskstr";

	if($class_type == 1)
	  {
	    $num_of_subnet_bit = 24 - $host_bits;
	  }
	if($class_type == 2)
	  {
	    $num_of_subnet_bit = 16 - $host_bits;
	  }
	if($class_type == 3)
	  {
	    $num_of_subnet_bit = 8 - $host_bits;
	  }

	$number_of_subnets = 2 ** $num_of_subnet_bit;

	print "\nThe number of subnets available for deployment are : $number_of_subnets \n";
      }
    else
      {
	print "Plz give a valid IP address \n\n";
      }
  }
else
  {
    print "Plz enter a valid IP address \n\n";
  }


sub calc_submask
  {
    for($i=0;$i<$_[0];$i++)
      {
	push(@submask,1);
      }

    for($j=$_[0];$j<32;$j++)
      {
	push(@submask,0);
      }

    print "The Subnet Mask in the Binary Format : \n";
    for($l=0;$l<32;$l++)
      {
	if(($l !=0) && ($l % 8 == 0))
	  {
	    print " ";
	  }
	print "@submask[$l]";
      }print "\n";

    for($x=0;$x<4;$x++)
      {
	$subcalnum = 0;
	for($y=0;$y<=7;$y++)
	  {
	    $tmp = pop @submask;
	    unshift(@temp,$tmp);
	  }

	for($k=0;$k<=7;$k++)
	  {
	    if(@temp[$k] == 1)
	      {
		$subcalnum = $subcalnum + (2 ** (7-$k));
	      }
	  }
	push(@subnum,$subcalnum);

#subnum is in inverse order so pop it ..
      }

    return @subnum;
  }

sub calc_host_bits
  {
    for($x=1;$x<=24;$x++)
      {
	$host_nums = 2 ** $x;
	if($host_nums > $_[0])
	  {
	    return $x;
	  }
      }
  }

sub validity
  {
    
    if($_[0] < 127 && $_[0] > 0)
      {
	$net_number = $base_addr."/8";
	print "\nYou have a Class A Address\n";
	print "The network number is $net_number\n";
	
	if($_[1] <= 16777214)
	  {
	    print "Valid request for number of hosts\n";
	    return 1;
	  }
	else
	  {
	    print "Invalid request for hosts\n\n";
	    return 0;
	  }
      }
    if($_[0] > 127 && $_[0] < 192)
      {
	$net_number = $base_addr."/16";
	print "\nYou have a Class B Address\n";
	print "The network number is $net_number\n";
	
       if($_[1] <= 16384)
	  {
	    print "Valid request for number of hosts\n";
	    return 2;
	  }
	else
	  {
	    print "Invalid request for hosts\n\n";
	    return 0;
	  }
      }
    if($_[0] > 191 && $_[0] < 224)
      {
	$net_number = $base_addr."/24";
	print "\nYou have a Class C Address\n";
	print "The network number is $net_number\n";

	if($_[1] <= 254)
	  {
	    print "Valid request for number of hosts\n";
	    return 3;
	  }
	else
	  {
	    print "Invalid request for hosts\n\n";
	    return 0;
	  }
      }
  }
