Литмир - Электронная Библиотека
Содержание  
A
A

11  struct if_nameindex *result, *ifptr;

12  char *namptr;

13  if ((buf = net_it_iflist(0, 0, &len)) == NULL)

14   return (NULL);

15  if ((result = malloc(len)) == NULL) /* завышенная оценка */

16   return (NULL);

17  ifptr = result;

18  namptr = (char*)result + len; /* имена начинаются с конца буфера */

19  lim = buf + len;

20  for (next = buf; next < lim; next += ifm->ifm_msglen) {

21   ifm = (struct if_msghdr*)next;

22   if (ifm->ifm_type == RTM_IFINFO) {

23    sa = (struct sockaddr*)(ifm + 1);

24    get_rtaddrs(ifm->ifm_addrs, sa, rti_info);

25    if ((sa = rti_infо[RTAX_IFP]) != NULL) {

26     if (sa->sa_family == AF_LINK) {

27      sdl = (struct sockaddr_in*)sa;

28      namptr -= sdl->sdl_nlen + 1;

29      strncpy(namptr, &sdl->sdl_data[0], sdl->sdl_nlen);

30      namptr[sdl->sdl_nlen] = 0; /* завершающий нуль */

31      ifptr->if_name = namptr;

32      ifptr->if_index = sdl->sdl_index;

33      ifptr++;

34     }

35    }

36   }

37  }

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, освобождает память, которая была выделена для массива структур

if_nameindex
и хранящихся в нем имен.

Листинг 18.14. Освобождение памяти, выделенной функцией if_nameindex

43 void

44 if_freenameindex(struct if_nameindex *ptr)

45 {

46  free(ptr);

47 }

Эта функция тривиальна, поскольку мы хранили и массив структур, и имена в одном и том же буфере. Если бы мы каждый раз вызывали функцию

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. В этом семействе поддерживаются только символьные сокеты.

210
{"b":"225366","o":1}