Читаем UNIX: разработка сетевых приложений полностью

45  *len = hdr.caplen; /* длина захваченного пакета */

46  return (ptr);

47 }

43-44 Мы вызываем библиотечную функцию pcap_next, возвращающую следующий пакет. Указатель на пакет является возвращаемым значением данной функции, а второй аргумент указывает на структуру pcap_pkthdr, которая тоже возвращается заполненной:

struct pcap_pkthdr {

 struct timeval ts;     /* временная метка */

 bpf_u_int32    caplen; /* длина захваченного фрагмента */

 bpf_u_int32    len;    /* полная длина пакета, находящегося в канале */

};

Временная отметка относится к тому моменту, когда пакет был считан устройством захвата пакетов, в противоположность моменту фактической передачи пакета процессу, которая может произойти чуть позже. Переменная caplenсодержит длину захваченных данных (вспомним, что в листинге 29.2 нашей переменной shaplenбыло присвоено значение 200 и она являлась вторым аргументом функции pcap_open_liveв листинге 29.5). Назначение устройства захвата пакетов состоит в захвате заголовков, а не всего содержимого каждого пакета. Переменная len — это полная длина пакета, находящегося в канале. Значение caplenбудет всегда меньше или равно значению len.

45-46 Перехваченная часть пакета возвращается через указатель (аргумент функции), и возвращаемым значением функции является указатель на пакет. Следует помнить, что указатель на пакет указывает фактически на заголовок канального уровня, который представляет собой 14-байтовый заголовок Ethernet в случае кадра Ethernet или 4-байтовый псевдоканальный (pseudo-link) заголовок в случае закольцовки на себя.

Если мы посмотрим на библиотечную реализацию функции pcap_next, мы увидим, что между различными функциями существует некоторое «разделение труда», схематически изображенное на рис. 29.5. Наше приложение вызывает функции pcap_, среди которых есть как зависящие, так и не зависящие от устройства захвата пакетов. Например, мы показываем, что реализация BPF вызывает функцию read, в то время как реализация DLPI вызывает функцию getmsg, а реализация Linux вызывает recvfrom.

Рис. 29.5. Организация вызовов функций для чтения из библиотеки захвата пакетов

Наша функция udp_checkпроверяет различные поля в заголовках IP и UDP. Она показана в листинге 29.13. Эту проверку необходимо выполнить, так как при получении пакета от устройства захвата пакетов уровень IP не замечает этого пакета. Для символьного сокета это не так.

44-61 Длина пакета должна включать хотя бы заголовки IP и UDP. Версия IP проверяется вместе с длиной и контрольной суммой заголовка IP. Если поле протокола указывает на дейтаграмму UDP, функция возвращает указатель на объединенный заголовок IP/UDP. В противном случае программа завершается, так как фильтр захвата пакетов, заданный при вызове функции pcap_setfilterв листинге 29.5, не должен возвращать пакеты никакого другого типа.

Листинг 29.13. Функция udp_check: проверка полей в заголовках IP и UDP

//udpcksum/udpread.c

38 struct udpiphdr*

39 udp_check(char *ptr, int len)

40 {

41  int hlen;

42  struct ip *ip;

43  struct udpiphdr *ui;

44  if (len sizeof(struct ip) + sizeof(struct udphdr))

45   err_quit("len = %d", len);

46  /* минимальная проверка заголовка IP */

47  ip = (struct ip*)ptr;

48  if (ip-ip_v != IPVERSION)

49   err_quit("ip_v = %d", ip-ip_v);

50  hlen = ip-ip_hl 2;

51  if (hlen sizeof(struct ip))

52   err_quit("ip_hl = %d", ip-ip_hl);

53  if (len hlen + sizeof(struct udphdr))

54   err_quit("len = %d, hlen = %d", len, hlen);

55  if ((ip-ip_sum = in_cksum((u_short )ip, hlen)) != 0)

56   err_quit("ip checksum error");

57  if (ip-ip_p == IPPROTO_UDP) {

58   ui = (struct udpiphdr*)ip;

59   return (ui);

60  } else

61  err_quit("not a UDP packet");

62 }

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT