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

ЖАНРЫ

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

uint8_t sdl_len;

sa_family_t sdl_family; /* AF_LINK */

uint16_t sdl_index; /* индекс интерфейса, присвоенный системой,

если > 0 */

uint8_t sdl_type; /* тип интерфейса из <net/if_types.h>.

IFT_ETHER и т.д. */

uint8_t sdl_nlen; /* длина имени, начинается с sdl_data[0] */

uint8_t sdl_alen; /* длина адреса канального уровня */

uint8_t sdl_slen; /* адрес селектора канального уровня */

char sdl_data[12]; /*
минимальная рабочая область.

может быть больше; содержит имя

интерфейса и адрес канального уровня */

};

У каждого интерфейса имеется уникальный положительный индекс. Далее в этой главе мы увидим, каким образом он возвращается функциями

if_nametoindex
и
if_nameindex
. В главе 21 при обсуждении параметров многоадресных сокетов IPv6 и в главе 27 при обсуждении дополнительных параметров сокетов IPv6 и IPv4 мы вновь вернемся к этим функциям.

Элемент

sdl_data
содержит и имя, и адрес канального уровня (например, 48-разрядный MAC-адрес интерфейса Ethernet). Имя начинается с
sdl_data[0]
и не заканчивается нулем. Начало адреса канального уровня смещено на
sdl_nlen
байтов относительно начала имени. В этом заголовочном файле для возвращения указателя на адрес канального уровня задается следующий макрос:

#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))

Эти структуры адреса сокета имеют переменную длину [128, с. 89]. Если адрес канального уровня и имя превышают 12 байт, размер структуры будет больше 20 байт. В 32-разрядных системах размер обычно округляется в большую сторону, до следующего числа, кратного 4 байтам. Мы также увидим на рис. 22.1, что когда одна из этих структур возвращается параметром сокета

IP_RECVIF
, все три длины становятся нулевыми, а элемента
sdl_data
не существует.

18.3. Чтение и запись

Создав маршрутизирующий сокет, процесс может отправлять ядру команды путем записи в этот сокет и считывать из него информацию от ядра. Существует 12 различных команд маршрутизации, 5 из которых могут быть запущены процессом. Они определяются в заголовочном файле

<net/route.h>
и показаны в табл. 18.1.

Таблица 18.1. Типы сообщений, проходящих по маршрутизирующему сокету

Тип сообщения К ядру? От ядра? Описание Тип структуры
RTM_ADD Добавить маршрут rt_msghdr
RTM_CHANGE Поменять шлюз, метрику или флаги rt_msghdr
RTM_DELADDR Адрес был удален из интерфейса ifa_msghdr
RTM_DELETE Удалить маршрут rt_msghdr
RTM_GET Сообщить о метрике и других характеристиках маршрута rt_msghdr
RTM_IFINFO Находится
ли интерфейс в активном состоянии
if_msghdr
RTM_LOCK Блокировка указанной метрики rt_msghdr
RTM_LOSING Возможно, неправильный маршрут rt_msghdr
RTM_MISS Поиск этого адреса завершился неудачно rt_msghdr
RTM_NEWSDDR Адрес добавлен к интерфейсу ifa_msghdr
RTM_NEWMDDR Групповой адрес добавлен к интерфейсу ifma_msghdr
RTM_REDIRECT Ядро получило указание использовать другой маршрут rt_msghdr
RTM_RESOLVE Запрос на определение адреса канального уровня по адресу получателя rt_msghdr

На маршрутизирующем сокете происходит обмен пятью различными структурами, как показано в последнем столбце таблицы:

rt_msghdr
,
if_msghdr
,
if_announcemsghdr
,
ifma_msghdr
и
ifa_msghdr
. Эти структуры представлены в листинге 18.2.

Листинг 18.2.Пять структур, возвращаемых с маршрутизирующими сообщениями

struct rt_msghdr { /* из <net/route.h> */

u_short rtm_msglen; /* для пропуска некорректных сообщений */

u_char rtm_version; /* для обеспечения двоичной совместимости в будущем */

u_char rtm_type; /* тип сообщения */

u_short rtm_index; /* индекс интерфейса, с которым связан адрес */

int rtm_flags; /* флаги */

int rtm_addrs; /* битовая маска, идентифицирующая sockaddr (структуру адреса

сокета) в msg */

pid_t rtm_pid; /* идентификация отправителя */

int rtm_seq; /* для идентификации действия отправителем */

int rtm_errno; /* причина неудачного выполнения */

int rtm_use; /* из rtentry */

u_long rtm_inits; /* какую метрику мы инициализируем */

struct rt_metrics rtm_rmx; /* сами метрики */

};

struct if_msghdr { /* из <net/if.h> */

u_short ifm_msglen; /* для пропуска некорректных сообщений */

u_char ifm_version; /* для обеспечения двоичной совместимости в будущем */

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