Литмир - Электронная Библиотека
Содержание  
A
A

Сейчас осуществляется поддержка BPF для Беркли-ядер, DLPI для Solaris 2.x, NIT для SunOS 4.1.x, пакетных сокетов (

SOCK_PACKET
,
PF_PACKET
) в Linux и нескольких других операционных системах. Библиотека
libcap
используется программой
tcpdump
. Всего в библиотеке насчитывается порядка 25 функций, но вместо того чтобы просто описывать их, мы продемонстрируем их фактическое использование на примере, рассматриваемом в следующем разделе. Названия всех функций начинаются с
pcap_
. Они описаны более подробно на странице руководства, которая называется
pcap
.

ПРИМЕЧАНИЕ

Библиотека libcap находится в свободном доступе по адресу http://www.tcpdump.org/.

29.6. Libnet: библиотека создания и отправки пакетов

Библиотека

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

Библиотека скрывает большую часть деталей формирования заголовков IP, UDP и TCP и обеспечивает приложению простой и переносимый интерфейс для отправки пакетов канального уровня и IP-пакетов через символьные сокеты. Как и

libcap
, библиотека
libnet
содержит достаточно много функций. Мы приведем пример использования небольшой их части, предназначенной для работы с символьными сокетами, но в следующем разделе. Для сравнения там же будет приведен код, непосредственно работающий с символьными сокетами. Все функции библиотеки начинаются с префикса
libnet_
. За более подробным их описанием вы можете обратиться к странице руководства
libnet
или к доступной в Сети документации.

ПРИМЕЧАНИЕ

Библиотека libnet свободно доступна по адресу http://www.packetfactory.net/libnet/. Руководство находится по адресу http://www.packetfactory.net/libnet/manual. На момент написания этой книги в Сети имелось руководство только по устаревшей версии 1.0. Актуальная версия 1.1 имеет значительно отличающийся интерфейс. В нашем примере используется API версии 1.1.

29.7. Анализ поля контрольной суммы UDP

Теперь мы приступаем к рассмотрению примера, в котором отсылается дейтаграмма UDP, содержащая запрос UDP к серверу имен, а затем считывается ответ с помощью библиотеки захвата пакетов. Цель данного примера — установить, вычисляется на сервере имен контрольная сумма UDP или нет. В случае IPv4 вычисление контрольной суммы не является обязательным. В большинстве систем в настоящее время вычисление контрольных сумм по умолчанию включено, но, к сожалению, в более старых системах, в частности SunOS 4.1.x, оно по умолчанию отключено. В настоящее время все системы, а особенно система, в которой работает сервер имен, всегда должны работать с включенными контрольными суммами UDP, поскольку поврежденные (содержащие ошибки) дейтаграммы могут повредить базу данных сервера.

ПРИМЕЧАНИЕ

Включение и выключение контрольных сумм обычно осуществляется сразу для всей системы, как показано в приложении Е [111].

Мы формируем дейтаграмму UDP (запрос DNS) и записываем ее в символьный сокет. Параллельно мы проделаем то же самое с помощью

libnet
. Для отправки запроса мы могли бы использовать обычный сокет UDP, но мы хотим показать, как использовать параметр сокета
IP_HDRINCL
для создания полной дейтаграммы IP.

Нет возможности получить контрольную сумму UDP при чтении из обычного сокета UDP, а также считывать пакеты UDP или TCP, используя символьный сокет (см. раздел 28.4). Следовательно, путем захвата пакетов нам нужно получить целую дейтаграмму UDP, содержащую ответ сервера имен.

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

Действие нашей программы иллюстрирует рис. 29.3. Мы записываем наши собственные дейтаграммы UDP в символьный сокет и считываем ответы, используя библиотеку

libcap
. Обратите внимание, что UDP также получает ответ сервера имен и отвечает сообщением о недоступности порта ICMP, так как ничего не знает о номере порта, выбранном нашим приложением. Сервер имен игнорирует эту ошибку ICMP. Также можно отметить, что написать подобную тестовую программу, использующую TCP, было бы сложнее, даже несмотря на то, что мы с легкостью можем записывать свои собственные сегменты TCP. Дело в том, что любой ответ на сегмент TCP, который мы генерируем, обычно инициирует отправку протоколом TCP ответного сегмента RST туда, куда был послан первый сегмент.

UNIX: разработка сетевых приложений - img_157.png

Рис. 29.3. Приложение, определяющее, включено ли на сервере вычисление контрольных сумм UDP

ПРИМЕЧАНИЕ

Указанную проблему можно обойти. Для этого нужно посылать сегменты TCP с IP- адресом отправителя, который принадлежит присоединенной подсети, но в настоящий момент не присвоен никакому другому узлу. Нужно также добавить данные ARP на посылающем узле для этого нового IP-адреса, чтобы узел отвечал на запросы ARP для него. В результате стек IP на посылающем узле будет игнорировать пакеты, приходящие на этот IP-адрес, в предположении, что посылающий узел не является маршрутизатором.

На рис. 29.4 приведены функции, используемые в нашей программе.

UNIX: разработка сетевых приложений - img_158.png

Рис. 29.4. Функции, которые используются в программе udpcksum

В листинге 29.1[1] показан заголовочный файл

udpcksum.h
, в который включен наш базовый заголовочный файл
unp.h
, а также различные системные заголовки, необходимые для получения доступа к определениям структур для заголовков пакетов IP и UDP.

Листинг 29.1. Заголовочный файл udpcksum.h

//udpcksum/udpcksum.h

 1 #include "unp.h"

 2 #include <pcap.h>

 3 #include <netinet/in_systm.h> /* необходим для ip.h */

 4 #include <netinet/in.h>

 5 #include <netinet/ip.h>

 6 #include <netinet/ip_var.h>

 7 #include <netinet/udp.h>

 8 #include <netinet/udp_var.h>

 9 #include <net/if.h>

10 #include <netinet/if_ether.h>

11 #define TTL_OUT 64 /* исходящее TTL */

12 /* объявление глобальных переменных */

13 extern struct sockaddr *dest, *local;

вернуться

1

Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.

332
{"b":"225366","o":1}