Протокол netlink (PF_NETLINK) обеспечивает обмен информацией между модулями ядра и программами пользовательского пространства. Протокол использует стандартный интерфейс для пользовательских программ и внутренний интерфейс API для модулей ядра. Ниже будет рассмотрен только пользовательский интерфейс сокета, а интерфейс ядра и старый вариант пользовательского интерфейса для работы через символьные устройства netlink не обсуждается.
Netlink обеспечивает для приложений сервис передачи дейтаграмм. Для netlink допустимо указывать тип сокета SOCK_RAW и SOCK_DGRAM и протокол не делает между ними различий.
Отметим, что использовать функции протокола netlink зачастую проще через библиотеку libnetlink, нежели напрямую через интерфейс с ядром.
Включаемый файл netlink.h содержит определения нескольких стандартных макросов для доступа или создания дейтаграмм netlink. Для доступа к буферам, передаваемым и принимаемым сокетом netlink, следует использовать только макросы из этого файла, которые кратко описаны в таблице 1.
#include <asm/types.h>
#include <linux/netlink.h>
int NLMSG_ALIGN(size_t len);
int NLMSG_LENGTH(size_t len);
int NLMSG_SPACE(size_t len);
void *NLMSG_DATA(struct nlmsghdr *nlh);
struct nlmsghdr *NLMSG_NEXT(struct nlmsghdr *nlh, int len);
int NLMSG_OK(struct nlmsghdr *nlh, int len);
int NLMSG_PAYLOAD(struct nlmsghdr *nlh, int len);
Таблица 1 Макросы netlink
Имя
|
Описание
|
NLMSG_ALIGN
|
Округляет размер сообщения netlink до ближайшего большего значения, выровненного по границе.
|
NLMSG_LENGTH
|
Принимает в качестве параметра размер поля данных (payload) и возвращает выровненное по границе значение размера для записи в поле nlmsg_len заголовка nlmsghdr.
|
NLMSG_SPACE
|
Возвращает размер, который займут данные указанной длины в пакете netlink.
|
NLMSG_DATA
|
Возвращает указатель на данные, связанные с переданным заголовком nlmsghdr.
|
NLMSG_NEXT
|
Возвращает следующую часть сообщения, состоящего из множества частей. Макрос принимает следующий заголовок nlmsghdr в сообщении, состоящем из множества частей. Вызывающее приложение должно проверить наличие в текущем заголовке nlmsghdr флага NLMSG_DONE – функция не возвращает значение NULL при завершении обработки сообщения. Второй параметр задает размер оставшейся части буфера сообщения. Макрос уменьшает это значение на размер заголовка сообщения.
|
NLMSG_OK
|
Возвращает значение TRUE (1), если сообщение не было усечено и его разборка прошла успешно.
|
NLMSG_PAYLOAD
|
Возвращает размер данных (payload), связанных с заголовком nlmsghdr.
|
Семейство netlink
Семейство netlink_family выбирает модуль ядра или группу netlink для обмена информацией. Члены семейства перечислены в таблице 2.
Таблица 2 Члены семейства netlink
Имя
|
Описание
|
NETLINK_ROUTE
|
Принимает обновления маршрутов и может использоваться для модификации маршрутной таблицы IPv4.
|
NETLINK_SKIP
|
Зарезервирован для ENskip.
|
NETLINK_USERSOCK
|
Зарезервирован для новых протоколов пользовательского пространства.
|
NETLINK_FIREWALL
|
Принимает пакеты от межсетевых экранов IPv4.
|
NETLINK_TCPDIAG
|
Мониторинг сокета TCP.
|
NETLINK_NFLOG
|
Операция ULOG.
|
NETLINK_XFRM
|
IPsec.
|
NETLINK_ARPD
|
Используется для управления таблицами arp в пользовательском пространстве.
|
NETLINK_ROUTE6
|
Принимает и передает обновления таблицы маршрутов IPv6 (af_inet6).
|
NETLINK_IP6_FW
|
Служит для приема сообщений о неудачном результате проверки правил на брандмауэре IPv6 (пока не реализован).
|
NETLINK_DNRTMSG
|
Маршрутные сообщения DECnet.
|
NETLINK_TAPBASE
|
Экземпляры фиктивного устройства ethertap, позволяющее имитировать драйвер Ethernet из пользовательского пространства.
|
...
|
NETLINK_TAPBASE+15
|
Сообщения netlink представляют собой поток байтов с одним или несколькими заголовками nlmsghdr и связанными с ними данными (payload). В сообщениях, состоящих из множества частей все заголовки, за исключением последнего содержат флаг NLM_F_MULTI, а в заголовке последнего сообщения установлен флаг NLMSG_DONE. Для доступа к байтовым потокам следует использовать только макросы NLMSG_*.
Протокол netlink не обеспечивает гарантированной доставки сообщений, пытаясь лишь приложить все разумные усилия для доставки сообщения адресату. При нехватке памяти или возникновении иных ошибок протокол может отбрасывать пакеты. Для обеспечения гарантированной доставки отправитель может запрашивать у получателя подтверждение, устанавливая в заголовке флаг NLM_F_ACK. В качестве подтверждений используются пакеты NLMSG_ERROR с кодом ошибки 0. Функции генерации подтверждений должно обеспечивать пользовательское приложение. Ядро пытается передавать сообщения NLMSG_ERROR для каждого поврежденного пакета. Пользовательским программам следует придерживаться такой же практики.
Каждое семейство netlink имеет свой набор из 32 multicast-групп. При вызове для сокета функции bind поле nl_groups в структуре sockaddr_nl должно содержать битовую маску групп, которым следует слышать сообщение. По умолчанию для этого поля установлено нулевое значение, которое отключает групповую передачу сообщений. Сокет может передавать групповые сообщения любым группам, установив в поле nl_groups битовую маску нужных групп перед вызовом функции sendmsg или connect. Возможность работы (приема или передачи) с групповыми сообщениями netlink имеют лишь приложения с флагом возможностей CAP_NET_ADMIN и программы, запущенные пользователем с эффективным идентификатором UID=0. Все отклики на групповые сообщения должны передаваться процессу-отправителю и членам группы.
Структура заголовка сообщений netlink показана ниже
struct nlmsghdr
{
__u32 nlmsg_len; /* размер сообщения с учетом заголовка */
__u16 nlmsg_type; /* тип сообщения (содержимое) */
__u16 nlmsg_flags;/* стандартные и дополнительные флаги */
__u32 nlmsg_seq; /* порядковый номер */
__u32 nlmsg_pid; /* Идентификатор процесса (PID), открывшего сокет */
};
Сообщения об ошибках имеют структуру:
struct nlmsgerr
{
int error; /* отрицательное значение кода ошибки или 0 для подтверждений */
struct nlmsghdr msg; /* заголовок сообщения, связанного с ошибкой */
};
После каждого заголовка nlmsghdr размещаются данные, указанного параметром nlmsg_type типа:
-
NLMSG_NOOP – пустое сообщение (игнорируется);
-
NLMSG_ERROR – сообщение об ошибке, содержащее в поле данных структуру nlmsgerr;
-
NLMSG_DONE – последняя часть сообщения.
Члены семейства netlink могут поддерживать дополнительные типы сообщений, описанные с соответствующих страницах руководства и доступных с помощью команды man (например, man 7 rtnetlink для NETLINK_ROUTE).
Флаги сообщений netlink, передаваемые в поле nlmsg_flags, перечислены в таблице.
Таблица 3 Флаги сообщений netlink
Флаг
|
Описание
|
Основные флаги
|
NLM_F_REQUEST
|
Устанавливается для всех запросов.
|
NLM_F_MULTI
|
Сообщение является частью составного сообщения, завершающегося флагом NLMSG_DONE.
|
NLM_F_ACK
|
Отклик с подтверждением успеха.
|
NLM_F_ECHO
|
Запрос эхо-отклика.
|
Дополнительные флаги для запросов GET
|
NLM_F_ROOT
|
Задает корень дерева
|
NLM_F_MATCH
|
Возвращает все найденные соответствия.
|
NLM_F_ATOMIC
|
Atomic GET. Этот флаг требует полномочий пользователя с эффективным UID=0 или наличия флага возможностей CAP_NET_ADMIN.
|
NLM_F_DUMP
|
NLM_F_ROOT|NLM_F_MATCH
|
Дополнительные флаги для запросов NEW
|
NLM_F_REPLACE
|
Записать взамен существующего объекта.
|
NLM_F_EXCL
|
Не переписывать, если объект уже существует.
|
NLM_F_CREATE
|
Создать объект, если он еще не создан.
|
NLM_F_APPEND
|
Добавить в конце списка объектов.
|
Форматы адресов
Адреса netlink для пользовательских программ и модулей ядра описываются структурой sockaddr_nl. Заданный такой структурой адрес может быть индивидуальным (unicast) или групповым.
struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* заполнение нулями */
pid_t nl_pid; /* идентификатор процесса */
__u32 nl_groups; /* маска групп */
};
Поле nl_pid содержит идентификатор процесса, владеющего сокетом-адресатом или 0, если сообщение адресовано ядру. Параметр nl_groups содержит маску, каждый бит которой представляет одну из групп netlink.
|