2016-10-18 6 views
0

Я ищу оператор выбора, который проверяет, находятся ли 2 IP-адреса в одной подсети, в зависимости от того, сколько бит в главной части маски. Я нашел this excellent question и отвечаю, но он работает только для адресов IPv4.Убедитесь, что два адреса IPv6 в одной подсети с использованием MySQL

Мое заявление MySQL для IPv4 выглядит следующим образом, где 3 это количество бит в принимающей части маски (21 бит сети):

SELECT FROM table WHERE ((-1 << 3) & INET_ATON(IPADDRESS1) = (-1 << 3) & INET_ATON(IPADDRESS2)) 

Можно ли создать аналог IPv6? (Это за пределами моей попытки даже). Я понимаю, что есть INET6_ATON, но -1, который я использую для создания маски 1 выше, не будет работать (из-за длины), а также, вероятно, по другим причинам.

Если это помогает, мы можем предположить, что адрес IPv6 находится в формате RFC 5952 или в полных 8 разделенных двоеточиями.

+0

я буду свистеть Рику на его соответствующий ответ [здесь] (http://dba.stackexchange.com/a/104844) – Drew

+0

Ссылка, предоставленная Дрю, может быть более актуальной, чем мой ответ ниже. Сообщите мне, нужны ли вам дополнительные рекомендации. –

ответ

0

У вас здесь есть ряд проблем. Большинство ответов: here и в reference implementation for IPv6

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

  • Ссылки относятся к эффективному способу обработки неперекрывающихся диапазонов, таких как IP-адреса. Тем не менее, часть решения состоит в том, чтобы иметь возможность добавлять/вычитать 1 из 128-битного значения. См. Функции IpIncr и IpDecr.

  • Для создания маски я бы рекомендовал преобразовать в шестнадцатиричный символ, а затем сыграть с подстроками. См. CONCAT, LEFT, RIGHT, REPEAT и т. Д. После того, как вы это сделали, сравнения строк должны легко обрабатывать проверку «в сети».

код будет проще в MySQL 8.0, поскольку BLOBs можно рассматривать как очень длинные битовые строки; ранее бит материал был ограничен BIGINT, что недостаточно для IPv6.

+0

Я прочитал ваш связанный ответ ... и не могу превратить это в решение (я еще не так умею). Я могу создать таблицу с бинарным (16) col всех возможных сетевых масок (128). Но как я могу превратить ваш оператор WHERE в select, который проверяет 2 IP-адреса в одной подсети X бит? – TSG

+0

Да, настольный звук выглядит практичным для создания маски. ('SELECT @mask: = mask FROM Masks WHERE bits = ...') Ссылка Drew показала, как протестировать ее (используя '@ mask'). Сделайте 'mask'' BINARY (32) '. –

+0

Надеюсь на что-то более простое ... будет ли это работать (если я сделаю строку 128 '1'): INET6_ATON (IPADD1) & (INET6_ATON ("1111..11") << 3) = INET6_ATON (IPADD2) & (INET6_ATON («1111..11») << 3) – TSG

0

У меня есть решение, когда адреса хранятся в виде строк.

Аналогичная проблема заключается в том, чтобы найти все адреса в базе данных, принадлежащие определенной подсети, что довольно похоже на проблему, указанную здесь, чтобы проверить, находятся ли два адреса в одной подсети.

Это немного сложно, особенно для IPv6. В IPv6 могут быть необязательно сжатые сегменты, такие как 1: 1, что эквивалентно 1: 0: 0: 0: 0: 0: 0: 1, что является основной причиной, по которой это сложно.

The IPAddress Java library произведет mysql SQL для поиска адресов в данной подсети. Ссылка описывает эту проблему более подробно. Отказ от ответственности: Я руководитель проекта.

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

Вот пример кода:

public static void main(String[] args) throws IPAddressStringException { 
    System.out.println(getSearchSQL("columnX", "1.2.3.4/16")); 
    System.out.println(getSearchSQL("columnX", "1:2:3:4:5:6:7:8/64")); 
    System.out.println(getSearchSQL("columnX", "1::8/64")); 
} 

static String getSearchSQL(String expression, String ipAddressStr) throws IPAddressStringException { 
    IPAddressString ipAddressString = new IPAddressString(ipAddressStr); 
    IPAddress ipAddress = ipAddressString.toAddress(); 
    IPAddressSection networkPrefix = ipAddress.getNetworkSection(ipAddress.getNetworkPrefixLength(), false); 
    StringBuilder sql = new StringBuilder("Select rows from table where "); 
    networkPrefix.getStartsWithSQLClause(sql, expression); 
    return sql.toString(); 
} 

Ouptut:

Select rows from table where (substring_index(columnX,'.',2) = '1.2') 
Select rows from table where (substring_index(columnX,':',4) = '1:2:3:4') 
Select rows from table where ((substring_index(columnX,':',4) = '1:0:0:0') OR ((substring_index(columnX,':',2) = '1:') AND (LENGTH (columnX) - LENGTH(REPLACE(columnX, ':', '')) <= 5))) 
+0

Я мог бы сделать это за пределами MySQL тоже (используя PHP), но моя цель состояла в том, чтобы делать это исключительно в MySQL (иначе поисковая нагрузка будет высокой) – TSG

 Смежные вопросы

  • Нет связанных вопросов^_^