Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Программное обеспечение » UNIX: разработка сетевых приложений - Уильям Стивенс

UNIX: разработка сетевых приложений - Уильям Стивенс

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 196 197 198 199 200 201 202 203 204 ... 263
Перейти на страницу:

Маршрут от отправителя (source route) — это список IP-адресов, указанных отправителем дейтаграммы IP. Если маршрут является жестким (строгим, strict), то дейтаграмма должна передаваться только между указанными узлами и пройти их все. Иными словами, все узлы, перечисленные в маршруте от отправителя, должны быть соседними друг для друга. Но если маршрут является свободным, или гибким (loose), дейтаграмма должна пройти все перечисленные в нем узлы, но может при этом пройти и еще какие-то узлы, не входящие в список.

ПРИМЕЧАНИЕ

Маршрутизация от отправителя (source routing) в IPv4 является предметом споров и сомнений. В [20] пропагандируется отказ от поддержки этой функции на всех маршрутизаторах, и многие организации и провайдеры действительно следуют этому принципу. Один из наиболее разумных способов использования маршрутизации от отправителя — это обнаружение с помощью программы traceroute асимметричных маршрутов, как показано на с. 108–109 [111], но в настоящее время даже этот способ становится непопулярен. Тем не менее определение и получение маршрута от отправителя — это часть API сокетов, и поэтому заслуживает описания.

Параметры IPv4, связанные с маршрутизацией от отправителя, называются параметрами маршрутизации от отправителя с записью (Loose Source and Record Routes — LSRR в случае свободной маршрутизации и Strict Source and Record Routes — SSRR в случае жесткой маршрутизации), так как при проходе дейтаграммы через каждый из перечисленных в списке узлов происходит замена указанного адреса на адрес интерфейса для исходящих дейтаграмм. Это позволяет получателю дейтаграммы обратить полученный список, превратив его в маршрут, по которому будет послан ответ отправителю. Примеры этих двух маршрутов от отправителя вместе с соответствующим выводом программы tcpdump, приведены в разделе 8.5 книги [111].

Маршрут от отправителя мы определяем как массив адресов IPv4, которому предшествуют три однобайтовых поля, как показано на рис. 27.1. Это формат буфера, который передается функции setsockopt.

Рис. 27.1. Передача маршрута от отправителя ядру

Перед параметром маршрута от отправителя мы поместили параметр NOP (нет действий), чтобы все IP-адреса были выровнены по 4-байтовой границе. Это не обязательно, но желательно, поскольку в результате мы выравниваем адреса, не расходуя дополнительно лишней памяти (все IP-параметры обычно выравниваются, чтобы в итоге занимать место, кратное 4 байтам).

На рис. 27.1 показано, что маршрут состоит из 10 адресов, но первый приведенный адрес удаляется из параметра маршрута от отправителя и становится адресом получателя, когда дейтаграмма IP покидает узел отправителя. Хотя в 40-байтовом пространстве, отведенном под данный параметр IP, хватает места только для 9 адресов (не забудьте о 3-байтовом заголовке параметра, который мы вскоре опишем), фактически в заголовке IPv4 у нас имеется 10 IP-адресов, так как к 9 адресам узлов добавляется адрес получателя.

Поле code — это либо 0x83 для параметра LSRR, либо 0x89 для параметра SSRR. Задаваемое нами значение поля len — это размер параметра в байтах, включая 3-байтовый заголовок и дополнительный адрес получателя, приведенный в конце списка. Для маршрута, состоящего из одного IP-адреса, это значение будет равно 11, для двух адресов — 15, и т.д. вплоть до максимального значения 43. Параметр NOP не является частью обсуждаемого параметра, и его длина не включается в значение поля len, но она входит в размер буфера, который мы сообщаем функции setsockopt. Когда первый адрес в списке удаляется из параметра маршрута от отправителя и добавляется в поле адреса получателя в заголовок IP, значение поля len уменьшается на 4 (см. рис. 9.32 и 9.33 [128]). Поле ptr — это указатель, или сдвиг, задающий положение следующего IP-адреса из списка, который должен быть обработан. Мы инициализируем это поле значением 4, что соответствует первому адресу IP. Значение этого поля увеличивается на 4 каждый раз, когда дейтаграмма обрабатывается одним из перечисленных в маршруте узлов.

Теперь мы переходим к определению трех функций, с помощью которых мы инициализируем, создаем и обрабатываем параметр маршрута от отправителя. Наши функции предназначены для работы только с этим параметром. Хотя в принципе возможно объединить параметр маршрута от отправителя с другими параметрами IP (такими как параметр извещения маршрутизатора), но на практике параметры редко комбинируются. В листинге 27.1[1] приведена функция inet_srcrt_init, а также некоторые статические переменные, используемые при составлении параметра.

Листинг 27.1. Функция inet_srcrt_init: инициализация перед записью маршрута от отправителя

//ipopts/sourceroute.с

 1 #include "unp.h"

 2 #include <netinet/in_systm.h>

 3 #include <netinet/ip.h>

 4 static u_char *optr;   /* указатель на формируемые параметры */

 5 static u_char *lenptr; /* указатель на длину параметра SRR */

 6 static int    ocnt;    /* количество адресов */

 7 u_char*

 8 inet_srcrt_init(int type)

 9 {

10  optr = Malloc(44); /* NOP, код параметра. len, указатель + до 10

                          адресов */

11  bzero(optr, 44); /* гарантирует наличие EOL на конце */

12  ocnt = 0;

13  *optr++ = IPOPT_NOP; /* выравнивающие NOP */

14  *optr++ = type ? IPOPT_SSRR : IPOPT_LSRR;

15  lenptr = optr++; /* поле длины заполняется позже */

16  *optr++ = 4; /* сдвиг на первый адрес */

17  return(optr - 4); /* указатель для setsockopt() */

18 }

Инициализация

10-17 Мы выделяем в памяти буфер, максимальный размер которого — 44 байт, и обнуляем его содержимое. Значение параметра EOL равно нулю, так что тем самым параметр инициализируется байтами EOL. Затем мы подготавливаем заголовок для маршрутизации от источника. Как показано на рис. 27.1, сначала мы обеспечиваем выравнивание при помощи параметра NOP, после чего указываем тип маршрута (гибкий, жесткий), длину и значение указателя. Мы сохраняем указатель в поле len. Это значение мы будем записывать при поочередном добавлении адресов к списку. Указатель на параметр возвращается вызывающему процессу, а затем передается как четвертый аргумент функции setsockopt.

Следующая функция, inet_srcrt_add, добавляет один IPv4-адрес к создаваемому маршруту от отправителя.

Листинг 27.2. Функция inet_srcrt_add: добавление одного IPv4-адреса к маршруту от отправителя

//ipopts/sourceroute.с

19 int

20 inet_srcrt_add(char *hostptr)

21 {

22  int len;

23  struct addrinfo *ai;

24  struct sockaddr_in *sin;

25  if (ocnt > 9)

26   err_quit("too many source routes with: %s", hostptr);

27  ai = Host_serv(hostptr, NULL, AF_INET, 0);

28  sin = (struct sockaddr_in*)ai->ai_addr;

29  memcpy(optr, &sin->sin_addr, sizeof(struct in_addr));

30  freeaddrinfo(ai);

31  optr += sizeof(struct in_addr);

32  ocnt++;

33  len = 3 + (ocnt * sizeof(struct in_addr));

34  *lenptr = len;

35  return(len + 1); /* размер для setsockopt() */

36 }

Аргумент

19-20 Аргумент функции указывает либо на имя узла, либо на адрес IP в точечно- десятичной записи.

Проверка переполнения

25-26 Мы проверяем количество переданных адресов и выполняем инициализацию, если обрабатывается первый адрес.

Получение двоичного IP-адреса и запись маршрута

29-37 Функция host_serv обрабатывает имя узла или его IP-адрес, а возвращаемый ей адрес в двоичной форме мы помещаем в список. Мы обновляем поле len и возвращаем полный размер буфера (с учетом параметров NOP), который вызывающий процесс затем передаст функции setsockopt.

Когда полученный маршрут от отправителя возвращается приложению функцией getsockopt, формат этого параметра отличается от того, что было показано на рис. 27.1. Формат полученного параметра маршрута от отправителя показан на рис. 27.2.

Рис. 27.2. Формат параметра маршрута от отправителя, возвращаемого функцией getsockopt

В первую очередь, мы можем отметить, что порядок следования адресов изменен ядром на противоположный относительно полученного маршрута от отправителя. Имеется в виду следующее: если в полученном маршруте содержались адреса А, В, С и D в указанном порядке, то под противоположным порядком подразумевается следующий: D, С, В, А. Первые 4 байта содержат первый IP-адрес из списка, затем следует однобайтовый параметр NOP (для выравнивания), затем — 3-байтовый заголовок параметра маршрута от отправителя, и далее остальные IP-адреса. После 3-байтового заголовка может следовать до 9 IP-адресов, и максимальное значение поля len в возвращенном заголовке равно 39. Поскольку параметр NOP всегда присутствует, длина буфера, возвращаемая функцией getsockopt, всегда будет равна значению, кратному 4 байтам.

1 ... 196 197 198 199 200 201 202 203 204 ... 263
Перейти на страницу:
Тут вы можете бесплатно читать книгу UNIX: разработка сетевых приложений - Уильям Стивенс.
Комментарии