Признаются ли срочные данные TCP?

В сегменте tcp с флагом URG могут быть и обычные данные. Как принимающий хост обрабатывает срочный пакет? Как он подтверждает срочные данные, если они не являются частью потока данных? Это признает остальное?

Я понимаю, что он обычно не используется, но если оба хоста поддерживают один и тот же RFC относительно флага URG, как они обрабатывают внеполосные данные?

Если срочными данными является сообщение об отмене, получатель отбросит все остальные данные, но отправителю все равно потребуется подтверждение о получении сообщения.

1 ответ

Решение

Немного предыстории:

Срочный механизм TCP позволяет определить точку в потоке данных как конец срочной информации. Таким образом, у нас есть Urgent Pointer, который содержит положительное смещение от порядкового номера в этом сегменте tcp. Это поле имеет значение только с установленным битом управления URG.


Расхождения по срочному указателю:

RFC 793 (1981, стр. 17):

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

RFC 1011 (1987, стр. 8):

Страница 17 не так. Указатель срочности указывает на последний октет срочных данных (не на первый октет несрочных данных).

То же самое в RFC 1122 (1989, стр. 84):

... указатель срочности указывает на порядковый номер октета LAST (не LAST+1) в последовательности срочных данных.

В понятном RFC 6093 (2011, стр. 6-7) говорится:

Принимая во внимание, что до тех пор, пока отправитель TCP и получатель TCP реализуют одинаковую семантику для указателя Urgent, нет никакой функциональной разницы в том, чтобы указатель Urgent указывал на "порядковый номер октета после срочных данных" против "последнего" октет срочных данных ", и что все известные реализации интерпретируют семантику срочного указателя как указывающую на" порядковый номер октета, следующего за срочными данными ".

Таким образом, обновление RFC 793, RFC 1011 и RFC 1122

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

Он соответствует практически всем существующим реализациям TCP.

Примечание: Linux предоставляет net.ipv4.tcp_stdurgsysctl переопределить поведение по умолчанию, но это sysctl влияет только на обработку входящих сегментов. Срочный указатель в исходящих сегментах будет по-прежнему установлен в соответствии с RFC 793.


Об обработке данных

Вы можете получить срочные данные двумя способами (имейте в виду, что концепция TCP "срочные данные" отображается в API сокета как "данные вне диапазона"):

  • с помощью recv с MSG_OOB флаг установлен. (обычно вы должны установить право собственности на сокет с чем-то вроде fcntl(sock, F_SETOWN, getpid()); и установить обработчик сигнала для SIGURG). Таким образом, вы будете уведомлены с SIGURG сигнал. Данные будут прочитаны отдельно от обычного потока данных.
  • с помощью recv без MSG_OOB флаг установлен. Ранее вы должны установить SO_OOBINLINE Опция сокета такая:

    int so_oobinline = 1; /* true */
    setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, &so_oobinline, sizeof so_oobinline);

    Данные остаются "встроенными". И вы можете определить срочно указатель с помощью ioctl:

    int flag; /* True when at mark */
    ioctl(sock, SIOCATMARK, &flag);

Кроме того, для новых приложений рекомендуется вообще не использовать механизм срочных данных, чтобы использовать (если это так) прием в режиме реального времени, как упоминалось выше.
Из RFC 1122:

Срочный механизм TCP НЕ является механизмом отправки "внеполосных" данных: так называемые "срочные данные" должны доставляться "в линию" пользователю TCP.

Также из RFC 793:

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

Таким образом, вы можете справиться, как вы хотите. Это проблема уровня приложения.

Соответственно, ответ на ваш вопрос о подтверждениях, когда все другие данные были отброшены, звучит так: "Вы можете реализовать их в своем приложении".
Что касается tcp-ack, я не нашел ничего особенного в случае срочных данных.



О длине "Срочных данных"

Практически все реализации действительно могут предоставить только один байт "внеполосных данных".
RFC 6093 говорит:

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

Таким образом, режим срочности TCP и его указатель срочности не могут обеспечить маркировку границ срочных данных на практике.
Ходят слухи, что есть некоторые реализации, которые ставят в очередь каждый из полученных срочных байтов. Известно, что некоторые из них не обеспечивают каких-либо ограничений на количество "срочных данных", которые они ставят в очередь. Таким образом, они становятся уязвимыми для тривиальных атак исчерпания ресурсов.


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


Еще несколько полезных ссылок:
TCP Urgent Pointer, управление буфером и вызов "Отправить"
Разница между push и срочными флагами в TCP
Понимание срочного указателя

Другие вопросы по тегам