Skip to content

Commit 924d9f5

Browse files
committed
Support blocklist in vwifi
Enable ability to use blocklist to block packets from specified interface. Support blocklist in vwifi kernel module, used as interfaces pair such as "owl2 blocks owl1", allow maximum blocklist size to be 1024 bytes now and maintained as global content within struct owl_content. Using userspace program to dynamically alter the blocklist maintaining in vwifi kernel module.
1 parent e5eb949 commit 924d9f5

File tree

3 files changed

+183
-1
lines changed

3 files changed

+183
-1
lines changed

blocklist_user.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <linux/netlink.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <sys/socket.h>
6+
#include <unistd.h>
7+
8+
#define MAX_PAYLOAD 1024
9+
#define LINE_LENGTH 20
10+
11+
struct sockaddr_nl src_addr, dest_addr;
12+
struct nlmsghdr *nlh = NULL;
13+
struct iovec iov;
14+
int sock_fd;
15+
struct msghdr msg;
16+
17+
int main()
18+
{
19+
/* Read interface pair from blocklist.txt */
20+
char *filename = "./scripts/blocklist.txt";
21+
FILE *fp = fopen(filename, "r");
22+
if (!fp) {
23+
printf("Error: couldn't open file %s\n", filename);
24+
exit(1);
25+
}
26+
27+
char buffer[NLMSG_SPACE(MAX_PAYLOAD)];
28+
char read_buf[LINE_LENGTH];
29+
memset(buffer, '\0', sizeof(buffer));
30+
31+
while (fgets(read_buf, LINE_LENGTH, fp)) {
32+
strcat(buffer, read_buf);
33+
}
34+
fclose(fp);
35+
36+
printf("%s", buffer);
37+
38+
sock_fd = socket(PF_NETLINK, SOCK_RAW, 31);
39+
if (sock_fd < 0)
40+
return -1;
41+
42+
memset(&src_addr, 0, sizeof(src_addr));
43+
src_addr.nl_family = AF_NETLINK;
44+
src_addr.nl_pid = getpid();
45+
46+
bind(sock_fd, (struct sockaddr *) &src_addr, sizeof(src_addr));
47+
48+
memset(&dest_addr, 0, sizeof(dest_addr));
49+
dest_addr.nl_family = AF_NETLINK;
50+
dest_addr.nl_pid = 0;
51+
dest_addr.nl_groups = 0;
52+
53+
nlh = (struct nlmsghdr *) calloc(1, NLMSG_SPACE(MAX_PAYLOAD));
54+
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
55+
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
56+
nlh->nlmsg_pid = getpid();
57+
nlh->nlmsg_flags = 0;
58+
59+
strcpy(NLMSG_DATA(nlh), buffer);
60+
61+
iov.iov_base = (void *) nlh;
62+
iov.iov_len = nlh->nlmsg_len;
63+
msg.msg_name = (void *) &dest_addr;
64+
msg.msg_namelen = sizeof(dest_addr);
65+
msg.msg_iov = &iov;
66+
msg.msg_iovlen = 1;
67+
68+
printf("Sedning message to kernel...\n");
69+
sendmsg(sock_fd, &msg, 0);
70+
printf("Waiting for message from kernel...\n");
71+
72+
recvmsg(sock_fd, &msg, 0);
73+
printf("Received message payload: %s\n", NLMSG_DATA(nlh));
74+
75+
close(sock_fd);
76+
77+
return 0;
78+
}

scripts/blocklist.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
owl2 blocks owl1
2+
owl1 blocks owl2

vwifi.c

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include <net/cfg80211.h>
1515
#include <uapi/linux/virtio_net.h>
1616

17+
#include <linux/netlink.h>
18+
#include <net/sock.h>
19+
1720
MODULE_LICENSE("Dual MIT/GPL");
1821
MODULE_AUTHOR("National Cheng Kung University, Taiwan");
1922
MODULE_DESCRIPTION("virtual cfg80211 driver");
@@ -60,6 +63,7 @@ struct owl_context {
6063
enum vwifi_state state; /**< indicate the program state */
6164
struct list_head vif_list; /**< maintaining all interfaces */
6265
struct list_head ap_list; /**< maintaining multiple AP */
66+
char *blocklist; /**< maintaining the blocklist */
6367
};
6468

6569
/* SME stands for "station management entity" */
@@ -150,6 +154,83 @@ MODULE_PARM_DESC(station, "Number of virtual interfaces running in STA mode.");
150154
/* Global context */
151155
static struct owl_context *owl = NULL;
152156

157+
/* Blocklist content */
158+
#define MAX_NETLINK_USER 31
159+
#define MAX_BLACKLIST_SIZE 1024
160+
161+
struct sock *nl_sk = NULL;
162+
163+
static int blocklist_check(char *dest, char *source)
164+
{
165+
if (!owl->blocklist || !*(owl->blocklist))
166+
return 0;
167+
168+
char *user_input =
169+
kmalloc(sizeof(char) * (strlen(owl->blocklist) + 1), GFP_KERNEL);
170+
strncpy(user_input, owl->blocklist, strlen(owl->blocklist));
171+
172+
char *token = strsep(&user_input, "\n");
173+
while (token != NULL) {
174+
char *blacklist_dest = strsep(&token, " ");
175+
strsep(&token, " ");
176+
char *blacklist_source = token;
177+
if (strcmp(dest, blacklist_dest) == 0 &&
178+
strcmp(source, blacklist_source) == 0) {
179+
kfree(user_input);
180+
return 1;
181+
}
182+
pr_info("owl: %s blocks packets from %s\n", blacklist_dest,
183+
blacklist_source);
184+
token = strsep(&user_input, "\n");
185+
}
186+
kfree(user_input);
187+
188+
return 0;
189+
}
190+
191+
static void blocklist_load(char *blist)
192+
{
193+
if (!owl->blocklist) {
194+
pr_info("owl->blocklist have to be kmalloc first\n");
195+
return;
196+
}
197+
memset(owl->blocklist, '\0', MAX_BLACKLIST_SIZE); /* clear the blocklist */
198+
strncpy(owl->blocklist, blist, strlen(blist));
199+
}
200+
201+
static void blocklist_nl_recv(struct sk_buff *skb)
202+
{
203+
struct nlmsghdr *nlh; /* netlink message header */
204+
int pid;
205+
struct sk_buff *skb_out;
206+
char *msg = "vwifi has received your blocklist";
207+
int msg_size = strlen(msg);
208+
209+
nlh = (struct nlmsghdr *) skb->data;
210+
211+
blocklist_load((char *) nlmsg_data(nlh));
212+
213+
/* pid of sending process */
214+
pid = nlh->nlmsg_pid;
215+
216+
skb_out = nlmsg_new(msg_size, 0);
217+
if (!skb_out) {
218+
pr_info("netlink: Failed to allocate new skb\n");
219+
return;
220+
}
221+
222+
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
223+
NETLINK_CB(skb_out).dst_group = 0; /* unicast group */
224+
strncpy(nlmsg_data(nlh), msg, msg_size);
225+
226+
if (nlmsg_unicast(nl_sk, skb_out, pid) < 0)
227+
pr_info("netlink: Error while sending back to user\n");
228+
}
229+
230+
struct netlink_kernel_cfg nl_config = {
231+
.input = blocklist_nl_recv,
232+
};
233+
153234
/**
154235
* enum virtio_vqs - queues for virtio frame transmission and receivement
155236
*
@@ -713,6 +794,13 @@ static netdev_tx_t owl_ndo_start_xmit(struct sk_buff *skb,
713794
}
714795
/* TX by interface of AP mode */
715796
else if (vif->wdev.iftype == NL80211_IFTYPE_AP) {
797+
/* Find the source interface name */
798+
char *source_name;
799+
list_for_each_entry (dest_vif, &vif->bss_list, bss_list) {
800+
if (ether_addr_equal(eth_hdr->h_source, dest_vif->ndev->dev_addr))
801+
source_name = dest_vif->ndev->name;
802+
}
803+
716804
/* Check if the packet is broadcasting */
717805
if (is_broadcast_ether_addr(eth_hdr->h_dest)) {
718806
list_for_each_entry (dest_vif, &vif->bss_list, bss_list) {
@@ -722,6 +810,10 @@ static netdev_tx_t owl_ndo_start_xmit(struct sk_buff *skb,
722810
dest_vif->ndev->dev_addr))
723811
continue;
724812

813+
/* Don't send packet from dest_vif's blocklist */
814+
if (blocklist_check(dest_vif->ndev->name, source_name))
815+
continue;
816+
725817
if (__owl_ndo_start_xmit(vif, dest_vif, skb))
726818
count++;
727819
}
@@ -731,7 +823,8 @@ static netdev_tx_t owl_ndo_start_xmit(struct sk_buff *skb,
731823
list_for_each_entry (dest_vif, &vif->bss_list, bss_list) {
732824
if (ether_addr_equal(eth_hdr->h_dest,
733825
dest_vif->ndev->dev_addr)) {
734-
if (__owl_ndo_start_xmit(vif, dest_vif, skb))
826+
if (!blocklist_check(dest_vif->ndev->name, source_name) &&
827+
__owl_ndo_start_xmit(vif, dest_vif, skb))
735828
count++;
736829
break;
737830
}
@@ -1782,6 +1875,7 @@ static void owl_free(void)
17821875
list_for_each_entry_safe (vif, safe, &owl->vif_list, list)
17831876
owl_delete_interface(vif);
17841877

1878+
kfree(owl->blocklist);
17851879
kfree(owl);
17861880
}
17871881

@@ -2832,6 +2926,7 @@ static int __init vwifi_init(void)
28322926
mutex_init(&owl->lock);
28332927
INIT_LIST_HEAD(&owl->vif_list);
28342928
INIT_LIST_HEAD(&owl->ap_list);
2929+
owl->blocklist = kmalloc(sizeof(char) * MAX_BLACKLIST_SIZE, GFP_KERNEL);
28352930

28362931
for (int i = 0; i < station; i++) {
28372932
struct wiphy *wiphy = owcfg80211_add();
@@ -2841,6 +2936,12 @@ static int __init vwifi_init(void)
28412936
goto interface_add;
28422937
}
28432938

2939+
nl_sk = netlink_kernel_create(&init_net, MAX_NETLINK_USER, &nl_config);
2940+
if (!nl_sk) {
2941+
pr_info("Error creating netlink socket\n");
2942+
goto cfg80211_add;
2943+
}
2944+
28442945
err = register_virtio_driver(&virtio_vwifi);
28452946
if (err)
28462947
goto err_register_virtio_driver;
@@ -2864,6 +2965,7 @@ static void __exit vwifi_exit(void)
28642965

28652966
unregister_virtio_driver(&virtio_vwifi);
28662967
owl_free();
2968+
netlink_kernel_release(nl_sk);
28672969
}
28682970

28692971
module_init(vwifi_init);

0 commit comments

Comments
 (0)