38 ifptr->if_name = NULL; /* отмечаем конец массива структур */
39 ifptr->if_index = 0;
40 free(buf);
41 return (result); /* вызывающий процесс должен освободить память
с помощью free, когда все сделано */
43 }
Получение списка интерфейсов, выделение места для результата
13-18
Мы вызываем нашу функцию
net_rt_iflist
для возвращения списка интерфейсов. Мы также используем возвращаемый размер в качестве размера буфера, который мы размещаем в памяти для записи массива возвращаемых структур
if_nameindex
. Оценка необходимого размера буфера несколько завышена, но это проще, чем проходить список интерфейсов дважды: один раз для подсчета числа интерфейсов и общего размера имен, а второй — для записи этой информации. Мы создаем массив
if_nameindex
в начале этого буфера и записываем имена интерфейсов, начиная с конца буфера.
Обработка только сообщений RTM_IFINFO
22-36
Мы обрабатываем все сообщения, ища сообщения
RTM_IFINFO
и следующие за ними структуры адреса сокета. Имя и индекс интерфейса записываются в создаваемый нами массив.
Завершение массива
38-39
Последняя запись в массиве имеет пустой указатель
if_name
и нулевой индекс.
Функция if_freenameindex
Последняя функция, показанная в листинге 18.13, освобождает память, которая была выделена для массива структур
Эта функция тривиальна, поскольку мы хранили и массив структур, и имена в одном и том же буфере. Если бы мы каждый раз вызывали функцию
malloc
, то для освобождения памяти нам бы пришлось проходить через весь массив, освобождать память, выделенную для каждого имени, а затем удалять сам массив (используя функцию
free
).
18.7. Резюме
Последняя из структур адреса сокета, с которой мы встретились в книге, это
sockaddr_dl
— структура адреса сокета канального уровня, имеющая переменную длину. Ядра Беркли-реализаций связывают их с интерфейсами, возвращая в одной из этих структур индекс интерфейса, его имя и аппаратный адрес.
В маршрутизирующий сокет процессом могут быть записаны 5 типов сообщений, и 12 различных сообщений могут быть асинхронно возвращены ядром через маршрутизирующий сокет. Мы привели пример, когда процесс запрашивает у ядра информацию о записи в таблице маршрутизации и ядро отвечает со всеми подробностями. Ответы ядра могут содержать до восьми структур адреса сокета, поэтому нам приходится анализировать сообщение, чтобы получить все фрагменты информации.
Функция
sysctl
предоставляет общий способ получения и хранения параметров операционной системы. При выполнении функции
sysctl
нас интересует получение следующей информации:
список интерфейсов;
таблица маршрутизации;
кэш ARP.
Изменения API сокетов, требуемые IPv6, включают четыре функции для сопоставления имен интерфейсов и их индексов. Каждому интерфейсу присваивается уникальный положительный индекс. В Беркли-реализациях с каждым интерфейсом уже связан индекс, поэтому нам несложно реализовать эти функции с помощью функции
sysctl
.
Упражнения
1. Что, как вы считаете, будет хранить поле
sdl_len
в структуре адреса сокета канального уровня для устройства с именем
eth10
, адрес канального уровня которого является 64-разрядным адресом IEEE EUI-64?
2. В листинге 18.3 отключите параметр сокета
SO_USELOOPBACK
перед вызовом функции
write
. Что происходит?
Глава 19
Сокеты управления ключами
19.1. Введение
С появлением архитектуры безопасности IP (IPSec, см. RFC 2401 [64]) возникла потребность в стандартном механизме управления индивидуальными ключами шифрования и авторизации. Документ RFC 2367 [73] предлагает универсальный интерфейс управления ключами, который может использоваться с IPSec и иными криптографическими сетевыми службами. Подобно маршрутизирующим сокетам, этот интерфейс принадлежит к отдельному семейству протоколов, которое называется PF_KEY. В этом семействе поддерживаются только символьные сокеты.