131     memcpy(ifi->ifi_dstaddr, sin6ptr,

132     sizeof(struct sockaddr_in6));

133    }

134 #endif

135    break;

136   default:

137    break;

138   }

139  }

140  free(buf);

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

142 }

102-104 Мы копируем IP-адрес, возвращенный из нашего начального вызова SIOCGIFCONF функции ioctl, в структуру, которую мы создаем.

106-119 Если интерфейс поддерживает широковещательную передачу, мы получаем широковещательный адрес с помощью вызова SIOCGIFBRDADDR функции ioctl. Мы выделяем память для структуры адреса сокета, содержащей этот адрес, и добавляем ее к структуре ifi_info, которую мы создаем. Аналогично, если интерфейс является интерфейсом типа «точка-точка», вызов SIOCGIFBRDADDR возвращает IP-адрес другого конца связи.

123-133 Обработка случая IPv6 — полная аналогия IPv4 за тем исключением, что вызов SIOCGIFBRDADDR не делается, потому что IPv6 не поддерживает широковещательную передачу.

В листинге 17.8 показана функция free_ifi_info, которой передается указатель, возвращенный функцией get_ifi_info. Эта функция освобождает всю динамически выделенную память.

Листинг 17.8. Функция free_ifi_info: освобождение памяти, которая была динамически выделена функцией get_ifi_info

//iосtl/get_ifi_info.c

143 void

144 free_ifi_info(struct ifi_info *ifihead)

145 {

146  struct ifi_info *ifi, *ifinext;

147  for (ifi = ifihead; ifi != NULL; ifi = ifinext) {

148   if (ifi->ifi_addr != NULL)

149    free(ifi->ifi_addr);

150   if (ifi->ifi_brdaddr != NULL)

151    free(ifi->ifi_brdaddr);

152   if (ifi->ifi_dstaddr != NULL)

153    free(ifi->ifi_dstaddr);

154   ifinext = ifi->ifi_next; /* невозможно получить ifi_next

                                   после вызова freed */

155   free(ifi);

156  }

157 }

17.7. Операции с интерфейсами

Как мы показали в предыдущем разделе, запрос SIOCGIFCONF возвращает имя и структуру адреса сокета для каждого сконфигурированного интерфейса. Существует множество других вызовов, позволяющих установить или получить все остальные характеристики интерфейса. Версия get этих вызовов (SIOCGxxx) часто запускается программой netstat, а версия set (SIOCSxxx) — программой ifconfig. Любой пользователь может получить информацию об интерфейсе, в то время как установка этой информации требует прав привилегированного пользователя.

Эти вызовы получают или возвращают структуру ifreq, адрес которой задается в качестве третьего аргумента функции ioctl. Интерфейс всегда идентифицируется по имени: le0, lo0, ppp0, — то есть по имени, заданному в элементе ifr_name структуры ifreq.

Многие из этих запросов используют структуру адреса сокета, для того чтобы задать или возвратить IP-адрес или маску адреса. Для IPv4 адрес или маска содержится в элементе sin_addr из структуры адреса сокета Интернета. Для IPv6 они помещаются в элемент sin6_addr структуры адреса сокета IPv6.

■ SIOCGIFADDR. Возвращает адрес направленной передачи в элементе ifr_addr.

■ SIOCSIFADDR. Устанавливает адрес интерфейса из элемента ifr_addr. Также вызывается функция инициализации для интерфейса.

■ SIOCGIFFLAGS. Возвращает флаги интерфейса в элементе ifr_flags. Имена различных флагов определяются в виде IFF_xxx в заголовочном файле <net/if.h>. Флаги указывают, например, включен ли интерфейс (IFF_UP), является ли он интерфейсом типа «точка-точка» (IFF_POINTOPOINT), поддерживает ли широковещательную передачу (IFF_BROADCAST) и т.д.

■ SIOCSIFFLAGS. Устанавливает флаги из элемента ifr_flags.

■ SIOCGIFDSTADDR. Возвращает адрес типа «точка-точка» в элементе ifr_dstaddr.

■ SIOCSIFDSTADDR. Устанавливает адрес типа «точка-точка» из элемента ifr_dstaddr.

■ SIOCGIFBRDADDR. Возвращает широковещательный адрес в элементе ifr_broadaddr. Приложение сначала должно получить флаги интерфейса, а затем сделать корректный вызов: SIOCGIFBRDADDR для широковещательного интерфейса или SIOCGIFDSTADDR — для интерфейса типа «точка-точка».

■ SIOCSIFBRDADDR. Устанавливает широковещательный адрес из элемента ifr_broadaddr.

■ SIOCGIFNETMASK. Возвращает маску подсети в элементе ifr_addr.

■ SIOCSIFNETMASK. Устанавливает маску подсети из элемента ifr_addr.


Перейти на страницу:
Изменить размер шрифта: