Netlink : Unicast ================= .. tab-set:: .. tab-item:: Netlink : Unicast * In this program, you are going to learn .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to communication between kernel and user space ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use user space APIs ? * `NLMSG_SPACE `_ * `NLMSG_DATA `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use kernel space APIs ? * `nlmsg_new `_ * `nlmsg_put `_ * `NETLINK_CB `_ * `nlmsg_unicast `_ * `netlink_kernel_create `_ * `netlink_kernel_release `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`Netlink ` * :ref:`User program : nl_user.c ` * :ref:`Kernel program : nl_kernel.c ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Summary ` .. _p1_netlinkUnicast_0: .. tab-set:: .. tab-item:: Netlink * Netlink is used to transfer information between the kernel and user-space processes. * Netlink is a datagram-oriented service. Both SOCK_RAW and SOCK_DGRAM are valid values for socket_type. .. _p1_netlinkUnicast_1: .. tab-set:: .. tab-item:: nl_user.c * To create a socket with ``socket()``, .. code-block:: c int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TESTFAMILY); * nl_pid field of the sockaddr_nl can be filled with the calling process' own pid. .. code-block:: c nlh->nlmsg_pid = getpid(); * ``Sending a Netlink Message`` In order to send a netlink message to the kernel or other user-space processes, another struct sockaddr_nl addr needs to be supplied as the destination address, the same as sending a packet with sendmsg(). If the message is destined for the kernel, both nl_pid and nl_groups should be supplied with 0. .. code-block:: c addr.nl_pid = 0; addr.nl_groups = 0; struct msghdr msg; msg.msg_name = (void * ) &addr; msg.msg_namelen = sizeof(addr); * The netlink socket requires its own message header as well. This is for providing a common ground for netlink messages of all protocol types. Because the Linux kernel netlink core assumes the existence of the following header in each netlink message, an application must supply this header in each netlink message it sends: .. code-block:: c struct nlmsghdr * nlh = (struct nlmsghdr * ) malloc(NLMSG_SPACE(MAX_PAYLOAD)); nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; * A netlink message thus consists of nlmsghdr and the message payload. Once a message has been entered, it enters a buffer pointed to by the nlh pointer. We also can send the message to the struct msghdr msg: .. code-block:: c struct iovec iov; iov.iov_base = (void * ) nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_iov = &iov; msg.msg_iovlen = 1; * After the above steps, a call to ``sendmsg()`` kicks out the netlink message: .. code-block:: c sendmsg(fd, &msg, 0); * ``recvmsg`` used for Receiving Netlink Messages, .. code-block:: c recvmsg(fd, &msg, 0); * See the full program below, .. literalinclude:: p1_netlinkUnicast/nl_user.c :language: c :linenos: :emphasize-lines: 13, 14, 15, 16, 22, 23, 24, 26, 29, 30, 31, 35, 36, 39, 40, 41, 42, 46, 51 .. _p1_netlinkUnicast_2: .. tab-set:: .. tab-item:: nl_kernel.c * ``nlmsg_new`` using this create a netlink message. .. code-block:: c struct sk_buff * skb_out; skb_out = nlmsg_new(message_size, GFP_KERNEL); * ``nlmsg_put`` used to populate the message with data. .. code-block:: c struct nlmsghdr * nlh = (struct nlmsghdr * ) skb->data; nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, message_size, 0); * ``nlmsg_unicast`` used to send the message to the user space application. .. code-block:: c result = nlmsg_unicast(socket, skb_out, pid); * ``netlink_kernel_create`` used to create a Netlink socket in the kernel. .. code-block:: c socket = netlink_kernel_create(&init_net, NETLINK_TESTFAMILY, &config); * ``netlink_kernel_release`` used to release the netlink socket created with ``netlink_kernel_create``. .. code-block:: c netlink_kernel_release(socket); * See the full program below, .. literalinclude:: p1_netlinkUnicast/nl_kernel.c :language: c :linenos: :emphasize-lines: 14, 18, 23, 30, 36, 37, 40, 46, 47, 50, 61 .. _p1_netlinkUnicast_3: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: p1_netlinkUnicast/Makefile :language: c :linenos: .. _p1_netlinkUnicast_4: .. tab-set:: .. tab-item:: Compile and Load .. code-block:: c :linenos: :emphasize-lines: 1, 3, 5, 7, 9 $ make all $ sudo insmod ./nl_kernel.ko $ ./nl_user $ sudo rmmod nl_kernel $ dmesg [168541.257012] Netlink initialized [168546.697217] Entering: test_nl_receive_message [168546.697220] Received message: Hello [168546.697224] Sent message: Hello from kernel unicast [168567.528336] Netlink released .. _p1_netlinkUnicast_5: .. tab-set:: .. tab-item:: Summary =============================== ======================================= User Space API Learning =============================== ======================================= socket To create a socket sendmsg To send netlink message recvmsg To receive netlink message =============================== ======================================= .. tab-set:: .. tab-item:: Summary =============================== ================================================= Kernel Space API Learning =============================== ================================================= nlmsg_new To create a netlink message nlmsg_put TO populate the message nlmsg_unicast To send the message to the user space application netlink_kernel_create To create a Netlink socket in the kernel netlink_kernel_release To release the netlink socket =============================== ================================================= .. card:: See Also * Previous Chapters * :doc:`../chapter1_basics/chapter1_basics` * :doc:`../chapter2_kthreads/chapter2_kthreads` * :doc:`../chapter3_tasklets/chapter3_tasklets` * :doc:`../chapter4_workqueue/chapter4_workqueue` * :doc:`../chapter5_timer/chapter5_timer` * :doc:`../chapter8_linkedList/chapter8_linkedList` * :doc:`../chapter9_fileSystem/chapter9_fileSystem` * Other Netlink topic * :doc:`p2_netlinkMulticast`