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

ЖАНРЫ

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

21 return (str);

22 }

7-21
Если длина равна нулю, то подразумевается маска 0.0.0.0. Если длина равна 5, хранится только первый байт 32-разрядной маски, а для оставшихся трех байтов подразумевается нулевое значение. Когда длина равна 8, хранятся все 4 байта маски.

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

write
на маршрутизирующем сокете сообщает нам, успешно ли была выполнена команда. Если это вся необходимая нам информация, мы вызываем функцию
shutdown
со вторым аргументом
SHUT_RD
, чтобы предотвратить отправку ответа. Например, если мы удаляем маршрут, то возвращение нуля функцией
write
означает успешное выполнение, а если удалить маршрут
не удалось, возвращается ошибка
ESRCH
[128, с. 608]. Аналогично, когда добавляется маршрут, возвращение ошибки
EEXIST
при выполнении функции
write
означает, что запись уже существует. В нашем примере из листинга 18.3 функция
write
возвращает ошибку
ESRCH
, если записи в таблице маршрутизации не существует (допустим, у нашего узла нет заданного по умолчанию маршрута).

18.4. Операции функции sysctl

Маршрутизирующие сокеты нужны нам главным образом для проверки таблицы маршрутизации и списка интерфейсов при помощи функции

sysctl
. В то время как создание маршрутизирующего сокета (символьного сокета в домене
AF_ROUTE
) требует прав привилегированного пользователя, проверить таблицу маршрутизации и список интерфейсов с помощью функции
sysctl
может любой процесс.

#include <sys/param.h>

#include <sys/sysctl.h>

int sysctl(int * name, u_int namelen, void * oldp, size_t * oldlenp,

void * newp, size_t Inewlen);

Возвращает: 0 в случае успешного выполнения

Эта функция использует имена, похожие на имена базы управляющей информации (Management Information Base, MIB) простого протокола управления сетью (Simple Network Management Protocol, SNMP). В главе 25 [111] подробно описываются SNMP и его MIB. Эти имена являются иерархическими.

Аргумент

name
— это массив целых чисел, задающий имя, a
namelen
задает число элементов массива. Первый элемент массива определяет, какой подсистеме ядра направлен запрос. Второй элемент определяет некую часть этой подсистемы, и т.д. На рис. 18.3 показана иерархическая организация с некоторыми константами, используемыми на первых трех уровнях.

Рис. 18.3. Иерархическая организация имен функции sysctl

Для получения значений используется аргумент

oldp
. Он указывает на буфер, в котором ядро сохраняет значение. Аргумент
oldenp
имеет тип «значение-результат»: когда функция вызывается, значение, на которое указывает
oldenp
, задает размер этого буфера, а по завершении функции значением этого аргумента становится количество данных, сохраненных ядром в буфере. Если размера буфера недостаточно, возвращается ошибка
ENOMEM
. В специальном случае
oldp
может быть пустым указателем, a
oldenp
— непустым указателем, и тогда ядро определяет, сколько данных возвратилось бы при вызове, сообщая это значение через
oldenp
.

Чтобы установить новое значение, используется аргумент

newp
, указывающий на буфер размера
newlen
. Если новое значение не задается,
newp
должен быть пустым указателем, a
newlen
должен быть равен нулю.

В руководстве (man) по применению функции

sysctl
подробно описывается различная системная информация, которую можно получить с помощью этой функции: информация о файловых системах, виртуальной памяти, ограничениях ядра, аппаратных характеристиках и т.д. Нас интересует сетевая подсистема, на которую указывает первый элемент массива name, равный
CTL_NET
(константы
CTL_ xxx
определяются в заголовочном файле
<sys/sysctl.h>
). Тогда второй элемент может быть одним из перечисленных ниже.

AF_INET
. Получение или установка переменных, влияющих на протоколы Интернета. Следующий уровень с помощью одной из констант
IPROTO_ xxx
задает протокол. BSD/OS 3.0 предоставляет на этом
уровне около 30 переменных, управляющих такими свойствами, как генерация ядром переадресации ICMP, использование параметров TCP из RFC 1323, отправка контрольных сумм UDP и т.д. Пример подобного применения функции
sysctl
мы покажем в конце этого раздела.

AF_LINK
. Получение или установка информации канального уровня, такой как число интерфейсов PPP.

AF_ROUTE
. Возвращение информации либо о таблице маршрутизации, либо о списке интерфейсов. Мы вскоре опишем эту информацию.

AF_UNSPEC
. Получение или установка некоторых переменных уровня сокета, таких как максимальный размер буфера отправки или приема сокета.

Когда вторым элементом массива

name
является
AF_ROUTE
, третий элемент (номер протокола) всегда нулевой (поскольку протоколы внутри семейства
AF_ROUTE
отличаются от протоколов, например, в семействе
AF_INET
), четвертый элемент — это семейство адресов, а пятый и шестой элементы задают выполняемые действия. Вся эта информация обобщается в табл. 18.3.

Таблица 18.3. Информация функции sysctl, возвращаемая для маршрутизирующего домена

name[] Возвращает таблицу Возвращает кэш APR маршрутизации Возвращает список интерфейсов
0 CTL_NET CTL_NET CTL_NET
1 AF_ROUTE AF_ROUTE AF_ROUTE
2 0 0 0
3 AF_INET AF_INET AF_INET
4 NET_RT_DUMP NET_RT_FLAGS NET_RT_IFLIST
5 0 RTF_LLINFO 0

Поддерживаются три операции, задаваемые элементом

name[4]
. (Константы
NET_RT_ xxx
определяются в заголовочном файле
<sys/socket.h>
.) Информация возвращается через указатель
oldp
при вызове функции
sysctl
. Этот буфер содержит переменное число сообщений
RTM_ xxx
(см. табл. 18.1).

1. Операция

NET_RT_DUMP
возвращает таблицу маршрутизации для семейства адресов, заданного элементом
name[3]
. Если задано нулевое семейство адресов, возвращаются таблицы маршрутизации для всех семейств адресов.

Рис. 18.4. Информация возвращаемая функцией sysctl для команд CTL_NET и NET_RT_IFLIST

Таблица маршрутизации возвращается как переменное число сообщений

RTM_GET
, причем за каждым сообщением следует до четырех структур адреса сокета: получатель, шлюз, маска сети и маска клонирования записи в таблице маршрутизации. Пример такого сообщения мы показали в правой части рис. 18.1, а в нашем коде в листинге 18.4 проводится анализ одного из сообщений. В результате применения этой операции функции
sysctl
ядром возвращается одно или несколько таких сообщений.

2. Операция

NET_RT_FLAGS
возвращает таблицу маршрутизации для семейства адресов, заданного элементом
name[3]
, но учитываются только те записи таблицы маршрутизации, для которых значение флага
RTF_ xxx
равно указанному в элементе
name[5]
. У всех записей кэша ARP в таблице маршрутизации установлен бит флага
RTF_LLINFO
.

Информация возвращается в том же формате, что и в предыдущем пункте.

3. Операция

NET_RT_IFLIST
возвращает информацию обо всех сконфигурированных интерфейсах. Если элемент
name[5]
ненулевой, это номер индекса интерфейса и возвращается информация только об этом интерфейсе. (Более подробно об индексах интерфейсов мы поговорим в разделе 18.6.) Все адреса, присвоенные каждому интерфейсу, также возвращаются, и если элемент
name[3]
ненулевой, возвращаются только адреса для семейства адресов, указанного в этом элементе.

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