Skip to content

Commit

Permalink
Support blocklist in vwifi
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vax-r committed Dec 23, 2023
1 parent e5eb949 commit b32140f
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 3 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ ccflags-y := -std=gnu99 -Wno-declaration-after-statement
KDIR ?= /lib/modules/$(shell uname -r)/build
GIT_HOOKS := .git/hooks/applied

all:
all: kmod vwifi-tool

kmod:
$(MAKE) -C $(KDIR) M=$(shell pwd) modules

vwifi-tool: vwifi-tool.c
$(CC) $(ccflags-y) -o $@ $<

clean:
$(MAKE) -C $(KDIR) M=$(shell pwd) clean
$(RM) vwifi-tool

check: all
@scripts/verify.sh
@scripts/verify.sh
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,66 @@ PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
4 packets transmitted, 4 received, 0% packet loss, time 3058ms
rtt min/avg/max/mdev = 0.054/0.141/0.342/0.117 ms
```
### vwifi-tool
A set of tools which supports more utilization for vwifi.
Currently supporting feature:
* display the status of vwifi driver
* Use netlink socket to communicate with vwifi driver to configure block list

#### Status checking
Simply utilize `vwifi-tool` without any options
```
$ ./vwifi-tool
vwifi status : not loaded
```
After vwifi driver is loaded into kernel, you should expect the following output
```
$ ./vwifi-tool
vwifi status : live
```
#### Blocklist test
vwifi also supports blocklist ability to allow some interfaces to block packets from certain interfaces.
We can use `vwifi-tool` to set or unset blocklist for vwifi, multiple options are explained as below
* `-d` : specify the destination interface for a blocklist pair
* `-s` : specify the source interface for a blocklist pair
* `-c` : `1` means to unset the blocklist in vwifi, default as `0`

Set the blocklist pair using vwifi-tool like the following
```
$ ./vwifi-tool -d owl2 -s owl1
```
You should see the following output, including your blocklist which will be sent to vwifi
```
vwifi status : live
blocklist:
owl2 blocks owl1
Configuring blocklist for vwifi...
Message from vwifi: vwifi has received your blocklist
```
Then you can try to do the ping test again
```
$ sudo ip netns exec ns1 ping -c 4 10.0.0.3
```
You should see the following output:
```
PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
--- 10.0.0.3 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3053ms
```
You can adjust the content of your blacklist and load it into vwifi anytime.

If you want to unset the blocklist in vwifi, simply add the option `-c` with vwifi-tool
```
$ ./vwifi-tool -c
```
You'll see the following output
```
vwifi status : live
Unset blocklist for vwifi...
Configuring blocklist for vwifi...
Message from vwifi: vwifi has received your blocklist
```
## Testing environment (virtio)
Below is our testing environment with virtio feature:

Expand Down
144 changes: 144 additions & 0 deletions vwifi-tool.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#include <getopt.h>
#include <linux/netlink.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#define MAX_PAYLOAD 1024
#define LINE_LENGTH 20
#define MAX_BLOCKLIST_PAIR 5

int main(int argc, char *argv[])
{
/* Check the status of vwifi kernel module */
char *kmod_status_file = "/sys/module/vwifi/initstate";
FILE *fp = fopen(kmod_status_file, "r");
if (!fp) {
printf("vwifi status : not loaded\n");
exit(1);
}
char read_buf[LINE_LENGTH];
fgets(read_buf, LINE_LENGTH, fp);
read_buf[strcspn(read_buf, "\n")] = 0;
if (strcmp("live", read_buf) == 0)
printf("vwifi status : live\n");
else {
printf("vwifi status : %s\n", read_buf);
exit(1);
}

/* Get opt arguments from command line to configure blocklist */
char *dest[MAX_BLOCKLIST_PAIR], *src[MAX_BLOCKLIST_PAIR],
blocklist_pair[MAX_BLOCKLIST_PAIR][LINE_LENGTH];
int d_ind = 0, s_ind = 0, clear = 0;
int c;

while ((c = getopt(argc, argv, "d:s:c")) != -1) {
switch (c) {
case 'd':
dest[d_ind++] = optarg;
break;
case 's':
src[s_ind++] = optarg;
break;
case 'c':
clear = 1;
break;
default:
printf("Invalid arguments\n");
break;
}
}

/* When no options are specified, simply display the status of vwifi */
if (!d_ind && !s_ind && !c)
return 0;

if (d_ind != s_ind) {
printf("Destination number doesn't match with Source number\n");
exit(1);
} else if (clear) {
/* When clear bit is set, we'll send a blank blocklist to vwifi so we
* can unset all blocklist pair */
printf("Unset blocklist for vwifi...\n");
d_ind = 0;
} else {
for (int i = 0; i < d_ind; i++) {
memset(blocklist_pair[i], '\0', sizeof(blocklist_pair[i]));
snprintf(blocklist_pair[i], sizeof(blocklist_pair[i]), "%s %s %s",
dest[i], "blocks", src[i]);
}
printf("blocklist:\n");
for (int i = 0; i < d_ind; i++) {
printf("%s\n", blocklist_pair[i]);
}
}

/* copy blocklist pair into message buffer */
char buffer[NLMSG_SPACE(MAX_PAYLOAD)];
memset(buffer, '\0', sizeof(buffer));

for (int i = 0; i < d_ind; i++) {
if (strlen(blocklist_pair[i]) + strlen(buffer) + 1 <
NLMSG_SPACE(MAX_PAYLOAD)) {
strcat(buffer, blocklist_pair[i]);
strcat(buffer, "\n");
} else {
printf(
"Error: Blocklist size exceeds the maximum size of buffer\n");
exit(1);
}
}

/* Use netlink socket to communicate with kernel module */
int sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
if (sock_fd < 0) {
printf("Error: Can't open socket\n");
exit(1);
}

struct sockaddr_nl src_addr = {
.nl_family = AF_NETLINK,
.nl_pid = getpid(),
};

bind(sock_fd, (struct sockaddr *) &src_addr, sizeof(src_addr));

struct sockaddr_nl dest_addr = {
.nl_family = AF_NETLINK,
.nl_pid = 0,
.nl_groups = 0,
};

struct nlmsghdr *nlh =
(struct nlmsghdr *) calloc(1, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;

strncpy(NLMSG_DATA(nlh), buffer, NLMSG_SPACE(MAX_PAYLOAD));

struct iovec iov = {
.iov_base = (void *) nlh,
.iov_len = nlh->nlmsg_len,
};

struct msghdr msg = {
.msg_name = (void *) &dest_addr,
.msg_namelen = sizeof(dest_addr),
.msg_iov = &iov,
.msg_iovlen = 1,
};

printf("Configuring blocklist for vwifi...\n");
sendmsg(sock_fd, &msg, 0);

recvmsg(sock_fd, &msg, 0);
printf("Message from vwifi: %s\n", (char *) NLMSG_DATA(nlh));

close(sock_fd);

return 0;
}
Loading

0 comments on commit b32140f

Please sign in to comment.