rtnetlink(7) сокет маршрутизации IPv4 в Linux

ОБЗОР

#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>

rtnetlink_socket = socket(AF_NETLINK, int socket_type, NETLINK_ROUTE);

ОПИСАНИЕ

Rtnetlink позволяет читать и изменять таблицы маршрутизации ядра. Он используется для взаимодействия различных подсистем внутри ядра (это здесь не описано), а также для взаимодействия пользовательских программ. Сетевыми маршрутами, IP-адресами, параметрами связи (link parameters), настройками соседства (neighbor setups), алгоритмами планирования очереди (queueing disciplines), классификацией трафика и и пакетными классификаторами можно управлять через сокеты NETLINK_ROUTE. Они основываются на сообщениях netlink; подробности смотрите в netlink(7).

Атрибуты маршрутизации

Некоторые сообщения rtnetlink содержат необязательные атрибуты после начального заголовка:

struct rtattr {
    unsigned short rta_len;    /* длина параметра */
    unsigned short rta_type;   /* тип параметра */
    /* данные … */
};

Этими атрибутами нужно управлять только с помощью макросов RTA_* или libnetlink, смотрите rtnetlink(3).

Сообщения

Rtnetlink поддерживает следующие типы сообщений (в дополнении к стандартным сообщениям netlink):
RTM_NEWLINK, RTM_DELLINK, RTM_GETLINK
Создание, удаление и получение информации об определённом сетевом интерфейсе. Эти сообщения содержат структуру ifinfomsg, за которой следует ряд структур rtattr.

struct ifinfomsg {
    unsigned char  ifi_family; /* AF_UNSPEC */
    unsigned short ifi_type;   /* тип устройства */
    int            ifi_index;  /* индекс интерфейса */
    unsigned int   ifi_flags;  /* флаги устройства */
    unsigned int   ifi_change; /* маска изменения */
};

В ifi_flags содержатся флаги устройства, смотрите netdevice(7); в ifi_index — уникальный индекс интерфейса (начиная с Linux 3.7 возможно передать ненулевое значение в сообщении RTM_NEWLINK; в этом случае создаётся связь (link) с заданным ifindex); элемент ifi_change зарезервирован на будущее и его значение всегда должно быть равно 0xFFFFFFFF.

Атрибуты маршрутизации
rta_typeтип значенияописание

IFLA_UNSPEC-не определено
IFLA_ADDRESSаппаратный адресадрес интерфейса L2
IFLA_BROADCASTаппаратный адресшироковещательный адрес L2
IFLA_IFNAMEстрока asciizимя устройства
IFLA_MTUunsigned intMTU устройства
IFLA_LINKintтип связи
IFLA_QDISCстрока asciizалгоритм очереди
IFLA_STATS см. ниже статистика интерфейса

Тип значения для IFLA_STATSstruct rtnl_link_stats (в Linux 2.4 и старее — struct net_device_stats).

RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR
Добавление, удаление или получение информации об IP-адресе, назначенном интерфейсу. В Linux 2.2 интерфейс может иметь несколько IP-адресов; эта концепция пришла на смену псевдонимам устройства, использовавшимся в версии 2.0. В Linux 2.2 эти сообщения поддерживают адреса IPv4 и IPv6. В них содержится структура ifaddrmsg, которая может быть указана после атрибутов маршрутизации rtattr.

struct ifaddrmsg {
    unsigned char ifa_family;    /* тип адреса */
    unsigned char ifa_prefixlen; /* длина префикса адреса */
    unsigned char ifa_flags;     /* флаги адреса */
    unsigned char ifa_scope;     /* область адреса */
    int           ifa_index;     /* индекс интерфейса */
};

Поле ifa_family представляет тип адресного семейства (AF_INET или AF_INET6), ifa_prefixlen — длину адресной маски адреса, если это применимо для семейства (в IPv4), ifa_scope — область адреса, ifa_index — индекс интерфейса, которому назначен адрес. Поле ifa_flags — слово флагов: IFA_F_SECONDARY — вторичный адрес (старый псевдоним интерфейса), IFA_F_PERMANENT — постоянный адрес, назначенный пользователем и другие недокументированные флаги.

Атрибуты
rta_typeтип значенияописание

IFA_UNSPEC-не определено
IFA_ADDRESSадрес raw-протоколаадрес интерфейса
IFA_LOCALадрес raw-протоколалокальный адрес
IFA_LABELстрока asciizназвание интерфейса
IFA_BROADCASTадрес raw-протоколашироковещательный адрес
IFA_ANYCASTадрес raw-протоколаадрес anycast
IFA_CACHEINFOstruct ifa_cacheinfoинформация об адресе
RTM_NEWROUTE, RTM_DELROUTE, RTM_GETROUTE
Создание, удаление или получение информации о сетевом маршруте. Эти сообщения содержат структуру rtmsg с необязательными дополнительными структурами rtattr. Для RTM_GETROUTE, если rtm_dst_len и rtm_src_len задать значение 0, то вы получите все записи определённой таблицы маршрутизации. В других полях, кроме rtm_table и rtm_protocol, 0 считается шаблоном (wildcard).

struct rtmsg {
    unsigned char rtm_family;   /* адресное семейство маршрута */
    unsigned char rtm_dst_len;  /* длина назначения */
    unsigned char rtm_src_len;  /* длина источника */
    unsigned char rtm_tos;      /* фильтр TOS */
    unsigned char rtm_table;    /* ID таблицы маршрутизации */
    unsigned char rtm_protocol; /* протокол марш-ции; см. ниже */
    unsigned char rtm_scope;    /* см. ниже */
    unsigned char rtm_type;     /* см. ниже */
    unsigned int  rtm_flags;
};
rtm_typeТип маршрута

RTN_UNSPECнеизвестный маршрут
RTN_UNICASTшлюз или прямой маршрут
RTN_LOCALмаршрут локального интерфейса
RTN_BROADCAST локальный широковещательный маршрут (широковещательная отправка)
RTN_ANYCAST локальный широковещательный маршрут (однонаправленная отправка)
RTN_MULTICASTмногоадресный маршрут
RTN_BLACKHOLEмаршрут для отброса пакетов
RTN_UNREACHABLEнедостижимый пункт назначения
RTN_PROHIBITмаршрут для отклонения пакетов
RTN_THROWпродолжение поиска маршрута в другой таблице
RTN_NATправило трансляции сетевого адреса
RTN_XRESOLVE ссылка на внешний определитель (не реализовано)
rtm_protocolПроисхождение маршрута

RTPROT_UNSPECнеизвестно
RTPROT_REDIRECT из-за перенаправления полученном по ICMP (не используется)
RTPROT_KERNELиз ядра
RTPROT_BOOTпри загрузке машины
RTPROT_STATICуказан администратором

Значения больше RTPROT_STATIC не учитываются ядром, они предназначены только для пользовательской информации. Они могут использоваться для пометки источника информации о маршрутизации или для отличения различных служб маршрутизации друг от друга. Уже назначенные идентификаторы для служб маршрутизации можно найти в <linux/rtnetlink.h>.

rtm_scope — расстояние до назначения:

RT_SCOPE_UNIVERSEглобальный маршрут
RT_SCOPE_SITE внутренний маршрут в локальной автономной системе
RT_SCOPE_LINKмаршрут на эту связи
RT_SCOPE_HOSTмаршрут на локальный узел
RT_SCOPE_NOWHEREназначение не существует

Значения от RT_SCOPE_UNIVERSE и до RT_SCOPE_SITE доступны пользователю.

Поле rtm_flags может иметь следующие значения:

RTM_F_NOTIFY если маршрут изменился — уведомить пользователя через rtnetlink
RTM_F_CLONEDмаршрут склонирован из другого маршрута
RTM_F_EQUALIZEмногопутевой уравниватель (не реализовано)

В rtm_table задаётся таблица маршрутизации:

RT_TABLE_UNSPECтаблица маршрутизации не задана
RT_TABLE_DEFAULTтаблица по умолчанию
RT_TABLE_MAINглавная таблица
RT_TABLE_LOCALлокальная таблица

Пользователь может назначать произвольные значения от RT_TABLE_UNSPEC и до RT_TABLE_DEFAULT.

Атрибуты
rta_typeтип значенияописание

RTA_UNSPEC-игнорируется
RTA_DSTадрес протоколаадрес маршрута назначения
RTA_SRCадрес протоколаадрес маршрута источника
RTA_IIFintиндекс входного интерфейса
RTA_OIFintиндекс выходного интерфейса
RTA_GATEWAYадрес протоколашлюз маршрута
RTA_PRIORITYintприоритет маршрута
RTA_PREFSRC
RTA_METRICSintметрика маршрута
RTA_MULTIPATH
RTA_PROTOINFO
RTA_FLOW
RTA_CACHEINFO

Заполнить эти значения!

RTM_NEWNEIGH, RTM_DELNEIGH, RTM_GETNEIGH
Добавление, удаление или получение информации о записи соседей по таблице (например, запись ARP). В сообщении содержится структура ndmsg:

struct ndmsg {
    unsigned char ndm_family;
    int           ndm_ifindex;  /* индекс интерфейса */
    __u16         ndm_state;    /* состояние */
    __u8          ndm_flags;    /* флаги */
    __u8          ndm_type;
};
struct nda_cacheinfo {
    __u32         ndm_confirmed;
    __u32         ndm_used;
    __u32         ndm_updated;
    __u32         ndm_refcnt;
};

В ndm_state содержится битовая маска следующих состояний:

NUD_INCOMPLETEзапись кэша в данный момент определяется
NUD_REACHABLEподтверждённая рабочая запись кэша
NUD_STALEустаревшая запись кэша
NUD_DELAYзапись ожидает срабатывания таймера
NUD_PROBEзапись кэша в данный момент проверяется повторно
NUD_FAILEDнекорректная запись кэша
NUD_NOARPустройство без кэша назначений
NUD_PERMANENTстатическая запись

Допустимые значения ndm_flags:

NTF_PROXYзапись прокси arp
NTF_ROUTERмаршрутизатор IPv6

Структура rtattr имеет следующие значения для поля rta_type:

NDA_UNSPECнеизвестный тип
NDA_DSTкэш адресов назначения соседей на сетевом уровне
NDA_LLADDRкэш адресов соседей на уровне связей
NDA_CACHEINFOстатистика кэша

Если значение поля rta_type равно NDA_CACHEINFO, то присутствует заголовок struct nda_cacheinfo.

RTM_NEWRULE, RTM_DELRULE, RTM_GETRULE
Добавление, удаление или получение правила маршрутизации. Содержит struct rtmsg.
RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC
Добавление, удаление или получение планирования очереди. В сообщении содержится struct tcmsg, а также может быть серия атрибутов.

struct tcmsg {
    unsigned char    tcm_family;
    int              tcm_ifindex;   /* индекс интерфейса */
    __u32            tcm_handle;    /* описатель qdisc */
    __u32            tcm_parent;    /* предок qdisc */
    __u32            tcm_info;
};
Атрибуты
rta_type  тип значения  описание

TCA_UNSPEC  -  не определено
TCA_KIND  строка asciiz  имя план-ания очереди
TCA_OPTIONS  байтовая последовательность  есть параметры qdisc
TCA_STATS  struct tc_stats  статистика qdisc
TCA_XSTATS  qdisc specific  стат-ка по опр. модулю
TCA_RATE  struct tc_estimator  ограничение по скорости

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

RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS
Добавление, удаление или получение класса трафика. В этих сообщениях содержится структура struct tcmsg, описанная ранее.
RTM_NEWTFILTER, RTM_DELTFILTER, RTM_GETTFILTER
Добавление, удаление или получение информации о фильтре трафика. В этих сообщениях содержится структура struct tcmsg, описанная ранее.

ВЕРСИИ

Свойство rtnetlink появилось в Linux 2.2.

ДЕФЕКТЫ

Данная справочная страница не полна.