66 printf("sent: %d bytes of data\n", packet_size);
67 }
Формирование запроса DNS
25-32
Мы начинаем с формирования запроса DNS, которое выполняется так же, как в строках 25–30 листинга 29.8.
34-40
Затем мы вызываем функцию
libnet_build_dnsv4
, которая принимает поля пакета DNS в виде отдельных аргументов. Нам достаточно знать содержимое запроса, а упорядочением этого содержимого в заголовке пакета DNS занимается функция.
Заполнение заголовка UDP и подготовка к вычислению контрольной суммы UDP
42-48
Мы формируем заголовок UDP, вызывая
функцию
libnet_build_udp
. Поля заголовка UDP принимаются этой функцией также в виде отдельных аргументов. Если значение переданной контрольной суммы равно 0,
libnet
автоматически рассчитывает контрольную сумму.
49-52
Если пользователь запретил вычисление контрольной суммы, мы должны отключить эту функцию
libnet
явным образом.
Заполнение заголовка IP
53-65
Окончательное формирование пакета требует построения заголовка IPv4 вызовом
libnet_build_ipv4
.
ПРИМЕЧАНИЕ
Библиотека libnet автоматически записывает поле ip_len в нужном порядке байтов. Это пример повышения переносимости программы благодаря использованию библиотек.
Отправка UDP-дейтаграммы
66-70
Мы вызываем функцию
libnet_write
для отправки подготовленной дейтаграммы в сеть.
Функция
send_dns_query
, использующая
libnet
, состоит всего из 67 строк, тогда как в версии, работавшей с символьными сокетами, общая длина кода составила 96 строк, в которых было по крайней мере 2 трюка, связанных с переносимостью.
29.8. Резюме
Символьные сокеты предоставляют возможность записывать и считывать IP-дейтаграммы, которые могут быть не поняты ядром, а доступ к канальному уровню позволяет считывать и записывать кадры канального уровня любыхтипов (не только дейтаграммы IP). Программа
tcpdump
— это, вероятно, наиболее широко используемая программа, имеющая непосредственный доступ к канальному уровню.
В различных операционных системах применяются различные способы доступа к канальному уровню. Мы рассмотрели пакетный фильтр Беркли, DLPI SVR4 и пакетные сокеты Linux (
SOCK_PACKET
). Но у нас имеется возможность, не вникая в различия перечисленных способов, использовать находящуюся в свободном доступе переносимую библиотеку захвата пакетов
libcap
.
Отправка символьных дейтаграмм осуществляется в разных системах по-разному. Свободно распространяемая библиотека
libnet
скрывает различия между системами и предоставляет интерфейс для вывода через символьные сокеты и непосредственно на канальном уровне.
Упражнения
1. Каково назначение флага
canjump
в листинге 29.7?
2. При работе программы
udpcksum
наиболее распространенным сообщением об ошибке является сообщение о недоступности порта ICMP (в пункте назначения не работает сервер имен) или недоступности узла ICMP. В обоих случаях нам не нужно ждать истечения времени ожидания, заданного функцией
udp_read
в листинге 29.6, так как сообщение о подобной ошибке фактически является ответом на наш запрос DNS. Модифицируйте программу таким образом, чтобы она перехватывала эти ошибки ICMP.