生成给定范围内的 IPv6 地址列表
Generate a list of IPv6 addresses within a given range
在 Maria DB table 中,我有两个 varbinary(16)
字段代表 IPv6 范围的开始和结束的 IPv6 地址。
我想使用 PHP 在此范围之间循环并生成范围内的每个 IPv6 地址。我试图将二进制转换为十进制来执行循环并增加十进制数,但循环不会产生任何迭代。
有什么帮助吗?
//The $IpStart_v6_FromDb/$IpStart_v6_End Vars are produced with INET6_ATON MariaDB function
$IpStartBin = decbin($IpStart_v6_FromDb);
$IpEndBin = decbin($IpEnd_v6_FromDb);
$ArIpRange = array();
$ArIpRange[] = $IpStartBin;
$x=0;
for(;;)
{
if ($IpStartBin==$IpEndBin) break;
$tLastIpBin = $ArIpRange[$x];
$tNextIpBin = decbin( (bindec($tLastIpBin) + 1) );
if ($tNextIpBin==$IpEndBin) break;
$ArIpRange[] = $tNextIpBin;
$x++;
}
foreach ($ArIpRange as $v)
{
echo "<br>IP range item:<br>".base64_encode($v); //debug
}
[编辑]
不好意思说我以为IPv6地址的长度是64位
因此,一些简单的故障排除或 reading the manual 会告诉您 decbin
需要一个整数作为输入。所以马上你就会得到两个变量的零。
此外,即使您确实纠正了这个问题(通过使用 bindec
),您谈论的是 128 位数字,除非您来自未来,否则它不是 PHP可以原生处理。
我建议将它们作为字符串处理。首先使用 this answer, find and remove the matching prefix using code from this answer 中的代码将它们归一化(填充缺失的零并用零替换 ::),然后通过将它们转换为更小的数字来处理其余部分。
并且,如评论中所述,请确保您不要尝试处理太大的范围,否则会使您的服务器不愉快。
<?php
//
// Generate a list of IPv6 addresses within a given range
function expand_ipv6(string $ip): ?string
{
//
$hex = unpack("H*", inet_pton($ip))[1] ?? "";
return (strlen($hex) === 32) ? implode(":", str_split($hex, 4)) : null;
}
$IpStart_v6_FromDb = "2001:db8::1234";
$IpEnd_v6_FromDb = "2001:db8::1299";
$ip1 = expand_ipv6($IpStart_v6_FromDb);
$ip2 = expand_ipv6($IpEnd_v6_FromDb);
if ($ip1 === null || $ip2 === null) {
die;
}
//
// length is 39 to account for 7 colons
for ($i = 0; $i < 39 && $ip1[$i] === $ip2[$i]; $i++);
$ipv6_prefix = substr($ip1, 0, $i);
$ipv6_start = hexdec(substr($ip1, $i));
$ipv6_end = hexdec(substr($ip2, $i));
if (strlen($ipv6_prefix) < 26) {
// adjust this to requirements to prevent too large ranges
die;
}
for ($a = $ipv6_start; $a <= $ipv6_end; $a++) {
$hex = dechex($a);
printf("%s%s\n", $ipv6_prefix, implode(":", str_split($hex, 4)));
}
在 Maria DB table 中,我有两个 varbinary(16)
字段代表 IPv6 范围的开始和结束的 IPv6 地址。
我想使用 PHP 在此范围之间循环并生成范围内的每个 IPv6 地址。我试图将二进制转换为十进制来执行循环并增加十进制数,但循环不会产生任何迭代。
有什么帮助吗?
//The $IpStart_v6_FromDb/$IpStart_v6_End Vars are produced with INET6_ATON MariaDB function
$IpStartBin = decbin($IpStart_v6_FromDb);
$IpEndBin = decbin($IpEnd_v6_FromDb);
$ArIpRange = array();
$ArIpRange[] = $IpStartBin;
$x=0;
for(;;)
{
if ($IpStartBin==$IpEndBin) break;
$tLastIpBin = $ArIpRange[$x];
$tNextIpBin = decbin( (bindec($tLastIpBin) + 1) );
if ($tNextIpBin==$IpEndBin) break;
$ArIpRange[] = $tNextIpBin;
$x++;
}
foreach ($ArIpRange as $v)
{
echo "<br>IP range item:<br>".base64_encode($v); //debug
}
[编辑]
不好意思说我以为IPv6地址的长度是64位
因此,一些简单的故障排除或 reading the manual 会告诉您 decbin
需要一个整数作为输入。所以马上你就会得到两个变量的零。
此外,即使您确实纠正了这个问题(通过使用 bindec
),您谈论的是 128 位数字,除非您来自未来,否则它不是 PHP可以原生处理。
我建议将它们作为字符串处理。首先使用 this answer, find and remove the matching prefix using code from this answer 中的代码将它们归一化(填充缺失的零并用零替换 ::),然后通过将它们转换为更小的数字来处理其余部分。
并且,如评论中所述,请确保您不要尝试处理太大的范围,否则会使您的服务器不愉快。
<?php
//
// Generate a list of IPv6 addresses within a given range
function expand_ipv6(string $ip): ?string
{
//
$hex = unpack("H*", inet_pton($ip))[1] ?? "";
return (strlen($hex) === 32) ? implode(":", str_split($hex, 4)) : null;
}
$IpStart_v6_FromDb = "2001:db8::1234";
$IpEnd_v6_FromDb = "2001:db8::1299";
$ip1 = expand_ipv6($IpStart_v6_FromDb);
$ip2 = expand_ipv6($IpEnd_v6_FromDb);
if ($ip1 === null || $ip2 === null) {
die;
}
//
// length is 39 to account for 7 colons
for ($i = 0; $i < 39 && $ip1[$i] === $ip2[$i]; $i++);
$ipv6_prefix = substr($ip1, 0, $i);
$ipv6_start = hexdec(substr($ip1, $i));
$ipv6_end = hexdec(substr($ip2, $i));
if (strlen($ipv6_prefix) < 26) {
// adjust this to requirements to prevent too large ranges
die;
}
for ($a = $ipv6_start; $a <= $ipv6_end; $a++) {
$hex = dechex($a);
printf("%s%s\n", $ipv6_prefix, implode(":", str_split($hex, 4)));
}