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

//udpcksum/senddnsquery-libnet.c

18 void

19 send_dns_query(void)

20 {

21  char qbuf[24], *ptr;

22  u_int16_t one;

23  int packet_size = LIBNET_UDP_H + LIBNET_DNSV4_H + 24;

24  static libnet_ptag_t ip_tag, udp_tag, dns_tag;

25  /* построение запроса внутри UDP-пакета */

26  ptr = qbuf;

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

28  ptr += 20;

29  one = htons(1);

30  memcpy(ptr, &one, 2); /* тип запроса = A */

31  ptr += 2;

32  memcpy(ptr, &one, 2); /* класс запроса = 1 (IP-адрес) */

33  /* формирование пакета DNS */

34  dns_tag = libnet_build_dnsv4(

35   1234 /* идентификатор */,

36   0x0100 /* флаги: рекурсия разрешена */,

37   1 /* кол-во запросов */, 0 /* кол-во записей в ответе */,

38   0 /* кол-во авторитетных записей */, 0 /* кол-во дополнительных */,

39   qbuf /* запрос */,

40   24 /* длина запроса */, 1, dns_tag);

41  /* формирование заголовка UDP */

42  udp_tag = libnet_build_udp(

43   ((struct sockaddr_in*)local)->

44    sin_port /* порт отправителя */,

45   ((struct sockaddr_in*)dest)->

46    sin_port /* порт получателя */,

47   packet_size /* длина */, 0 /* контрольная сумма */,

48   NULL /* полезные данные */, 0 /* длина полезн. данных */, l, udp_tag);

49  /* Так как мы установили контр. сумму равной нулю, libnet автоматически */

50  /* рассчитает контр. сумму UDP. Эту функцию можно отключить. */

51  if (zerosum)

52   if (libnet_toggle_checksum(l, udp_tag, LIBNET_OFF) < 0)

53    err_quit("turning off checksums: %s\n", libnet_geterror(l));

54  /* формирование IP-заголовка */

55  ip_tag = libnet_build_ipv4(packet_size + LIBNET_IPV4_H /* длина */,

56   0 /* tos */, 0 /* IP ID */, 0 /* фрагмент*/,

57   TTL_OUT /* ttl */, IPPROTO_UDP /* протокол */,

58   0 /* контр. сумма */,

59   ((struct sockaddr_in*)local)->sin_addr.s_addr /* отправитель */,

60   ((struct sockaddr_in*)dest)->sin_addr.s_addr /* получатель */,

61   NULL /* полезные данные */, 0 /* длина полезн. данных */, l, ip_tag);

62  if (libnet_write(l) < 0) {

63   err_quit("libnet_write: %s\n", libnet_geterror(l));

64  }

65  if (verbose)

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 явным образом.

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

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

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

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

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

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

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