[PATCH] wg-quick: Android: Add up/down hook support
Adam Irr
adam.irr at outlook.com
Sat Mar 27 20:58:25 UTC 2021
Hello,
I have been using my Nvidia Shield with a self-built kernel module as a
Wireguard server with the support of this patch to have access to my
home network. There is a corresponding change needed in the Android
app[1] to make this work. I am not super familiar with C so please take
time to scrutinize this code - particularly the memory management. If
its easier to provide feedback on a Github pull request, let me know and
I can open one.
[1] https://github.com/WireGuard/wireguard-android/pull/23
Thank you,
Adam
-----
>From 77e9153510fbcacafe20b2813ca11464768f1fd0 Mon Sep 17 00:00:00 2001
From: Adam Irr <adam.irr at outlook.com>
Date: Sat, 27 Mar 2021 13:47:09 -0700
Subject: [PATCH] wg-quick: Android: Add up/down hook support
This change allows Pre/Post Up/Down commands to be run
for Android devices. This provides a mechanism for Android
devices to behave like a server and automatically set up
routing rules.
Signed-off-by: Adam Irr <adam.irr at outlook.com>
---
src/wg-quick/android.c | 91 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 84 insertions(+), 7 deletions(-)
diff --git a/src/wg-quick/android.c b/src/wg-quick/android.c
index 941c7b8..7d3cd03 100644
--- a/src/wg-quick/android.c
+++ b/src/wg-quick/android.c
@@ -1097,6 +1097,9 @@ static void cmd_usage(const char *program)
" - DNS: an optional DNS server to use while the device is up.\n"
" - ExcludedApplications: optional blacklist of applications
to exclude from the tunnel.\n\n"
" - IncludedApplications: optional whitelist of applications
to include in the tunnel.\n\n"
+ " - PreUp, PostUp, PreDown, PostDown: script snippets which
will be executed\n"
+ " by a root shell at the corresponding phases of the link.\n"
+ " The string \\`%i' is expanded to INTERFACE."
" See wg-quick(8) for more info and examples.\n");
}
@@ -1110,7 +1113,39 @@ static void cmd_up_cleanup(void)
free(cleanup_iface);
}
-static void cmd_up(const char *iface, const char *config, unsigned int
mtu, const char *addrs, const char *dnses, const char
*excluded_applications, const char *included_applications)
+static void run_hooks(const char *cmds, const char *iface)
+{
+ if (cmds == NULL)
+ return;
+ size_t len = strlen(cmds), iface_len = strlen(iface), j = 0,
iface_count = 0;
+ if (len > (1<<16))
+ return;
+ for (size_t i = 0; i < len - 1; ++i) {
+ if (cmds[i] == '%' && cmds[++i] == 'i') {
+ iface_count++;
+ }
+ }
+
+ // Allocate enough space for the full command after replacing %i
with the interface name
+ _cleanup_free_ char *current_cmd = xmalloc(len + ((iface_len - 2) *
iface_count) + 1);
+
+ for (size_t i = 0; i < len; ++i) {
+ if (cmds[i] != '\n') {
+ if (cmds[i] == '%' && cmds[++i] == 'i') {
+ strcpy(current_cmd + j, iface);
+ j += iface_len;
+ } else {
+ current_cmd[j++] = cmds[i];
+ }
+ } else if (j != 0) {
+ current_cmd[j] = '\0';
+ j = 0;
+ cmd("%s", current_cmd);
+ }
+ }
+}
+
+static void cmd_up(const char *iface, const char *config, unsigned int
mtu, const char *addrs, const char *dnses, const char
*excluded_applications, const char *included_applications, const char
*pre_up_cmds, const char *post_up_cmds)
{
DEFINE_CMD(c);
unsigned int netid = 0;
@@ -1127,7 +1162,9 @@ static void cmd_up(const char *iface, const char
*config, unsigned int mtu, cons
add_if(iface);
set_config(iface, config);
listen_port = determine_listen_port(iface);
+ run_hooks(pre_up_cmds, iface);
up_if(&netid, iface, listen_port);
+ run_hooks(post_up_cmds, iface);
set_addr(iface, addrs);
set_dnses(netid, dnses);
set_routes(iface, netid);
@@ -1140,7 +1177,7 @@ static void cmd_up(const char *iface, const char
*config, unsigned int mtu, cons
exit(EXIT_SUCCESS);
}
-static void cmd_down(const char *iface)
+static void cmd_down(const char *iface, char *pre_down_cmds, char
*post_down_cmds)
{
DEFINE_CMD(c);
bool found = false;
@@ -1159,12 +1196,32 @@ static void cmd_down(const char *iface)
exit(EMEDIUMTYPE);
}
+ run_hooks(pre_down_cmds, iface);
del_if(iface);
+ run_hooks(post_down_cmds, iface);
broadcast_change();
exit(EXIT_SUCCESS);
}
-static void parse_options(char **iface, char **config, unsigned int
*mtu, char **addrs, char **dnses, char **excluded_applications, char
**included_applications, const char *arg)
+static void clean_hook_cmd(const char *line, const size_t len, char
*output)
+{
+ size_t j = 0;
+ bool found_prefix = false;
+ bool found_cmd_start = false;
+ for (size_t i = 0; i < len; ++i) {
+ if (!found_cmd_start && isspace(line[i]))
+ continue;
+ if (found_prefix && !isspace(line[i]))
+ found_cmd_start = true;
+ if (line[i] == '=')
+ found_prefix = true;
+
+ output[j++] = line[i];
+ }
+ output[j] = '\0';
+}
+
+static void parse_options(char **iface, char **config, unsigned int
*mtu, char **addrs, char **dnses, char **excluded_applications, char
**included_applications, char **pre_up_cmds, char **post_up_cmds, char
**pre_down_cmds, char **post_down_cmds, const char *arg)
{
_cleanup_fclose_ FILE *file = NULL;
_cleanup_free_ char *line = NULL;
@@ -1254,6 +1311,22 @@ static void parse_options(char **iface, char
**config, unsigned int *mtu, char *
} else if (!strncasecmp(clean, "MTU=", 4) && j > 4) {
*mtu = atoi(clean + 4);
continue;
+ } else if (!strncasecmp(clean, "PreUp=", 6) && j > 4) {
+ clean_hook_cmd(line, len, clean);
+ *pre_up_cmds = concat_and_free(*pre_up_cmds, "\n",
clean + 6);
+ continue;
+ } else if (!strncasecmp(clean, "PostUp=", 7) && j > 4) {
+ clean_hook_cmd(line, len, clean);
+ *post_up_cmds = concat_and_free(*post_up_cmds, "\n",
clean + 7);
+ continue;
+ } else if (!strncasecmp(clean, "PreDown=", 8) && j > 4) {
+ clean_hook_cmd(line, len, clean);
+ *pre_down_cmds = concat_and_free(*pre_down_cmds, "\n",
clean + 8);
+ continue;
+ } else if (!strncasecmp(clean, "PostDown=", 9) && j > 4) {
+ clean_hook_cmd(line, len, clean);
+ *post_down_cmds = concat_and_free(*post_down_cmds,
"\n", clean + 9);
+ continue;
}
}
*config = concat_and_free(*config, "", line);
@@ -1278,17 +1351,21 @@ int main(int argc, char *argv[])
_cleanup_free_ char *excluded_applications = NULL;
_cleanup_free_ char *included_applications = NULL;
unsigned int mtu;
+ _cleanup_free_ char *pre_up_cmds = NULL;
+ _cleanup_free_ char *post_up_cmds = NULL;
+ _cleanup_free_ char *pre_down_cmds = NULL;
+ _cleanup_free_ char *post_down_cmds = NULL;
if (argc == 2 && (!strcmp(argv[1], "help") || !strcmp(argv[1],
"--help") || !strcmp(argv[1], "-h")))
cmd_usage(argv[0]);
else if (argc == 3 && !strcmp(argv[1], "up")) {
auto_su(argc, argv);
- parse_options(&iface, &config, &mtu, &addrs, &dnses,
&excluded_applications, &included_applications, argv[2]);
- cmd_up(iface, config, mtu, addrs, dnses, excluded_applications,
included_applications);
+ parse_options(&iface, &config, &mtu, &addrs, &dnses,
&excluded_applications, &included_applications, &pre_up_cmds,
&post_up_cmds, &pre_down_cmds, &post_down_cmds, argv[2]);
+ cmd_up(iface, config, mtu, addrs, dnses, excluded_applications,
included_applications, pre_up_cmds, post_up_cmds);
} else if (argc == 3 && !strcmp(argv[1], "down")) {
auto_su(argc, argv);
- parse_options(&iface, &config, &mtu, &addrs, &dnses,
&excluded_applications, &included_applications, argv[2]);
- cmd_down(iface);
+ parse_options(&iface, &config, &mtu, &addrs, &dnses,
&excluded_applications, &included_applications, &pre_up_cmds,
&post_up_cmds, &pre_down_cmds, &post_down_cmds, argv[2]);
+ cmd_down(iface, pre_down_cmds, post_down_cmds);
} else {
cmd_usage(argv[0]);
return 1;
--
2.25.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-wg-quick-Android-Add-up-down-hook-support.patch
Type: text/x-patch
Size: 7191 bytes
Desc: not available
URL: <http://lists.zx2c4.com/pipermail/wireguard/attachments/20210327/1fe2514e/attachment.bin>
More information about the WireGuard
mailing list