Шаблон LEX для сопоставления сжатого текстового представления адреса IP версии 6 - PullRequest
0 голосов
/ 16 октября 2019

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

Я ищу шаблон LEX для адреса IP версии 6 только для адресов, представленных в сжатой текстовой форме. Эта форма описана в разделе 2.2 RFC 5952 (и, возможно, других связанных RFC) и представляет собой относительно небольшое подмножество всех возможных форматов адресов IPv6.

Если у кого-то есть такой, который хорошо протестированили в курсе одного, пожалуйста, перешлите его.

1 Ответ

1 голос
/ 18 октября 2019

RFC 5952 §2.2 формально не описывает сжатую форму адреса IPv6. Целью RFC 5952 является создание «канонической формы текстового представления»;то есть набор текстовых кодировок, который имеет отношение один к одному с набором адресов IPv6. Раздел 2.2 перечисляет несколько аспектов сжатой формы, которые приводят к опциям кодирования;каноническое представление должно исключать все опции.

Сжатый синтаксис фактически описан в пункте 2 RFC 4291 §2.2 . Этот синтаксис достаточно легко описать как регулярное выражение, хотя он немного раздражает;было бы проще в синтаксисе, который включает пересечение двух регулярных выражений (например, Ragel предоставляет этот оператор), но в этом случае достаточно простого перечисления возможностей.

Если вы действительно хотите ограничить совпаденияк каноническим представлениям, перечисленным в RFC 5952 §4.2 , тогда у вас есть немного более сложная задача из-за требования, что сжатый цикл 0 должен быть самым длинным циклом 0 в несжатом адресе или первымтакой прогон, если имеется более одного самого длинного прогона одинаковой длины.

Это было бы возможно, сделав намного более длинное перечисление допустимых форм, где сжатый прогон удовлетворяет ограничению «первый самый длинный». Но я действительно не уверен, что в создании этого монстра есть какая-то ценность, так как RFC 5952 совершенно ясно, что цель состоит в том, чтобы ограничить набор представлений , создаваемых соответствующим приложением (выделение добавлено):

… [A] ll реализации ДОЛЖНЫ принимать и иметь возможность обрабатывать любой допустимый RFC4291 формат.

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

IPv6-адрес, соответствующий пункту 1 RFC 4291 §2.2 можно легко описать в синтаксисе lex:

piece      [[:xdigit:]]{1,4}
%%
{piece}(:{piece}){7}      { /* an uncompressed IPv6 address */ }

Попутно, хотя это кажется ненужным по тем же причинам, указанным выше, очень просто ограничить {piece} каноническими 16-битными представлениями (только в нижнем регистре, без начальных нулей):

piece    0|[1-9a-f][0-9a-f]{0,3}

Сложность связана с требованием в пункте 2, чтобы только один прогон из 0 был соmpressed. Легко написать регулярное выражение, которое позволяет опустить только одно число:

(({piece}:)*{piece})?::({piece}(:{piece})*)?

, но эта формулировка больше не ограничивает число частей до 8. Также довольно легко написать регулярное выражение, которое позволяет опускатьштук, ограничивая количество полей:

{piece}(:{piece}?){1,6}:{piece}|:(:{piece}){1,7}|({piece}:){1,7}:|::

Что желательно, так это пересечение этих двух шаблонов плюс шаблон для несжатых адресов. Но, как уже упоминалось, нет возможности написать пересечения в (f) lex. Таким образом, мы заканчиваем перечислять возможности. Простое перечисление - это число исходных несжатых фрагментов:

(?x:  /* Flex's extended syntax allows whitespace and continuation lines */
    {piece}(:{piece}){7}
  | {piece}             ::{piece}(:{piece}){0,5}
  | {piece}:{piece}     ::{piece}(:{piece}){0,4}
  | {piece}(:{piece}){2}::{piece}(:{piece}){0,3}
  | {piece}(:{piece}){3}::{piece}(:{piece}){0,2}
  | {piece}(:{piece}){4}::{piece}(:{piece})?
  | {piece}(:{piece}){5}::{piece}
  | {piece}(:{piece}){0,6}::
  | ::{piece}(:{piece}){0,6}
  | ::
)

Это все еще исключает различные формы встраивания адресов IPv4 в IPv6, но должно быть понятно, как добавить их, если это необходимо.

...