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

Функция if_nameindex

Функция if_nameindex

Следующая функция, if_nameindex, возвращает массив структур if_nameindex, содержащих все имена интерфейсов и индексы. Она показана в листинге 18.13.

Листинг 18.13. Возвращение всех имен и индексов интерфейсов

//libroute/if_nameindex.c
 1 #include "unpifi.h"
 2 #include "unproute.h"
 3 struct if_nameindex*
 4 if_nameindex(void)
 5 {
 6  char *buf, *next, *lim;
 7  size_t len;
 8  struct if_msghdr *ifm;
 9  struct sockaddr *sa, *rti_info[RTAX_MAX];
10  struct sockaddr_dl *sdl;
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 и нулевой индекс.

Оглавление книги


Генерация: 1.160. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз