UNIX: разработка сетевых приложений
Шрифт:
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));
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
.
SIOCGIFMETRIC
. Возвращает метрику интерфейса в элементе ifr_metric
. Метрика поддерживается ядром для каждого интерфейса, но используется демоном маршрутизации routed
. Метрика интерфейса добавляется к счетчику количества переходов.
Поделиться с друзьями: