Чтение онлайн

ЖАНРЫ

UNIX: разработка сетевых приложений
Шрифт:

Следующая функция,

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 байтам.

ПРИМЕЧАНИЕ

Формат, приведенный на рис. 27.2, определен в заголовочном файле <netinet/ip_var.h> в виде следующей структуры:

#define MAX_IPOPTLEN 40

struct ipoption {

struct in_addr ipopt_dst; /*
адрес первого получателя */

char ipopt_list[MAX_IPOPTLEN]; /* соответствующие параметры */

};

В листинге 27.3 мы анализируем эти данные, не используя указанную структуру.

Возвращаемый формат отличается от того, который был передан функции

setsockopt
. Если нам было бы нужно преобразовать формат, показанный на рис. 27.2, к формату, показанному на рис. 27.1, нам следовало бы поменять местами первые и вторые 4 байта и изменить значение поля
len
, добавив к имеющемуся значению 4. К счастью, нам не нужно этого делать, так как Беркли-реализации автоматически используют обращенный маршрут от получателя для сокета TCP. Иными словами, данные, возвращаемые функцией
getsockopt
(представленные на рис. 27.2), носят чисто информативный характер. Нам не нужно вызывать функцию
setsockopt
, чтобы указать ядру на необходимость использования данного маршрута для дейтаграмм IP, отсылаемых по соединению TCP, — ядро сделает это само. Подобный пример с нашим сервером TCP мы вскоре увидим.

Следующей из рассматриваемых нами функций, связанных с параметром маршрутизации, полученный маршрут от отправителя передается в формате, показанном на рис. 27.2. Затем она выводит соответствующую информацию. Эту функцию

inet_srtcrt_print
мы показываем в листинге 27.3.

Листинг 27.3. Функция inet_srtcrt_print: вывод полученного маршрута от отправителя

//ipopts/sourceroute.c

37 void

38 inet_srcrt_print(u_char *ptr, int len)

39 {

40 u_char c;

41 char str[INET_ADDRSTRLEN];

42 struct in_addr hop1;

43 memcpy(&hop1, ptr, sizeof(struct in_addr));

44 ptr += sizeof(struct in_addr);

45 while ((c = *ptr++) == IPOPT_NOP); /* пропуск параметров NOP */

46 if (с == IPOPT_LSRR)

47 printf("received LSRR: ");

48 else if (c == IPOPT_SSRR)

49 printf("received SSRR: ");

50 else {

51 printf("received option type %d\n", c);

52 return;

53 }

54 printf("%s ", Inet_ntop(AF_INET, &hop1, str, sizeof(str)));

55 len = *ptr++ - sizeof(struct in_addr); /* вычитаем адрес получателя */

56 ptr++; /* пропуск указателя */

57 while (len > 0) {

58 printf("%s ", Inet_ntop(AF_INET, ptr, str, sizeof(str)));

59 ptr += sizeof(struct in_addr);

60 len -= sizeof(struct in_addr);

61 }

62 printf("\n");

63 }

Сохраняем первый адрес IP, пропускаем все параметры NOP
Поделиться с друзьями: