<?php
/**
* This script will generate a pseudo IPv4 in Class E IP space (240.0.0.0 - 255.255.255.255)
* for IPv6 users based on the 52 first bits of their IP. Class E address space is reserved
* as experimental and no actual traffic should originate from it.
*
* @author NewEraCracker
* @version 2.0.1
* @date 2014/07/03
* @license Public Domain
*/
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('::')));
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('::1')));
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('::ffff')));
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('ffff::1:0')));
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('1::ffff:0')));
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('1:2:3:4:5:6:7::')));
var_dump(NewEra_IPv6Hack::ip_unpack(NewEra_IPv6Hack::ip_pack('::2:3:4:5:6:7:8')));
class NewEra_IPv6Hack
{
/** @Link : http://php.net/manual/en/function.inet-pton.php */
public static function ip_pack($ip)
{
if(strpos($ip, '.') !== false)
{
// Pack IPv4
$ip = trim($ip, ':f');
$ip = pack('N', ip2long($ip));
return $ip;
}
elseif(strpos($ip, ':') !== false)
{
// Expand IPv6
$ip = self::ipv6_expand($ip);
// Pack IPv6
$ip = pack('H'.strlen($ip), $ip);
return $ip;
}
return false;
}
/** @Link : http://php.net/manual/en/function.inet-ntop.php */
public static function ip_unpack($ip)
{
if(strlen($ip) == 4)
{
// Unpack IPv4
list(, $ip) = unpack('N', $ip);
$ip = long2ip($ip);
return $ip;
}
elseif(strlen($ip) == 16)
{
// Unpack IPv6
$ip = bin2hex($ip);
// Compact IPv6
$res = '';
for($i = strlen($ip); $i > 0; $i = ($i-4))
{
$seg = substr($ip, $i-4, 4);
$seg = ltrim($seg, '0');
if($seg != '')
{
$res = $seg.($res==''?'':':').$res;
}
else
{
if(strpos($res, '::') === false)
{
var_dump($i);
// Check iteration number to make sure ::1 case is handled
if($res != '' && $res[0] == ':' && $i > 4)
{
continue;
}
$res = ':'.$res;
continue;
}
$res = '0'.($res==''?'':':').$res;
}
}
// Handle ::2:3:4:5:6:7:8 and 1:2:3:4:5:6:7:: cases
if(substr_count($res, ':') == 8)
{
$res = str_replace('::', ':0:', $res);
$res = trim($res, ':');
}
return $res;
}
return false;
}
/** Expand an IPv6 address */
public static function ipv6_expand($ip)
{
$ip = explode(':', $ip);
$res = '';
$expand = true;
foreach($ip as $seg)
{
if($seg == '' && $expand)
{
// This will expand a compacted IPv6
$res .= str_pad('', (((8 - count($ip)) + 1) * 4), '0', STR_PAD_LEFT);
// Only expand once, otherwise it will cause troubles with ::1 or ffff::
$expand = false;
}
else
{
// This will pad to ensure each IPv6 part has 4 digits.
$res .= str_pad($seg, 4, '0', STR_PAD_LEFT);
}
}
return $res;
}
/** Shift an IPv6 to right (IPv6 >> 1). This will be handy to generate a fake IPv4 */
public static function ipv6_shift_right($ip)
{
$ip = self::ipv6_expand($ip);
$ip = substr($ip, -1).substr($ip, 0, -1);
$ip = substr(chunk_split($ip, 4, ':'), 0, -1);
return $ip;
}
/** Create a fake IPv4 address from a given IPv6 address */
public static function ipv6_to_ipv4($ip)
{
if(strpos($ip, ':') === false || strpos($ip, '.') !== false)
{
return false;
}
$ip = self::ipv6_shift_right($ip);
$ip = self::ip_pack($ip);
// First 8 bits of IPv4 will be:
// - The last 4 bits of unshifted IPv6, all set to true via mask
// - The first 4 bits of unshifted IPv6, all in their original state via mask
// This ensures an IPv4 in Class E space (240.0.0.0 - 255.255.255.255)
$ipv4 = chr(ord($ip[0]) | 0xf0);
for($i=1;$i<7;$i+=2)
{
// Convert 48 bits of IPv6 in last 24 bits of IPv4 via XOR
$ipv4 .= chr(ord($ip[$i]) ^ ord($ip[$i+1]));
}
return self::ip_unpack($ipv4);
}
/** Convert a V4overV6 to IPv4 */
public static function v4overv6_to_ipv4($ip)
{
if(strpos($ip, '.') !== false)
{
$ip = trim($ip, ':f');
return $ip;
}
return false;
}
/** This will test if it is a V4overV6 or an IPv6 and do the convertion */
public static function all_to_ipv4($ip)
{
$v4overv6_test = self::v4overv6_to_ipv4($ip);
if($v4overv6_test !== false)
{
return $v4overv6_test;
}
return self::ipv6_to_ipv4($ip);
}
}
?>