UNIX: разработка сетевых приложений
18.2. Структура адреса сокета канального уровня
Структуры адреса сокета канального уровня будут встречаться нам как значения, содержащиеся в некоторых сообщениях, возвращаемых на маршрутизирующем сокете. В листинге 18.1 [1] показано определение структуры, задаваемой в заголовочном файле
.<net/if_dl.h>Листинг 18.1. Структура адреса сокета канального уровня
struct sockaddr_dl {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. В главе 21 при обсуждении параметров многоадресных сокетов IPv6 и в главе 27 при обсуждении дополнительных параметров сокетов IPv6 и IPv4 мы вновь вернемся к этим функциям.if_nameindexЭлемент
содержит и имя, и адрес канального уровня (например, 48-разрядный MAC-адрес интерфейса Ethernet). Имя начинается сsdl_dataи не заканчивается нулем. Начало адреса канального уровня смещено на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_data18.3. Чтение и запись
Создав маршрутизирующий сокет, процесс может отправлять ядру команды путем записи в этот сокет и считывать из него информацию от ядра. Существует 12 различных команд маршрутизации, 5 из которых могут быть запущены процессом. Они определяются в заголовочном файле
и показаны в табл. 18.1.<net/route.h>Таблица 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. Эти структуры представлены в листинге 18.2.ifa_msghdrЛистинг 18.2. Пять структур, возвращаемых с маршрутизирующими сообщениями