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

Макрокоманда

SETPASS
определяет конкретный тип сообщений, который должен пересылаться приложению, а макрокоманда
SETBLOCK
блокирует один конкретный тип сообщений. Макрокоманда
WILLPASS
возвращает значение 1, если определенный тип пропускается фильтром. Макрокоманда
WILLBLOCK
возвращает значение 1, если определенный тип блокирован фильтром, и нуль в противном случае.

В качестве примера рассмотрим приложение, которое будет получать только ICMPv6-извещения маршрутизатора:

struct icmp6_filter myfilt;

fd = Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);

ICMP6_FILTER_SETBLOCKALL(&myfilt);

ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &myfilt);

Setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &myfilt, sizeof(myfilt));

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

socket
и
setsockopt
, будут добавлены в очередь на сокете. Параметр
ICMP6_FILTER
 — лишь средство оптимизации условий функционирования приложения.

28.5. Программа ping

В данном разделе приводится версия программы

ping
, работающая как с IPv4, так и с IPv6. Вместо того чтобы представить известный доступный исходный код, мы разработали оригинальную программу, и сделано это по двум причинам. Во-первых, свободно доступная программа
ping
страдает общей болезнью программирования, известной как «ползучий улучшизм» (стремление к постоянным ненужным усложнениям программы в погоне за мелкими улучшениями): она поддерживает 12 различных параметров. Наша цель при исследовании программы
ping
в том, чтобы понять концепции и методы сетевого программирования и не быть при этом сбитыми с толку ее многочисленными параметрами. Наша версия программы
ping
поддерживает только один параметр и занимает в пять раз меньше места, чем общедоступная версия. Во-вторых, общедоступная версия работает только с IPv4, а нам хочется показать версию, поддерживающую также и IPv6.

Действие программы ping предельно просто: по некоторому IP-адресу посылается эхо-запрос ICMP, и этот узел отвечает эхо-ответом ICMP. Оба эти сообщения поддерживаются в обеих версиях — и в IPv4, и в IPv6. На рис. 28.1 приведен формат ICMP-сообщений.

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

Рис. 28.1. Формат сообщений эхо-запроса и эхо-ответа ICMPv4 и ICMPv6

В табл. А.5 и А.6 приведены значения поля тип (type) для этих сообщений и говорится, что значение поля код (code) равно нулю. Далее будет показано, что в поле идентификатор (identifier) указывается идентификатор процесса

ping
, а значение поля порядковый номер (sequence number) увеличивается на 1 для каждого отправляемого пакета. В поле дополнительные данные (optional data) сохраняется 8-байтовая отметка времени отправки пакета. Правила ICMP-запроса требуют, чтобы идентификатор, порядковый номер и все дополнительные данные возвращались в эхо-ответе. Сохранение отметки времени отправки пакета позволяет вычислить RTT при получении ответа.

В листинге 28.1[1] приведены примеры работы нашей программы. В первом используется версия IPv4, а во втором IPv6. Обратите внимание, что мы установили для нашей программы

ping
флаг set-user-ID (установка идентификатора пользователя при выполнении), потому что для создания символьного сокета требуются права привилегированного пользователя.

Листинг 28.1. Примеры вывода программы ping

freebsd % <b>ping www.google.com</b>

PING www.google.com (216.239.57.99): 56 data bytes

64 bytes from 216.239.57.99: seq=0, ttl=53, rtt=5.611 ms

64 bytes from 216.239.57.99: seq=1, ttl=53, rtt=5.562 ms

64 bytes from 216.239.57 99: seq=2, ttl=53, rtt=5.589 ms

64 bytes from 216.239.57.99: seq=3, ttl=53, rtt=5.910 ms

freebsd % <b>ping www.kame.net</b>

PING orange.kame.net (2001:200:0:4819:203:47ff:fea5:3085): 56 data bytes

64 bytes from 2001:200:0:4819:203:47ff:fea5:3085: seq=0, hlim=52, rtt=422.066 ms

64 bytes from 2001:200:0:4819:203:47ff:fea5:3085: seq=1, hlim=52, rtt=417.398 ms

64 bytes from 2001:200:0:4819:203:47ff:fea5:3085: seq=2, hlim=52, rtt=416.528 ms

64 bytes from 2001:200:0:4819.203.47ff:fea5:3085: seq=3, hlim=52, rtt=429.192 ms

На рис. 28.2 приведен обзор функций, составляющих программу

ping
.

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

Рис. 28.2. Обзор функций программы ping

Данная программа состоит из двух частей: одна половина читает все, что приходит на символьный сокет, и выводит эхо-ответы ICMP, а другая половина один раз в секунду посылает эхо-запросы ICMP. Вторая половина запускается один раз в секунду сигналом

SIGALRM
.

В листинге 28.2 приведен заголовочный файл

ping.h
, подключаемый во всех файлах программы.

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

//ping/ping.h

 1 #include &quot;unp.h&quot;

 2 #include &lt;netinet/in_systm.h&gt;

 3 #include &lt;netinet/in.h&gt;

 4 #include &lt;netinet/ip_icmp.h&gt;

 5 #define BUFSIZE 1500

 6 /* глобальные переменные */

 7 char sendbuf[BUFSIZE];

 8 int datalen; /* размер данных после заголовка ICMP */

 9 char *host;

10 int nsent; /* увеличиваем на 1 для каждого sendto() */

11 pid_t pid; /* наш PID */

12 int sockfd;

13 int verbose;

14 /* прототипы функций */

вернуться

1

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

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