#! /usr/bin/perl

# This joinblock only takes one network argument.  it figures out the other
# and reports it

# Author : Ed Landa (elanda@comstar.net)
# Version : 
#
# Copyright 1997 ComStar Communication, Inc.


if ($ARGV[0])
{
   $blk1=$ARGV[0];
}
else
{
   print "ERROR: No block1\n";
	exit;
}

# Parse it up
($ip1,$bits1) = split('/',$blk1);
($a1,$b1,$c1,$d1) = split(/\./,$ip1);

$bits=$bits1;

# Error check the splitting
if (($bits > 30) || ($bits < 2))
{
   print "ERROR: It is not possible to join this Network/Mask.\n\n";
	exit;
}


# Now check the first block to make sure it falls on the new network boundary
($fa1,$fb1,$fc1,$fd1,$la1,$lb1,$lc1,$ld1) = &unmask($a1,$b1,$c1,$d1,$bits-1);
print "$fa1.$fb1.$fc1.$fd1 $la1.$lb1.$lc1.$ld1\n";
if ( ($a1 != $fa1) || ($b1 != $fb1) || ($c1 != $fc1) || ($d1 != $fd1) )
{
   print "ERROR: First network does not fall on new boundary.\n\n";
	exit;
}

# Make a call with the info that was entered
($fa1,$fb1,$fc1,$fd1,$la1,$lb1,$lc1,$ld1) = &unmask($a1,$b1,$c1,$d1,$bits);

# Does the returned start-of-block match what was input?
if ( ($a1, $b1, $c1, $d1) != ($fa1, $fb1, $fc1, $fd1) )
{
   print "ERROR: Invalid Network/Mask entered.\n\n";
	exit;
}

# Add one to the end of the first block.  Do we get the beginning of the 
# next block?
($a3,$b3,$c3,$d3) = incaddr($la1,$lb1,$lc1,$ld1);

# OK, go with it

print "$a3.$b3.$c3.$d3/$bits\n";
exit;


sub incaddr {
   local ($la, $lb, $lc, $ld) = @_;
	local ($a, $b, $c, $d);

   $a=0+$la; $b=0+$lb; $c=0+$lc; $d=0+$ld;

	$d=$ld+1;
	if ($d>255)
	{
		$d=0;
		$c=$lc+1;
		if ($c>255)
		{
			$c=0;
			$b=$lb+1;
			if ($b>255)
			{
				$b=0;
				$a=$la+1;
				if ($a>255)
				{
					print "ERROR: Error in splitting block.  You should never see this.\n\n";
					exit;
				}
			}
		}
	}
   return($a,$b,$c,$d);
}

# Take a network and mask and return the starting and ending IP addresses
# of that range
sub unmask {
   local ($a, $b, $c, $d, $mask) = @_;

	$add1 = (($a * (256**3)) + ($b * (256**2)) + ($c * (256**1)) + $d);
	$mb = (2**32)-(2**(32-$mask));
	$mb2 = 2**(32-$mask)-1;

	$add2 = ($add1 & $mb);
	$add3 = ($add2 | $mb2);

	($fa,$fb,$fc,$fd) = &unp($add2);
	($la,$lb,$lc,$ld) = &unp($add3);

   return ($fa, $fb, $fc, $fd, $la, $lb, $lc, $ld);
}

# Convert 32 bit IP address to dotted quad
sub unp {
	local($o) = @_[0];
	local($r);
	local($a,$b,$c,$d);

	$d = $o & 0x000000ff;
        $o >>= 8;
	$c = $o & 0x000000ff;
        $o >>= 8;
	$b = $o & 0x000000ff;
        $o >>= 8;
	$a = $o & 0x000000ff;

	return($a,$b,$c,$d);
	}


