Язык программирования С, лабораторная работа 4.
Структуры: битовые поля.

Задание

Анализ заголовка IP-пакета.

Программа должна проанализировать данные со стандартного ввода, полученные с помощью вызова команды 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-битового поля и организация доступа к нему с помощью логических операций.

Задача:

  1. Разработать структуру, позволяющую хранить заголовок IP-пакета, с учетом всех существующих в протоколе однобитовых и многобитовых полей заголовка
  2. Сформировать и заполнить массив таких структур, проанализировав входные данные.
  3. Вывести информацию о каждом заголовке в человекочитаемом формате.
В качестве тестового набора данных можно использовать файл packets.txt. Если разработанная программа носит имя lab4, то ее запуск с указанным тестовым набором можно осуществить, например, так:
cat packets.txt | ./lab4