-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfastecho_module.c
138 lines (102 loc) · 3.09 KB
/
fastecho_module.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
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <net/sock.h>
#include "fastecho.h"
#define DEFAULT_PORT 8888
#define DEFAULT_BACKLOG 128
//set module info
MODULE_DESCRIPTION("The fastest echo in kernel module");
MODULE_AUTHOR("lrf141");
MODULE_LICENSE("MIT");
//set module param
static ushort port = DEFAULT_PORT;
static ushort backlog = DEFAULT_BACKLOG;
module_param(port, ushort, S_IRUGO);
module_param(backlog, ushort, S_IRUGO);
struct echo_server_param param;
struct socket *listen_sock;
struct task_struct *echo_server;
static int open_listen(struct socket **);
static void close_listen(struct socket *);
static int fastecho_init_module(void){
int error;
printk(MODULE_NAME ": module loaded!!\n");
error = open_listen(&listen_sock);
if(error < 0){
printk(KERN_ERR MODULE_NAME ": listen socket open error\n");
return error;
}
param.listen_sock = listen_sock;
echo_server = kthread_run(echo_server_daemon, ¶m, MODULE_NAME);
if(IS_ERR(echo_server)){
printk(KERN_ERR MODULE_NAME ": cannot start server daemon\n");
close_listen(listen_sock);
}
return 0;
}
static void fastecho_cleanup_module(void){
send_sig(SIGTERM, echo_server, 1);
kthread_stop(echo_server);
close_listen(listen_sock);
printk(MODULE_NAME ": module unloaded!\n");
}
static int open_listen(struct socket **result){
struct socket *sock;
struct sockaddr_in addr;
int error;
int opt = 1;
//using IPv4, TCP/IP
error = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
if(error < 0){
printk(KERN_ERR MODULE_NAME ": socket create error = %d\n", error);
return error;
}
printk(MODULE_NAME ": socket create ok....\n");
//set tcp_nodelay
error = kernel_setsockopt(sock,
SOL_TCP, TCP_NODELAY,
(char *)&opt, sizeof(opt));
if(error < 0){
printk(KERN_ERR MODULE_NAME ": setsockopt tcp_nodelay setting error = %d\n", error);
sock_release(sock);
return error;
}
printk(MODULE_NAME ": setsockopt ok....\n");
//setting sockaddr_in
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(DEFAULT_PORT);
//bind
error = kernel_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if(error < 0){
printk(KERN_ERR MODULE_NAME ": socket bind error = %d\n", error);
sock_release(sock);
return error;
}
printk(MODULE_NAME ": socket bind ok....\n");
//listen
error = kernel_listen(sock, DEFAULT_BACKLOG);
if(error < 0){
printk(KERN_ERR MODULE_NAME ": socket listen error = %d\n", error);
sock_release(sock);
return error;
}
printk(MODULE_NAME ": socket listen ok....\n");
*result = sock;
return 0;
}
static void close_listen(struct socket *sock){
kernel_sock_shutdown(sock, SHUT_RDWR);
sock_release(sock);
}
module_init(fastecho_init_module);
module_exit(fastecho_cleanup_module);