-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
4 changed files
with
312 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Oops, something went wrong.