
在 goole 和 github 上搜索 IP 段转 cidr ,整整找了两天都没有发现支持 ipv6 段转 cidr 的 PHP 版本代码。无奈只能找个 ipv4 的版本作参考模仿着实现支持 ipv6 ,但似乎行不通(经调试发现“$startaddr & $mask”与运算有问题,已在代码块标注),路过的大佬麻烦帮忙指点下
github 上 ipv4 版本
/** * ip 段转 cidr (仅支持 ipv4 ) * @param $startip IP 起始地址 * @param $endip IP 结束地址 * @return array 返回 cidr 数组 */ function ipv4_range_to_cidr($startip, $endip) { $cidr2mask = [ 0x00000000, 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF ]; $startaddr = ip2long($startip); $endaddr = ip2long($endip); $cidrlist = array(); while ($endaddr >= $startaddr) { $maxsize = 32; while ($maxsize > 0) { $mask = $cidr2mask[$maxsize - 1]; $maskedbase = $startaddr & $mask; if ($maskedbase != $startaddr) { break; } $maxsize -=1; } $x = log($endaddr - $startaddr + 1) / log(2); $maxdiff = 32 - floor($x); $new_maxsize = $maxsize < $maxdiff ? $maxdiff : $maxsize; $cidrlist[] = long2ip($startaddr) . "/" . $new_maxsize; $startaddr += pow(2, (32 - $new_maxsize)); } return $cidrlist; } 模仿写的 ipv6 版本
/** * ip 段转 cidr (仅支持 ipv6 ) * @param $startip IP 起始地址 * @param $endip IP 结束地址 * @return array 返回 cidr 数组 */ function ipv6_range_to_cidr($startip, $endip) { $max = ip2long6('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF'); $cidr2mask = []; $count = 0; while(bccomp($max, "0") !== -1) { $cidr2mask[] = $max; $e = bcpow(2, $count); $max = bcsub($max, $e); $count++; } $cidr2mask = array_reverse($cidr2mask); $startaddr = ip2long6($startip); $endaddr = ip2long6($endip); $cidrlist = array(); while (bccomp($endaddr, $startaddr) !== -1) { $maxsize = 128; while ($maxsize > 0) { $mask = $cidr2mask[$maxsize - 1]; $maskedbase = $startaddr & $mask; //与运算数据溢出?求路过朋友帮忙指点下 if ($maskedbase != $startaddr) { break; } $maxsize -=1; } $x = log(bcadd(bcsub($endaddr, $startaddr), "1")) / log(2); $maxdiff = 128 - floor($x); $new_maxsize = $maxsize < $maxdiff ? $maxdiff : $maxsize; $cidrlist[] = long2ip6($startaddr) . "/" . $new_maxsize; $startaddr = bcadd($startaddr, bcpow(2, (128 - $new_maxsize))); } return $cidrlist; } /** * 整数转换为 IPV6 地址 * @param $ipv6long * @return string */ function long2ip6($ipv6long) { $bin = gmp_strval(gmp_init($ipv6long, 10), 2); if (strlen($bin) < 128) { $pad = 128 - strlen($bin); for ($i = 1; $i <= $pad; $i++) { $bin = "0" . $bin; } } $bits = 0; $ipv6 = ''; while ($bits <= 7) { $bin_part = substr($bin, ($bits * 16), 16); $ipv6 .= dechex(bindec($bin_part)) . ":"; $bits++; } // compress return inet_ntop(inet_pton(substr($ipv6, 0, -1))); } /** * IPV6 地址转换为整数 * @param $ipv6 * @return string */ function ip2long6($ipv6) { $ip_n = inet_pton($ipv6); $bits = 15; // 16 x 8 bit = 128bit $ipv6lOng= ''; while ($bits >= 0) { $bin = sprintf("%08b", (ord($ip_n[$bits]))); $ipv6lOng= $bin . $ipv6long; $bits--; } return gmp_strval(gmp_init($ipv6long, 2), 10); } 1 Rache1 2022-04-07 15:37:00 +08:00 |
2 pray123 OP @Rache1 奇怪,我这边访问不了网站 https://packagist.org/packages/s1lentium/iptools |
3 Rache1 2022-04-08 09:16:12 +08:00 @pray123 那就看 github https://github.com/S1lentium/IPTools |
5 Rache1 2022-04-08 15:52:47 +08:00 |
6 Atomo 2022-04-09 02:07:09 +08:00 |