[PATCH wireguard-tools] wg-quick: android: add support for {Pre, Post}{Up, Down} hooks

Claire Elaina <[email protected]>
Newsgroups com.zx2c4.lists.wireguard
Message-ID <[email protected]>
---
 src/wg-quick/android.c | 96 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 89 insertions(+), 7 deletions(-)

diff --git a/src/wg-quick/android.c b/src/wg-quick/android.c
index 1263ee4..8a8df47 100644
--- a/src/wg-quick/android.c
+++ b/src/wg-quick/android.c
@@ -60,6 +60,15 @@ static void *xcalloc(size_t nmemb, size_t size)
 	exit(errno);
 }
 
+static void *xrealloc(void *ptr, size_t size)
+{
+	void *ret = realloc(ptr, size);
+	if (ret)
+		return ret;
+	perror("Error: realloc");
+	exit(errno);
+}
+
 static void *xstrdup(const char *str)
 {
 	char *ret = strdup(str);
@@ -126,6 +135,27 @@ static void free_command_buffer(struct command_buffer *c)
 	free(c->line);
 }
 
+struct str_list {
+	char **items;
+	size_t len;
+};
+
+static void append_str_list(struct str_list *l, char *item)
+{
+	l->len++;
+	l->items = xrealloc(l->items, sizeof(char*) * l->len);
+	l->items[l->len - 1] = item;
+}
+
+static void free_str_list(struct str_list *l)
+{
+	if (!l)
+		return;
+	for (size_t i = 0; i < l->len; ++i)
+		free(l->items[i]);
+	free(l->items);
+}
+
 static void freep(void *p)
 {
 	free(*(void **)p);
@@ -140,6 +170,7 @@ static void fclosep(FILE **f)
 #define _cleanup_regfree_ _cleanup_(regfree)
 
 #define DEFINE_CMD(name) _cleanup_(free_command_buffer) struct command_buffer name = { 0 };
+#define DEFINE_STR_LIST(name) _cleanup_(free_str_list) struct str_list name = { 0 };
 
 static char *vcmd_ret(struct command_buffer *c, const char *cmd_fmt, va_list args)
 {
@@ -239,6 +270,12 @@ _printf_(1, 2) static void cndc(const char *cmd_fmt, ...)
 	}
 }
 
+static void execute_hooks(const struct str_list *hooks)
+{
+	for (size_t i = 0; i < hooks->len; ++i)
+		cmd("%s", hooks->items[i]);
+}
+
 /* Values are from AOSP repository platform/frameworks/native in libs/binder/ndk/include_ndk/android/binder_status.h. */
 enum {
 	STATUS_OK = 0,
@@ -1112,7 +1149,7 @@ 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 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 struct str_list *pre_up, const struct str_list *post_up)
 {
 	DEFINE_CMD(c);
 	unsigned int netid = 0;
@@ -1127,6 +1164,7 @@ static void cmd_up(const char *iface, const char *config, unsigned int mtu, cons
 	atexit(cmd_up_cleanup);
 
 	add_if(iface);
+	execute_hooks(pre_up);
 	set_config(iface, config);
 	listen_port = determine_listen_port(iface);
 	up_if(&netid, iface, listen_port);
@@ -1135,6 +1173,7 @@ static void cmd_up(const char *iface, const char *config, unsigned int mtu, cons
 	set_routes(iface, netid);
 	set_mtu(iface, mtu);
 	set_users(netid, excluded_applications, included_applications);
+	execute_hooks(post_up);
 	broadcast_change();
 
 	free(cleanup_iface);
@@ -1142,7 +1181,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, const struct str_list *pre_down, const struct str_list *post_down)
 {
 	DEFINE_CMD(c);
 	bool found = false;
@@ -1161,12 +1200,14 @@ static void cmd_down(const char *iface)
 		exit(EMEDIUMTYPE);
 	}
 
+	execute_hooks(pre_down);
 	del_if(iface);
+	execute_hooks(post_down);
 	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 parse_options(char **iface, char **config, unsigned int *mtu, char **addrs, char **dnses, char **excluded_applications, char **included_applications, struct str_list *pre_up, struct str_list *post_up, struct str_list *pre_down, struct str_list *post_down, const char *arg)
 {
 	_cleanup_fclose_ FILE *file = NULL;
 	_cleanup_free_ char *line = NULL;
@@ -1236,6 +1277,27 @@ static void parse_options(char **iface, char **config, unsigned int *mtu, char *
 		}
 		clean[j] = '\0';
 
+		char *line_value = strchr(line, '=');
+		_cleanup_free_ char *unstripped_value = NULL;
+		if (line_value) {
+			/* Skip equal sign. */
+			line_value++;
+
+			/* Skip leading whitespace. */
+			while (isspace(line_value[0]))
+				line_value++;
+
+			/* Calculate length of the value without trailing whitespace. */
+			size_t line_value_len = strlen(line_value);
+			while (line_value_len && isspace(line_value[line_value_len - 1]))
+				line_value_len--;
+
+			/* Create the string. */
+			unstripped_value = xmalloc(line_value_len + 1);
+			memcpy(unstripped_value, line_value, line_value_len);
+			unstripped_value[line_value_len] = '\0';
+		}
+
 		if (clean[0] == '[')
 			in_interface_section = false;
 		if (!strcasecmp(clean, "[Interface]"))
@@ -1256,6 +1318,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 > 6) {
+				append_str_list(pre_up, unstripped_value);
+				unstripped_value = NULL;
+				continue;
+			} else if (!strncasecmp(clean, "PostUp=", 7) && j > 7) {
+				append_str_list(post_up, unstripped_value);
+				unstripped_value = NULL;
+				continue;
+			} else if (!strncasecmp(clean, "PreDown=", 8) && j > 8) {
+				append_str_list(pre_down, unstripped_value);
+				unstripped_value = NULL;
+				continue;
+			} else if (!strncasecmp(clean, "PostDown=", 9) && j > 9) {
+				append_str_list(post_down, unstripped_value);
+				unstripped_value = NULL;
+				continue;
 			}
 		}
 		*config = concat_and_free(*config, "", line);
@@ -1279,6 +1357,10 @@ int main(int argc, char *argv[])
 	_cleanup_free_ char *dnses = NULL;
 	_cleanup_free_ char *excluded_applications = NULL;
 	_cleanup_free_ char *included_applications = NULL;
+	DEFINE_STR_LIST(pre_up);
+	DEFINE_STR_LIST(post_up);
+	DEFINE_STR_LIST(pre_down);
+	DEFINE_STR_LIST(post_down);
 	unsigned int mtu;
 	char prop[PROP_VALUE_MAX + 1];
 
@@ -1289,12 +1371,12 @@ int main(int argc, char *argv[])
 		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, &post_up, &pre_down, &post_down, argv[2]);
+		cmd_up(iface, config, mtu, addrs, dnses, excluded_applications, included_applications, &pre_up, &post_up);
 	} 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, &post_up, &pre_down, &post_down, argv[2]);
+		cmd_down(iface, &pre_down, &post_down);
 	} else {
 		cmd_usage(argv[0]);
 		return 1;
-- 
2.49.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.