C Programming

Netlink 7 C Function

The user-space tasks, as well as the kernel, communicate with one another via Netlink. It is made up of an inner kernel API for the core plugins and a common sockets-centered user space task interface. In this instructional article, the core kernel interface is not described. Additionally, there is indeed an outdated Netlink interface accessible through the Netlink character peripherals. This interface isn’t described here and is solely included for backward compatibility. Datagrams are the focus of the Netlink’s service. There are two acceptable options for the socket style: SOCK_RAW and SOCK_DGRAM. The Netlink interface, meanwhile, somehow doesn’t differentiate between the datagrams and raw sockets.

Netlink Families

The Netlink clan determines the kernel package or the Netlink set to use for communication. The existing Netlink families designated are the following:

  • NETLINK_ROUTE: It accepts the routing as well as connection updates which could be used to change the IPs, link settings, neighbor configurations, queueing disciplines, communication classifications, and packet classifications.
  • NETLINK_W1: The messages sent by the 1-wire network.
  • NETLINK_USERSOCK: Used only by the user-mode interface protocols.
  • NETLINK_FIREWALL: Transfer the IPv4 packets via the user mode to Netfilter being used by the core package IP queue. Since being deemed unnecessary for a protracted duration of time (in favor of the far more sophisticated nfnetlink queue function), NETLINK FIREWALL is finally eliminated in Linux 3.5.
  • NETLINK_SOCK_DIAG: Asks the core for details on the sockets belonging to the different protocol variants.
  • NETLINK CRYPTO: Requesting cipher data using the Netlink interface both authenticated with the kernel’s encryption API and permits setting up the kernel’s cryptographic API.
  • NETLINK_IP6_FW: Transfers IPv6 frames via user mode to Netfilter. Utilized by the kernel component ip6 queue.

The interface Netlink isn’t trustworthy. It makes every effort to deliver the information to its intended recipients. However, if a storage issue or any other mistake arises, it could lose communications. By enabling the NLM F ACK flag, the transmitter can ask the recipient for an affirmation to ensure a trustworthy transmission. NLMSG ERROR packets with the fault field set to 0 are acknowledgments. The acknowledgments for messages received should be produced by the program itself.

For each dropped packet, the kernel attempts to give an NLMSG ERROR response. This pattern should also be followed by the user processes. In any event, it is difficult to transmit the data from the kernel to the user in a trustworthy manner.

Whereas, if the socket storage is filled, the kernel is unable to transmit a Netlink message because the information will be lost and the core with its user-space operation would no longer share the very same notion of the status of the core. The app is responsible for determining when it occurs as a result of the ENOBUFS failure that recvmsg(2) returns and resynchronizes.

Example:

We will discuss a program to use the Netlink() function for communication between the kernel and the normal systems. First, we take a look at the user side of this program. For this, we have to add the main socket and the Netlink headers in the code to make use of the sockets in the C program along with the Netlink() function, i.e. “socket.h” and “Netlink.h”.

After this, we set the maximum payload size to 1024 and set the defining structures, i.e. sockaddr_nl, src_adr, dest_adr. The null structure “nlmsghdr” is also defined with “*nl” and iovec structure. The main() function is started with the creation of a socket using the “socket” function. This function contains the PF_NETLINK domain name for the socket and the SOCK_RAW socket type. The NETLINK_TEST socket protocol is defined in the parameters of the socket function.

The memset() function is used to point towards the “src_adr” block of the struct memory where the value 0 is set to several bytes that the “src_Adr” structure contains. Using the src_adr structure, we set the family, process id, and groups of the particular socket to AF_NETLINK, self process ID, and 0, respectively. Similar to a TCP/IP connection, the established socket is linked to a local (origin) connection ip through the Netlink bind() function. The memset() function is again used to point towards the “dest_adr” block of the struct memory where the value 0 is set to several bytes that the destination structure contains.

Using the dest_adr structure, we assign the family, process id, and groups for the particular destination socket to AF_NETLINK, 0 process ID, and 0 groups, respectively. Using the malloc() function, we assign the dynamic memory to structure “nlmsghdr” and save the return result, i.e. succeeded or not. The null structure pointer “nl” points towards the message length, process id, and flag 0 to fill the Netlink message header. The strcpy() function is here to copy the string within the “nl” null pointer structure.


Therefore, the communication payload plus nlmsghdr makes up a Netlink message. When a communication is received, it goes into the buffer that the nl pointer is pointing at. We may also submit the updated message to the structure msghdr “msg”. The “nl” structure pointer can read the message from the kernel and display it on the shell via the use of the NLMSG_DATA() function.

Lastly, the Netlink socket descriptor is used to close the Netlink socket.

Within the kernel program space, we create a NULL structure “sock” along with its pointer “*nl_sk”. The nl_data_ready() function uses this structure and some length to wake it up and make the data ready after a sleep. The netlink_test() function is here to wait for a message that comes down from the user space to the kernel and print it out. In the end, the kernel space releases the socket.

The “Hello you!” message is displayed on our screen after executing this example.

Conclusion

This is about the use of the NETLINK() 7 function of C within our C programs separately for the user-space and the kernel-space. We discussed its uses by sending a message from the user space to the relevant kernel space. This article’s sample code can be implemented on any compiler.

About the author

Omar Farooq

Hello Readers, I am Omar and I have been writing technical articles from last decade. You can check out my writing pieces.