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

64-72
 Нам нужно обнаружить все альтернативные имена (псевдонимы), которые могут существовать для интерфейса, то есть присвоенные этому интерфейсу дополнительные адреса. Обратите внимание в наших примерах, следующих за листингом 17.3, что в Solaris псевдоним содержит двоеточие, в то время как в 4.4BSD имя интерфейса в псевдониме не изменяется. Чтобы обработать оба случая, мы сохраняем последнее имя интерфейса в
lastname
и сравниваем его только до двоеточия, если оно присутствует. Если двоеточия нет, мы игнорируем этот интерфейс в том случае, когда имя эквивалентно последнему обработанному интерфейсу.

Получение флагов интерфейса

73-77
 Мы выполняем вызов
SIOCGIFFLAGS
функции
ioctl
(см. раздел 16.5), чтобы получить флаги интерфейса. Третий аргумент функции
ioctl
— это указатель на структуру
ifreq
, содержащую имя интерфейса, для которого мы хотим получить флаги. Мы создаем копию структуры
ifreq
, перед тем как запустить функцию ioctl, поскольку в противном случае этот вызов перезаписал бы IP-адрес интерфейса, потому что оба они являются элементами одного и того же объединения из листинга 17.1. Если интерфейс не активен, мы игнорируем его.

В листинге 17.6 представлена третья часть нашей функции.

Листинг 17.6. Получение и возвращение адресов интерфейса

//ioctl/get_ifi_infо.c

78   ifi = Calloc(1, sizeof(struct ifi_info));

79   *ifipnext = ifi; /* prev указывает на новую структуру */

80   ifipnext = &ifi->ifi_next; /* сюда указывает указатель на

                                   следующую структуру */

81   ifi->ifi_flags = flags; /* значения IFF_xxx */

82   ifi->ifi_myflags = myflags; /* значения IFI_xxx */

83 #if defined(SIOCGIFMTU) && defined(HAVE_STRUCT_IFREQ_IFR_MTU)

84   Ioctl(sockfd, SIOCGIFMTU, &ifrcopy);

85   ifi->ifi_mtu = ifrcopy.ifr_mtu;

86 #else

87   ifi->ifi_mtu = 0;

88 #endif

89   memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);

90   ifi->ifi_name[IFI_NAME-1] = '\0';

91   /* если sockaddr_dl относится к другому интерфейсу, он игнорируется */

92   if (sdlname == NULL || strcmp(sdlname, ifr->ifr_name) != 0)

93    idx = hlen = 0;

94   ifi->ifi_index = idx;

95   ifi->ifi_hlen = hlen;

96   if (ifi->ifi_hlen > IFI_HADDR)

97    ifi->ifi_hlen = IFI_HADDR;

98   if (hlen)

99    memcpy(ifi->ifi_haddr, haddr, ifi->ifi_hlen);

Выделение памяти и инициализация структуры ifi_info

78-99
На этом этапе мы знаем, что возвратим данный интерфейс вызывающему процессу. Мы выделяем память для нашей структуры
ifi_info
и добавляем ее в конец связного списка, который мы создаем. Мы копируем флаги и имя интерфейса в эту структуру. Далее мы проверяем, заканчивается ли имя интерфейса нулем, и поскольку функция
callос
инициализирует выделенную в памяти область нулями, мы знаем, что
ifi_hlen
инициализируется нулем, a
ifi_next
— пустым указателем.

В листинге 17.7 представлена последняя часть нашей функции.

Листинг 17.7. Получение и возврат адреса интерфейса

100   switch (ifr->ifr_addr.sa_family) {

101   case AF_INET:

102    sinptr = (struct sockaddr_in*)&ifr->ifr_addr;

103    ifi->ifi_addr = Calloc(1, sizeof(struct sockaddr_in));

104    memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));

105 #ifdef SIOCGIFBRDADDR

106    if (flags & IFF_BROADCAST) {

107     Ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy);

108     sinptr = (struct sockaddr_in*) &ifrcopy.ifr_broadaddr;

109     ifi->ifi_brdaddr = Calloc(1, sizeof(struct sockaddr_in));

110     memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));

111    }

112 #endif

113 #ifdef SIOCGIFDSTADDR

114    if (flags & IFF_POINTOPOINT) {

115     Ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);

116     sinptr = (struct sockaddr_in*) &ifrcopy.ifr_dstaddr;

117     ifi->ifi_dstaddr = Calloc(1, sizeof(struct sockaddr_in));

118     memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));

119    }

120 #endif

121    break;

122   case AF_INET6:

123    sin6ptr = (struct sockaddr_in6*)&ifr->ifr_addr;

124    ifi->ifi_addr = Calloc(1, sizeof(struct sockaddr_in6));

125    memcpy(ifi->ifi_addr, sin6ptr, sizeof(struct sockaddr_in6));

126 #ifdef SIOCGIFDSTADDR

127    if (flags & IFF_POINTOPOINT) {

128     Ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);

129     sin6ptr = (struct sockaddr_in6*)&ifrcopy.ifr_dstaddf;

130     ifi->ifi_dstaddr = Calloc(1, sizeof(struct sockaddr_in6));

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