Литмир - Электронная Библиотека
Содержание  
A
A
Вывод аппаратного адреса

20-22
 Выводится аппаратный адрес, возвращаемый
ioctl
.

При запуске этой программы на нашем узле

hpux
мы получаем:

hpux % <b>prmac</b>

192.6.38.100: 0:60:b0:c2:68:9b

192.168.1.1: 0:60:b0:b2:28:2b

127.0.0.1: ioctl SIOCGARP: Invalid argument

17.9. Операции с таблицей маршрутизации

Для работы с таблицей маршрутизации предназначены два вызова функции

ioctl
. Эти два вызова требуют, чтобы третий аргумент функции ioctl был указателем на структуру
rtentry
, которая определяется в заголовочном файле
&lt;net/route.h&gt;
. Обычно эти вызовы исходят от программы
route
. Их может делать только привилегированный пользователь. При наличии маршрутизирующих сокетов (глава 18) для выполнения этих запросов используются именно они, а не функция
ioctl
.

■ 

SIOCADDRT
. Добавить запись в таблицу маршрутизации.

■ 

SIOCDELRT
. Удалить запись из таблицы маршрутизации.

Нет способа с помощью функции

ioctl
перечислить все записи таблицы маршрутизации. Эту операцию обычно выполняет программа
netstat
с флагом
-r
. Программа получает таблицу маршрутизации, считывая память ядра (
/dev/kmem
). Как и в случае с просмотром кэша ARP, в разделе 18.4 мы увидим более простой (и предпочтительный) способ, предоставляемый функцией
sysctl
.

17.10. Резюме

Команды функции

ioctl
, используемые в сетевых приложениях, можно разделить на шесть категорий:

1. Операции с сокетами (находимся ли мы на отметке внеполосных данных?).

2. Операции с файлами (установить или сбросить флаг отсутствия блокировки).

3. Операции с интерфейсами (возвратить список интерфейсов, получить широковещательный адрес).

4. Операции с кэшем ARP (создать, изменить, получить, удалить).

5. Операции с таблицей маршрутизации (добавить или удалить).

6. Операции с потоками STREAMS (см. главу 31).

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

ioctl
с кэшем ARP и таблицей маршрутизации используются лишь несколькими специализированными программами.

Упражнения

1. В разделе 17.7 мы сказали, что широковещательный адрес, возвращаемый запросом SIOCGIFBRDADDR, возвращается в элементе

ifr_broadaddr
. Но на с. 173 [128] сказано, что он возвращается в элементе
ifr_dstaddr
. Имеет ли это значение?

2. Измените программу

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

3. Измените функцию

get_ifi_info
так, чтобы она возвращала информацию об адресе с альтернативным именем, если дополнительный адрес находится не в той подсети, в которой находится предыдущий адрес для данного интерфейса. Таким образом, наша версия из раздела 17.6 будет игнорировать альтернативные имена в диапазоне от 206.62.226.44 до 206.62.226.46, и это вполне нормально, поскольку они находятся в той же подсети, что и первичный адрес интерфейса 206.62.226.33. Но если альтернативное имя находится в другой подсети, допустим 192.3.4.5, возвратите структуру
ifi_info
с информацией о дополнительном адресе.

4. Если ваша система поддерживает вызов

SIOCGIGNUM
функции
ioctl
, измените листинг 17.4 так, чтобы запустить этот вызов, и используйте возвращаемое значение как начальный размер буфера.

Глава 18

Маршрутизирующие сокеты

18.1. Введение

Традиционно доступ к таблице маршрутизации Unix внутри ядра осуществлялся с помощью команд функции

ioctl
. В разделе 17.9 мы описали две операции:
SIOCADDRT
и
SIOCDELRT
, предназначенные для добавления и удаления маршрута. Мы также отметили, что не существует операции чтения всей таблицы маршрутизации — вместо этого программы, такие как
netstat
, считывают память ядра, для того чтобы получить содержимое таблицы маршрутизации. И еще одно добавление. Демонам маршрутизации, таким как
gated
, необходимо отслеживать сообщения ICMP (Internet Control Message Protocol — протокол управляющих сообщений Интернета) об изменении маршрутов, получаемых ядром, и для этого они часто создают символьный (неструктурированный) сокет ICMP (см. главу 28), а затем прослушивают на этом сокете все получаемые сообщения ICMP.

В 4.3BSD Reno интерфейс подсистемы маршрутизации ядра был упрощен за счет создания семейства адресов (домена)

AF_ROUTE
. Единственный тип сокетов, поддерживаемый для этого семейства, — это символьный сокет (raw socket). Маршрутизирующие сокеты поддерживают три типа операций.

1. Процесс может отправить ядру сообщение, записав его в маршрутизирующий сокет. Таким образом добавляются и удаляются маршруты.

2. Процесс может прочитать сообщение от ядра через маршрутизирующий сокет. Так ядро уведомляет процесс о том, что сообщение ICMP об изменении маршрутизации было получено и обработано.

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

3. Процесс может использовать функцию

sysctl
(см. раздел 18.4) либо для просмотра таблицы маршрутизации, либо для перечисления всех сконфигурированных интерфейсов.

Первые две операции требуют прав привилегированного пользователя, а третью операцию может выполнить любой процесс.

ПРИМЕЧАНИЕ

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

Технически третья операция выполняется при помощи общей функции sysctl, а не маршрутизирующего сокета. Но мы увидим, что среди ее входных параметров есть семейство адресов (для описываемых в этой главе операций используется семейство AF_ROUTE), а результат она возвращает в том же формате, который используется ядром для маршрутизирующего сокета. Действительно, в ядре 4.4BSD обработка функции sysctl для семейства AF_ROUTE является частью кода маршрутизирующего сокета [128, с. 632–643].

Функция sysctl появилась в 4.4BSD. К сожалению, не все реализации, поддерживающие маршрутизирующие сокеты, предоставляют ее. Например, AIX 4.2, Digital Unix 4.0 и Solaris 2.6 поддерживают маршрутизирующие сокеты, но ни одна из этих систем не поддерживает утилиту sysctl.

199
{"b":"225366","o":1}