Читаем 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 }

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

Все книги серии Мастер-класс

Секреты резьбы по дереву
Секреты резьбы по дереву

Изделия из древесины и материалов, имитирующих ее текстуру, привычным образом окружают нас в повседневной жизни, поэтому мы относимся к ней как к чему-то обыденному. Но как только ее коснется умелая рука мастера резьбы по дереву, рождается произведение искусства и раскрываются такие качества древесины, как богатая фактура, разнообразие цветов, особая теплота. Эта книга поможет читателю открыть для себя удивительный мир творчества и познать секреты резьбы по дереву. Автор надеется, что начинающие резчики найдут в ней интересный и полезный материал, который позволит им стать мастерами. В приложении представлены рисунки орнаментов и различных узоров, которые на первых порах можно копировать, а по мере приобретения навыка на их основе разрабатывать свои образцы.

Галина Алексеевна Серикова

Сделай сам / Хобби и ремесла / Руководства / Дом и досуг / Словари и Энциклопедии

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

Все жанры