Программа должна проанализировать данные со стандартного ввода, полученные с помощью вызова команды tcpdump -x -n tcp, которая перехватывет, декодирует и представляет в промежуточном формате набор входящих и исходящих сетевых пакетов протокола TCP. Примерный вывод tcpdump:
... 10:42:23.181592 IP 149.154.167.41.https > 10.0.220.4.41356: Flags [.], ack 530, win 18195, length 0 0x0000: 4500 0028 c74d 4000 3906 57ba 959a a729 0x0010: 0a00 dc04 01bb a18c d0be 0b07 34d1 d3db 0x0020: 5010 4713 be3e 0000 0000 0000 0000 10:42:23.844093 IP 149.154.167.41.https > 10.0.220.4.41356: Flags [P.], seq 106:211, ack 530, win 18195, length 105 0x0000: 4500 0091 c74e 4000 3906 5750 959a a729 0x0010: 0a00 dc04 01bb a18c d0be 0b07 34d1 d3db 0x0020: 5018 4713 a7cb 0000 076a 2240 eb53 fa3b 0x0030: 6e8f b8b3 ba56 35ca e33f 3312 8528 582d 0x0040: d444 5c78 d0b5 c1d2 2459 8847 d3b8 2b09 0x0050: 45c2 f5c1 4fe5 0298 2f9d d6c6 ad52 2100 0x0060: 1627 6600 aeca e084 1abe 155e 3864 353f 0x0070: 0b0a ff73 244a c789 4a2b 9ecd 6a25 366e 0x0080: 2037 6191 72ef d0b2 b027 c58c bfca 2e5b 0x0090: d8 ...Первая строка каждого пакета сформирована в человекочитаемом формате и кратко описывает содержимое пакета. Последующие строки начинаются с табуляции и формируют содержимое пакета в шестнадцатиричном виде. По правилам сетевого формата данных многобайтовые целочисленные значения расположены в оперативной памяти в формате big-endian (https://ru.wikipedia.org/wiki/Порядок_байтов), что подразумевает, например, что машинное слово 0x4500 в оперативной памяти сначала хранит старший байт 0x45, а затем - младший байт 0x00. Пакет начинается с заголовка IP-протокола, структура которого описана в RFC 791 (оригинал: https://datatracker.ietf.org/doc/html/rfc791, русский перевод: https://www.lissyara.su/doc/rfc/rfc_791/).
Следует учитывать, что не только байтовый, но и битовый порядок расположения описанных в документации полей IP-заголовка подчиняется формату big-endian. В то время как системы на базе микропроцессоров x86 и x86_64 поддерживают формат litle-endian. Поэтому битовые поля в структурах языка C на микропроцессорах x86 и x86_64 охватывают биты от младшего к старшему, в то время как все сетевые стандарты при описании битовых полей предполагают расположение от старшего к младшему. Например, описанный в формате big-endian IP-пакет начинается с двух четырехбитовых полей - Version и IHL, расположенных последовательно в одном байте. На системах litle-endian в битовых структурах языка C эти два поля меняются местами, сначала идет IHL, затем - Version.
Битовый порядок расположения очень серьезно влияет и на поля, значения которых частично захватывают несколько байтов. Например, поля Flags(3 бита) и Fragment Offset (13 битов) идут в структуре IP-заголовка последовательно и охватывают суммарно 2 байта. При этом Fragment Offset занимает младшую часть первого байта и полностью второй. Однако при использовании формата little-endian битовое расположение подразумевает, что биты в памяти расположены от младшего к старшему, поэтому Flags будет разрывать поле Fragment Offset на две части, вне зависимости от того определено оно в структуре языка Си до Fragment Offset или после него. Решением может служить объявление полей Flags и Fragment Offset в виде одного 16-битового поля и организация доступа к нему с помощью логических операций.
Задача:
cat packets.txt | ./lab4