Skip to content

Commit f84e040

Browse files
committed
Support blocklist in vwifi
Use vwifi-tool to display the status of vwifi and provide 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. When we detect the packet's source interface and destination interface is in the blocklist, we discard the packet. Using userspace program with netlink to communicate with kernel and allow the ability to dynamically alter the blocklist maintaining in vwifi kernel module. According to #48, we set blocklist in order to filter packet which is unwanted and discard it when AP is forwarding the package. So far the discarded package are simply being ignored by the program, we may need future improvement to delete them thoroughly. Resolves: #48
1 parent e5eb949 commit f84e040

File tree

4 files changed

+358
-3
lines changed

4 files changed

+358
-3
lines changed

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ ccflags-y := -std=gnu99 -Wno-declaration-after-statement
55
KDIR ?= /lib/modules/$(shell uname -r)/build
66
GIT_HOOKS := .git/hooks/applied
77

8-
all:
8+
all: kmod vwifi-tool
9+
10+
kmod:
911
$(MAKE) -C $(KDIR) M=$(shell pwd) modules
1012

13+
vwifi-tool: vwifi-tool.c
14+
$(CC) $(ccflags-y) -o $@ $<
15+
1116
clean:
1217
$(MAKE) -C $(KDIR) M=$(shell pwd) clean
18+
$(RM) vwifi-tool
1319

1420
check: all
15-
@scripts/verify.sh
21+
@scripts/verify.sh

README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,68 @@ PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
344344
4 packets transmitted, 4 received, 0% packet loss, time 3058ms
345345
rtt min/avg/max/mdev = 0.054/0.141/0.342/0.117 ms
346346
```
347+
### vwifi-tool
348+
A set of tools which supports more utilization for vwifi.
349+
Currently supporting feature:
350+
* display the status of vwifi driver
351+
* Use netlink socket to communicate with vwifi driver to configure block list
347352

353+
#### Status checking
354+
We can use `vwifi-tool` to check the status of vwifi driver by executing the following command:
355+
```
356+
$ ./vwifi-tool
357+
```
358+
If vwifi is loaded into kernel, you should see the following output:
359+
```
360+
vwifi status : live
361+
```
362+
Otherwise, vwifi isn't loaded into kernel yet, the output will be:
363+
```
364+
vwifi status : not loaded
365+
```
366+
#### Blocklist test
367+
vwifi also supports blocklist ability to allow some interfaces to block packets from certain interfaces.
368+
We can use `vwifi-tool` to set or unset blocklist for vwifi, multiple options are explained as below
369+
* `-d` : specify the destination interface for a blocklist pair
370+
* `-s` : specify the source interface for a blocklist pair
371+
* `-c` : `1` means to unset the blocklist in vwifi, default as `0`
372+
373+
Set the blocklist pair using vwifi-tool like the following
374+
```
375+
$ ./vwifi-tool -d owl2 -s owl1
376+
```
377+
You should see the following output, including your blocklist which will be sent to vwifi
378+
```
379+
vwifi status : live
380+
blocklist:
381+
owl2 blocks owl1
382+
Configuring blocklist for vwifi...
383+
Message from vwifi: vwifi has received your blocklist
384+
```
385+
Then you can try to do the ping test again
386+
```
387+
$ sudo ip netns exec ns1 ping -c 4 10.0.0.3
388+
```
389+
You should see the following output:
390+
```
391+
PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
392+
393+
--- 10.0.0.3 ping statistics ---
394+
4 packets transmitted, 0 received, 100% packet loss, time 3053ms
395+
```
396+
You can adjust the content of your blacklist and load it into vwifi anytime.
397+
398+
If you want to unset the blocklist in vwifi, simply add the option `-c` with vwifi-tool
399+
```
400+
$ ./vwifi-tool -c
401+
```
402+
You'll see the following output
403+
```
404+
vwifi status : live
405+
Unset blocklist for vwifi...
406+
Configuring blocklist for vwifi...
407+
Message from vwifi: vwifi has received your blocklist
408+
```
348409
## Testing environment (virtio)
349410
Below is our testing environment with virtio feature:
350411

vwifi-tool.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#include <getopt.h>
2+
#include <linux/netlink.h>
3+
#include <stdbool.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <sys/socket.h>
8+
#include <unistd.h>
9+
10+
#define MAX_PAYLOAD 1024
11+
#define LINE_LENGTH 20
12+
#define MAX_BLOCKLIST_PAIR 5
13+
14+
15+
/* The function aims to check the status of vwifi kernel module */
16+
bool vwifi_status_check()
17+
{
18+
char *kmod_status_file = "/sys/module/vwifi/initstate";
19+
FILE *fp = fopen(kmod_status_file, "r");
20+
if (!fp) {
21+
printf("vwifi status : not loaded\n");
22+
return false;
23+
}
24+
25+
char read_buf[LINE_LENGTH];
26+
fgets(read_buf, LINE_LENGTH, fp);
27+
read_buf[strcspn(read_buf, "\n")] =
28+
0; /* Remove newline character from string */
29+
if (!strcmp("live", read_buf))
30+
printf("vwifi status : live\n");
31+
else {
32+
printf("vwifi status : %s\n", read_buf);
33+
return false;
34+
}
35+
return true;
36+
}
37+
38+
/* Check if command line options are specified */
39+
bool opt_set(int d, int s, int c)
40+
{
41+
return (d || s || c) ? true : false;
42+
}
43+
44+
/* Check whether the number of source interfaces matches with the number of
45+
* destination interfaces */
46+
bool blocklist_pair_check(int src_len, int dest_len)
47+
{
48+
return (src_len == dest_len) ? true : false;
49+
}
50+
51+
/* Check whether to clear the blocklist or not */
52+
bool blocklist_clear(int clear)
53+
{
54+
return clear ? true : false;
55+
}
56+
57+
/* Send blocklist to kernel using netlink socket */
58+
bool blocklist_send(char *blocklist)
59+
{
60+
int sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
61+
if (sock_fd < 0) {
62+
printf("Error: Can't open socket\n");
63+
return false;
64+
}
65+
66+
struct sockaddr_nl src_addr = {
67+
.nl_family = AF_NETLINK,
68+
.nl_pid = getpid(),
69+
};
70+
71+
bind(sock_fd, (struct sockaddr *) &src_addr, sizeof(src_addr));
72+
73+
struct sockaddr_nl dest_addr = {
74+
.nl_family = AF_NETLINK,
75+
.nl_pid = 0,
76+
.nl_groups = 0,
77+
};
78+
79+
struct nlmsghdr *nlh =
80+
(struct nlmsghdr *) calloc(1, NLMSG_SPACE(MAX_PAYLOAD));
81+
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
82+
nlh->nlmsg_pid = getpid();
83+
nlh->nlmsg_flags = 0;
84+
85+
strncpy(NLMSG_DATA(nlh), blocklist, NLMSG_SPACE(MAX_PAYLOAD));
86+
87+
struct iovec iov = {
88+
.iov_base = (void *) nlh,
89+
.iov_len = nlh->nlmsg_len,
90+
};
91+
92+
struct msghdr msg = {
93+
.msg_name = (void *) &dest_addr,
94+
.msg_namelen = sizeof(dest_addr),
95+
.msg_iov = &iov,
96+
.msg_iovlen = 1,
97+
};
98+
99+
printf("Configuring blocklist for vwifi...\n");
100+
sendmsg(sock_fd, &msg, 0);
101+
102+
recvmsg(sock_fd, &msg, 0);
103+
printf("Message from vwifi: %s\n", (char *) NLMSG_DATA(nlh));
104+
105+
close(sock_fd);
106+
107+
return true;
108+
}
109+
110+
int main(int argc, char *argv[])
111+
{
112+
if (!vwifi_status_check())
113+
exit(1);
114+
115+
/* Get opt arguments from command line to configure blocklist */
116+
char *dest[MAX_BLOCKLIST_PAIR], *src[MAX_BLOCKLIST_PAIR],
117+
blocklist_pair[MAX_BLOCKLIST_PAIR][LINE_LENGTH];
118+
int blocklist_len = 0, dest_len = 0, src_len = 0, clear = 0;
119+
int c;
120+
121+
while ((c = getopt(argc, argv, "d:s:c")) != -1) {
122+
switch (c) {
123+
case 'd':
124+
dest[dest_len++] = optarg;
125+
break;
126+
case 's':
127+
src[src_len++] = optarg;
128+
break;
129+
case 'c':
130+
clear = 1;
131+
break;
132+
default:
133+
printf("Invalid arguments\n");
134+
break;
135+
}
136+
}
137+
138+
/* When no options are specified, simply display the status of vwifi */
139+
if (!opt_set(dest_len, src_len, clear))
140+
return 0;
141+
142+
if (!blocklist_pair_check(src_len, dest_len)) {
143+
printf("Destination number doesn't match with Source number\n");
144+
exit(1);
145+
}
146+
147+
blocklist_len =
148+
blocklist_clear(clear)
149+
? 0
150+
: (dest_len < MAX_BLOCKLIST_PAIR ? dest_len : MAX_BLOCKLIST_PAIR);
151+
152+
for (int i = 0; i < blocklist_len; i++) {
153+
memset(blocklist_pair[i], '\0', sizeof(blocklist_pair[i]));
154+
snprintf(blocklist_pair[i], sizeof(blocklist_pair[i]), "%s %s %s",
155+
dest[i], "blocks", src[i]);
156+
}
157+
158+
if (blocklist_len) {
159+
printf("blocklist:\n");
160+
for (int i = 0; i < blocklist_len; i++) {
161+
printf("%s\n", blocklist_pair[i]);
162+
}
163+
} else {
164+
printf("Unset blocklist for vwifi...\n");
165+
}
166+
167+
/* Copy blocklist pair into message buffer */
168+
char buffer[NLMSG_SPACE(MAX_PAYLOAD)];
169+
memset(buffer, '\0', sizeof(buffer));
170+
171+
for (int i = 0; i < blocklist_len; i++) {
172+
if (strlen(blocklist_pair[i]) + strlen(buffer) <
173+
NLMSG_SPACE(MAX_PAYLOAD)) {
174+
strcat(buffer, blocklist_pair[i]);
175+
strcat(buffer, "\n");
176+
} else {
177+
printf(
178+
"Error: Blocklist size exceeds the maximum size of buffer\n");
179+
exit(1);
180+
}
181+
}
182+
183+
/* Send blocklist buffer to kernel */
184+
if (!blocklist_send(buffer))
185+
exit(1);
186+
187+
return 0;
188+
}

0 commit comments

Comments
 (0)