forked from sachinites/UdemyCourseOnNetlink
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNetlinkRtLKM.c
executable file
·170 lines (128 loc) · 6.39 KB
/
NetlinkRtLKM.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* Find my other courses on : http://csepracticals.wixsite.com/csepracticals
* at great discounts and offers */
/* Demo Greetings Linux Kernel Module written for
* kernel 4.4.0-31-generic and 5.0.0-36-generic*/
/* #include Minimum required header files to write a kernel
* Module*/
#include <linux/module.h> /*Include this for any kernel Module you write*/
#include <linux/netlink.h> /*Use it for Netlink functionality*/
#include <net/sock.h> /*Network namespace and socket Based APIs*/
#include <linux/string.h> /*for memset/memcpy etc..., do not use <string.h>, that is for user space*/
#include <linux/kernel.h> /*for scnprintf*/
#define __KERNEL__
#include "common.h"
/*Global variables of this LKM*/
static struct sock *nl_sk = NULL; /*Kernel space Netlink socket ptr*/
/* Reciever function for Data received over netlink
* socket from user space
* skb - socket buffer, a unified data structiure for
* packaging the data type being transported from one kernel
* subsystem to another or from kernel space to user-space
* or from user-space to kernel space. The internal member of this
* socket buffer is not accessed directly, but rather kernel APIs
* provide setters/getters for this purpose. We will use them as
* we would need along the way*/
/* When the Data/msg comes over netlink socket from userspace, kernel
* packages the data in sk_buff data structures and invokes the below
* function with pointer to that skb*/
static void netlink_recv_msg_fn(struct sk_buff *skb_in){
struct nlmsghdr *nlh_recv, *nlh_reply;
char *user_space_data;
int user_space_data_len;
struct sk_buff *skb_out;
char kernel_reply[256];
int user_space_process_port_id;
int res;
printk(KERN_INFO "%s() invoked", __FUNCTION__);
/*skb carries Netlink Msg which starts with Netlink Header*/
nlh_recv = (struct nlmsghdr*)(skb_in->data);
nlmsg_dump(nlh_recv);
user_space_process_port_id = nlh_recv->nlmsg_pid;
printk(KERN_INFO "%s(%d) : port id of the sending user space process = %u\n",
__FUNCTION__, __LINE__, user_space_process_port_id);
user_space_data = (char*)nlmsg_data(nlh_recv);
user_space_data_len = skb_in->len;
printk(KERN_INFO "%s(%d) : msg recvd from user space= %s, skb_in->len = %d, nlh->nlmsg_len = %d\n",
__FUNCTION__, __LINE__, user_space_data, user_space_data_len, nlh_recv->nlmsg_len);
if(nlh_recv->nlmsg_flags & NLM_F_REQUEST){
/*Sending reply back to user space process*/
memset(kernel_reply, 0 , sizeof(kernel_reply));
/*defined in linux/kernel.h */
snprintf(kernel_reply, sizeof(kernel_reply),
"Msg from Process %d has been processed by kernel", nlh_recv->nlmsg_pid);
/*Get a new sk_buff with empty Netlink hdr already appended before payload space
* i.e skb_out->data will be pointer to below msg :
*
* +----------+---------------+
* |Netlink Hdr| payload |
* ++---------+---------------+
*
* */
skb_out = nlmsg_new(sizeof(kernel_reply), 0/*Related to memory allocation, skip...*/);
/*Add a TLV*/
nlh_reply = nlmsg_put(skb_out,
0, /*Sender is kernel, hence, port-id = 0*/
nlh_recv->nlmsg_seq, /*reply with same Sequence no*/
NLMSG_DONE, /*Metlink Msg type*/
sizeof(kernel_reply), /*Payload size*/
0); /*Flags*/
/* copy the paylod now. In userspace, use NLMSG_DATA, in kernel space
* use nlmsg_data*/
strncpy(nlmsg_data(nlh_reply), kernel_reply, sizeof(kernel_reply));
/*Finaly Send the msg to user space space process*/
res = nlmsg_unicast(nl_sk, skb_out, user_space_process_port_id);
if(res < 0){
printk(KERN_INFO "Error while sending the data back to user-space\n");
kfree_skb(skb_out); /*free the internal skb_data also*/
}
}
}
static struct netlink_kernel_cfg cfg = {
.input = netlink_recv_msg_fn, /*This fn would recieve msgs from userspace for
Netlink protocol no 31*/
/* There are other parameters of this structure, for now let us
* not use them as we are just kid !!*/
};
/*Init function of this kernel Module*/
static int __init NetlinkGreetings_init(void) {
/* All printk output would appear in /var/log/kern.log file
* use cmd -> tail -f /var/log/kern.log in separate terminal
* window to see output*/
printk(KERN_INFO "Hello Kernel, I am kernel Module NetlinkGreetingsLKM.ko\n");
/* Now Create a Netlink Socket in kernel space*/
/* Arguments :
* Network Namespace : Read here :
* https://blogs.igalia.com/dpino/2016/04/10/network-namespaces
* Netlink Protocol ID : NETLINK_TEST_PROTOCOL
* Netlink Socket Configuration Data
* */
/*Now create a Netlink socket*/
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST_PROTOCOL, &cfg);
if(!nl_sk){
printk(KERN_INFO "Kernel Netlink Socket for Netlink protocol %u failed.\n", NETLINK_TEST_PROTOCOL);
return -ENOMEM; /*All errors are defined in ENOMEM for kernel space, and in stdio.h for user space*/
}
printk(KERN_INFO "Netlink Socket Created Successfully");
/*This fn must return 0 for module to successfully make its way into kernel*/
return 0;
}
/*Exit function of this kernel Module*/
static void __exit NetlinkGreetings_exit(void) {
printk(KERN_INFO "Bye Bye. Exiting kernel Module NetlinkGreetingsLKM.ko \n");
/*Release any kernel resources held by this module in this fn*/
netlink_kernel_release(nl_sk);
nl_sk = NULL;
}
/*Every Linux Kernel Module has Init and Exit functions - just
* like normal C program has main() fn.*/
/* Registration of Kernel Module Init Function.
* Whenever the Module is inserted into kernel using
* insmod cmd, below function is triggered. You can do
* all initializations here*/
module_init(NetlinkGreetings_init);
/* Registration of Kernel Module Exit Function.
* Whenever the Module is removed from kernel using
* rmmod cmd, below function is triggered. You can do
* cleanup in this function.*/
module_exit(NetlinkGreetings_exit);
MODULE_LICENSE("GPL");