u_short ifm_index; /* индекс интерфейса, с которым связан адрес */
struct if_data ifm_data; /* статистические и другие сведения */
};
struct ifa_msghdr { /* из <net/if.h> */
u_short ifam_msglen; /* для пропуска некорректных сообщений */
u_char ifam_version; /*
для обеспечения двоичной совместимости в будущем */
u_char ifam_type; /* тип сообщения */
int ifam_addrs; /* как rtm_addrs */
int ifam_flags; /* значение ifa_flags */
u_short ifam_index; /* индекс интерфейса, с которым связан адрес */
int ifam_metric; /* значение ifa_metric */
};
struct ifma_msghdr { /* из <net/if.h> */
u_short ifmam_msglen; /* для пропуска некорректных сообщений */
u_char ifmam_version; /* для обеспечения двоичной совместимости в будущем */
u_char ifmam_type; /* тип сообщения */
int ifmam_addrs; /* аналог rtm_addrs */
int ifmam_flags; /* значение ifa_flags */
u_short ifmam_index; /* индекс связанного ifp */
};
struct if_announcemsghdr { /* из <net/if.h> */
u_short ifan_msglen; /* для пропуска некорректных сообщений */
u_char ifan_version; /* для обеспечения двоичной совместимости в будущем */
u_char ifan_type; /* тип сообщения */
u_short ifan_index; /* индекс связанного ifp */
char ifan_name[IFNAMSIZ]; /* название интерфейса, напр. "en0" */
u_short ifan_what; /* тип объявления */
};
Первые три элемента каждой структуры одни и те же: длина, версия и тип сообщения. Тип — это одна из констант из первого столбца табл. 18.1. Элемент длины
xxx_msglen
позволяет приложению пропускать типы сообщений, которые оно не распознает.
Элементы
rtm_addrs
,
ifm_addrs
и
ifam_addrs
являются битовыми масками, указывающими, какая из возможных восьми структур адреса сокета следует за сообщением. В табл. 18.2 показаны константы и значения для битовой маски, определяемые в заголовочном файле
<net/route.h>
.
Таблица 18.2. Константы, используемые для ссылки на структуры адреса сокета в маршрутизирующих сообщениях
Битовая маска, константа
Битовая маска, значение
Индекс массива, константа
Индекс массива, значение
Структура адреса сокета содержит
RTA_DST
0x01
RTAX_DST
0
Адрес получателя
RTA_GATEWAY
0x02
RTAX_GATEWAY
1
Адрес шлюза
RTA_NETMASK
0x04
RTAX_NETMASK
2
Маска сети
RTA_GENMASK
0x08
RTAX_GENMASK
3
Маска
клонирования
RTA_IFP
0x10
RTAX_IFP
4
Имя интерфейса
RTA_IFA
0x20
RTAX_IFA
5
Адрес интерфейса
RTA_AUTHOR
0x40
RTAX_AUTHOR
6
Отправитель запроса на перенаправление
RTA_BRD
0x80
RTAX_BRD
7
Адрес получателя типа «точка-точка» или широковещательный
RTAX_MAX
8
Максимальное количество элементов
В том случае, когда имеется множество структур адреса сокета, они всегда располагаются в порядке, показанном в таблице.
Пример: получение и вывод записи из таблицы маршрутизации
Теперь мы покажем пример использования маршрутизирующих сокетов. Наша программа получает аргумент командной строки, состоящий из адреса IPv4 в точечно-десятичной записи, и отправляет ядру сообщение
RTM_GET
для получения этого адреса. Ядро ищет адрес в своей таблице маршрутизации IPv4 и возвращает сообщение
RTM_GET
с информацией о соответствующей записи из таблицы маршрутизации. Например, если мы выполним на нашем узле
freebsd
такой код
freebsd # getrt 206.168.112.219
dest: 0.0.0.0
gateway: 12.106.32.1
netmask: 0.0.0.0
мы увидим, что этот адрес получателя использует маршрут по умолчанию (который хранится в таблице маршрутизации с IP-адресом получателя 0.0.0.0 и маской 0.0.0.0). Маршрутизатор следующей ретрансляции — это интернет-шлюз нашей системы. Если мы выполним
freebsd # getrt 192.168.42.0
dest: 192.168.42.0
gateway: AF_LINK, index=2
netmask: 255.255.255.0
задав в качестве получателя главную сеть Ethernet, получателем будет сама сеть. Теперь шлюзом является исходящий интерфейс, возвращаемый в качестве структуры
sockaddr_dl
с индексом интерфейса 2.
Перед тем как представить исходный код, мы показываем на рис. 18.1, что именно мы пишем в маршрутизирующий сокет и что возвращает ядро.
Рис. 18.1. Обмен данными с ядром на маршрутизирующем сокете для команды RTM_GET
Мы создаем буфер, содержащий структуру
rt_msghdr
, за которой следует структура адреса сокета, содержащая адрес получателя, информацию о котором должно найти ядро. Тип сообщения (
rtm_type
) —
RTM_GET
, а битовая маска (
rtm_addrs
) —
RTA_DST
(вспомните табл. 18.2). Эти значения указывают, что структура адреса сокета, следующая за структурой
rt_msghdr
, — это структура, содержащая адрес получателя. Эта команда может использоваться с любым семейством протоколов (предоставляющим таблицу маршрутизации), поскольку семейство адресов, в которое входит искомый адрес, указано в структуре адреса сокета.