Метод хранения адресов IPv6 и как всем этим пользоваться?

Технические вопросы по UTM 5.0
Ответить
taf
Сообщения: 309
Зарегистрирован: Вс янв 30, 2005 11:41

Метод хранения адресов IPv6 и как всем этим пользоваться?

Сообщение taf »

Добрый день!

По условиям задачи требуется получать адреса из базы напрямую. Пока все было на IPv4, проблем небыло, и вот настала пора IPv6 и тут...

Кто-нибудь реализовывал выборку IPv6 в человеческом виде из базы напрямую? Проблема в том, что первые 64-бита адреса хранятся в поле ip_ext, младшие 64-бит в поле ip (это пример из ip_groups)

taf
Сообщения: 309
Зарегистрирован: Вс янв 30, 2005 11:41

Сообщение taf »

В общем, пришлось колхозить в скрипте такие конструкции:

Код: Выделить всё

    $proto = 0;
    if ($ip_ext == 0)
    {
        $proto = 4;
        $a = sprintf("%u.%u.%u.%u",
                                     (($ip>>24) & 255),
                                     (($ip>>16) & 255),
                                     (($ip>>8)  & 255),
                                     ( $ip      & 255));
        $m = sprintf("%u.%u.%u.%u",
                                       (($mask>>24) & 255),
                                       (($mask>>16) & 255),
                                       (($mask>>8)  & 255),
                                       ( $mask      & 255));
        $addr = NetAddr::IP::Lite->new($a."/".$m);
    }
    else
    {
        $proto = 6;
        $a = sprintf("%x:%x:%x:%x:%x:%x:%x:%x",
                                                 (($ip_ext>>48) & 65535),
                                                 (($ip_ext>>32) & 65535),
                                                 (($ip_ext>>16) & 65535),
                                                 ( $ip_ext      & 65535),
                                                 (($ip>>48) & 65535),
                                                 (($ip>>32) & 65535),
                                                 (($ip>>16) & 65535),
                                                 ( $ip      & 65535));
        $m = sprintf("%x:%x:%x:%x:%x:%x:%x:%x",
                                                   (($mask_ext>>48) & 65535),
                                                   (($mask_ext>>32) & 65535),
                                                   (($mask_ext>>16) & 65535),
                                                   ( $mask_ext      & 65535),
                                                   (($mask>>48) & 65535),
                                                   (($mask>>32) & 65535),
                                                   (($mask>>16) & 65535),
                                                   ( $mask      & 65535));
        $addr = NetAddr::IP::Lite->new6($a."/".$m);
    }

Аватара пользователя
Magnum72
Сообщения: 1947
Зарегистрирован: Чт сен 22, 2005 06:54
Контактная информация:

Сообщение Magnum72 »

Код: Выделить всё

SELECT 
  ipg.ip_group_id,
  LOWER(
    CONCAT(
      IF (
        ipg.ip_ext != 0,
        CONCAT_WS(
          ':',
          SUBSTR(LPAD(HEX(ipg.ip_ext), 16, '0'), 1, 4),
          SUBSTR(LPAD(HEX(ipg.ip_ext), 16, '0'), 5, 4),
          SUBSTR(LPAD(HEX(ipg.ip_ext), 16, '0'), 9, 4),
          RIGHT(LPAD(HEX(ipg.ip_ext), 16, '0'), 4)
        ),
        ""
      ),
      IF (
        ipg.ip_ext != 0,
        CONCAT_WS(
          ':',
          SUBSTR(LPAD(HEX(ipg.ip), 16, '0'), 1, 4),
          SUBSTR(LPAD(HEX(ipg.ip), 16, '0'), 5, 4),
          SUBSTR(LPAD(HEX(ipg.ip), 16, '0'), 9, 4),
          RIGHT(LPAD(HEX(ipg.ip), 16, '0'), 4)
        ),
        INET_NTOA(ipg.ip & 0xffffffff)
      )
    )
  ) AS ip 
FROM
  UTM5.ip_groups AS ipg;

taf
Сообщения: 309
Зарегистрирован: Вс янв 30, 2005 11:41

Сообщение taf »

Доработаный для PG вариант с хранимой процедурой:

Код: Выделить всё

CREATE FUNCTION inet_ntoa_ipv6(ip bigint, ip_ext bigint) RETURNS text
    LANGUAGE sql
    AS $_$

SELECT
    LOWER(
        CONCAT(
            CASE
                WHEN ip_ext != 0 THEN
                CONCAT_WS(
                    ':',
                    SUBSTR(LPAD(TO_HEX(ip_ext), 16, '0'), 1, 4),
                    SUBSTR(LPAD(TO_HEX(ip_ext), 16, '0'), 5, 4),
                    SUBSTR(LPAD(TO_HEX(ip_ext), 16, '0'), 9, 4),
                    RIGHT(LPAD(TO_HEX(ip_ext), 16, '0'), 4)
                )
            END,
            CASE
                WHEN ip_ext != 0 THEN
                    ':'
            END,
            CASE
                WHEN ip_ext != 0 THEN
                CONCAT_WS(
                    ':',
                    SUBSTR(LPAD(TO_HEX(ip), 16, '0'), 1, 4),
                    SUBSTR(LPAD(TO_HEX(ip), 16, '0'), 5, 4),
                    SUBSTR(LPAD(TO_HEX(ip), 16, '0'), 9, 4),
                    RIGHT(LPAD(TO_HEX(ip), 16, '0'), 4)
                )
                ELSE INET_NTOA(ip & x'ffffffff'::bigint)
            END
        )
    )
    as result
$_$;
пример запроса:

Код: Выделить всё

select
    inet_ntoa_ipv6(ip, ip_ext) as ip,
    inet_ntoa_ipv6(mask, mask_ext) as mask
from
    ip_groups
where
    uname ='USER_LOGIN' and is_deleted=0;

Аватара пользователя
Magnum72
Сообщения: 1947
Зарегистрирован: Чт сен 22, 2005 06:54
Контактная информация:

Сообщение Magnum72 »

Функция для MySQL

Код: Выделить всё

DROP FUNCTION net_ntoa_ipv6;

DELIMITER $$

CREATE DEFINER = root@localhost FUNCTION `net_ntoa_ipv6` (ip BIGINT, ip_ext BIGINT) RETURNS CHAR(48) CHARSET utf8 COLLATE utf8_unicode_ci DETERMINISTIC 
BEGIN

  # Example: SELECT net_ntoa_ipv6(ip,ip_ext) FROM UTM5.ip_groups;

  SELECT 
    LOWER(
      CONCAT(
        IF (
          ip_ext != 0,
          CONCAT_WS(
            ':',
            SUBSTR(LPAD(HEX(ip_ext), 16, '0'), 1, 4),
            SUBSTR(LPAD(HEX(ip_ext), 16, '0'), 5, 4),
            SUBSTR(LPAD(HEX(ip_ext), 16, '0'), 9, 4),
            RIGHT(LPAD(HEX(ip_ext), 16, '0'), 4)
          ),
          ""
        ),
        IF (ip_ext != 0, ':', ""),
        IF (
          ip_ext != 0,
          CONCAT_WS(
            ':',
            SUBSTR(LPAD(HEX(ip), 16, '0'), 1, 4),
            SUBSTR(LPAD(HEX(ip), 16, '0'), 5, 4),
            SUBSTR(LPAD(HEX(ip), 16, '0'), 9, 4),
            RIGHT(LPAD(HEX(ip), 16, '0'), 4)
          ),
          INET_NTOA(ip & 0xffffffff)
        )
      )
    ) AS result INTO @result ;
  RETURN @result ;
END $$
DELIMITER ;
Последний раз редактировалось Magnum72 Ср мар 23, 2016 13:13, всего редактировалось 1 раз.

taf
Сообщения: 309
Зарегистрирован: Вс янв 30, 2005 11:41

Сообщение taf »

Или в MySQL CONCAT_WS работает иначе, чем в PG, или в вашем случае 4-й и 5-й слипнутся без разделительного ":"

Аватара пользователя
Magnum72
Сообщения: 1947
Зарегистрирован: Чт сен 22, 2005 06:54
Контактная информация:

Сообщение Magnum72 »

Поправил, спасибо.

Ответить