Сокет Netlink используется для достиженияПользовательский процесспротивПроцесс ядраСпециальная межпроцессная связь (IPC) также является наиболее часто используемым интерфейсом для связи между сетевыми приложениями и ядром.
В ядре Linux есть много приложений, которые используют netlink для связи с ядром, например
- Демон маршрутизации (NETLINK_ROUTE)
- Протокол сокета пользовательского режима (NETLINK_USERSOCK)
- Брандмауэр (NETLINK_FIREWALL)
- подсистема netfilter (NETLINK_NETFILTER)
- События ядра для уведомления пользовательского режима (NETLINK_KOBJECT_UEVENT)
- Общий сетевой канал (NETLINK_GENERIC)
Netlink — очень хороший способ двусторонней передачи данных между ядром и пользовательскими приложениями.Приложения пользовательского режима могут использовать стандартные API-интерфейсы сокетов для использования мощных функций, предоставляемых netlink, в то время как режим ядра должен использовать специальные API-интерфейсы ядра для использования netlink.
Запуск приложений из клиента TRACE MODE – NetLinkLight
Вообще говоря, существует три способа связи между пользовательским пространством и пространством ядра: /proc、ioctl、Netlink . Первые два являются однонаправленными, и Netlink может реализовать дуплексную связь.
По сравнению с системными вызовами, файловой системой ioctl и / proc, Netlink имеет следующие преимущества:
- netlink прост в использовании, просто нужно include/linux/netlink.h Просто добавьте новый тип определения протокола netlink в (например, #define NETLINK_TEST 20 Затем приложения ядра и пользовательского режима могут немедленно использовать тип протокола netlink для обмена данными через API сокетов)
- Netlink — это асинхронный механизм связи. Сообщения, передаваемые между ядром и приложениями пользовательского режима, хранятся в очереди буфера сокета. Отправка сообщений сохраняет сообщение только в очереди получения сокета получателя, не дожидаясь, пока получатель получит сообщение.
- Часть ядра, использующая netlink, может быть реализована в модулях, а часть приложения и часть ядра, использующая netlink, не имеют зависимости во время компиляции.
- Netlink поддерживает многоадресную рассылку.Модуль ядра или приложение может многоадресно передать сообщение группе netlink.Любой модуль ядра или приложение, принадлежащее группе neilink, может получить сообщение.Механизм уведомления о событиях ядра в пользовательском режиме использует эту функцию.
- Ядро может использовать netlink, чтобы сначала инициировать сеанс
Протокол Netlink основан на сокете BSD и AF_NETLINK Кластер адресов, использующий 32-битную адресацию номера порта, каждый протокол Netlink обычно связан с одной или группой основных служб / компонентов, таких как NETLINK_ROUTE Используется для получения и установки информации о маршрутах и ссылках, NETLINK_KOBJECT_UEVENT Используется ядром для отправки уведомлений процессу udev в пользовательском пространстве и т. Д.
Два, структура данных пользовательского режима
Приложения пользовательского режима используют стандартные API-интерфейсы сокетов, такие как sendto (), recvfrom (), sendmsg (), recvmsg ().
Простой обзор медиаконвертора GigaLink
Связь Netlink похожа на обычную связь UDP Socket, struct sockaddr_nl Это коммуникационный адрес netlink, который совпадает с обычным socket struct sockaddr_in похожий.
1. Структура struct sockaddr_nl:
struct sockaddr_nl < __kernel_sa_family_t nl_family; / * AF_NETLINK (соответствует AF_INET) * / unsigned short nl_pad; /* zero */ __u32 nl_pid; / * идентификатор порта (номер порта связи) * / __u32 nl_groups; /* multicast groups mask */ >;
2. Структура struct nlmsghd:
/ * struct nlmsghd — это заголовок сообщения netlink * / struct nlmsghdr < __u32 nlmsg_len; /* Length of message including header */ __u16 nlmsg_type; /* Message content */ __u16 nlmsg_flags; /* Additional flags */ __u32 nlmsg_seq; /* Sequence number */ __u32 nlmsg_pid; /* Sending process port ID */ >;
- nlmsg_type: статус сообщения, ядро находится в include/uapi/linux/netlink.h Следующие четыре основных типа сообщений определены в:
#define NLMSG_NOOP 0x1 /* Nothing. */ #define NLMSG_ERROR 0x2 /* Error */ #define NLMSG_DONE 0x3 /* End of a dump */ #define NLMSG_OVERRUN 0x4 /* Data lost */ #define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
- nlmsg_flags: флаги сообщений, они используются для обозначения типа сообщения, как показано ниже.
/* Flags values */ #define NLM_F_REQUEST 1 /* It is request message. */ #define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ #define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ #define NLM_F_ECHO 8 /* Echo this request */ #define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ /* Modifiers to GET request */ #define NLM_F_ROOT 0x100 /* specify tree root */ #define NLM_F_MATCH 0x200 /* return all matching */ #define NLM_F_ATOMIC 0x400 /* atomic GET */ #define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) /* Modifiers to NEW request */ #define NLM_F_REPLACE 0x100 /* Override existing */ #define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ #define NLM_F_CREATE 0x400 /* Create, if it does not exist */ #define NLM_F_APPEND 0x800 /* Add to end of list */
3. Структура struct msghdr
struct iovec < /* Scatter/gather array items */ void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfer */ >; / * iov_base: iov_base указывает на буфер пакетов, то есть на параметр buff, iov_len — это длина буфера. В msghdr разрешено передавать несколько баффов одновременно, организованных в виде массива в msg_iov, msg_iovlen записывает длину массива (то есть сколько есть баффов) * / struct msghdr < void *msg_name; /* optional address */ socklen_t msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data, see below */ size_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ >;
Три, структура данных ядра netlink
1. Тип сообщения Netlink:
#define NETLINK_ROUTE 0 /* Routing/device hook */ #define NETLINK_UNUSED 1 /* Unused number */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */ #define NETLINK_SOCK_DIAG 4 /* socket monitoring */ #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ #define NETLINK_XFRM 6 /* ipsec */ #define NETLINK_SELINUX 7 /* SELinux event notifications */ #define NETLINK_ISCSI 8 /* Open-iSCSI */ #define NETLINK_AUDIT 9 /* auditing */ #define NETLINK_FIB_LOOKUP 10 #define NETLINK_CONNECTOR 11 #define NETLINK_NETFILTER 12 /* netfilter subsystem */ #define NETLINK_IP6_FW 13 #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ #define NETLINK_GENERIC 16 /* leave room for NETLINK_DM (DM Events) */ #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ #define NETLINK_ECRYPTFS 19 #define NETLINK_RDMA 20 #define NETLINK_CRYPTO 21 /* Crypto layer */ #define NETLINK_INET_DIAG NETLINK_SOCK_DIAG #define MAX_LINKS 32
2. Часто используемые макросы Netlink:
#define NLMSG_ALIGNTO 4U / * Макрос NLMSG_ALIGN (len) используется для получения наименьшего значения, которое не меньше len и выровнено по байтам * / #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) nlmsg_len), (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) / * Определяем, является ли сообщение> len * / #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) (nlh)->nlmsg_len nlmsg_len — NLMSG_SPACE((len)))
3. Общие функции ядра Netlink
Функция ядра netlink_kernel_create используется для создания сокета ядра и взаимодействия с пользовательским режимом.
static inline struct sock * netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg) / * net: net указывает на сетевое пространство имен, в котором он расположен. Обычно определен в net_namespace.c (extern struct net init_net); unit: тип протокола netlink cfg: cfg хранит параметры конфигурации ядра netlink (как показано ниже) */ /* optional Netlink kernel configuration parameters */ struct netlink_kernel_cfg < unsigned int groups; unsigned int flags; void (* input) (struct sk_buff * skb); / * функция обратного вызова input * / struct mutex *cb_mutex; void (*bind)(int group); bool (*compare)(struct net *net, struct sock *sk); >;
4. Одноадресная передача netlink_unicast () и многоадресная передача netlink_broadcast ()
/ * Отправить одноадресное сообщение * / extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock); /* ssk: netlink socket skb: указатель буфера skb portid: номер порта связи nonblock: указывает, является ли функция неблокирующей, если она равна 1, функция вернется немедленно, когда нет доступного буфера приема, и если он равен 0, функция может использовать временный сон, когда нет буфера приема */ / * Отправляем многоадресное сообщение * / extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 portid, __u32 group, gfp_t allocation); /* ssk: То же, что и выше (соответствует возвращаемому значению netlink_kernel_create), skb: ядро skb buff portid: идентификатор порта group: это объединенное значение операции «ИЛИ» соответствующих масок всех целевых групп многоадресной рассылки. Распределение: укажите метод распределения памяти ядра, обычно GFP_ATOMIC используется для контекста прерывания, а GFP_KERNEL используется для других случаев. Этот параметр существует, потому что API может потребоваться выделить один или несколько буферов для клонирования многоадресных сообщений. */
Четыре, экземпляр netlink
1. Программа пользовательского режима (sendto (), recvfrom ())
#include #include #include #include #include #include #include #include #define NETLINK_TEST 30 #define MSG_LEN 125 #define MAX_PLOAD 125 typedef struct _user_msg_info < struct nlmsghdr hdr; char msg[MSG_LEN]; >user_msg_info; int main(int argc, char **argv) < int skfd; int ret; user_msg_info u_info; socklen_t len; struct nlmsghdr *nlh = NULL; struct sockaddr_nl saddr, daddr; char *umsg = «hello netlink!!»; / * Создание сокета NETLINK * / skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST); if(skfd == -1) < perror(«create socket errorn»); return -1; >memset( saddr.nl_family = AF_NETLINK; //AF_NETLINK saddr.nl_pid = 100; // номер порта (ID порта) saddr.nl_groups = 0; if(bind(skfd, (struct sockaddr *) perror(«bind() errorn»); close(skfd); return -1; >memset( daddr.nl_family = AF_NETLINK; daddr.nl_pid = 0; // to kernel daddr.nl_groups = 0; nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD)); memset(nlh, 0, sizeof(struct nlmsghdr)); nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD); nlh->nlmsg_flags = 0; nlh->nlmsg_type = 0; nlh->nlmsg_seq = 0; nlh->nlmsg_pid = saddr.nl_pid; //self port memcpy(NLMSG_DATA(nlh), umsg, strlen(umsg)); ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) if(!ret) < perror(«sendto errorn»); close(skfd); exit(-1); >printf(«send kernel:%sn», umsg); memset( len = sizeof(struct sockaddr_nl); ret = recvfrom(skfd, daddr, if(!ret) < perror(«recv form kernel errorn»); close(skfd); exit(-1); >printf(«from kernel:%sn», u_info.msg); close(skfd); free((void *)nlh); return 0; >
2. Код модуля ядра Netlink.
#include #include #include #include #include #define NETLINK_TEST 30 #define MSG_LEN 125 #define USER_PORT 100 MODULE_LICENSE(«GPL»); MODULE_AUTHOR(«zhangwj»); MODULE_DESCRIPTION(«netlink example»); struct sock *nlsk = NULL; extern struct net init_net; int send_usrmsg(char *pbuf, uint16_t len) < struct sk_buff *nl_skb; struct nlmsghdr *nlh; int ret; / * Создаем пространство sk_buff * / nl_skb = nlmsg_new(len, GFP_ATOMIC); if(!nl_skb) < printk(«netlink alloc failuren»); return -1; >/ * Устанавливаем заголовок сообщения netlink * / nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0); if(nlh == NULL) < printk(«nlmsg_put failaure n»); nlmsg_free(nl_skb); return -1; >/ * Копируем данные и отправляем * / memcpy(nlmsg_data(nlh), pbuf, len); ret = netlink_unicast(nlsk, nl_skb, USER_PORT, MSG_DONTWAIT); return ret; > static void netlink_rcv_msg(struct sk_buff *skb) < struct nlmsghdr *nlh = NULL; char *umsg = NULL; char *kmsg = «hello users. «; if(skb->len >= nlmsg_total_size(0)) < nlh = nlmsg_hdr(skb); umsg = NLMSG_DATA(nlh); if(umsg) < printk(«kernel recv from user: %sn», umsg); send_usrmsg(kmsg, strlen(kmsg)); >> > struct netlink_kernel_cfg cfg = < .input = netlink_rcv_msg, /* set recv callback */ >; int test_netlink_init(void) < /* create netlink socket */ nlsk = (struct sock *)netlink_kernel_create(cfg); if(nlsk == NULL) < printk(«netlink_kernel_create error !n»); return -1; >printk(«test_netlink_initn»); return 0; > void test_netlink_exit(void) < if (nlsk)< netlink_kernel_release(nlsk); /* release ..*/ nlsk = NULL; >printk(«test_netlink_exit!n»); > module_init(test_netlink_init); module_exit(test_netlink_exit);
# #Desgin of Netlink # MODULE_NAME :=netlink_test obj-m :=$(MODULE_NAME).o KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
4. Результаты запуска
Сначала вставьте скомпилированный модуль ядра Netlink в систему (insmod netlink_test.ko), а затем запустите приложение, вы увидите следующий вывод:
# Печать приложения send kernel:hello netlink!! from kernel:hello users. # Ядро печати [25024.276345] test_netlink_init [25117.548350] kernel recv from user: hello netlink!!
Источник: russianblogs.com
Для чего предназначена программа netlink
netlink_socket = socket(PF_NETLINK, socket_type , netlink_family );
ОПИСАНИЕ
Netlink используется для передачи информации с модуля ядра в процессы пользовательского пространства. Он состоит из стандартного, базирующегося на сокетах, интерфейса для процессов пользователя и внутреннего ядра API, предназначенного для модулей ядра. Внутренний интерфейс ядра на этой странице не описывается.
Кроме того, существует устаревший интерфейс netlink, работающий с помощью символьных устройств netlink. Этот интерфейс здесь также не описывается и предназначен только для совместимости с его предыдущими версиями. Netlink — это служба, ориентированная на датаграммы. В качестве socket_type могут использоваться как SOCK_RAW , так и SOCK_DGRAM ; несмотря на это, протокол netlink не проводит границы между датаграммными и raw-сокетами.
netlink_family выбирает модуль ядра или группу netlink для связи. В данный момент определены следующие семейства: NETLINK_ROUTE Получает обновления маршрутов и может быть использована для изменения таблицы маршрутизации IPv4 (см. rtnetlink (7)). NETLINK_FIREWALL Получает пакеты, посылаемые кодом сетевого экрана (firewall) IPv4. NETLINK_ARPD Для управления таблицей arp в пространстве пользователя.
NETLINK_ROUTE6 Принимает и посылает обновления таблицы маршрутизации IPv6. NETLINK_IP6_FW для получения пакетов, не прошедших проверку сетевого экрана (firewall) IPv6 (в настоящее время функция еще не реализована). NETLINK_TAPBASE . NETLINK_TAPBASE+15 являются экземплярами устройства ethertap . Ethertap является псевдосетевым туннельным устройством, позволяющим эмулировать сетевой драйвер из пространства пользователя. NETLINK_SKIP зарезервировано для ENskip NETLINK_USERSOCK зарезервировано для будущих протоколов пространства пользователя.
Сообщения netlink состоят из потока байтов с одним или несколькими заголовками nlmsghdr и соответствущей «полезной» нагрузкой. В первом и всех последующих заголовках сообщений, состоящих из нескольких частей, установлен флаг NLM_F_MULTI . Исключение составляет лишь последний заголовок, имеющий тип NLMSG_DONE . Доступ к потоку байтов можно получить только с помощью стандартных макросов NLMSG_* ; см. netlink (3).
Netlink не является надежным протоколом. Он делает все возможное для доставки сообщения по адресу (адресам), но может «отбрасывать» пакеты при нехватке памяти или возникновении других ошибок в работе. Для повышения надежности передачи отправитель может запросить подтверждение от получателя, установив флаг NLM_F_ACK . Подтверждающим является пакет NLMSG_ERROR с полем ошибки, равным нулю.
Приложение должно само создавать запросы, отсылаемые полученным сообщениям. Ядро пытается послать сообщение NLMSG_ERROR всем непринятым пакетам. Процесс пользователя также должен следовать этому соглашению.
Каждое семейство netlink имеет набор из 32-х многоадресных групп. Когда вызов bind (2) отправляется сокету, поле nl_groups структуры sockaddr_nl должно содержать битовую маску групп, которые оно хочет прослушивать. По умолчанию значение этого поля равно нулю, что означает, что многоадресные передачи не будут приниматься. Сокет может передавать многоадресные сообщения любой из многоадресных групп, присвоив nl_groups битовую маску групп, которым он желает передавать данные при вызове sendmsg (2) или connect (2). Принимать или посылать сообщения многадресной группы netlink могут только пользователи с идентификатором эффективного пользователя, равным 0, или имеющие возможность CAP_NET_ADMIN . Любые ответы на сообщение, полученное многоадресной группой, должны быть отправлены посылающему процессу и многадресной группе.
struct nlmsghdr < __u32 nlmsg_len; /* Длина сообщения, включая заголовок */ __u16 nlmsg_type; /* Содержимое сообщения */ __u16 nlmsg_flags;/* Дополнительные флаги */ __u32 nlmsg_seq; /* Hомер последовательности */ __u32 nlmsg_pid; /* PID процесса, открывшего сокет */ >; struct nlmsgerr < int error; /* отрицательный номер ошибки или 0 для подтверждений. */ struct nlmsghdr msg; /* заголовок сообщения, вызвавшего ошибку */ >;
После каждого вызова nlmsghdr производится нагрузка. nlmsg_type может быть одним из стандартных типов сообщения; сообщения NLMSG_NOOP должны игнорироваться; сообщение NLMSG_ERROR сигнализирует об ошибке, нагрузка содержит структуру nlmsgerr ; сообщение NLMSG_DONE заканчивает сообщение, состоящее из нескольких частей.
Семейство netlink обычно определяет и другие сообщения (см. соответствующие страницы руководства, например, rtnetlink (7) для NETLINK_ROUTE ).
Стандартные биты флагов в nlmsg_flags | |
NLM_F_REQUEST:установлен для всех сообщений с запросами | |
NLM_F_MULTI:T | |
сообщение является частью сообщения, состоящего из нескольких | |
частей, и оканчивается | |
NLMSG_DONE | |
T> | |
NLM_F_ACK:ответ с подтверждением при успехе | |
NLM_F_ECHO:послать эхо этого запроса |
Дополнительные флаги для запросов GET | |
NLM_F_ROOT | Вернуть полную таблицу вместо одной записи. |
NLM_F_MATCH | Пока не реализовано. |
NLM_F_ATOMIC | Вернуть небольшой (atomic) образ таблицы. |
NLM_F_DUMP | пока не описано. |
Дополнительные флаги для запросов NEW | |
NLM_F_REPLACE | Переписать существующий объект. |
NLM_F_EXCL | Hе перезаписывать, если объект уже существует. |
NLM_F_CREATE | Создать объект, если он еще не существует. |
NLM_F_APPEND | Добавить в конец списка объектов. |
Обратите внимание, что NLM_F_ATOMIC требует CAP_NET_ADMIN или прав суперпользователя.
ФОРМАТЫ АДРЕСОВ
Структура sockaddr_nl описывает клиент netlink в пространстве пользователя или в ядре. sockaddr_nl может быть как одноадресной (передача информации только на один адрес), так и принадлежать группе netlink (значение nl_groups не равно нулю).
struct sockaddr_nl < sa_family_t nl_family; /* AF_NETLINK */ unsigned short nl_pad; /* ноль */ pid_t nl_pid; /* pid процесса */ __u32 nl_groups; /* маска многоадресных групп */ >;
nl_pid — pid процесса, владеющего целевым сокетом или 0, если пункт назначения находится в ядре. nl_groups — битовая маска, в которой каждый бит представляет собой номер группы netlink.
НАЙДЕННЫЕ ОШИБКИ
Эта страница руководства содержит неполную информацию о рассматриваемой функции.
ЗАМЕЧАНИЯ
В большинстве случаев лучше использовать netlink с помощью libnetlink , чем с помощью низкоуровневого интерфейса ядра.
ВЕРСИИ
Сокетный интерфейс для netlink появился в Linux 2.2.
Linux 2.0 поддерживал более примитивный интерфейс, базирующийся на устройствах (он все еще является совместимым с предыдущими версиями). Этот устаревший интерфейс на данной странице не описывается.
Источник: www.opennet.ru
NETLINK
Протокол netlink используется для передачи информации между ядром ипроцессами в пользовательском пространстве. Он состоит из стандартного,основанного на сокетах, интерфейса для процессов пользователя и внутреннегоAPI ядра, предназначенного для модулей ядра. Внутренний интерфейс ядра вэтой странице не описан. Кроме того, существует устаревший интерфейсnetlink, работающий через символьные устройства netlink. Этот интерфейсздесь также не описан; он предназначен только для обратной совместимости.
Netlink обеспечивает для приложений сервис передачи датаграмм. В качестве socket_type могут использоваться типы сокетов как SOCK_RAW , так и SOCK_DGRAM . Несмотря на это, протокол netlink не различает датаграмные инеструктурированные (raw) сокеты.
После каждого nlmsghdr следует полезная нагрузка:
Заметим, что NLM_F_ATOMIC требует мандата CAP_NET_ADMIN илиэффективного UID 0.
Дополнительные биты флагов для запросов NEW | |
NLM_F_REPLACE | Переписать существующий подходящий объект. |
NLM_F_EXCL | Не перезаписывать, если объект уже существует. |
NLM_F_CREATE | Создать объект, если он ещё не существует. |
NLM_F_APPEND | Добавить в конец списка объектов. |
Тип поля nlmsg_seq и nlmsg_pid скрыт в ядре netlink.
Форматы адресов
Структура sockaddr_nl описывает клиент netlink в пространствепользователя или в ядре. Она может быть как одноадресной (передачаинформации только на один адрес), так и посылаться многоадресной группеnetlink (значение nl_groups не равно нулю).
nl_pid — одиночный адрес сокета netlink. Он всегда равен 0, если местомназначения является ядро. Для процесса пользовательского пространствазначение nl_pid , обычно, равно PID процесса, которому принадлежит сокетназначения. Однако, значением nl_pid определяется сокет netlink, а непроцесс.
Если процессу принадлежит несколько сокетов netlink, то значение nl_pid может быть равно ID процесса только у одного сокета. Есть дваспособа назначить nl_pid сокету netlink. Если приложение задаёт nl_pid до вызова bind (2), то приложение само должно убедиться, что значение nl_pid уникально. Если приложение устанавливает его равным 0, топрисвоение уникального значения выполняется ядром. Первому сокету netlinkядро назначает ID процесса, который его открыл, а всем последующимсоздаваемым процессом сокетам netlink, будет назначено уникальное значение nl_pid .
Параметры сокета
ВЕРСИИ
Linux 2.0 поддерживал более примитивный интерфейс на основе устройств(который всё ещё доступен для совместимости). Этот устаревший интерфейсздесь не описывается.
ЗАМЕЧАНИЯ
В большинстве случаев лучше использовать netlink с помощью функций библиотек libnetlink или libnl , а не через низкоуровневый интерфейс ядра.
ДЕФЕКТЫ
ПРИМЕР
В следующем примере создаётся сокет netlink семейства NETLINK_ROUTE ,который будет прослушивать многоадресные группы RTMGRP_LINK (события осоздании/удалении/включении/выключении сетевых интерфейсов) и RTMGRP_IPV4_IFADDR (события о добавлении/удалении адресов IPv4).
Сокет Netlink используется для достиженияПользовательский процесспротивПроцесс ядраСпециальная межпроцессная связь (IPC) также является наиболее часто используемым интерфейсом для связи между сетевыми приложениями и ядром.
В ядре Linux есть много приложений, которые используют netlink для связи с ядром, например
- Демон маршрутизации (NETLINK_ROUTE)
- Протокол сокета пользовательского режима (NETLINK_USERSOCK)
- Брандмауэр (NETLINK_FIREWALL)
- подсистема netfilter (NETLINK_NETFILTER)
- События ядра для уведомления пользовательского режима (NETLINK_KOBJECT_UEVENT)
- Общий сетевой канал (NETLINK_GENERIC)
Netlink — очень хороший способ двусторонней передачи данных между ядром и пользовательскими приложениями.Приложения пользовательского режима могут использовать стандартные API-интерфейсы сокетов для использования мощных функций, предоставляемых netlink, в то время как режим ядра должен использовать специальные API-интерфейсы ядра для использования netlink.
Вообще говоря, существует три способа связи между пользовательским пространством и пространством ядра: /proc、ioctl、Netlink . Первые два являются однонаправленными, и Netlink может реализовать дуплексную связь.
По сравнению с системными вызовами, файловой системой ioctl и / proc, Netlink имеет следующие преимущества:
Протокол Netlink основан на сокете BSD и AF_NETLINK Кластер адресов, использующий 32-битную адресацию номера порта, каждый протокол Netlink обычно связан с одной или группой основных служб / компонентов, таких как NETLINK_ROUTE Используется для получения и установки информации о маршрутах и ссылках, NETLINK_KOBJECT_UEVENT Используется ядром для отправки уведомлений процессу udev в пользовательском пространстве и т. Д.
Два, структура данных пользовательского режима
Приложения пользовательского режима используют стандартные API-интерфейсы сокетов, такие как sendto (), recvfrom (), sendmsg (), recvmsg ().
Связь Netlink похожа на обычную связь UDP Socket, struct sockaddr_nl Это коммуникационный адрес netlink, который совпадает с обычным socket struct sockaddr_in похожий.
1. Структура struct sockaddr_nl:
2. Структура struct nlmsghd:
3. Структура struct msghdr
Три, структура данных ядра netlink
2. Часто используемые макросы Netlink:
3. Общие функции ядра Netlink
Функция ядра netlink_kernel_create используется для создания сокета ядра и взаимодействия с пользовательским режимом.
4. Одноадресная передача netlink_unicast () и многоадресная передача netlink_broadcast ()
Однажды, в одном из проектов, мне понадобилось организовать строгий и надежный контроль над всеми сетевыми интерфейсами, таблицами маршрутизации, а так же получать нотификации о каких-либо изменениях. Было принято стратегическое решение — не использовать старые-добрые ioctl netdevice (SIOCGIFMETRIC, SIOCSIFNAME и т.п.) или непосредственные вызовы соответствующих утилит (ifconfig, route и т.д.), а найти более современное и болле удобное решение.
Оно было найдено — libnetlink. Это библиотека, предоставляющая большое количество методов для коммуникации с ядром, с помощью механизма netlink. Данная библиотека идеально подходила для моих целей, позволяя решить огромное количество задач. К сожалению, у библиотеки оказался не особо удобный и довольно сложный API, требовавший совершать множество непонятных действий. Особого веселья добавляло практически полное отсутствие документации и вообще любых материалов на эту тему.
Подумав, я решил как следует разобраться в netlink и написать свою библиотеку. В данный момент реализован весь функционал для работы с нотификацией, сетевыми интерфейсами, таблицами маршрутизации, разумеется поддерживаются IPv4 и IPv6. В достаточно скором времени данный проектик будет представлен на суд общественности 🙂 А пока я бы хотел познакомить всех интересующихся с прекрасным миром netlink, на примере простого монитора сетевых интерфейсов.
Что такое netlink?
Создание сокета netlink.
Объявление netlink сокета выглядит вполне стандартно:
socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
Где AF_NETLINK — протокол netlink
SOCK_RAW — тип сокета
NETLINK_ROUTE — семейство netlink протокола.
Последний параметр может быть различным, в зависимости от того, что мы именно хотим получить от netlink.
Приведу таблицу со наиболее интересными параметрами (полный список параметров можно посмотреть в документации):
NLM_F_REPLACE — заменить существующий аналогичный объект
NLM_F_EXCL — не заменять, если такой объект уже существует
NLM_F_CREATE — создать объект, если он не существует
NLM_F_APPEND — добавить объект в список к уже существующему
Для идентификации клиентов (на уровне ядра и на пользовательском уровне) существует специальная адресная структура — nladdr:
nl_groups — это битовая маска, каждый бит которой представляет номер группы netlink. При вызове bind() для сокета netlink следует указывать битовую маску группы, которую желает прослушивать приложение, в данном контексте. Различные группы могут быть объединены с помощью логического или.
Основные группы определены в заголовочном файле netlink.
Пример некоторых из них:
RTMGRP_LINK — эта группа получает уведомления об изменениях в сетевых интерфейсах (интерфейс удалился, добавился, опустился, поднялся)
RTMGRP_IPV4_IFADDR — эта группа получает уведомления об изменениях в IPv4 адресах интерфейсов (адрес был добавлен или удален)
RTMGRP_IPV6_IFADDR — эта группа получает уведомления об изменениях в IPv6 адресах интерфейсов (адрес был добавлен или удален)
RTMGRP_IPV4_ROUTE — эта группа получает уведомления об изменениях в таблице маршрутизации для IPv4 адресов
RTMGRP_IPV6_ROUTE — эта группа получает уведомления об изменениях в таблице маршрутизации для IPv6 адресов
После структуры заголовка nlmsghdr всегда расположен указатель на блок данных. Доступ к нему можно получить с помощью макросов, о которых будет рассказано далее.
Макросы netlink
От теории к практике.
Ну что же. Думаю, что я уже успел надоесть со скучной теорией 🙂 Может быть что-то показалось запутанным или не понятным — постараюсь разжевать все в наглядных примерах, там на самом деле нет ничего сложного.
Ниже приведено обещанное приложение, которое будет получать уведомления об изменениях в сетевых интерфейсах и таблице маршрутизации.
В примере введен целый ряд новых структур:
Эта структура непосредственно передается через сокет. Она содержит в себе указатель на блок полезных данных, количество данных блоков, а так же ряд дополнительных флагов и полей, пришедших, по большей части, с платформы BSD.
Эта структура используется для представления сетевого устройства, его семейства, типа, индекса и флагов.
Эта структура служит для представления сетевого адреса, назначенного на сетевой интерфейс.
Эта структура служит для хранения какого либо параметра соединения или адреса.
Исходный код, монитор
Компиляция программы:
gcc monitor.c -o monitor
И результат работы:
Вот и все. Очень надеюсь, что данный материал будет полезен кому-то.
Если будет достаточное количество желающих (больше одного человека:) ) — могу написать продолжение и рассмотреть, например, взаимодействие с модулем ядра или реализацию работы с IPv6.
- NETLink – основной модуль по организации и поддержанию коммуникационного канала
- NETLinkConfig – конфигуратор модуля NETLink
- NETLinkLogger – монитор журнала событий активности соединений GSM шлюзов и ПО сбора данных
Описание
Пользовательскому ПО предоставляется два варианта обмена данными с приборами на удаленном объекте:
Гибкость в выборе вариантов дает возможность применения также и программы производителя прибора учета в целях конфигурирования, чтения данных и т.п., что позволяет отказаться от дополнительных затрат на организацию выезда специалиста на объект для настройки прибора учета.
Дополнительные возможности программы:
Конвертация форматов Modbus позволяет подсоединять к GSM шлюзам на удаленных объектах оборудование, работающее по последовательному порту с использованием протокола Modbus/RTU. После выполнения конвертации, данные в пользовательское приложение, поступают по протоколу Modbus TCP. Это предоставляет возможность сбора данных с оборудования объекта средствами SCADA-систем.
При использовании GSM шлюзов RG 104/105 в модификации с дискретными входами/выходами Сервер соединений обеспечивает считывание информации о состоянии входов и управление выходами по протоколу Modbus TCP.
ОПИСАНИЕ
Протокол netlink используется для передачи информации между ядром и процессами в пользовательском пространстве. Он состоит из стандартного, основанного на сокетах, интерфейса для процессов пользователя и внутреннего API ядра, предназначенного для модулей ядра. Внутренний интерфейс ядра в этой странице не описан. Кроме того, существует устаревший интерфейс netlink, работающий через символьные устройства netlink. Этот интерфейс здесь также не описан; он предназначен только для обратной совместимости.
Netlink обеспечивает для приложений сервис передачи датаграмм. В качестве socket_type могут использоваться типы сокетов как SOCK_RAW, так и SOCK_DGRAM. Несмотря на это, протокол netlink не различает датаграмные и неструктурированные (raw) сокеты.
По значению netlink_family выбирается модуль ядра или группа netlink для связи. В данный момент определены следующие семейства netlink:
После каждого nlmsghdr следует полезная нагрузка:
Заметим, что NLM_F_ATOMIC требует мандата CAP_NET_ADMIN или эффективного UID 0.
Дополнительные биты флагов для запросов NEW | |
NLM_F_REPLACE | Переписать существующий подходящий объект. |
NLM_F_EXCL | Не перезаписывать, если объект уже существует. |
NLM_F_CREATE | Создать объект, если он ещё не существует. |
NLM_F_APPEND | Добавить в конец списка объектов. |
Тип поля nlmsg_seq и nlmsg_pid скрыт в ядре netlink.
Форматы адресов
Структура sockaddr_nl описывает клиент netlink в пространстве пользователя или в ядре. Она может быть как одноадресной (передача информации только на один адрес), так и посылаться многоадресной группе netlink (значение nl_groups не равно нулю).
nl_pid — одиночный адрес сокета netlink. Он всегда равен 0, если местом назначения является ядро. Для процесса пользовательского пространства значение nl_pid, обычно, равно PID процесса, которому принадлежит сокет назначения. Однако, значением nl_pid определяется сокет netlink, а не процесс.
Если процессу принадлежит несколько сокетов netlink, то значение nl_pid может быть равно ID процесса только у одного сокета. Есть два способа назначить nl_pid сокету netlink. Если приложение задаёт nl_pid до вызова bind(2), то приложение само должно убедиться, что значение nl_pid уникально. Если приложение устанавливает его равным 0, то присвоение уникального значения выполняется ядром. Первому сокету netlink ядро назначает ID процесса, который его открыл, а всем последующим создаваемым процессом сокетам netlink, будет назначено уникальное значение nl_pid.
ВЕРСИИ
Linux 2.0 поддерживал более примитивный интерфейс на основе устройств (который всё ещё доступен для совместимости). Этот устаревший интерфейс здесь не описывается.
NETLINK_SELINUX появился в Linux 2.6.4.
NETLINK_AUDIT появился в Linux 2.6.6.
NETLINK_KOBJECT_UEVENT появился в Linux 2.6.10.
NETLINK_W1 и NETLINK_FIB_LOOKUP появились в Linux 2.6.13.
NETLINK_INET_DIAG, NETLINK_CONNECTOR и NETLINK_NETFILTER появились в Linux 2.6.14.
NETLINK_GENERIC и NETLINK_ISCSI появились в Linux 2.6.15.
ЗАМЕЧАНИЯ
В большинстве случаев лучше использовать netlink с помощью функций библиотек libnetlink или libnl, а не через низкоуровневый интерфейс ядра.
ДЕФЕКТЫ
ПРИМЕР
В следующем примере создаётся сокет netlink семейства NETLINK_ROUTE, который будет прослушивать многоадресные группы RTMGRP_LINK (события о создании/удалении/включении/выключении сетевых интерфейсов) и RTMGRP_IPV4_IFADDR (события о добавлении/удалении адресов IPv4).
- Проект день рождения снеговика в доу средняя группа
- Что такое металлы определение кратко
- Что такое раскопки кратко
- Как правильно писать школу
- Музыка для самостоятельной деятельности в детском саду
Источник: obrazovanie-gid.ru