forked from ccp-project/ccp-kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ccp_nl.c
100 lines (85 loc) · 2.86 KB
/
ccp_nl.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
#include <net/tcp.h>
#include "ccp_nl.h"
#define CCP_MULTICAST_GROUP 22
ccp_nl_recv_handler ccp_msg_reader = NULL;
struct sock *nl_sk;
// callback from userspace ccp
// all messages will be PatternMsg OR InstallFoldMsg
// lookup ccp socket id, install new pattern
void nl_recv(struct sk_buff *skb) {
int ok;
struct nlmsghdr *nlh = nlmsg_hdr(skb);
if (ccp_msg_reader == NULL) {
pr_info("ccp_msg_reader not ready\n");
return;
}
//printk(KERN_INFO "[ ");
//for (i = 0; i < hdr->Len; i++) {
// printk(KERN_INFO "%02x, ", (u32) buf[i]);
//}
//printk(KERN_INFO "]\n");
ok = ccp_msg_reader((char*)nlmsg_data(nlh), nlh->nlmsg_len);
if (ok < 0) {
pr_info("message read failed: %d.\n", ok);
}
}
int ccp_nl_sk(ccp_nl_recv_handler msg) {
struct netlink_kernel_cfg cfg = {
.input = nl_recv,
};
ccp_msg_reader = msg;
nl_sk = netlink_kernel_create(&init_net, NETLINK_USERSOCK, &cfg);
if (!nl_sk) {
printk(KERN_ALERT "Error creating netlink socket.\n");
return -1;
}
return 0;
}
void free_ccp_nl_sk(void) {
netlink_kernel_release(nl_sk);
}
// send IPC message to userspace ccp
int nl_sendmsg(
struct ccp_datapath *dp,
struct ccp_connection *conn,
char *msg,
int msg_size
) {
int res;
struct sk_buff *skb_out;
struct nlmsghdr *nlh;
//pr_info("ccp: sending nl message: (%d) type: %02x len: %02x sid: %04x", msg_size, *msg, *(msg + sizeof(u8)), *(msg + 2*sizeof(u8)));
skb_out = nlmsg_new(
msg_size, // @payload: size of the message payload
GFP_NOWAIT // @flags: the type of memory to allocate.
);
if (!skb_out) {
printk(KERN_ERR "Failed to allocate new skb\n");
return -1;
}
nlh = nlmsg_put(
skb_out, // @skb: socket buffer to store message in
0, // @portid: netlink PORTID of requesting application
0, // @seq: sequence number of message
NLMSG_DONE, // @type: message type
msg_size, // @payload: length of message payload
0 // @flags: message flags
);
memcpy(nlmsg_data(nlh), msg, msg_size);
// https://www.spinics.net/lists/netdev/msg435978.html
// "It is process context but with a spinlock (bh_lock_sock) held, so
// you still can't sleep. IOW, you have to pass a proper gfp flag to
// reflect this."
// Use an allocation without __GFP_DIRECT_RECLAIM
res = nlmsg_multicast(
nl_sk, // @sk: netlink socket to spread messages to
skb_out, // @skb: netlink message as socket buffer
0, // @portid: own netlink portid to avoid sending to yourself
CCP_MULTICAST_GROUP, // @group: multicast group id
GFP_NOWAIT // @flags: allocation flags
);
if (res < 0) {
return res;
}
return 0;
}