Repository navigation
Expand file tree
/
Copy pathlee_netlink.c
More file actions
219 lines (161 loc) · 4.23 KB
/
Copy pathlee_netlink.c
File metadata and controls
219 lines (161 loc) · 4.23 KB
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2020, li-insects-awaken
*/
struct leenetlink_area * spring_area;
struct lee_sock {
struct sock sock;
wait_queue_head_t tar_halt;
};
static const struct net_proto_family spring_netlink_family_ops = {
.family = SPRING_NETLINK,
.create = spring_netlink_create,
};
static struct proto lee_netlink_proto = {
.name = "NETLINK",
.owner = THIS_MODULE,
.obj_size = sizeof(struct lee_sock),
};
static int leenetlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
int err;
unsigned int groups;
struct lee_sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
if (!nladdr->nl_groups) {
err = -EINVAL;
goto out;
}
groups = spring_area[sk->index].groups;
if (groups < 64) {
groups &= (1UL << groups) - 1;
list_add_tail(sock->sk, &spring_area[sk->index].multi_groups_list;
}
out:
return err;
}
int netlink_unicast(struct sock *sock, struct sk_buff *skb, unsigned int portid)
{
int ret;
int has_sleep;
unsigned long deleaytime;
struct sock *otsock;
delaytime = sock->sk_sndtimeo;
targetsock = via_otsock_adopt_portid(sock, portid);
if (!targetsock) {
kfree_skb(skb);
ret = -1;
goto unicast_failed;
}
has_sleep = atomic_read(&targetsock->sk_rmem_alloc) - targetsock->sk_rcvbuf;
if (has_sleep >= 0) {
wait_queue_t taskhalt = {
.private = cpu_rq(smp_processor_id())->curr;
.func = default_wait_function,
.task_list = {NULL, NULL}
};
set_current_task(TASK_INTERRUPTIBLE);
add_wait_queue(&leesock->tar_halt, &taskhalt);
}
skb_queue_tail(&targetsock->sk_receive_queue, skb);
targetsock->sk_data_ready(targetsock);
return 0;
unicast_failed:
return ret;
}
static int user_kernel_create_netlink_sock(bool which, int protocol)
{
struct sock *uk_sock;
struct spring_netlink_sock *sns;
uk_sock = kzalloc(sizeof(*uk_sock));
if (!uk_sock)
return -ENOMEM;
sns = sns_of(uk_sock);
}
struct sock * lee_netlink_kernel_create(unsigned int netlinkindex, struct netlink_kernel_cfg * leecfg)
{
unsigned long groups = 32;
if (!spring_area)
painic("spring_area must be not null");
if (netlinkindex < 0 || netlinkindex > 32)
goto kernel_create_failed;
if (leecfg->groups < 32)
groups = 32;
mutex_lock(&spring_area_lock);
if (spring_area[netlinkindex].has_registered) {
pr_err("This netlink protocol has been registered\n");
goto kernel_create_failed;
}
spring_area[netlinkindex].groups = groups;
mutex_unlock(&spring_area_lock);
kernel_create_failed:
return NULL;
}
static int is_ple(unsigned int detection_tmp)
{
do {
if (detection_tmp & 1)
goto checkedout;
detection_tmp >>= 1;
} while (detection_tmp);
return LEE_NETLINK_PLE;
checkedout:
return LEE_NETLINK_SUCCESS;
}
static int leenetlink_recvmsg(struct socket * sock, struct msghdr *msg, size_t len)
{
}
static int leenetlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
{
int ret;
unsigned int has_ple;
unsigned int has_bound;
struct sk_buff *skb;
struct sockaddr_nl * addr_lee;
addr_lee = (struct sockaddr_nl *)msg->msg_name;
if (addr_lee->nl_family != AF_NETLINK) {
ret = FAMILY_ERROR;
goto family_error;
}
has_ple = is_ple(addr_lee->nl_groups);
family_error:
return ret;
}
static const struct proto_ops spring_netlink_ops = {
.family = PF_LEENETLINK,
.owner = THIS_MODULE,
.release = leenetlink_relase,
.bind = leenetlink_bind,
.connect = leenetlink_connect,
.sendmsg = leenetlink_sendmsg,
.recvmsg = leenetlink_recvmsg,
};
static lee_netlink_create(struct net *net, struct socket *sock, int protocol)
{
int err;
struct sock *sk;
struct lee_sock * leesock;
if (!spring_area.has_register) {
err = -ENODEV;
goto lee_netlink_create_failure;
}
sock->ops = &spring_netlink_ops;
sk = sk_alloc(net, PF_LEENETLINK, GFP_KERNEL, &lee_netlink_proto);
if (!sk)
return -ENOMEM;
sk->sk_rcvbuf = 32768;
init_waitqueue_head(&leesock->tar_halt);
return 0;
lee_netlink_create_failure:
return err;
}
static int __init spring_netlinkport_init(void)
{
int ret;
spring_area = kcalloc(MAX_LINKS, sizeof(*spring_area), GFP_KERNEL);
if (!spring_area)
goto alloc_area_fail;
sock_register(&spring_netlink_ops);
alloc_area_fail:
panic("alloc spring_netlink_area has failure\n");
}
core_initcall(spring_netlinkport_init);