So guys, now let us discuss the implementation of our API and netlink message to kernel.
Right.
So you can see that I have opened the file userspace dot c which will represent our userspace program
and I have hash included all the required header files.
You can see that because we will going to eventually create a netlink socket.
We need a socket dot h header file and we will have to use netlink message header and other related
data structures.
Therefore we have to hash include linux slash netlink dot h.
Right.
So now, as a first step of writing this function, first of all, we need a way to specify the destination
address.
In this case, the destination is nothing, but it is a kernel space.
We need to specify the destination address in terms of netlink semantics.
Right.
So for that we will going to make use of the data structure socket.
Underscore netlink.
This data structure is used to specify the source or destination address which are being communicated
over the netlink socket.
So let us initialize this data structure.
And finally we will going to specify the address family for the netlink.
The address family for the netlink is af underscore netlink.
So this is basically a constant value.
And then we have to specify the port ID of the destination process.
In this case, the destination process is the kernel and the kernel has the port ID zero, which is
again a constant.
Now we will have to create Netlink message header which is appended by the payload.
You can see in this function the second argument is a pointer to the payload.
Right?
So now let us create a netlink message header.
So of course we will have to specify as much space as required to ship our netlink header appended by
the payload data.
So you can see that now you will come across certain macros, which you are seeing for the first time.
So Netlink message header LAN is actually the macro which expands to the size of the Netlink message
header.
So you can see in the file Linux slash netlink dot h.
You can see all the macros which netlink APIs uses.
So you can see that Netlink message header land is here and you can see it is nothing, but it is the
size of the Netlink message header.
However, we do some kind of alignment in the kernel code and therefore it is advisable that you always
use these macros instead of directly using the definition of this macros in your code.
Always, always use these macros which are provided by the Linux APIs.
This netlink message align macro actually actually aligns any integral number to the multiple of four.
So you can see the definition of this netlink message align is here.
Suppose the land value that you specify is say 18 bytes.
The netlink message align will going to return you.
20 Right.
And another example is that if you specify this value as 23, then netlink message align will going
to return you 24 Right.
So basically Netlink message align aligns whatever integral values you specify into a next bigger integer,
which is a multiple of four.
And now coming back to our code since the size of the payload that we need to send is equal to the message
size which is specified in the third argument.
So here you can actually mention the how much payload you want to ship, right?
So you can see that we have taken as much memory which can contain the netlink message header followed
by the payload.
Now the next thing that we need to do is to specify the all the fields of this netlink header.
So the very first thing that we will fill is the Netlink message header.
LAN Right.
And we already know that the Netlink message header LAN is the total length of the message which we
are sending from the userspace to kernel space.
So here you can specify exactly the same amount of memory which we have logged in the previous line.
Now the next thing we have to fill is the port ID of this Netlink message header so we can use the function
getpid which will actually return the process id of the userspace program.
Right.
Then the flags value we can copy as it is, which has passed as the fifth argument to this Netlink API.
Netlink message type is being given as the fourth argument to this API.
So you can simply copy the netlink message type as it is into the netlink header.
And finally, the fifth field of the Netlink message header is the sequence number.
For now you can just mention it as zero, right?
So now with this we have filled up all the fields of the Netlink header and now what is remaining is
to fill the payload data behind this Netlink header.
Right?
So for that you can use MCP or string copy.
Now you can see here is another macro called Netlink message data.
The definition of this netlink message data is here.
If you read this definition very carefully, you will find out that Netlink message data does nothing.
It simply returns the address of the start of payload data which is sitting behind this Netlink header.
So you can see in this slide the Netlink message data will simply returns the pointer to the start of
this green box.
That is the payload, right?
So coming back to our code here, we are simply copying the message which we have passed to as the second
argument to this function into the payload part of this netlink message header.
Right.
So now with this, we have completely prepared the Netlink message, which is to be shipped to the kernel
space.
Now, the second step that we discussed is the wrapping of this netlink message data inside the vector
data structure.
So for that we will simply take our vector variable.
And to the base field of this vector, we will specify the address of the netlink header that we are
going to send.
And the second field, as we discussed, we will going to specify the total length of the message that
we are sending to the kernel space.
And this completes our step number two.
Now the step number three was the second round of wrapping our data.
And remember that we have to use the struct message header data structure for that purpose.
Right now, as a final step, we will going to fill up the fields of this outer message header.
Right.
So let us initialize this data structure first.
And then in the message name field, we will have to specify the address of the destination address.
We have already taken the variable of this destination address.
Right?
Then in the message name length field, we will have to specify the size of the destination address.
And finally, we have to specify the address of the i o vector, which inside which indirectly we have
encapsulated our data, which is to be sent to the kernel space.
And finally, we have to specify the number of units of this vector.
In this case it is one.
And now in the step number four, we will simply have to send this data to the kernel space.
So for that you can use the API, send message, specify the file descriptor of the netlink socket,
which is passed as a first argument to this API.
In the next lecture video we will going to discuss how to create this file descriptor for netlink sockets.
And then specify the address of this outer message header.
And this API will simply send your message which is hidden inside this outer message header to the kernel
space and the return value of this send message API is the number of bytes that is sent to the kernel
space.
Right.
So this value will be negative in case if for any reason the API send message fails.
So in that scenario.
Send message will return a negative value and we can print a global variable.
Error number to see what is the reason for the failure.
This error number is a global variable which is specified to which we have an access through a file.
Error number dot h.
And finally, we can return the number of bytes that this function sends so you can see that the implementation
of this function is fairly simple and straightforward.
It is divided into 4 or 5 steps that we have already discussed.
Also note that in order to manipulate the Netlink header, always make use of these macros which is
provided by the Linux kernel APIs.
All these macros you can find in the file Linux slash Netlink dot h.
So now we have discussed the function which can send messages to the kernel space.
But as of now we don't have an infrastructure in the user space to make an invocation to this function.
So now let us proceed forward and complete the remaining part of our user space program and see how
this API is able to send your messages to the kernel space.
So in the next lecture video, we will going to design our user space application, which is two threaded
application that we have already discussed.
As of now, just ensure that your user space dot c file compiles well without any error.