Find the next IPv6 address

  • (2 Pages)
  • +
  • 1
  • 2

21 Replies - 445 Views - Last Post: 27 February 2018 - 04:34 PM Rate Topic: -----

#1 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Find the next IPv6 address

Posted 26 February 2018 - 11:01 AM

Hi,

for one of my libraries I need to find the previous/next IP address. While for IPv4 this is trivial, it's a challenge for IPv6. The only way to do that, which I have found so far is converting the IP's bytestream into a set of integers, using unpack(C*), and doing the bit addition there.

So I wonder if there are other (sensible /1/) methods to accomplish that?

1 - bcmath would work, but is IMO not sensible

Cheers, Dormilich

This post has been edited by Dormilich: 26 February 2018 - 11:01 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Find the next IPv6 address

#2 ArtificialSoldier  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 1989
  • View blog
  • Posts: 6,065
  • Joined: 15-January 14

Re: Find the next IPv6 address

Posted 26 February 2018 - 11:17 AM

Assuming the address isn't abbreviated, wouldn't you just add 1 to get the next address?
Was This Post Helpful? 0
  • +
  • -

#3 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Re: Find the next IPv6 address

Posted 26 February 2018 - 11:20 AM

In theory - yes, but PHP can't do bit addition out of the box. and using bcmath (since IPv6 easily exceeds the 64 bit integer range) is terribly performant.
Was This Post Helpful? 0
  • +
  • -

#4 ArtificialSoldier  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 1989
  • View blog
  • Posts: 6,065
  • Joined: 15-January 14

Re: Find the next IPv6 address

Posted 26 February 2018 - 11:23 AM

I suppose you just need to wait for 128-bit processors.

If you can split it up into 2 64-bit chunks, convert to int, and test the least significant to see if it's the max int in order to add 1 to the most significant, wouldn't that work?
Was This Post Helpful? 0
  • +
  • -

#5 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Re: Find the next IPv6 address

Posted 26 February 2018 - 11:26 AM

It would work if I knew how to split the IP. But then it's pretty similar to what I already have (splitting it into 16 8-bit chunks).
Was This Post Helpful? 0
  • +
  • -

#6 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3777
  • View blog
  • Posts: 13,674
  • Joined: 08-August 08

Re: Find the next IPv6 address

Posted 26 February 2018 - 01:02 PM

View PostDormilich, on 26 February 2018 - 12:26 PM, said:

It would work if I knew how to split the IP.

Do you mean that the digits may not be fully represented (ie xffaa:0:a1:ffff....) or are you talking about byte order?

In order to avoid dealing with sign issues I think I'd use 32 bits at a time:
$binaryData = "\x00\x00\x0A\x00\x00\x00\x0A\x0A\x00\x00\x00\x03\x00\x00\x00\x04";
$data = [];

for($offset = 0; $offset < 13; $offset+=4) {
    $data[] = unpack("N", $binaryData, $offset);
}

var_dump($data);


Was This Post Helpful? 0
  • +
  • -

#7 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3777
  • View blog
  • Posts: 13,674
  • Joined: 08-August 08

Re: Find the next IPv6 address

Posted 26 February 2018 - 07:52 PM

I'm not sure if this would work for you, but it seems reasonably fast, averaging a little less than 10-5 seconds.
<?php
$binaryIPv6 = "\xF0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
define ("MAX32" , 4294967295);

showHex($binaryIPv6);
$totalTime = 0;
for($test = 0; $test < 100; $test++) {
    $start = microtime(true);
    $binaryIPv6 = incrementIPv6($binaryIPv6);
    $end = microtime(true);
    showHex($binaryIPv6);
    $diff = $end - $start;
    $totalTime += $diff;
}

$averageTime = $totalTime/100;
echo "Average: ".$averageTime."<br>";

function incrementIPv6($ip6)
{
    $data = [];
    for($offset = 0; $offset < strlen($ip6); $offset+=4) {
        $data[] = unpack("N", $ip6, $offset);
    }

    $index = count($data)-1;
    $data[$index][1]++;
    $carry = $data[$index][1] > MAX32;
    while($carry && $index > 0) {
        $data[$index][1] = 0;
        $index--;
        $data[$index][1]++;
        $carry = $data[$index][1] > MAX32;
    }

    $hex = '';
    for($i = 0; $i < count($data); $i++) {
        $hex .= pack("N", $data[$i][1]);
    }

    return $hex;
}

function showHex($hex)
{
    for($i = 0; $i < strlen($hex); $i++) {
        printf("%02X ",ord(substr($hex, $i,1)));
    }
    echo "\n<br>\n";
}


Was This Post Helpful? 0
  • +
  • -

#8 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Re: Find the next IPv6 address

Posted 27 February 2018 - 01:17 AM

to avoid confusion I'll post what I currently have:
    public function next()
    {
        $bytes = $this->bytes();
        $i = count( $bytes );

        while ( $i-- ) {
            if ( $bytes[ $i ] === 255 ) {
                $bytes[ $i ] = 0;
            }
            else {
                $bytes[ $i ]++;
                break;
            }
        }

        array_unshift( $bytes, 'C*' );
        $binary = call_user_func_array( 'pack', $bytes );

        return new static( $binary );
    }

    private function bytes()
    {
        // `$this->in_addr` being inet_pton($ip_string)
        return array_values( unpack( 'C*', $this->in_addr ) );
    }



I'll have a look at pack(N) later, when I have more time.

This post has been edited by Dormilich: 27 February 2018 - 01:16 AM

Was This Post Helpful? 0
  • +
  • -

#9 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3777
  • View blog
  • Posts: 13,674
  • Joined: 08-August 08

Re: Find the next IPv6 address

Posted 27 February 2018 - 06:30 AM

Yours is about 1.5 * 10-6 faster than mine, likely because mine does four unpacks and then four packs, which apparently takes more time than the difference between math on four integers vs 16 integers.
Was This Post Helpful? 0
  • +
  • -

#10 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Re: Find the next IPv6 address

Posted 27 February 2018 - 06:33 AM

Well, the question was more about if there are alternate ways of doing IP increment than by using pack(). (although I'll check if pack(N) works better than pack(C*))
Was This Post Helpful? 0
  • +
  • -

#11 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3777
  • View blog
  • Posts: 13,674
  • Joined: 08-August 08

Re: Find the next IPv6 address

Posted 27 February 2018 - 07:04 AM

Ah, well you can just use ord() and chr():
function increment($ip6) {
    for($i = strlen($ip6)-1; $i >= 0; $i--) {
        $x = ord(substr($ip6,$i,1));
        if($x == 255) {
            $ip6[$i] =chr(0);
        } else {
            $x++;
            $ip6[$i] = chr($x);
            break;
        }
    }
    return $ip6;
}


It seems to be a bit faster than the other methods too, but the first run always seems to take around the average of the two.

This post has been edited by CTphpnwb: 27 February 2018 - 07:17 AM
Reason for edit:: Fixed bug.

Was This Post Helpful? 1
  • +
  • -

#12 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Re: Find the next IPv6 address

Posted 27 February 2018 - 07:26 AM

Are you sure this is correct? The idea is nice but fails for 9 and f.
Was This Post Helpful? 0
  • +
  • -

#13 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3777
  • View blog
  • Posts: 13,674
  • Joined: 08-August 08

Re: Find the next IPv6 address

Posted 27 February 2018 - 07:33 AM

Works on my system, but mine is big endian. Maybe yours is little endian?
<?php
$funcTime = 0;

$nextIp = inet_pton("00FF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0");
show($nextIp);
for ($i = 0; $i < 100; $i++) {
    $start = microtime(true);
    $nextIp = increment($nextIp);
    $end = microtime(true);
    $funcTime = $end - $start;
    show($nextIp);
}
echo "average: ".($funcTime/100)."<br><br>";

function increment($ip6)
{
    for ($i = strlen($ip6) - 1; $i >= 0; $i--) {
        $x = ord(substr($ip6, $i, 1));
        if ($x == 255) {
            $ip6[$i] = chr(0);
        } else {
            $x++;
            $ip6[$i] = chr($x);
            break;
        }
    }
    return $ip6;
}

function show($x)
{
    for ($i = 0; $i < strlen($x); $i++) {
        printf("%02X ", ord(substr($x, $i, 1)));
    }
    echo "\n<br>\n";
}


Output:
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F1 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F2 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F3 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F4 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F5 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F6 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F7 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F8 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F9 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FA 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FB 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FD 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE 
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0A 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 13 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 15 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1A 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1B 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1C 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1D 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1F 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 25 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 26 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 29 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2A 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2B 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2C 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2D 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2E 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 31 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 32 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 33 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 34 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 35 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 36 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 37 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 38 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3A 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3B 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3C 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3D 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3E 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 44 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 45 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 46 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4A 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4B 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4E 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4F 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 51 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 52 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 53 
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 54 
average: 1.9073486328125E-8


Was This Post Helpful? 0
  • +
  • -

#14 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4184
  • View blog
  • Posts: 13,226
  • Joined: 08-June 10

Re: Find the next IPv6 address

Posted 27 February 2018 - 08:01 AM

I didn't expect $ip6 to be the IP byte stream ...
Was This Post Helpful? 0
  • +
  • -

#15 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3777
  • View blog
  • Posts: 13,674
  • Joined: 08-August 08

Re: Find the next IPv6 address

Posted 27 February 2018 - 08:11 AM

I think that's part of why this method is faster. Less copy/move going on.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2