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

14  ptr += 2;

15  *((uint16_t*)ptr) = htons(0x0100); /* флаги */

16  ptr += 2;

17  *((uint16_t*)ptr) = htons(1); /* количество запросов */

18  ptr += 2;

19  *((uint16_t*)ptr) = 0; /* количество записей в ответе */

20  ptr += 2;

21  *((uint16_t*)ptr) = 0; /* количество авторитетных записей */

22  ptr += 2;

23  *((uint16_t*)ptr) = 0; /* количество дополнительных записей */

24  ptr += 2;

25  memcpy(ptr, "\001a\014root-servers\003net\000", 20);

26  ptr += 20;

27  *((uint16_t*)ptr) = htons(1); /* тип запроса = А */

28  ptr += 2;

29  *((uint16_t*)ptr) = htons(1); /* класс запроса = 1 (IP-адрес) */

30  ptr += 2;

31  nbytes = (ptr - buf) - sizeof(struct udpiphdr);

32  udp_write(buf, mbytes),

33  if (verbose)

35  printf("sent: %d bytes of data\n", nbytes);

36 }

Инициализация указателя на буфер

11-12 В буфере bufимеется место для 20-байтового заголовка IP, 8-байтового заголовка UDP и еще 100 байт для пользовательских данных. Указатель ptrустановлен на первый байт пользовательских данных.

Формирование запроса DNS

13-24 Для понимания деталей устройства дейтаграммы UDP требуется понимание формата сообщения DNS. Эту информацию можно найти в разделе 14.3 [111]. Мы присваиваем полю идентификации значение 1234, сбрасываем флаги, задаем количество запросов — 1, а затем обнуляем количество записей ресурсов (RR, resource records), получаемых в ответ, количество RR, определяющих полномочия, и количество дополнительных RR.

25-30 Затем мы формируем простой запрос, который располагается после заголовка: запрос типа А IP-адреса узла a.root-servers.net. Это доменное имя занимает 20 байт и состоит из 4 фрагментов: однобайтовая часть a, 12-байтовая часть root-servers, 3-байтовая часть netи корневая часть, длина которой занимает 0 байт. Тип запроса 1 (так называемый запрос типа А), и класс запроса также 1.

Запись дейтаграммы UDP

31-32 Это сообщение состоит из 36 байт пользовательских данных (восемь 2-байтовых полей и 20-байтовое доменное имя). Мы вызываем нашу функцию udp_writeдля формирования заголовков UDP и IP и последующей записи дейтаграммы UDP в наш символьный сокет.

В листинге 29.9 показана функция open_output, работающая с символьными сокетами.

Листинг 29.9. Функция open_output: подготовка символьного сокета

 2 int rawfd; /* символьный сокет */

 3 void

 4 open_output(void)

 5 {

 6  int on=1;

 7  /*

 8   * Для отправки IP-дейтаграмм нужен символьный сокет

 9   * Для его создания нужны права привилегированного пользователя.

10   * Кроме того, необходимо указать параметр сокета IP_HDRINCL.

11   */

12  rawfd = Socket(dest-sa_family, SOCK_RAW, 0);

13  Setsockopt(rawfd, IPPROTO_IP, IP_HDRINCL, on., sizeof(on));

14 }

Объявление дескриптора символьного сокета

2 Мы объявляем глобальную переменную, в которой будет храниться дескриптор символьного сокета.

Создание сокета и установка IP_HDRINCL

7-13 Мы создаем символьный сокет и включаем параметр сокета IP_HDRINCL. Это позволяет нам формировать IP-дейтаграммы целиком, включая заголовок IP.

В листинге 29.10 показана наша функция udp_write, которая формирует заголовки IP и UDP, а затем записывает дейтаграмму в символьный сокет.

Листинг 29.10. Функция udp_write: формирование заголовков UDP и IP и запись дейтаграммы IP в символьный сокет

//udpcksum/udpwrite.c

19 void

20 udp_write(char *buf, int userlen)

21 {

22  struct udpiphdr *ui;

23  struct ip *ip;

24  /* заполнение заголовка и вычисление контрольной суммы */

25  ip = (struct ip*)buf;

26  ui = (struct udpiphdr*)buf;

27  bzero(ui, sizeof(*ui));

28  /* добавляем 8 к длине псевдозаголовка */

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

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

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

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

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

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

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

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

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