UNIX: разработка сетевых приложений
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Как и в предыдущей программе, мы открываем сокет PF_KEY и сохраняем идентификатор нашего процесса для последующего его использования.55-56Формирование общего заголовка сообщенийМы формируем заголовок сообщения47-56. ПолеSADB_ADDустанавливается непосредственно перед отправкой сообщения, поскольку оно должно соответствовать истинной его длине. В переменнойsadb_msg_lenхранится текущая длина сообщения, а указатель р всегда указывает на первый неиспользуемый байт буфера.lenДобавление расширения SAМы добавляем обязательное расширение57-67(см. листинг 19.3). ПолеSAдолжно иметь сетевой порядок байтов, поэтому нам приходится применять функциюsadb_sa_spiк значению в порядке байтов узла. Мы отключаем защиту от повторов и устанавливаем состояниеhtonlравнымSA(см. табл. 19.4). Алгоритм аутентификации выбирается в соответствии с аргументом командной строки, а шифрование отключается при помощи константыSADB_SASTATE_MATURE.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Запись сообщения в сокетМы выводим сообщение на экран вызовом функции95-98, после чего записываем его в сокет.print_sadb_msgСчитывание ответаМы считываем все сообщения из сокета до тех пор, пока не будет получено сообщение, адресованное нашему процессу (проверяется по PID) и имеющее тип99-111. Это сообщение выводится на экран функцийSADB_ADD, после чего программа завершает работу.print_sadb_msgПример
Мы запускаем программу, требуя от нее установки соглашения о безопасности, касающегося трафика между узлами 127.0.0.1 и 127.0.0.1 (то есть локального трафика):
macosx % <b>add 127.0.0.1 127.0.0.1 HMAC-SHA-1-96 160 \</b><b> 0123456789abcdef0123456789abcdef01234567</b>Sending add message:SADB Message Add, errno 0, satype IPsec AH, seq 0, pid 6246SA: SPI=39030 Replay Window=0 State=MatureAuthentication Algorithm: HMAC-SHA-1Encryption Algorithm: NoneSource address: 127.0.0.1/32Dest address: 127.0.0.1/32Authentication key. 160 bits: 0x0123456789abcdef0123456789abcdef01234567Reply returned:SADB Message Add, errno 0, satype IPsec AH, seq 0, pid 6246SA: SPI=39030 Replay Window=0 State=MatureAuthentication Algorithm: HMAC-SHA-1Encryption Algorithm: NoneSource address: 127.0.0.1/32Dest address: 127.0.0.1/32Обратите внимание, что в ответе системы отсутствует ключ. Дело в том; что ответ направляется на все сокеты PF_KEY, которые, однако, могут принадлежать к разным доменам, а данные о ключах не должны передаваться между доменами. После добавления записи в базу данных мы даем команду
, чтобы проверить, задействуется ли соглашение о безопасности, после чего запрашиваем дамп базы данных и смотрим, что в ней изменилось.ping 127.0.0.1macosx % <b>dump</b>