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

ЖАНРЫ

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

57 memcpy(ifi->ifi_haddr, ifisave->ifi_haddr, IFI_HADDR);

58 }

59 ifam = (struct ifa_msghdr*)next;

60 sa = (struct sockaddr*)(ifam + 1);

61 get_rtaddrs(ifam->ifam_addrs, sa, rti_info);

62 if ((sa = rti_infо[RTAX_IFA]) != NULL) {

63 ifi->ifi_addr = Calloc(1, sa->sa_len);

64 memcpy(ifi->ifi_addr, sa, sa->sa_len);

65 }

66 if ((flags & IFF_BROADCAST) && (sa = rti_infо[RTAX_BRD]) |= NULL) {

67 ifi->ifi_brdaddr = Calloc(1, sa->sa_len);

68 memcpy(ifi->ifi_brdaddr, sa, sa->sa_len);

69 }

70 if ((flags & IFF_POINTOPOINT) &&

71 (sa = rti_infо[RTAX_BRD]) != NULL) {

72 ifi->ifi_dstaddr = Calloc(1, sa->sa_len);

73 memcpy(ifi->ifi_dstaddr, sa, sa->sa_len);

74 }

75 } else

76 err_quit("unexpected message type %d", ifm->ifm_type);

77 }

78 /* "ifihead"
указывает на первую структуру в связном списке */

79 return (ifihead); /* указатель на первую структуру в связном списке */

80 }

Возвращение IP-адресов

44-65
Сообщение
RTM_NEWADDR
возвращается функцией
sysctl
для каждого адреса, связанного с интерфейсом: для первичного адреса и для всех альтернативных имен (псевдонимов). Если мы уже заполнили IP-адрес для этого интерфейса, то мы имеем дело с альтернативным именем. Поэтому если вызывающему процессу нужен адрес псевдонима, мы должны выделить память для другой структуры
ifi_info
, скопировать заполненные поля и затем заполнить возвращенный адрес.

Возвращение широковещательного адреса и адреса получателя

66-75
Если интерфейс поддерживает широковещательную передачу, возвращается широковещательный адрес, а если интерфейс является интерфейсом типа «точка-точка», возвращается адрес получателя.

18.6. Функции имени и индекса интерфейса

Документ RFC 3493 [36] определяет четыре функции, обрабатывающие имена и индексы интерфейсов. Эти четыре функции используются во многих случаях, когда необходимо описать интерфейс. Они были предложены в процессе разработки API IPv6 (главы 21 и 27), однако индексы интерфейсов имеются и в API IPv4 (например, в вызове

IP_RECVIF
или
AF_LINK
для маршрутизирующего сокета). Основной принцип, объявляемый в этом документе, состоит в том, что каждый интерфейс имеет уникальное имя и уникальный положительный индекс (нуль в качестве индекса никогда не используется).

#include <net/if.h>

unsigned int if_nametoindex(const char * ifname);

Возвращает: положительный индекс интерфейса в случае успешного выполнения, 0 в случае ошибки

char *if_indextoname(unsigned int ifindex, char * ifname);

Возвращает:
указатель на имя интерфейса в случае успешного выполнения, NULL в случае ошибки

struct if_nameindex *if_nameindex(void);

Возвращает: непустой указатель в случае успешного выполнения, NULL в случае ошибки

void if_freenameindex(struct if_nameindex * Iptr);

Функция

if_nametoindex
возвращает индекс интерфейса, имеющего имя
ifname
. Функция
if_indextoname
возвращает указатель на имя интерфейса, если задан его индекс
ifindex
. Аргумент
ifname
указывает на буфер размера
IFNAMSIZ
(определяемый в заголовочном файле <net/if.h> из листинга 17.1), который вызывающий процесс должен выделить для хранения результата, и этот указатель возвращается в случае успешного выполнения функции
if_indextoname
.

Функция

if_nameindex
возвращает указатель на массив структур
if_nameindex
:

struct if_nameindex {

unsigned int if_index; /* 1, 2. ... */

char *if_name; /* имя, завершаемое нулем: "le0", ... */

};

Последняя запись в этом массиве содержит структуру с нулевым индексом

if_index
и с пустым указателем
ifname
. Память для этого массива, а также для имен, на которые указывают элементы массива, выделяется динамически и освобождается при вызове функции
if_freenameindex
.

Теперь мы представим реализацию этих четырех функций с использованием маршрутизирующих сокетов.

Функция if_nametoindex

В листинге 18.11 показана функция

if_nametoindex
.

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

//libroute/if_nametoindex.c

1 #include "unpifi.h"

2 #include "unproute.h"

3 unsigned int

4 if_nametoindex(const char *name)

5 {

6 unsigned int idx, namelen;

7 char *buf, *next, *lim;

8 size_t len;

9 struct if_msghdr *ifm;

10 struct sockadd *sa, *rti_info[RTAX_MAX];

11 struct sockaddr_dl *sdl;

12 if ((buf = net_rt_iflist(0, 0, &len)) == NULL)

13 return(0);

14 namelen = strlen(name);

15 lim = buf + len;

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

17 ifm = (struct if_msghdr*)next;

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

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

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

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