#!/usr/bin/perl
# Revision: $Id: mkv6 5682 2009-11-06 15:09:04Z leland $
#
# quick and dirty utility to generate IPv6 address for hosting beta testers generated from their ipv4 address
# and vlan association.
############################################
# syntax:  mkv6
#  returns ipv6 address and prefix-length, and default gateway
#  and configures them on eth0
#########################################################
# 2009-08-04:  LV:  Updated to include support for new ipv4 prefix allocated by RIPE.
# 2009-11-03:  LV:  Reset VLAN indicators to their definitive values.
#                   Obtain ipv4 address from eth0 via ifconfig and use it to 
#                    generate the ipv6 address and gateway.
#                   Insert ipv6 address and default gateway using /sbin/ip
#                   Todo -- support for doing the same with ifconfig natively
#                           for linux distos that do not have /sbin/ip
# 2009-11-04:  LV:  Support for ifconfig/route added.
# 2009-11-06:  LV:  Fixed bug where failed to obtain address if 
#                    	operating system language is french.
#		    Added additional verbosity...
#	  	    Optionally use hostid to work out IP address.
#########################################################


$iputil = "/sbin/ip";
$ifconfig = "/sbin/ifconfig";
$iproute = "/sbin/route";
$hostid = "/usr/bin/hostid";

$ipv6prefix = "2001:4b98:";
$ipv6length = "/64";

# HASH MAP USED IN CASE OF VLAN REMAPPING... 
# AS *WAS* THE CASE FOR VLAN43 WHICH HAD 
# ADDRESSING FOR VLAN41 IN IPV6 -- THIS IS NOW
# FIXED... COULD POTENTIALLY REMOVE THIS MAP
# BUT MAY BE USEFUL IN THE FUTURE...
%VLAN = (
		41 => 41, 
		43 => 43, 
		45 => 45,
		47 => 47,
		51 => 51
	);

sub to_dec {
	my $a = shift;
	my $tmp = sprintf("%u", hex($a));
	return $tmp;
}

sub to_hex {
	$dec = shift;
	my $return = "NULL";

	my $tmp = sprintf("%x", $dec);
	if (length ($tmp) < 2) {
		$return = "0" . $tmp;
	}
	else {
		$return = $tmp;
	}
	return $return;
}

sub get_vlan {
	my $first = shift;
	my $second = shift;
	my $third = shift;

	if ($first == 217) { return 41; }
	if ($first == 92) { 
		if ($second != 243) { 
			die "Invalid IPv4 address - cannot continue\n";
		}

		if ($third <= 15) { return 41; }
		elsif ($third <= 19) { return 43; }
		elsif ($third <= 23) { return 45; }
		elsif ($third <= 27) { return 43; }
		elsif ($third <= 31) { return 45; }
		else {
			die "Invalid IPv4 address - cannot continue\n";
		}
	}
	elsif ($first == 95) {
		if (( $third < 160) || ( $third > 175) || ( $second != 142)) { 
			die "Invalid IPv4 address - cannot continue\n";
		}
		if ($third < 164) { return 47; }
		elsif ($third < 168) { return 51; }
		elsif ($third < 172) { return 47; }
		elsif ($third < 176) { return 51; }
		else { 
			die "Invalid IPv4 address - cannot continue\n";
		}
	}
	else {
		die "Invalid IPv4 address - cannot continue\n";
	}
}

sub get_ipv4 {

	my $ipv4addy = "";

	if (-f $hostid ) {
		print "Using hostid to obtain address..\n";
		my $tmpid = `$hostid`;
		print "DBG:  $tmpid ... \n";
		$tmpid =~ /(\w{2})(\w{2})(\w{2})(\w{2})/;
		my $a = &to_dec($2);
		my $b = &to_dec($1); 
		my $c = &to_dec($4);
		my $d = &to_dec($3);
		$ipv4addy = "$a.$b.$c.$d";
		return $ipv4addy;
	}		

	print "Using ifconfig -a to obtain address..\n";

	my $ifconf = `$ifconfig -a`;
	my @lines = split(/\n/, $ifconf);
	my $found = 0;
	for (@lines) { 
		if (/eth0/) { 
			$found = 1; 
		}
		if ($found == 1 && /inet add?r\:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/) {
			$ipv4addy = $1;
			$found = 0;
			return $ipv4addy;
		}
	}
	die "Cannot determine ipv4 address -- language output of ifconfig?\n";
}

print "Attempting to obtain current ipv4 address..\n";
my $ipv4addr = &get_ipv4();
print "Got $ipv4addr ... \n";

if ($ipv4addr =~ /\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/) {
	$a = $1; $b = $2; $c = $3; $d = $4;

	my $tmp_vlan = &get_vlan($a, $b, $c);
	my $ipv6addr = $ipv6prefix . $VLAN{$tmp_vlan} . "::" . &to_hex($a) . &to_hex($b) . ":" . &to_hex($c) . &to_hex($d) . ":" . $d . $ipv6length;
	print "-- Adding $ipv6addr to device eth0\n-- setting IPv6 default gateway via FE80::6" . $VLAN{$tmp_vlan} . " on eth0\n";

	if (-f $iputil) {
		`$iputil -6 addr add $ipv6addr dev eth0`;
		`$iputil -6 route add default via FE80::6$VLAN{$tmp_vlan} dev eth0`;
	}
	else {
		`$ifconfig eth0 inet6 add $ipv6addr`;
		`$iproute -A inet6 add default gw FE80::6$VLAN{$tmp_vlan} dev eth0`;
	}

}




		

