#### ASpath-tree v.4.2 - Released on Thu APR 17 2003, h.16:58:12
#### File: lib/ipv6prefix.pl Last modified on Sun DEC 8 2002, h.22:17:43

# Routines for various operations on IPv6 prefixes
# Rules for pTLA assignement updated at March 2002

# Routine to evaluate an IPv6 prefix:
#	 output = 0 stands for invalid prefix
#	 output = 1 stands for 6bone pTLA prefix
#	 output = 2 stands for 6bone unaggregated prefix
#	 output = 3 stands for the prefixes assigned by RIRs
#	 output = 4 stands for the 6to4 prefix
#	 output = 5 stands for 6to4 prefixes longer than /16
#
sub check_prefix {
	my ($prefix) = @_;
	my ($normprefix, $addr, $lprefix, $conflprefix, $output, $hexprefix);
	$normprefix = &normal($prefix);
	($addr,$lprefix) = split(/\//,$normprefix);
	if (&includedprefix($prefix,"3ffe::/16")) {
		$hexprefix = join('',split(/:/,$addr));
		$hexprefix = substr($hexprefix,0,8);
		$hexprefix = $hexprefix . ("0" x (8-length($hexprefix)));

		if ((hex($hexprefix) >= hex('3ffe0000')) && (hex($hexprefix) <= hex('3ffe3f00'))) {$conflprefix = 24}
		elsif ((hex($hexprefix) >= hex('3ffe8000')) && (hex($hexprefix) <= hex('3ffe83f0'))) {$conflprefix = 28}
		elsif ((hex($hexprefix) >= hex('3ffe4000')) && (hex($hexprefix) <= hex('3ffe7fff'))) {$conflprefix = 32}
		else {$conflprefix = 0}

		if ($conflprefix == 0 || ($lprefix < $conflprefix)) {$output = 0}
		elsif ($lprefix == $conflprefix) {$output = 1}
		else {$output = 2}
	}
	elsif (&includedprefix($prefix,"2001::/16")) {
		if ($lprefix >= 29 && $lprefix <= 35) {$output = 3}
		elsif ($lprefix < 29) {$output = 0}
		else {$output = 2}
	}
	elsif (&includedprefix($prefix,"2002::/16")) {
		if ($lprefix == 16) {$output = 4}
		else {$output = 5}
	}
	else {$output = 0}
	return ($output);
}

# Normalize prefix format xxxx:xxxx::/yy
sub normal {
	my ($prefix) = @_;
	my ($addr, $lprefix, $binaddr, $binaddrout, $i, $output);

	($addr,$lprefix) = split(/\//,$prefix);
	$binaddr = &addr2bin($addr);

	$nblocks = int($lprefix/16);
	if ($lprefix % 16) {$nblocks++}

	$output = &bin2hex(substr($binaddr,0,$nblocks*16));

	while (($nblocks>0) && (substr($output,($nblocks-1)*4,4) eq "0000")) {
		$nblocks--;
		$output = substr($output,0,$nblocks*4);
	}
	for ($i=$nblocks;$i>1;$i--) {substr($output,($i-1)*4,0) = ":"}
	if ($nblocks<8) {$output .= "::"}
	$output .= "/$lprefix";

	return($output);
}

# Check if prefix1 is included in prefix2
sub includedprefix {
	my ($prefix1, $prefix2) = @_;
	my ($lprefix1, $lprefix2, $addr1, $addr2, $binaddr1, $binaddr2, $answer);

	($addr1,$lprefix1) = split(/\//,$prefix1);
	($addr2,$lprefix2) = split(/\//,$prefix2);
	if ($lprefix1 >= $lprefix2) {
		$binaddr1 = &addr2bin($addr1);
		$binaddr2 = &addr2bin($addr2);
		$answer = (substr($binaddr1,0,$lprefix2) eq substr($binaddr2,0,$lprefix2));
	}
	else {$answer = 0}
	return($answer);
}

# Convert hex IPv6 addresses into binary format
sub addr2bin {
	my ($addr) = @_;
	my ($binaddr, $begin, $end) = ('', '', '');
	my ($lbegin, $lend, $i, $len, $foundcc) = (0, 0, 0, 0);
	my (@vec) = ();

	@vec = split(/:/,$addr);
	$len = @vec;

	while (($i < $len) && (!$foundcc)) {
		if ($vec[$i] =~ /[\dABCDEF]/i) {
			$begin .= &hex2bin($vec[$i]);
			$lbegin++;
		}
		else {$foundcc = 1}
		$i++;
	}
	if ($foundcc) {
		$foundcc = 0;
		$i = ($len - 1);
		while (($i >= 0) && (!$foundcc)) {
			if ($vec[$i] =~ /[\dABCDEF]/i) {
				$end .= &hex2bin($vec[$i]);
				$lend++;
			}
			else {$foundcc = 1}
			$i++;
		}
	}
	$binaddr = $begin;
	for ($i=0;$i<(8-$lend-$lbegin);$i++) {
		$binaddr .= "0000000000000000";
	}
	$binaddr .= $end;
	return($binaddr);
}

# Convert 1 to 4 digits hex format into bin format
sub hex2bin {
	my ($input) = @_;
	my ($output, $i, $digit) = ('', 0, '');
	my (@hex_in_bin) = ("0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111");

	$input = ("0" x (4-length($input))) . $input;

	for ($i=0; $i<4; $i++) {
		$digit = substr($input,$i,1);
		$output .= $hex_in_bin[hex($digit)];
	}
	($output);
}

# Convert bin format into hex format
sub bin2hex {
	my ($input) = @_;
	my ($i, $nblocks, $decvalue, $output) = (0, 0, 0 , '');
	my (@hex_symbols) = ("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");

	my $len = length($input);
	if ($len % 16) {
		$input = $input . ("0" x (16 - ($len % 16)));
		$len += 16 - ($len % 16);
	}

	$nblocks = int($len/4);
	for ($i=0; $i<$nblocks; $i++) {
		$decvalue = substr($input,($i*4),1)*8+substr($input,($i*4)+1,1)*4+substr($input,($i*4)+2,1)*2+substr($input,($i*4)+3,1);
		$output .= $hex_symbols[$decvalue];
	}
	return ($output);
}

(1);
#### ASpath-tree v.4.2 - Released on Thu APR 17 2003, h.16:58:12
#### File: lib/ipv6prefix.pl Last modified on Sun DEC 8 2002, h.22:17:43
