Создайте список адресов IPv6 в заданном диапазоне - PullRequest
0 голосов
/ 04 апреля 2019

В таблице Maria DB у меня есть два поля varbinary(16), которые представляют адреса IPv6 для начала и конца диапазона IPv6.

Я хочу использовать PHP для циклического перехода между этим диапазоном и генерировать каждый адрес IPv6, которыйв пределах диапазона.Я пытался превратить двоичное в десятичное, чтобы сделать цикл и увеличить десятичное число, но цикл не производит итерации.

Любая помощь?

//The $IpStart_v6_FromDb/$IpStart_v6_End Vars are produced with INET6_ATON MariaDB function
$IpStartBin = decbin($IpStart_v6_FromDb);
$IpEndBin = decbin($IpEnd_v6_FromDb);
$ArIpRange = array();
$ArIpRange[] = $IpStartBin;
$x=0;
for(;;)
{
    if ($IpStartBin==$IpEndBin) break;
    $tLastIpBin = $ArIpRange[$x];
    $tNextIpBin = decbin( (bindec($tLastIpBin) + 1) );
    if ($tNextIpBin==$IpEndBin) break;
    $ArIpRange[] = $tNextIpBin;
    $x++;
}
foreach ($ArIpRange as $v)
{
    echo "<br>IP range item:<br>".base64_encode($v); //debug
}

[РЕДАКТИРОВАТЬ]

Мне стыдно сказать, что я думал, что длина адреса IPv6 составляет 64 бита.

1 Ответ

1 голос
/ 04 апреля 2019

Итак, простое устранение неполадок или чтение руководства сказали бы, что decbin ожидает целое число в качестве входных данных.Так что сразу же вы получаете ноль обратно для обеих переменных.

Более того, даже если вы действительно исправили эту проблему (используя bindec,), вы говорите о 128-битных числах, которые, если толькоВы из будущего, не то, что PHP может обрабатывать изначально.

Я бы предложил обрабатывать их как строки.Сначала нормализуйте их (заполните пропущенные нули и замените :: нулями), используя код из этого ответа , найдите и удалите соответствующий префикс, используя код из этого ответа , а затем разберитесь сотдохните, преобразовав их в гораздо меньшие числа.

И, как уже упоминалось в комментариях, убедитесь, что вы не пытаетесь работать с слишком большим диапазоном, иначе ваш сервер будет несчастлив.

<?php
// https://stackoverflow.com/a/55521768/1255289
// Generate a list of IPv6 addresses within a given range

function expand_ipv6(string $ip): ?string
{
    // https://stackoverflow.com/a/12095836/1255289
    $hex = unpack("H*", inet_pton($ip))[1] ?? "";
    return (strlen($hex) === 32) ? implode(":", str_split($hex, 4)) : null;
}

$IpStart_v6_FromDb = "2001:db8::1234";
$IpEnd_v6_FromDb = "2001:db8::1299";

$ip1 = expand_ipv6($IpStart_v6_FromDb);
$ip2 = expand_ipv6($IpEnd_v6_FromDb);
if ($ip1 === null || $ip2 === null) {
    die;
}

// https://stackoverflow.com/a/35838357/1255289
// length is 39 to account for 7 colons
for ($i = 0; $i < 39 && $ip1[$i] === $ip2[$i]; $i++);

$ipv6_prefix = substr($ip1, 0, $i);
$ipv6_start = hexdec(substr($ip1, $i));
$ipv6_end = hexdec(substr($ip2, $i));

if (strlen($ipv6_prefix) < 26) {
    // adjust this to requirements to prevent too large ranges
    die;
}

for ($a = $ipv6_start; $a <= $ipv6_end; $a++) {
    $hex = dechex($a);
    printf("%s%s\n", $ipv6_prefix, implode(":", str_split($hex, 4)));
}
...