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

12  if (ip-ip_p != IPPROTO_ICMP)

13   return; /* не ICMP */

14  icmp = (struct icmp*)(ptr + hlen1); /* начало ICMP-заголовка */

15  if ((icmplen = len - hlen1) 8)

16   return; /* плохой пакет */

17  if (icmp-icmp_type == ICMP_ECHOREPLY) {

18   if (icmp-icmp_id != pid)

19    return; /* это не ответ на наш ECHO_REQUEST */

20   if (icmplen 16)

21    return; /* недостаточно данных */

22  tvsend = (struct timeval*)icmp-icmp_data;

23  tv_sub(tvrecv, tvsend);

24  rtt = tvrecv-tv_sec * 1000.0 + tvrecv-tv_usec / 1000.0;

25  printf("%d bytes from %s: seq=%u, ttl=%d, rtt=%.3f ms\n",

26   icmplen, Sock_ntop_host(pr-sarecv, pr-salen),

27   icmp-icmp_seq, ip-ip_ttl, rtt);

28  } else if (verbose) {

29   printf(" %d bytes from %s: type = %d, code = %d\n",

30   icmplen, Sock_ntop_host(pr-sarecv, pr-salen),

31   icmp-icmp_type, icmp-icmp_code);

32  }

33 }

Извлечение указателя на ICMP-заголовок

10-16 Значение поля длины заголовка IPv4, умноженное на 4, дает размер заголовка IPv4 в байтах. (Следует помнить, что IPv4-заголовок может содержать параметры.) Это позволяет нам установить указатель icmp так, чтобы он указывал на начало ICMP-заголовка. Мы проверяем, относится ли данный пакет к протоколу ICMP и имеется ли в нем достаточно данных для проверки временной отметки, включенной нами в эхо-запрос. На рис. 28.3 приведены различные заголовки, указатели и длины, используемые в коде.

Рис. 28.3. Заголовки, указатели и длина при обработке ответов ICMPv4

Проверка эхо-ответа ICMP

17-21 Если сообщение является эхо-ответом ICMP, то необходимо проверить поле идентификатора, чтобы выяснить, относится ли этот ответ к посланному данным процессом запросу. Если программа ping запущена на одном узле несколько раз, каждый процесс получает копии всех полученных ICMP-сообщений.

22-27 Путем вычитания времени отправки сообщения (содержащегося в части ICMP-ответа, отведенной под дополнительные данные) из текущего времени (на которое указывает аргумент функции tvrecv) вычисляется значение RTT. Время RTT преобразуется из микросекунд в миллисекунды и выводится на экран вместе с полем порядкового номера и полученным значением TTL. Поле порядкового номера позволяет пользователю проследить, не были ли пакеты пропущены, переупорядочены или дублированы, а значение TTL показывает количество транзитных узлов между двумя узлами.

Вывод всех полученных ICMP-сообщений при включении параметра verbose

28-32 Если пользователем указан параметр командной строки -v, также выводятся поля типа и кода из всех других полученных ICMP-сообщений.

Обработка сообщений ICMPv6 управляется функцией proc_v6, приведенной в листинге 28.8. Она аналогична функции proc_v4, представленной в листинге 28.6. Однако поскольку символьные сокеты IPv6 не передают процессу заголовок IPv6, ограничение на количество транзитных узлов приходится получать в виде вспомогательных данных. Для этого нам приходится подготавливать сокет функцией init_v6, представленной в листинге 28.7.

Листинг 28.7. Функция init_v6: подготовка сокета

 1 void

 2 init_v6

 3 {

 4 #ifdef IPV6

 5  int on = 1;

 6  if (verbose == 0) {

 7   /* установка фильтра, пропускающего только пакеты ICMP6_ECHO_REPLY. если

        не включен параметр verbose (вывод всех ICMP-сообщений) */

 8   struct icmp6_filter myfilt;

 9   ICMP6_FILTER_SETBLOCKALL(myfilt);

10   ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, myfilt);

11   setsockopt(sockfd, IPPROTO_IPV6, ICMP6_FILTER, myfilt,

12    sizeof(myfilt));

13   /* игнорируем ошибку, потому что фильтр - необязательная оптимизация */

14  }

15  /* следующую ошибку тоже игнорируем; придется обойтись без вывода

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

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

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

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

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

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

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

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

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