LINUX.ORG.RU
ФорумAdmin

Хранение IPv6 в Binary

 , , , ,


0

1

Доброй ночи. Нужна помощь. Произвольные IP адреса (IPv4, IPv6) преобразуются в двоичное представление с помощью inet_pton() на PHP и записываются в базу данных в поле BINARY(16). Поскольку версия базы данных в сферическом приближении не содержит функций INET_ATON() / INET_NTOA() для IPv6 (знаю что некоторые последние содержат, но далеко не везде они стоят) то MySQL запрос формируется костылем вида «x’».bin2hex($ip).«’» (ну либо UNHEX() - не принципиально).

Теперь о проблеме. Если адрес IPv4, то в базе первые 4 байта будут заполнены данными, остальные нулями. Итого если исходное значение переменной в бинарном виде (длина 4 байта) скормить функции inet_ntop - получается исходный IP адрес. Если этой же функции скормить 16-байтное значение с нулями, прочитанное из базы данных - оно преобразуется в IPv4 адрес вида aaaa:bbbb::

Использовать костыли вида

$back = inet_ntop(substr($bin,0,4));

(так - работает) с проверкой по сравнению хвоста строки с нуль-чарами не вариант. Как посоветуете решить данную проблему чтобы и IPv6 и IPv4 при чтении из базы подавались функции inet_ntop и на выходе всегда был корректный результат?



Последнее исправление: Dima_228 (всего исправлений: 1)

костыли

Если хочешь без костылей, конвертируй ipv4 в ipv6 (0:0:0:0:0:ffff:<ipv4>), и сохраняй. При вытаскивании можно преобразовывать обратно.

goingUp ★★★★★
()

Ну как тебе писали, то мапить в подсеть ::ffff:0:0/96. Тогда у тебя все адреса будут IPV6. Вот не знаю, правда, будет ли это очередной костыль. Нужно будет попробовать, конечно.

turtle_bazon ★★★★★
()
Ответ на: комментарий от turtle_bazon

То есть, грубо говоря, IPv4 дополнить нулями спереди, а не так как оно сейчас в MySQL дополняется сзади?

Dima_228
() автор топика

Что мешает хранить в виде текстовых строк? Нужно миллиарды адресов в одной базе держать и шерстить?

Harald ★★★★★
()
Ответ на: комментарий от Harald

Текстовые строки, тем более varchar, рано или поздно приведут к таблице на гигабайт, поиск по ней будет сильно тормозить систему. Я минимизирую размер хранимых данных.

Две колонки - думал над этим, сейчас именно так и реализовано (пишется INET_ATON в INT и все в BINARY) но мне нужен очень простой код на запись и простой на чтение. В идеале inet_ntop(hex2bin()) и обратно bin2hex(inet_pton()), все. Никаких проверок, IF’ов и так далее.

Вот тестовый кусок кода.

$ipv4 = 1481458231; $ipv6hex0 = «584d4237»; $ipv6hex1 = «584d4237000000000000000000000000»; $ipv6hex2 = «000000000000000000000000584d4237»; $ipv6hex3 = «00000000000000000000ffff584d4237»; echo long2ip($ipv4).«»; //возвращает 88.77.66.55 echo inet_ntop(hex2bin($ipv6hex0)).«»; //возвращает 88.77.66.55 echo inet_ntop(hex2bin($ipv6hex1)).«»; //возвращает 584d:4237:: echo inet_ntop(hex2bin($ipv6hex2)).«»; //возвращает ::88.77.66.55 echo inet_ntop(hex2bin($ipv6hex3)).«»; //возвращает ::ffff:88.77.66.55

Получается, это особенность работы функции inet_ntop() в PHP что ведущие нули преобразуются в ::, вместо того чтобы на выходе получать IPv4 в обычном формате?

Dima_228
() автор топика
Ответ на: комментарий от Dima_228

Прошу прощения, в коде кто-то сожрал переводы строк.

Dima_228
() автор топика
Ответ на: комментарий от Dima_228

ведущие нули преобразуются в ::

Это специфика нотации IPV6. Там оно в любом месте может преобразоваться - и в начале, и в середине, и в конце. Главное, чтобы не допускалась недоднозначность.

turtle_bazon ★★★★★
()
Ответ на: комментарий от Dima_228

Текстовые строки, тем более varchar, рано или поздно приведут к таблице на гигабайт, поиск по ней будет сильно тормозить систему.

Всё равно поиск будет по индексу, скорее всего. Так что зависит от того, как планируется вести поиск.

turtle_bazon ★★★★★
()
Ответ на: комментарий от Harald

Гигабайт это мало, но когда одна таблица разрастается до гигабайта и больше без partitioning - начинается белый и пушистый по производительности.

Преобразование двоичных данных в строковое читабельное представление IP адреса все таки решил костылем:

if (substr($bin, 4)==«\0\0\0\0\0\0\0\0\0\0\0\0»)

Либо inet_ntop передается вся строка, либо substr первые 4 байта. Конец истории. Из строки в двоичный код inet_pton нормально справляется.

Dima_228
() автор топика
Ответ на: комментарий от Dima_228

рано или поздно приведут к таблице на гигабайт, поиск по ней будет сильно тормозить систему. Я минимизирую размер хранимых данных.

Я такой фигней более 20-ти лет назад тоже занялся. Результат не самый прекрасный получился. При больших выборках обратное преобразование занимало много времени. Храните в char (не varchar).

anc ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.