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

ЖАНРЫ

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

62 saext->sadb_sa_state = SADB_SASTATE_MATURE;

63 saext->sadb_sa_auth = alg;

64 saext->sadb_sa_encrypt = SADB_EALG_NONE;

65 saext->sadb_sa_flags = 0;

66 len += saext->sadb_sa_len * 8;

67 p += saext->sadb_sa_len * 8;

68 addrext = (struct sadb_address*)p;

69 addrext->sadb_address_len = (sizeof(*addrext) + salen(src) + 7) / 8;

70 addrext->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;

71 addrext->sadb_address_proto = 0; /* any protocol */

72 addrext->sadb_address_prefixlen = prefix_all(src);

73 addrext->sadb_address_reserved = 0;

74 memcpy(addrext + 1, src, salen(src));

75 len += addrext->sadb_address_len * 8,

76 p += addrext->sadb_address_len * 8;

77 addrext = (struct sadb_address*)p;

78 addrext->sadb_address_len = (sizeof(*addrext) + salen(dst) + 7) / 8;

79 addrext->sadb_address_exttype = SADB_EXT_ADDRESS_DST;

80 addrext->sadb_address_proto = 0; /* any protocol */

81 addrext->sadb_address_prefixlen = prefix_all(dst);

82 addrext->sadb_address_reserved = 0;

83 memcpy(addrext + 1, dst, salen(dst));

84 len += addrext->sadb_address_len * 8;

85 p += addrext->sadb_address_len * 8;

86 keyext = (struct sadb_key*)p;

87 /*
обеспечивает выравнивание */

88 keyext->sadb_key_len = (sizeof(*keyext) + (keybits / 8) + 7) / 8;

89 keyext->sadb_key_exttype = SADB_EXT_KEY_AUTH;

90 keyext->sadb_key_bits = keybits;

91 keyext->sadb_key_reserved = 0;

92 memcpy(keyext + 1, keydata, keybits / 8);

93 len += keyext->sadb_key_len * 8;

94 p += keyext->sadb_key_len * 8;

95 msg->sadb_msg_len = len / 8;

96 printf("Sending add message:\n");

97 print_sadb_msg(buf, len);

98 Write(s, buf, len);

99 printf("\nReply returned:\n");

100 /* считывание и вывод ответа SADB_ADD, игнорируя любые другие */

101 for (;;) {

102 int msglen;

103 struct sadb_msg *msgp;

104 msglen = Read(s, &buf, sizeof(buf));

105 msgp = (struct sadb_msg*)&buf;

106 if (msgp->sadb_msg_pid == mypid &&

107 msgp->sadb_msg_type == SADB_ADD) {

108 print_sadb_msg(msgp, msglen);

109 break;

110 }

111 }

112 close(s);

113 }

Открытие
сокета PF_KEY и сохранение PID

55-56
Как и в предыдущей программе, мы открываем сокет PF_KEY и сохраняем идентификатор нашего процесса для последующего его использования.

Формирование общего заголовка сообщений

47-56
Мы формируем заголовок сообщения
SADB_ADD
. Поле
sadb_msg_len
устанавливается непосредственно перед отправкой сообщения, поскольку оно должно соответствовать истинной его длине. В переменной
len
хранится текущая длина сообщения, а указатель р всегда указывает на первый неиспользуемый байт буфера.

Добавление расширения SA

57-67
Мы добавляем обязательное расширение
SA
(см. листинг 19.3). Поле
sadb_sa_spi
должно иметь сетевой порядок байтов, поэтому нам приходится применять функцию
htonl
к значению в порядке байтов узла. Мы отключаем защиту от повторов и устанавливаем состояние
SA
равным
SADB_SASTATE_MATURE
(см. табл. 19.4). Алгоритм аутентификации выбирается в соответствии с аргументом командной строки, а шифрование отключается при помощи константы
SADB_EALG_NONE
.

Добавление адреса отправителя

68-76
К сообщению добавляется расширение
SADB_EXT_ADDRESS_SRC
, содержащее адрес отправителя для соглашения о безопасности.

Значение протокола устанавливается равным нулю, что подразумевает действительность соглашения для всех протоколов. Длина префикса устанавливается равной соответствующей длине версии IP (то есть 32 разряда для IPv4 и 128 разрядов для IPv6). При расчете значения поля длины мы добавляем к реальному значению число 7 перед делением на 8, что гарантирует выравнивание по 64-разрядной границе, обязательное для всех расширений, передаваемых через сокеты PF_KEY. Структура

sockaddr
копируется в буфер после заголовка расширения.

Добавление адреса получателя

77-85
Адрес получателя добавляется в сообщение
SADB_EXT_ADDRESS_DST
. Процедура в точности совпадает с описанной выше.

Добавление ключа

86-94
К сообщению добавляется расширение
SADB_EXT_KEY_AUTH
, содержащее ключ авторизации. Расчет поля длины производится точно так же, как и для обоих адресов. Ключ переменной длины требует соответствующего количества дополняющих нулей. Мы устанавливаем значение количества битов и копируем ключ вслед за заголовком расширения.

Поделиться с друзьями: