我有一个起始IPv4 IP地址5.39.28.128
(或::ffff:5.39.28.128
),我有IPv6网络掩码长度122
,我如何计算范围内的最后一个IP ?
我认为我需要将开始IP转换为二进制,我像下面这样做,我不知道从那里去哪里得到结束IP。
$ipNumber = ip2long('5.39.28.128');
$ipBinary = decbin($ipNumber);
echo $ipBinary; // 101001001110001110010000000
原因是我将MaxMind GeoIP数据库以CSV格式导入MySQL数据库(因此MySQL函数可以在需要时使用)。MaxMind不再提供结束IP,而是提供开始IP和IPv6网络掩码长度。
给你。我从这个问题的回答中复制了inet_to_bits
函数。
<?php
function inet_to_bits($inet) {
$inet = inet_pton($inet);
$unpacked = unpack('A16', $inet);
$unpacked = str_split($unpacked[1]);
$binaryip = '';
foreach ($unpacked as $char) {
$binaryip .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
}
return $binaryip;
}
function bits_to_inet($bits) {
$inet = "";
for($pos=0; $pos<128; $pos+=8) {
$inet .= chr(bindec(substr($bits, $pos, 8)));
}
return inet_ntop($inet);
}
$ip = "::ffff:5.39.28.128";
$netmask = 122;
// Convert ip to binary representation
$bin = inet_to_bits($ip);
// Generate network address: Length of netmask bits from $bin, padded to the right
// with 0s for network address and 1s for broadcast
$network = str_pad(substr($bin, 0, $netmask), 128, '1', STR_PAD_RIGHT);
// Convert back to ip
print bits_to_inet($network);
输出:::ffff:5.39.28.191
解决方法很简单:
// Your input data
$networkstart = '5.39.28.128';
$networkmask = 122;
// First find the length of the block: IPv6 uses 128 bits for the mask
$networksize = pow(2, 128 - $networkmask);
// Reduce network size by one as we really need last IP address in the range,
// not first one of subsequent range
$networklastip = long2ip(ip2long($networkstart) + $networksize - 1);
$ networklasttip将包含最后一个IP地址。
现在这是一个很好的解决方案,只有IPv4地址在IPv6地址空间。否则需要使用IPv6 to/from 128位整数函数,而不是ip2long/long2ip。然而,对于MaxMind数据代码的使用是足够的,因为我还没有看到任何实际的IPv6数据。