+#if defined TIZEN_EXT
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+#define MAX_SIZE_ERROR_BUFFER 256
+#define MAX_CMD_SIZE 80
+
+typedef struct {
+ struct vpn_provider *provider;
+ struct wireguard_info *info;
+} wg_allowed_ip_route_cb_data_s;
+
+static int wg_execute_cmd(const char *format, ...)
+{
+ int status = 0;
+ int rv = 0;
+ char cmd[MAX_CMD_SIZE] = { 0, };
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+ pid_t pid = 0;
+ va_list va_ptr;
+ gchar **args = NULL;
+
+ va_start(va_ptr, format);
+ vsnprintf(cmd, (unsigned int) MAX_CMD_SIZE, format, va_ptr);
+ va_end(va_ptr);
+
+ if (strlen(cmd) == 0)
+ return -EIO;
+
+ DBG("command: %s", cmd);
+
+ args = g_strsplit_set(cmd, " ", -1);
+
+ errno = 0;
+ if (!(pid = fork())) {
+ DBG("pid(%d), ppid (%d)", getpid(), getppid());
+
+ errno = 0;
+ if (execv(args[0], args) == -1) {
+ DBG("Fail to execute command (%s)",
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
+ g_strfreev(args);
+ exit(1);
+ }
+ } else if (pid > 0) {
+ if (waitpid(pid, &status, 0) == -1)
+ DBG("wait pid (%u) status (%d)", pid, status);
+
+ if (WIFEXITED(status)) {
+ rv = WEXITSTATUS(status);
+ DBG("exited, status=%d", rv);
+
+ } else if (WIFSIGNALED(status)) {
+ DBG("killed by signal %d", WTERMSIG(status));
+
+ } else if (WIFSTOPPED(status)) {
+ DBG("stopped by signal %d", WSTOPSIG(status));
+
+ } else if (WIFCONTINUED(status)) {
+ DBG("continued");
+ }
+
+ g_strfreev(args);
+ return rv;
+ }
+
+ DBG("failed to fork(%s)", strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
+ g_strfreev(args);
+
+ return -EIO;
+}
+
+static gboolean wg_add_allowed_ip_route_cb(gpointer user_data)
+{
+ wg_allowed_ip_route_cb_data_s *cb_data = user_data;
+ const char *allowed_ips;
+ char **tokens = NULL;
+ char **toks = NULL;
+ int i;
+
+ DBG("");
+
+ allowed_ips = vpn_provider_get_string(cb_data->provider, "WireGuard.AllowedIPs");
+ if (!allowed_ips) {
+ DBG("WireGuard.AllowedIPs is missing");
+ goto done;
+ }
+
+ tokens = g_strsplit(allowed_ips, ",", -1);
+ if (g_strv_length(tokens) == 0)
+ goto done;
+
+ for (i = 0; tokens[i]; i++) {
+ int len = strlen(tokens[i]);
+ char *ptr = tokens[i];
+ int j = -1;
+
+ //skip forward spaces
+ while (++j < len && ptr[j] == ' ')
+ ;// Do Nothing
+
+ if (!ptr[j])
+ continue;
+
+ toks = g_strsplit(ptr + j, "/", -1);
+ if (g_strv_length(toks) != 2) {
+ DBG("Ignore AllowedIPs value [%s]", ptr + j);
+ g_strfreev(toks);
+ continue;
+ }
+ g_strfreev(toks);
+
+ DBG("Allowed IP: [%s], Device Name: [%s]", ptr + j, cb_data->info->device.name);
+
+ // TODO: Remove system call to add route entry present in wg_execute_cmd()
+ if (!g_strcmp0("0.0.0.0/0", ptr + j)) {
+ // TODO: Update default route because user wants all data to be routed from wg0,
+ // when 0.0.0.0/0 is passed in allowed ips list.
+ // Should we replace the default route?
+ // If yes, then how to recover default route when wg0 tunnel is removed.
+ } else {
+ wg_execute_cmd("/usr/sbin/ip route add %s dev %s", ptr + j, cb_data->info->device.name);
+ }
+ }
+
+done:
+ if (tokens)
+ g_strfreev(tokens);
+
+ free(cb_data);
+
+ return FALSE;
+}
+#endif /* TIZEN_EXT */
+