| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- <?php
- namespace MGModule\DNSManager2\mgLibs\custom\vendor;
- use MGModule\DNSManager2\mgLibs\custom\vendor\MathBigInteger;
- /* Copyright (c) 2011, Sam Clarke <http://www.samclarke.com/>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <organization> nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL SAM CLARKE BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- class IPv6
- {
- public static function ipv6_range($prefix)
- {
- // Split in address and prefix length
- list($firstaddrstr, $prefixlen) = explode('/', $prefix);
- // Parse the address into a binary string
- $firstaddrbin = inet_pton($firstaddrstr);
- // Convert the binary string to a string with hexadecimal characters
- # unpack() can be replaced with bin2hex()
- # unpack() is used for symmetry with pack() below
- $unpacked = unpack('H*', $firstaddrbin);
- $firstaddrhex = reset($unpacked);
- // Overwriting first address string to make sure notation is optimal
- $firstaddrstr = inet_ntop($firstaddrbin);
- // Calculate the number of 'flexible' bits
- $flexbits = 128 - $prefixlen;
- // Build the hexadecimal string of the last address
- $lastaddrhex = $firstaddrhex;
- // We start at the end of the string (which is always 32 characters long)
- $pos = 31;
- while ($flexbits > 0)
- {
- // Get the character at this position
- $orig = substr($lastaddrhex, $pos, 1);
- // Convert it to an integer
- $origval = hexdec($orig);
- // OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
- $newval = $origval | (pow(2, min(4, $flexbits)) - 1);
- // Convert it back to a hexadecimal character
- $new = dechex($newval);
- // And put that character back in the string
- $lastaddrhex = substr_replace($lastaddrhex, $new, $pos, 1);
- // We processed one nibble, move to previous position
- $flexbits -= 4;
- $pos -= 1;
- }
- // Convert the hexadecimal string to a binary string
- # Using pack() here
- # Newer PHP version can use hex2bin()
- $lastaddrbin = pack('H*', $lastaddrhex);
- // And create an IPv6 address from the binary string
- $lastaddrstr = inet_ntop($lastaddrbin);
-
- return array($prefix, $firstaddrstr, $lastaddrstr);
- }
- /**
- * Converts human readable representation to a 128bit int
- * which can be stored in MySQL using DECIMAL(39,0).
- *
- * Requires PHP to be compiled with IPv6 support.
- * This could be made to work without IPv6 support but
- * I don't think there would be much use for it if PHP
- * doesn't support IPv6.
- *
- * @param string $ip IPv4 or IPv6 address to convert
- * @return string 128bit string that can be used with DECIMNAL(39,0) or false
- */
- public static function inet_ptoi($ip)
- {
- // make sure it is an ip
- if (filter_var($ip, FILTER_VALIDATE_IP) === false)
- return false;
- $parts = unpack('N*', inet_pton($ip));
- // fix IPv4
- if (strpos($ip, '.') !== false)
- $parts = array(1=>0, 2=>0, 3=>0, 4=>$parts[1]);
- foreach ($parts as &$part)
- {
- // convert any unsigned ints to signed from unpack.
- // this should be OK as it will be a PHP float not an int
- if ($part < 0)
- $part += 4294967296;
- }
- // use BCMath if the extension exists
- if (function_exists('bcadd'))
- {
- $decimal = $parts[4];
- $decimal = bcadd($decimal, bcmul($parts[3], '4294967296'));
- $decimal = bcadd($decimal, bcmul($parts[2], '18446744073709551616'));
- $decimal = bcadd($decimal, bcmul($parts[1], '79228162514264337593543950336'));
- }
- // otherwise use the pure PHP BigInteger
- else
- {
- $decimal = new MathBigInteger($parts[4]);
- $part3 = new MathBigInteger($parts[3]);
- $part2 = new MathBigInteger($parts[2]);
- $part1 = new MathBigInteger($parts[1]);
- $decimal = $decimal->add($part3->multiply(new MathBigInteger('4294967296')));
- $decimal = $decimal->add($part2->multiply(new MathBigInteger('18446744073709551616')));
- $decimal = $decimal->add($part1->multiply(new MathBigInteger('79228162514264337593543950336')));
- $decimal = $decimal->toString();
- }
- return $decimal;
- }
- /**
- * Converts a 128bit int to a human readable representation.
- *
- * Requires PHP to be compiled with IPv6 support.
- * This could be made to work without IPv6 support but
- * I don't think there would be much use for it if PHP
- * doesn't support IPv6.
- *
- * @param string $decimal 128bit int
- * @return string IPv4 or IPv6
- */
- public static function inet_itop($decimal)
- {
- $parts = array();
- // use BCMath if the extension exists
- if (function_exists('bcadd'))
- {
- $parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0);
- $decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336'));
- $parts[2] = bcdiv($decimal, '18446744073709551616', 0);
- $decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616'));
- $parts[3] = bcdiv($decimal, '4294967296', 0);
- $decimal = bcsub($decimal, bcmul($parts[3], '4294967296'));
- $parts[4] = $decimal;
- }
- // otherwise use the pure PHP BigInteger
- else
- {
- $decimal = new MathBigInteger($decimal);
- list($parts[1],) = $decimal->divide(new MathBigInteger('79228162514264337593543950336'));
- $decimal = $decimal->subtract($parts[1]->multiply(new MathBigInteger('79228162514264337593543950336')));
- list($parts[2],) = $decimal->divide(new MathBigInteger('18446744073709551616'));
- $decimal = $decimal->subtract($parts[2]->multiply(new MathBigInteger('18446744073709551616')));
- list($parts[3],) = $decimal->divide(new MathBigInteger('4294967296'));
- $decimal = $decimal->subtract($parts[3]->multiply(new MathBigInteger('4294967296')));
- $parts[4] = $decimal;
- $parts[1] = $parts[1]->toString();
- $parts[2] = $parts[2]->toString();
- $parts[3] = $parts[3]->toString();
- $parts[4] = $parts[4]->toString();
- }
- foreach ($parts as &$part)
- {
- // convert any signed ints to unsigned for pack
- // this should be fine as it will be treated as a float
- if ($part > 2147483647)
- $part -= 4294967296;
- }
- $ip = inet_ntop(pack('N4', $parts[1], $parts[2], $parts[3], $parts[4]));
- // fix IPv4 by removing :: from the beginning
- if (strpos($ip, '.') !== false)
- return substr($ip, 2);
- return $ip;
- }
- }
- //example
- //echo inet_ptoi('::FFFF:FFFF:FFFF:FFFF') . "\n";
- //echo inet_ptoi('::FFFF:FFFF') . "\n";
- //echo inet_ptoi('255.255.255.255') . "\n";
- //echo inet_itop(inet_ptoi('::FFFF:FFFF:FFFF:FFFF')) . "\n";
- //echo inet_itop(inet_ptoi('::FFFF:FFFF')) . "\n";
- /* Output:
- 18446744073709551615
- 4294967295
- 4294967295
- ::ffff:ffff:ffff:ffff
- 255.255.255.255
- */
|