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

ЖАНРЫ

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

Листинг 17.1. Структуры ifconf и ifreq, используемые в различных вызовах функции ioctl, относящихся к интерфейсам

//<net/if.h> struct ifconf {

int ifc_len; /* размер буфера, "значение-результат" */

union {

caddr_t ifcu_buf; /* ввод от пользователя к ядру */

struct ifreq *ifcu_req; /* ядро возвращает пользователю */

} ifc_ifcu;

};

#define ifc_buf ifc_ifcu.ifcu_buf /*
адрес буфера */

#define ifc_req ifc_ifcu.ifcu_req /* массив возвращенных структур */

#define IFNAMSIZ 16

struct ifreq {

char ifr_name[IFNAMSIZ]; /* имя интерфейса, например "le0" */

union {

struct sockaddr ifru_addr;

struct sockaddr ifru_dstaddr;

struct sockaddr ifru_broadaddr;

short ifru_flags;

int ifru_metric;

caddr_t ifru_data;

} ifr_ifru;

};

#define ifr_addr ifr_ifru.ifru_addr /* адрес */

#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* другой конец линии передачи, называемой

"точка-точка" */

#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* широковещательный адрес */

#define ifr_flags ifr_ifru.ifru_flags /* флаги */

#define ifr_metric ifr_ifru.ifru_metric /* метрика */

#define ifr_data ifr_ifru.ifru_data /* с использованием интерфейсом */

Прежде чем вызвать функцию

ioctl
, мы выделяем в памяти место для буфера и для структуры
ifconf
, а затем инициализируем эту структуру. Мы показываем это на рис. 17.1, предполагая, что наш буфер имеет размер 1024 байта. Третий аргумент функции
ioctl
— это указатель на нашу структуру
ifconf
.

Рис. 17.1. Инициализация структуры ifconf перед вызовом SIOCGIFCONF

Если мы предположим, что ядро возвращает две структуры

ifreq
, то при завершении функции
ioctl
мы можем получить ситуацию, представленную на рис. 17.2. Затененные области были изменены функцией
ioctl
. Буфер заполняется двумя структурами, и элемент
ifc_len
структуры
ifconf
обновляется, с тем чтобы соответствовать количеству информации, хранимой в буфере. Предполагается, что на этом рисунке каждая структура
ifreq
занимает 32
байта.

Рис. 17.2. Значения, возвращаемые в результате вызова SIOCGIFCONF

Указатель на структуру

ifreq
также используется в качестве аргумента оставшихся функций
ioctl
интерфейса, показанных в табл. 17.1, которые мы описываем в разделе 17.7. Отметим, что каждая структура
ifreq
содержит объединение (
union
), а директивы компилятора
#define
позволяют непосредственно обращаться к полям объединения по их именам. Помните о том, что в некоторых системах в объединение
ifr_ifru
добавлено много зависящих от реализации элементов.

17.6. Функция get_ifi_info

Поскольку многим программам нужно знать обо всех интерфейсах системы, мы разработаем нашу собственную функцию

get_ifi_info
, возвращающую связный список структур — по одной для каждого активного в настоящий момент интерфейса. В этом разделе мы покажем, как эта функция реализуется с помощью вызова
SIOCGIFCONF
функции
ioctl
, а в главе 18 мы создадим ее другую версию, использующую маршрутизирующие сокеты.

ПРИМЕЧАНИЕ

BSD/OS предоставляет функцию getifaddrs, имеющую аналогичную функциональность.

Поиск по всему дереву исходного кода BSD/OS 2.1 показывает, что 12 программ выполняют вызов SIOCGIFCONF функции ioctl для определения присутствующих интерфейсов.

Сначала мы определяем структуру

ifi_info
в новом заголовочном файле, который называется
unpifi.h
, показанном в листинге 17.2.

Листинг 17.2. Заголовочный файл unpifi.h

//ioctl/unpifi.h

1 /* Наш собственный заголовочный файл для программ, которым требуется

2 информация о конфигурации интерфейса. Включаем его вместо "unp.h". */

3 #ifndef __unp_ifi_h

4 #define __unp_ifi_h

5 #include "unp.h"

6 #include <net/if.h>

7 #define IFI_NAME 16 /* то же, что и IFNAMSIZ в заголовке <net/if.h> */

8 #define IFI_HADDR 8 /* с учетом 64-битового интерфейса EUI-64 в будущем */

9 struct ifi_info {

10 char ifi_name[IFI_NAME]; /* имя интерфейса, заканчивается

символом конца строки */

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