23 int msglen;
24 struct sadb_msg *msgp;
25 msglen = Read(s, &buf, sizeof(buf));
26 msgp = (struct sadb_msg*)&buf;
27 print_sadb_msg(msgp, msglen);
28 if (msgp->sadb_msg_seq == 0)
29 goteof = 1;
30 }
31 close(s);
32 }
33 int
34 main(int argc, char **argv)
35 {
36 int satype = SADB_SATYPE_UNSPEC;
37 int c;
38 opterr = 0; /* отключение записи в stderr для getopt() */
39 while ((c = getopt(argc, argv, "t:")) != -1) {
40 switch (c) {
41 case 't':
42 if ((satype = getsatypebyname(optarg)) == -1)
43 err_quit("invalid -t option %s", optarg);
44 break;
45 default:
46 err_quit("unrecognized option: %c", c);
47 }
48 }
49 sadb_dump(satype);
50 }
В этом листинге мы впервые встречаемся с функцией
getopt
, определяемой стандартом POSIX. Третий аргумент представляет собой строку символов, которые могут быть приняты в качестве аргументов командной строки: в нашем случае только
t
. За символом следует двоеточие, означающее, что за ключом должно быть указано численное значение. В программах, которые могут принимать несколько аргументов, эти аргументы должны объединяться. Например, в листинге 29.3 соответствующая строка имеет вид
0i:l:v
. Это означает, что ключи
i
и
l
сопровождаются дополнительными аргументами, а
0
и
v
— не сопровождаются.
Эта функция работает с четырьмя глобальными переменными, определенными в заголовочном файле
<unistd.h>
.
extern char *optarg;
extern int optind, opterr, optopt;
Перед вызовом
getopt
мы устанавливаем
opterr
в нуль, чтобы функция не направляла сообщений об ошибках в стандартный поток вывода этих сообщений, потому что мы хотим обрабатывать их самостоятельно. В стандарте POSIX говорится, что если первый символ третьего аргумента функции — двоеточие, то это тоже должно отключать вывод сообщений в стандартный поток сообщений об ошибках, однако не все реализации в настоящий момент выполняют данное требование.
Открытие сокета PF_KEY
1-8
Сначала мы открываем сокет
PF_KEY
. Для этого требуются определенные привилегии, поскольку сокет дает доступ к управлению ключами.
Формирование запроса SADB_DUMP
9-15
Мы начинаем с обнуления структуры
sadb_msg
, что позволяет нам не инициализировать поля, которые должны остаться нулевыми. Затем мы заполняем все интересующие нас поля по отдельности.
Если при открытии сокета в качестве третьего аргумента использовалась константа
PF_KEY_V2
, все сообщения, направляемые в такой сокет, должны иметь версию
PF_KEY_V2
. Нужный нам тип сообщения —
SADB_DUMP
. Длина сообщения устанавливается равной длине заголовка без расширений, поскольку для запроса дампа расширения не нужны. Наконец, идентификатор процесса устанавливается равным идентификатору нашего процесса. Это обязательное условие для всех сообщений.
Отображение и отправка сообщения SADB_DUMP
16-18
Мы отображаем сообщение при помощи функции
print_sadb_msg
. Мы не приводим листинг этой функции, потому что он достаточно длинный и не представляет особого интереса, однако он включен в набор свободно распространяемых программ, доступный для скачивания с сайта этой книги. Функция принимает сообщение, подготовленное к отправке или полученное от ядра, и выводит всю содержащуюся в этом сообщении информацию в удобной для чтения форме.
После вызова функции подготовленное сообщение записывается в сокет.
Чтение ответов
19-30
Программа считывает сообщения и выводит их в цикле при помощи функции
print_sadb_msg
. Последнее сообщение последовательности имеет порядковый номер 0, что мы трактуем как «конец файла».
Закрытие сокета PF_KEY
31
Мы закрываем открытый в начале работы сокет управления ключами.
Обработка аргументов командной строки
38-48
На долю функции
main
остается не так уж много работы. Программа принимает единственный аргумент — тип соглашений о безопасности, которые должны быть запрошены из базы. По умолчанию тип равен
SADB_SATYPE_UNSPEC
. Указав другой тип в аргументе командной строки, пользователь может выбрать интересующие его записи. Наша программа вызывает нашу же функцию
getsatypebyname
, возвращающую значение типа (константу) по его названию.
Вызов функции sadb_dump
49
Наконец, мы вызываем функцию
sadb_dump
, которая уже была описана.
Пробный запуск
Ниже приведен пример выполнения программы дампа базы данных безопасности в системе с двумя статическими соглашениями о безопасности.
macosx % <b>dump Sending dump message:</b>
SADB Message Dump, errno 0, satype Unspecified, seq 0, pid 20623
Messages returned:
SADB Message Dump, errno 0. satype IPsec AH, seq 1, pid 20623
SA: SPI=258 Replay Window=0 State=Mature
Authentication Algorithm: HMAC-MD5
Encryption Algorithm: None