Intereting Posts
Как разобрать необработанные данные POST в массив? FatalErrorException: Ошибка: вызов функции-члена имеет () для не-объекта регулярное выражение php для соответствия определенному шаблону url Пример теста PHPUnit на Laravel 5.4 не работает с 404 позволить пользователю изменить свой собственный пароль? Перейдите на PHP 5.4 на MAC и удалите версию 5.3.10 Почему этот PHP-код (комета) не работает? ffmpeg Progress Bar – Процент кодирования в PHP Как подключить Google и разрешить моему пользователю приглашать своих контактов Мягкое удаление Каскадирование с помощью Laravel 5.2 Как проверить, имеет ли строка хотя бы одну букву, номер и специальный символ в php Извлечь X количество слов, окружающих заданную строку поиска внутри строки Запустите PHP-код, когда пользователь нажимает ссылку и передает переменные amazon CloudWatchLogs putLogEvents Ошибка: класс «Facebook \ FacebookSession» не найден с помощью фанкойла PHP SDK

PHP5 вычисляет диапазон IPv6 от префикса cidr?

Я могу сделать это с помощью IPv4, используя фрагменты кода из различных онлайн-источников. Мне было интересно, есть ли способ сделать это с помощью IPv6.

В принципе мне просто нужна форма, в которой я могу ввести адрес и префикс IPv6 (например: адрес / 68), и он вычисляет сетевой адрес, первый полезный адрес, последний полезный адрес и широковещательный адрес. Затем просто печатает на экране. Не хотите хранить его в базе данных или что-то еще.

Как мне это сделать?

Спасибо всем заранее!

Прежде всего: IPv6 не имеет сетевых и широковещательных адресов. Вы можете использовать все адреса в префиксе. Второе: в локальной сети длина префикса всегда (ну, 99.x% времени) a / 64. Маршрутизация a / 68 приведет к поломке функций IPv6, таких как автоматическая настройка без сохранения состояния.

Ниже приведена подробная версия префиксного калькулятора IPv6:

<?php /* * This is definitely not the fastest way to do it! */ // An example prefix $prefix = '2001:db8:abc:1400::/54'; // 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 $firstaddrhex = reset(unpack('H*', $firstaddrbin)); // 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); // Report to user echo "Prefix: $prefix\n"; echo "First: $firstaddrstr\n"; echo "Last: $lastaddrstr\n"; ?> 

Он должен выводить:

 Prefix: 2001:db8:abc:1400::/54 First: 2001:db8:abc:1400:: Last: 2001:db8:abc:17ff:ffff:ffff:ffff:ffff 

Для тех, кто спотыкается на этот вопрос, вы можете сделать это более эффективно, используя функции dtr_pton и dtr_ntop и класс dTRIP найденный в GitHub .

Мы также заметили отсутствие фокуса и инструментов с IPv6 в PHP и собрали эту статью, http://www.highonphp.com/5-tips-for-working-with-ipv6-in-php , что может быть помощи другим.

Источник функции

Это преобразует и IP в двоичное представление:

 /** * dtr_pton * * Converts a printable IP into an unpacked binary string * * @author Mike Mackintosh - mike@bakeryphp.com * @param string $ip * @return string $bin */ function dtr_pton( $ip ){ if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)){ return current( unpack( "A4", inet_pton( $ip ) ) ); } elseif(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)){ return current( unpack( "A16", inet_pton( $ip ) ) ); } throw new \Exception("Please supply a valid IPv4 or IPv6 address"); return false; } 

Это преобразует двоичное представление в печатный IP:

 /** * dtr_ntop * * Converts an unpacked binary string into a printable IP * * @author Mike Mackintosh - mike@bakeryphp.com * @param string $str * @return string $ip */ function dtr_ntop( $str ){ if( strlen( $str ) == 16 OR strlen( $str ) == 4 ){ return inet_ntop( pack( "A".strlen( $str ) , $str ) ); } throw new \Exception( "Please provide a 4 or 16 byte string" ); return false; } 

Примеры

Используя функцию dtr_pton вы можете:

 $ip = dtr_pton("fe80:1:2:3:a:bad:1dea:dad"); $mask = dtr_pton("ffff:ffff:ffff:ffff:ffff:fff0::"); 

Получите свою сеть и трансляцию:

 var_dump( dtr_ntop( $ip & $mask ) ); var_dump( dtr_ntop( $ip | ~ $mask ) ); 

И ваш результат будет:

 string(18) "fe80:1:2:3:a:ba0::" string(26) "fe80:1:2:3:a:baf:ffff:ffff" 

Ну, для потомков я добавляю свой code здесь. А также благодаря вам, ребята, которые помогли мне прибить это, поскольку мне это было нужно для скрипта ipv6 / ip2country .

Это немного вдохновило код, размещенный здесь by @ mikemacintosh и @ Sander Steffann , немного улучшенный (витиеватое мышление) и возвращает хороший объект, который упаковывает все данные, которые вам нужны / не нужны:

 /** * This: * <code> * Ipv6_Prefix2Range('2001:43f8:10::/48'); * </code> * returns this: * <code> * object(stdClass)#2 (4) { * ["Prefix"]=> * string(17) "2001:43f8:10::/48" * ["FirstHex"]=> * string(32) "200143f8001000000000000000000000" * ["LastHex"]=> * string(32) "200143f80010ffffffffffffffffffff" * ["MaskHex"]=> * string(32) "ffffffffffff00000000000000000000" * // Optional bin equivalents available * } * </code> * * Tested against: * @link https://www.ultratools.com/tools/ipv6CIDRToRange * * @param string $a_Prefix * @param bool $a_WantBins * @return object */ function Ipv6_Prefix2Range($a_Prefix, $a_WantBins = false){ // Validate input superficially with a RegExp and split accordingly if(!preg_match('~^([0-9a-f:]+)[[:punct:]]([0-9]+)$~i', trim($a_Prefix), $v_Slices)){ return false; } // Make sure we have a valid ipv6 address if(!filter_var($v_FirstAddress = $v_Slices[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)){ return false; } // The /## end of the range $v_PrefixLength = intval($v_Slices[2]); if($v_PrefixLength > 128){ return false; // kind'a stupid :) } $v_SuffixLength = 128 - $v_PrefixLength; // Convert the binary string to a hexadecimal string $v_FirstAddressBin = inet_pton($v_FirstAddress); $v_FirstAddressHex = bin2hex($v_FirstAddressBin); // Build the hexadecimal string of the network mask // (if the manually formed binary is too large, base_convert() chokes on it... so we split it up) $v_NetworkMaskHex = str_repeat('1', $v_PrefixLength) . str_repeat('0', $v_SuffixLength); $v_NetworkMaskHex_parts = str_split($v_NetworkMaskHex, 8); foreach($v_NetworkMaskHex_parts as &$v_NetworkMaskHex_part){ $v_NetworkMaskHex_part = base_convert($v_NetworkMaskHex_part, 2, 16); $v_NetworkMaskHex_part = str_pad($v_NetworkMaskHex_part, 2, '0', STR_PAD_LEFT); } $v_NetworkMaskHex = implode(null, $v_NetworkMaskHex_parts); unset($v_NetworkMaskHex_part, $v_NetworkMaskHex_parts); $v_NetworkMaskBin = inet_pton(implode(':', str_split($v_NetworkMaskHex, 4))); // We have the network mask so we also apply it to First Address $v_FirstAddressBin &= $v_NetworkMaskBin; $v_FirstAddressHex = bin2hex($v_FirstAddressBin); // Convert the last address in hexadecimal $v_LastAddressBin = $v_FirstAddressBin | ~$v_NetworkMaskBin; $v_LastAddressHex = bin2hex($v_LastAddressBin); // Return a neat object with information $v_Return = array( 'Prefix' => "{$v_FirstAddress}/{$v_PrefixLength}", 'FirstHex' => $v_FirstAddressHex, 'LastHex' => $v_LastAddressHex, 'MaskHex' => $v_NetworkMaskHex, ); // Bins are optional... if($a_WantBins){ $v_Return = array_merge($v_Return, array( 'FirstBin' => $v_FirstAddressBin, 'LastBin' => $v_LastAddressBin, 'MaskBin' => $v_NetworkMaskBin, )); } return (object)$v_Return; } 

Мне нравятся функции и классы и не нравится код, который нельзя использовать повторно, где реализована функция повторного использования.

PS : Если вы найдете проблемы с этим, пожалуйста, вернитесь ко мне. Я далеко от эксперта по IPv6.