Чтение онлайн

ЖАНРЫ

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

11 short ifi_index; /* индекс интерфейса */

12 short ifi_mtu; /* MTU для интерфейса */

13 u_char ifi_haddr[IFI_HADDR]; /* аппаратный адрес */

14 u_short ifi_hlen; /* количество байтов в аппаратном адресе: 0, 6, 8 */

15 short ifi_flags; /* константы IFF_xxx из <net/if.h> */

16 short if_myflags; /* наши флаги IFI_xxx */

17 struct sockaddr *ifi_addr; /* первичный адрес */

18 struct sockaddr *ifi_brdaddr; /*
широковещательный адрес */

19 struct sockaddr *ifi_dstaddr; /* адрес получателя */

20 s truct ifi_info *ifi_next; /* следующая из этих структур */

21 };

22 #define IFI_ALIAS 1 /* ifi_addr - это псевдоним */

23 /* прототипы функций */

24 struct ifi_info *get_ifi_info((int, int);

25 struct ifi_info *Get_ifi_info(int, int);

26 void free_ifi_info(struct ifi_info*);

27 #endif /* _unp_ifi_h */

9-21
Связный список этих структур возвращается нашей функцией. Элемент
ifi_next
каждой структуры указывает на следующую структуру. Мы возвращаем в этой структуре информацию, которая может быть востребована в типичном приложении: имя интерфейса, индекс интерфейса, MTU, аппаратный адрес (например, адрес Ethernet), флаги интерфейса (чтобы позволить приложению определить, поддерживает ли приложение широковещательную или многоадресную передачу и относится ли этот интерфейс к типу «точка-точка»), адрес интерфейса, широковещательный адрес, адрес получателя для связи «точка-точка». Вся память, используемая для хранения структур
ifi_info
вместе со структурами адреса сокета, содержащимися в них, выделяется динамически. Следовательно, мы также предоставляем функцию
free_ifi_info
для освобождения всей этой памяти.

Перед тем как представить реализацию нашей функции

ifi_info
, мы покажем простую программу, которая вызывает эту функцию и затем выводит информацию. Эта программа, представленная в листинге 17.3, является уменьшенной версией программы
ifconfig
.

Листинг 17.3. Программа prifinfo, вызывающая нашу функцию ifi_info

//ioctl/prifinfo.c

1 #include "unpifi.h"

2 int

3 main(int argc, char **argv)

4 {

5 struct ifi_info *ifi, *ifihead;

6 struct sockaddr *sa;

7 u_char *ptr;

8 int i, family, doaliases;

9 if (argc != 3)

10 err_quit("usage: prifinfo <inet4|inet6> <doaliases>");

11 if (strcmp(argv[1], "inet4") == 0)

12 family = AF_INET;

13 else if (strcmp(argv[1], "inet6") == 0)

14 family = AF_INET6;

15 else

16 err_quit("invalid <address-family>");

17 doaliases = atoi(argv[2]);

18 for (ifihead = ifi = Get_ifi_info(family, doaliases);

19 ifi ! = NULL; ifi = ifi->ifi_next) {

20 printf("%s: <", ifi->ifi_name);

21 if (ifi->ifi_index != 0)

22 printf("%d) ", ifi->ifi_index);

23 printf("<");

24 if (ifi->ifi_flags & IFF_UP) printf ("UP ");

25 if (ifi->ifi_flags & IFF_BROADCAST) printf("BCAST ");

26 if (ifi->ifi_flags & IFF_MULTICAST) printf("MCAST ");

27 if (ifi->ifi_flags & IFF_LOOPBACK) printf("LOOP ");

28 if (ifi->ifi_flags & IFF_POINTOPOINT) printf("P2P ");

29 printf(">\n");

30 if ((i = ifi->ifi_hlen) > 0) {

31 ptr = ifi->ifi_haddr;

32 do {

33 printf("%s%x", (i == ifi->ifi_hlen) ? " " : ":", *ptr++);

34 } while (--i > 0);

35 printf("\n");

36 }

37 if (ifi->ifi_mtu != 0)

38 printf(" MTU: %d\n". ifi->ifi_mtu);

39 if ((sa = ifi->ifi_addr) != NULL)

40 printf(" IP addr: %s\n", Sock_ntop_host(sa, sizeof(*sa)));

41 if ((sa = ifi->ifi_brdaddr) != NULL)

42 printf(" broadcast addr, %s\n",

43 Sock_ntop_host(sa, sizeof(*sa)));

44 if ((sa = ifi->ifi_dstaddr) != NULL)

45 printf(" destination addr %s\n\",

46 Sock_ntop_host(sa, sizeof(*sa)));

47 }

48 free_ifi_info(ifihead);

49 exit(0);

59 }

18-47
Программа представляет собой цикл
for
, в котором один раз вызывается функция
get_ifi_info
, а затем последовательно перебираются все возвращаемые структуры
ifi_info
.

20-36
Выводятся все имена интерфейсов и флаги. Если длина аппаратного адреса больше нуля, он выводится в виде шестнадцатеричного числа (наша функция
get_ifi_info
возвращает нулевую длину
ifi_hlen
, если адрес недоступен).

Поделиться с друзьями: