简体   繁体   中英

How to calculate end IP in the range, based on start IP and network mask length

I have a starting IPv4 IP address 5.39.28.128 (or ::ffff:5.39.28.128 ) and I have the IPv6 network mask length 122 , how can I calculate the last IP in the range?

I believe I need to convert the start IP to binary, which I'm doing like below, I don't know where to go from there to get the end IP.

$ipNumber = ip2long('5.39.28.128');
$ipBinary = decbin($ipNumber);

echo $ipBinary; // 101001001110001110010000000

The reason is I'm importing the MaxMind GeoIP database in CSV format into a MySQL database (so MySQL functions can be used if needed). MaxMind no longer provide the end IP, in favour of providing the start IP and the IPv6 network mask length instead.

Here you are. I've copied the inet_to_bits function from this response to another question .

<?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);

Output:

::ffff:5.39.28.191

Solution is quite simple:

// 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);

$networklastip will have last IP address in the range.

Now this is good solution ONLY for IPv4 addresses in IPv6 address space. Otherwise you need to use IPv6 to/from 128 bit integer functions instead of ip2long/long2ip. However for use by MaxMind data code above is sufficient as I have not seen any actual IPv6 data from them yet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM