UNIX: разработка сетевых приложений
Вывод аппаратного адресаВыводится аппаратный адрес, возвращаемый20-22.ioctlПри запуске этой программы на нашем узле
мы получаем:hpuxhpux % <b>prmac</b>192.6.38.100: 0:60:b0:c2:68:9b192.168.1.1: 0:60:b0:b2:28:2b127.0.0.1: ioctl SIOCGARP: Invalid argument17.9. Операции с таблицей маршрутизации
Для работы с таблицей маршрутизации предназначены два вызова функции
. Эти два вызова требуют, чтобы третий аргумент функции ioctl был указателем на структуруioctl, которая определяется в заголовочном файлеrtentry. Обычно эти вызовы исходят от программы<net/route.h>. Их может делать только привилегированный пользователь. При наличии маршрутизирующих сокетов (глава 18) для выполнения этих запросов используются именно они, а не функцияroute.ioctl■
. Добавить запись в таблицу маршрутизации.SIOCADDRT■
. Удалить запись из таблицы маршрутизации.SIOCDELRTНет способа с помощью функции
перечислить все записи таблицы маршрутизации. Эту операцию обычно выполняет программаioctlс флагомnetstat. Программа получает таблицу маршрутизации, считывая память ядра (-r). Как и в случае с просмотром кэша ARP, в разделе 18.4 мы увидим более простой (и предпочтительный) способ, предоставляемый функцией/dev/kmem.sysctl17.10. Резюме
Команды функции
, используемые в сетевых приложениях, можно разделить на шесть категорий:ioctl1. Операции с сокетами (находимся ли мы на отметке внеполосных данных?).
2. Операции с файлами (установить или сбросить флаг отсутствия блокировки).
3. Операции с интерфейсами (возвратить список интерфейсов, получить широковещательный адрес).
4. Операции с кэшем ARP (создать, изменить, получить, удалить).
5. Операции с таблицей маршрутизации (добавить или удалить).
6. Операции с потоками STREAMS (см. главу 31).
Мы будем использовать операции с сокетами и файлами, а получение списка интерфейсов — это настолько типичная операция, что для этой цели мы разработали собственную функцию. Мы будем применять ее много раз в оставшейся части книги. Вызовы функции
с кэшем ARP и таблицей маршрутизации используются лишь несколькими специализированными программами.ioctlУпражнения
1. В разделе 17.7 мы сказали, что широковещательный адрес, возвращаемый запросом SIOCGIFBRDADDR, возвращается в элементе
. Но на с. 173 [128] сказано, что он возвращается в элементеifr_broadaddr. Имеет ли это значение?ifr_dstaddr2. Измените программу
так, чтобы она делала первый вызовget_ifi_infoдля одной структурыSIOCGIFCONF, а затем каждый раз в цикле увеличивайте длину на размер одной из этих структур. Затем поместите в цикл операторы, которые выводили бы размер буфера при каждом вызове независимо от того, возвращает функцияifreqошибку или нет, и при успешном выполнении выведите возвращаемую длину буфера. Запустите программуioctlи посмотрите, как ваша система обрабатывает вызов, когда размер буфера слишком мал. Выведите также семейство адресов для всех возвращаемых структур, семейство адресов которых не совпадает с указанным в первом аргументе функцииprifinfo, чтобы увидеть, какие еще структуры возвращает ваша система.get_ifi_info3. Измените функцию
так, чтобы она возвращала информацию об адресе с альтернативным именем, если дополнительный адрес находится не в той подсети, в которой находится предыдущий адрес для данного интерфейса. Таким образом, наша версия из раздела 17.6 будет игнорировать альтернативные имена в диапазоне от 206.62.226.44 до 206.62.226.46, и это вполне нормально, поскольку они находятся в той же подсети, что и первичный адрес интерфейса 206.62.226.33. Но если альтернативное имя находится в другой подсети, допустим 192.3.4.5, возвратите структуруget_ifi_infoс информацией о дополнительном адресе.ifi_info4. Если ваша система поддерживает вызов
функцииSIOCGIGNUM, измените листинг 17.4 так, чтобы запустить этот вызов, и используйте возвращаемое значение как начальный размер буфера.ioctlГлава 18
Маршрутизирующие сокеты
18.1. Введение
Традиционно доступ к таблице маршрутизации Unix внутри ядра осуществлялся с помощью команд функции
. В разделе 17.9 мы описали две операции:ioctlиSIOCADDRT, предназначенные для добавления и удаления маршрута. Мы также отметили, что не существует операции чтения всей таблицы маршрутизации — вместо этого программы, такие какSIOCDELRT, считывают память ядра, для того чтобы получить содержимое таблицы маршрутизации. И еще одно добавление. Демонам маршрутизации, таким какnetstat, необходимо отслеживать сообщения ICMP (Internet Control Message Protocol — протокол управляющих сообщений Интернета) об изменении маршрутов, получаемых ядром, и для этого они часто создают символьный (неструктурированный) сокет ICMP (см. главу 28), а затем прослушивают на этом сокете все получаемые сообщения ICMP.gatedВ 4.3BSD Reno интерфейс подсистемы маршрутизации ядра был упрощен за счет создания семейства адресов (домена)
. Единственный тип сокетов, поддерживаемый для этого семейства, — это символьный сокет (raw socket). Маршрутизирующие сокеты поддерживают три типа операций.AF_ROUTE1. Процесс может отправить ядру сообщение, записав его в маршрутизирующий сокет. Таким образом добавляются и удаляются маршруты.
2. Процесс может прочитать сообщение от ядра через маршрутизирующий сокет. Так ядро уведомляет процесс о том, что сообщение ICMP об изменении маршрутизации было получено и обработано.
Некоторые операции включают оба шага: например, процесс отправляет ядру сообщение через маршрутизирующий сокет, запрашивая всю информацию по данному маршруту, после чего через маршрутизирующий сокет считывает ответ ядра.
3. Процесс может использовать функцию
(см. раздел 18.4) либо для просмотра таблицы маршрутизации, либо для перечисления всех сконфигурированных интерфейсов.sysctlПервые две операции требуют прав привилегированного пользователя, а третью операцию может выполнить любой процесс.
ПРИМЕЧАНИЕНекоторые версии 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.