Как отличить расширение от заголовка верхнего уровня

Я пытаюсь проанализировать пакет IPv6, полученный через необработанный сокет, и решить, является ли он ICMPv6 или нет. Я могу обрабатывать заголовки Ethernet и IPv6, но есть необязательные заголовки расширения. Если поле Next Header заголовка IPv6 не равно ICMPv6, мне нужно перебрать все расширения, которые могут предшествовать.

Сама итерация не является проблемой, поскольку каждый заголовок расширения имеет свою длину. Однако я не могу найти хороший способ отличить заголовок расширения, который может следовать, от других протоколов верхнего уровня, таких как TCP и UDP. Я могу либо проверить, является ли Next Header одним из известных заголовков расширения (в этом случае я могу выполнить итерацию), либо является ли Next Header протоколом верхнего уровня (в этом случае мне придется остановиться, поскольку ICMP< /эм>..).

В обоих подходах я полагаюсь на какой-то самостоятельный список констант, по которым я проверяю Next Header, и этот список может измениться в будущем. Разве нет лучшего способа узнать, когда я нахожусь в конце заголовков расширения, а за ним следует заголовок верхнего уровня (или ничего)?


person Raven    schedule 16.02.2017    source источник
comment
К сожалению, невозможно определить, что означает неизвестное следующее значение заголовка. Вам придется полагаться на таблицы в вашем коде.   -  person Sander Steffann    schedule 17.02.2017


Ответы (2)


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


Обновление:

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

Однако существует только 256 возможных значений, поэтому можно знать, какое из них возможно. Однако будьте осторожны: почти половина доступных кодов в настоящее время не назначена, но в будущем может быть назначена либо типам расширенных заголовков, либо типам протоколов. До тех пор, пока коды не будут исчерпаны, ваше программное обеспечение должно будет распознавать три категории:

  • заголовок расширения,
  • заголовок протокола и
  • неизвестно.

Кроме того, что касается реализации такого теста, я бы рекомендовал создать и использовать таблицу поиска вместо построения сложного условного выражения. Что-то в этом роде:

enum header_type { HDR_PROTOCOL, HDR_EXTENSION, HDR_UNKNOWN };

const enum header_type header_types[256] = {
    [0x00] = HDR_EXTENSION,  // IPv6 hop-by-hop option
    [0x01] = HDR_PROTOCOL,   // ICMP
    // ... both extension and protocol headers in this range ...
    [0x8e] = HDR_PROTOCOL,   // robust header compression
    [0x8f] = HDR_UNKNOWN,    // unassigned
    // ... more unassigned ...
    [0xfd] = HDR_UNKNOWN,    // for experimentation
    [0xfe] = HDR_UNKNOWN,    // for experimentation
    [0xff] = HDR_UNKNOWN,    // reserved
};

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

person John Bollinger    schedule 16.02.2017
comment
Кроме того, IANA поддерживает список возможных значений протокола IPv4 / следующего заголовка IPv6 (всего 256 возможных значений) по адресу Назначенные номера интернет-протокола. - person Ron Maupin; 17.02.2017
comment
Теперь я вижу, что не сказал, что уже просматриваю поле Next Header заголовка расширения. Проблема еще в том, что я искал какой-то стандартный способ узнать, будет ли следующий заголовок тоже расширением или нет. Как указал @RonMaupin, значений не так много, поэтому я написал такую ​​функцию pastebin.com/SXeshCmA, но я надеялся на лучший подход. - person Raven; 17.02.2017
comment
@Raven, я обновил этот ответ информацией и рекомендациями, касающимися вашего исправленного вопроса. - person John Bollinger; 17.02.2017

Там действительно нечего делать, кроме как ходить по цепи, и похоже, что это то, что вы делаете. Как вы спрашиваете в своем комментарии, «стандартный способ узнать, будет ли следующий заголовок также расширением или нет», — если это одно из значений, которое означает, что это заголовок расширения IPv6. Первоначально, за исключением заголовка расширения Hop-by-hop (который игнорируется большинством сетевых администраторов, поскольку не рекомендуется позволять конечным устройствам диктовать маршрутизацию), все промежуточные узлы (маршрутизаторы и т. д.) должны были игнорировать заголовки расширения:

За одним исключением заголовки расширений не проверяются и не обрабатываются ни одним узлом на пути доставки пакета, пока пакет не достигнет узла (или каждого из набора узлов в случае многоадресной рассылки), указанного в поле адреса назначения протокола IPv6. заголовок. Там обычное демультиплексирование в поле «Следующий заголовок» заголовка IPv6 вызывает модуль для обработки первого заголовка расширения или заголовка верхнего уровня, если заголовок расширения отсутствует. Содержимое и семантика каждого заголовка расширения определяют, следует ли переходить к следующему заголовку. Поэтому заголовки расширения должны обрабатываться строго в том порядке, в котором они появляются в пакете; получатель не должен, например, сканировать пакет в поисках определенного типа заголовка расширения и обрабатывать этот заголовок до обработки всех предыдущих.

Исключением, упомянутым в предыдущем абзаце, является заголовок Hop-by-Hop Options, который содержит информацию, которая должна быть проверена и обработана каждым узлом на пути доставки пакета, включая исходный и конечный узлы. Заголовок Hop-by-Hop Options, если он присутствует, должен следовать сразу за заголовком IPv6. На его присутствие указывает нулевое значение в поле «Следующий заголовок» заголовка IPv6.

Если в результате обработки заголовка узлу требуется перейти к следующему заголовку, но значение «Следующий заголовок» в текущем заголовке не распознано узлом, он должен отбросить пакет и отправить источнику сообщение ICMP Parameter Problem. пакета со значением кода ICMP, равным 1 ("обнаружен нераспознанный тип следующего заголовка"), и полем указателя ICMP, содержащим смещение нераспознанного значения в исходном пакете. То же самое действие должно быть предпринято, если узел встречает нулевое значение Next Header в любом заголовке, кроме заголовка IPv6.

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

RFC 6564, Единый формат заголовков расширений IPv6 пытается некоторые заказывают заголовки расширения IPv6, но, к сожалению, ничего не могут сделать с ранее определенными заголовками расширения IPv6.

В RFC 7045, Передача и обработка заголовков расширений IPv6 обсуждаются проблемы, связанные с Заголовки расширения IPv6.

person Ron Maupin    schedule 17.02.2017