Cleanup driver and wpa_supplicant when tech power on is failed
[platform/core/connectivity/net-config.git] / src / vpnsvc-internal.c
index a3b4132..0c71d45 100755 (executable)
@@ -35,7 +35,9 @@
 
 #include "vpnsvc-internal.h"
 #include "log.h"
+#include "util.h"
 
+#define BUF_SIZE_FOR_CMD 1024
 #define BUF_SIZE_FOR_ERR 100
 
 #define CONNMAN_SERVICE "net.connman"
@@ -49,19 +51,23 @@ static char iptables_filter_prefix[] = "CAPI_VPN_SERVICE_";
 static char iptables_filter_out[] = "OUTPUT";
 static char iptables_filter_in[] = "INPUT";
 static char iptables_filter_interface_wlan[] = "wlan0";
-/* static char iptables_register_fmt[] = "%s -N %s%s -w;" "%s -F %s%s -w;" "%s -A %s%s -j RETURN -w;" "%s -I %s -j %s%s -w;"; */
-static char iptables_register_fmt[] = "%s -N %s%s -w;" "%s -F %s%s -w;" "%s -A %s%s -j DROP -w;" "%s -A %s%s -j RETURN -w;" "%s -I %s -j %s%s -w;";
-static char iptables_unregister_fmt[] = "%s -D %s -j %s%s -w;" "%s -F %s%s -w;" "%s -X %s%s -w;";
-static char iptables_rule_fmt[] = "%s -%c %s%s -%c %s/%d -j ACCEPT -w;";
-static char iptables_rule_with_interface_fmt[] = "%s -%c %s%s -%c %s -%c %s/%d -j ACCEPT -w;";
+static char iptables_nat_chain_name[] = "CAPI_VPN_SERVICE_NAT_OUTPUT";
+
+#define IPTABLES_FMT_CREATE_CHAIN "%s -N %s%s -w"
+#define IPTABLES_FMT_APPEND_DROP_RULE "%s -A %s%s -j DROP -w"
+#define IPTABLES_FMT_APPEND_RETURN_RULE "%s -A %s%s -j RETURN -w"
+#define IPTABLES_FMT_INSERT_RULE "%s -I %s -j %s%s -w"
+#define IPTABLES_FMT_DEL_RULE "%s -D %s -j %s%s -w"
+#define IPTABLES_FMT_FLUSH_CHAIN "%s -F %s%s -w"
+#define IPTABLES_FMT_DEL_CHAIN "%s -X %s%s -w"
+#define IPTABLES_FMT_APPEND_ACCEPT_RULE "%s -%c %s%s -%c %s/%d -j ACCEPT -w"
+#define IPTABLES_FMT_APPEND_ACCEPT_RULE_WITH_INTF "%s -%c %s%s -%c %s -%c %s/%d -j ACCEPT -w"
+#define IPTABLES_FMT_DEL_RULE_FROM_NAT "%s -t nat -D %s -j %s -w"
+#define IPTABLES_FMT_FLUSH_CHAIN_FROM_NAT "%s -t nat -F %s -w"
+#define IPTABLES_FMT_DEL_CHAIN_FROM_NAT "%s -t nat -X %s -w"
+
 /*static char iptables_usage_fmt[] = "%s -L %s%s -n -v -w;";*/
 /* iptables -t nat -A CAPI_VPN_SERVICE_OUTPUT -p udp -d <vpn dns address> --dport 53 -j DNAT --to <vpn defice address:53> */
-static char iptables_nat_chain_name[] = "CAPI_VPN_SERVICE_NAT_OUTPUT";
-#if 0
-static char iptables_nat_register_init_fmt[] = "%s -t nat -N %s -w;" "%s -t nat -F %s -w;" "%s -t nat -I %s -j %s -w;";
-static char iptables_nat_register_rule_fmt[] = "%s -t nat -A %s -p udp -d %s --dport 53 -j DNAT --to %s:53 -w;";
-#endif
-static char iptables_nat_unregister_fmt[] = "%s -t nat -D %s -j %s -w;" "%s -t nat -F %s -w;" "%s -t nat -X %s -w;";
 
 typedef unsigned long int ipv4;        /* Declare variable type for ipv4 net address. */
 
@@ -91,108 +97,6 @@ static in_addr_t host2net(ipv4 host)
        return net;
 }
 
-static int add_routes(char* iface_name, char* routes[], int prefix[], size_t nr_routes)
-{
-       struct rtentry rt;
-       struct sockaddr_in addr;
-       int sk;
-       unsigned int i = 0;
-       char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
-       DBG("Enter add_routes");
-
-       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-       if (sk < 0) {
-               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               return VPNSVC_ERROR_IO_ERROR;
-       }
-
-       for (i = 0; i < nr_routes; i++) {
-               memset(&rt, 0, sizeof(rt));
-               rt.rt_flags = RTF_UP;
-
-               memset(&addr, 0, sizeof(addr));
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = inet_addr(routes[i]);
-               memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
-
-               memset(&addr, 0, sizeof(addr));
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = INADDR_ANY;
-               memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
-
-               /* set mask using by prefix length */
-               memset(&addr, 0, sizeof(addr));
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = INADDR_ANY;
-               addr.sin_addr.s_addr = host2net(make_mask(prefix[i]));
-               memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
-
-               rt.rt_dev = iface_name;
-
-               if (ioctl(sk, SIOCADDRT, &rt) < 0) {
-                       ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-                       close(sk);
-                       return VPNSVC_ERROR_IO_ERROR;
-               }
-       }
-
-       close(sk);
-
-       return VPNSVC_ERROR_NONE;
-}
-
-static int add_dns_routes(char* if_name, char** dns_servers, size_t nr_dns)
-{
-       struct rtentry rt;
-       struct sockaddr_in addr;
-       int sk;
-       unsigned int i = 0;
-       char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
-       DBG("Enter add_routes");
-
-       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-       if (sk < 0) {
-               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               return VPNSVC_ERROR_IO_ERROR;
-       }
-
-       for (i = 0; i < nr_dns; i++) {
-               memset(&rt, 0, sizeof(rt));
-               rt.rt_flags = RTF_UP;
-
-               memset(&addr, 0, sizeof(addr));
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = inet_addr(dns_servers[i]);
-               memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
-
-               memset(&addr, 0, sizeof(addr));
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = INADDR_ANY;
-               memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
-
-               /* set mask using by prefix length */
-               memset(&addr, 0, sizeof(addr));
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = INADDR_ANY;
-               addr.sin_addr.s_addr = host2net(make_mask(32));
-               memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
-
-               rt.rt_dev = if_name;
-
-               if (ioctl(sk, SIOCADDRT, &rt) < 0) {
-                       ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-                       close(sk);
-                       return VPNSVC_ERROR_IO_ERROR;
-               }
-       }
-
-       close(sk);
-
-       return VPNSVC_ERROR_NONE;
-}
-
 static void connman_connection_open(void)
 {
        if (global_connection == NULL) {
@@ -253,10 +157,8 @@ static char *connman_default_profile(GDBusConnection *connection)
 
        if (message) {
                g_variant_get(message, "(a(oa{sv}))", &iter);
-               while (g_variant_iter_loop(iter, "(oa{sv})", &key, &value)) {
+               if (g_variant_iter_loop(iter, "(oa{sv})", &key, &value))
                        profile = strdup(key);
-                       break;
-               }
 
                if (value)
                        g_variant_iter_free(value);
@@ -574,17 +476,6 @@ static int del_dns_suffix()
        return VPNSVC_ERROR_NONE;
 }
 
-
-static void iptables_exec(char *cmdline)
-{
-       FILE *fp = NULL;
-
-       fp = popen(cmdline, "r");
-
-       if (fp != NULL)
-               pclose(fp);
-}
-
 #if 0
 static void dns_nat_register(char **vpn_dns_address, size_t nr_dns, char *vpn_device_address)
 {
@@ -609,92 +500,170 @@ static void dns_nat_register(char **vpn_dns_address, size_t nr_dns, char *vpn_de
 
 static void dns_nat_unregister(void)
 {
-       int size = 0;
-       char buf[8192];
+       char buf[BUF_SIZE_FOR_CMD];
 
-       snprintf(buf + size, sizeof(buf) - size, iptables_nat_unregister_fmt,
-                       iptables_cmd, iptables_filter_out, iptables_nat_chain_name,
-                       iptables_cmd, iptables_nat_chain_name,
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_RULE_FROM_NAT,
+                       iptables_cmd, iptables_filter_out, iptables_nat_chain_name);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN_FROM_NAT,
                        iptables_cmd, iptables_nat_chain_name);
-       size = strlen(buf);
-       DBG("iptable dns nat unreg cmd : %s", buf);
-       iptables_exec(buf);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_CHAIN_FROM_NAT,
+                       iptables_cmd, iptables_nat_chain_name);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
 }
 
 static void iptables_register(void)
 {
-       int size = 0;
-       char buf[8192], *filter;
+       char buf[BUF_SIZE_FOR_CMD] = {0, };
+       char *filter;
 
        filter = iptables_filter_out;
-       snprintf(buf + size, sizeof(buf) - size, iptables_register_fmt,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, filter, iptables_filter_prefix, filter);
-       size = strlen(buf);
+
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_CREATE_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_DROP_RULE,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_RETURN_RULE,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_INSERT_RULE,
+                       iptables_cmd, filter, iptables_filter_prefix, filter);
+
        filter = iptables_filter_in;
-       snprintf(buf + size, sizeof(buf) - size, iptables_register_fmt,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, filter, iptables_filter_prefix, filter);
-       DBG("iptable reg cmd : %s", buf);
-       iptables_exec(buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_CREATE_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_DROP_RULE,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_RETURN_RULE,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_INSERT_RULE,
+                       iptables_cmd, filter, iptables_filter_prefix, filter);
 }
 
 static void iptables_unregister(void)
 {
-       int size = 0;
-       char buf[8192], *filter;
+       char buf[BUF_SIZE_FOR_CMD] = {0, };
+       char *filter;
 
        filter = iptables_filter_out;
-       snprintf(buf + size, sizeof(buf) - size, iptables_unregister_fmt,
-                        iptables_cmd, filter, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter);
-       size = strlen(buf);
+
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_RULE,
+                       iptables_cmd, filter, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
        filter = iptables_filter_in;
-       snprintf(buf + size, sizeof(buf) - size, iptables_unregister_fmt,
-                        iptables_cmd, filter, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter,
-                        iptables_cmd, iptables_filter_prefix, filter);
-       DBG("iptable unreg cmd : %s", buf);
-       iptables_exec(buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_RULE,
+                       iptables_cmd, filter, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_CHAIN,
+                       iptables_cmd, iptables_filter_prefix, filter);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
 }
 
 static void iptables_rule(const char c, const char *addr, const int mask)
 {
-       int size = 0;
-       char buf[4096];
-
-       snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
-                        iptables_filter_prefix, iptables_filter_out, 'd', addr, mask);
-       size = strlen(buf);
-       snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
-                        iptables_filter_prefix, iptables_filter_in, 's', addr, mask);
-       DBG("iptable cmd : %s", buf);
-       iptables_exec(buf);
+       char buf[BUF_SIZE_FOR_CMD];
+
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE,
+                       iptables_cmd, c, iptables_filter_prefix,
+                       iptables_filter_out, 'd', addr, mask);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE,
+                       iptables_cmd, c,  iptables_filter_prefix,
+                       iptables_filter_in, 's', addr, mask);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
 }
 
 static void iptables_rule_interface(const char c, const char *addr, const int mask, const char *interface)
 {
-       int size = 0;
-       char buf[4096];
+       char buf[BUF_SIZE_FOR_CMD];
 
-       snprintf(buf + size, sizeof(buf) - size,
-                       iptables_rule_with_interface_fmt, iptables_cmd,
-                       c, iptables_filter_prefix, iptables_filter_out,
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE_WITH_INTF,
+                       iptables_cmd, c, iptables_filter_prefix, iptables_filter_out,
                        'o', interface, 'd', addr, mask);
-       size = strlen(buf);
-       snprintf(buf + size, sizeof(buf) - size,
-                       iptables_rule_with_interface_fmt, iptables_cmd,
-                       c, iptables_filter_prefix, iptables_filter_in,
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE_WITH_INTF,
+                       iptables_cmd, c, iptables_filter_prefix, iptables_filter_in,
                        'i', interface, 's', addr, mask);
-       DBG("iptable cmd : %s", buf);
-       iptables_exec(buf);
+       if (netconfig_execute_cmd(buf))
+               ERR("Failed to execute command: %s", buf);
 }
 
 void iptables_add_orig(const char *addr, const int mask)
@@ -734,7 +703,7 @@ static int get_interface_index(const char *iface_name)
        memset(&ifr, 0, sizeof(ifr));
 
        if (*iface_name)
-       strncpy(ifr.ifr_name, iface_name, strlen(iface_name));
+               strncpy(ifr.ifr_name, iface_name, IFNAMSIZ - 1);
 
        /* get an interface name by ifindex */
        if (ioctl(sk, SIOCGIFINDEX, &ifr) < 0) {
@@ -748,14 +717,48 @@ static int get_interface_index(const char *iface_name)
        return ifr.ifr_ifindex;
 }
 
+static int check_interface_precondition(const char *iface_name)
+{
+
+       int sk;
+       struct ifreq ifr_tun;
+       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0) {
+               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       memset(&ifr_tun, 0, sizeof(ifr_tun));
+       g_strlcpy((char *)ifr_tun.ifr_name, iface_name, sizeof(ifr_tun.ifr_name));
+
+       /* local ip */
+       if (ioctl(sk, SIOCGIFADDR, &ifr_tun) < 0) {
+               ERR("Fail to get local IP address: %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_INVALID_PARAMETER;
+       }
+
+       /* remote ip */
+       if (ioctl(sk, SIOCGIFDSTADDR, &ifr_tun) < 0) {
+               ERR("Fail to get remote IP address: %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_INVALID_PARAMETER;
+       }
+
+       close(sk);
+
+       return VPNSVC_ERROR_NONE;
+}
+
 
 int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpnsvc_tun_s *handle_s)
 {
        struct ifreq ifr;
-       size_t len = 0;
        char buf[BUF_SIZE_FOR_ERR] = { 0 };
 
-       DBG("enter vpn_daemon_init, iface_name : %s, iface_name_len : %d, fd : %d\n", iface_name, iface_name_len, fd);
+       DBG("enter vpn_daemon_init, iface_name : %s, iface_name_len : %zd, fd : %d\n", iface_name, iface_name_len, fd);
 
        memset(&ifr, 0, sizeof(ifr));
 
@@ -769,6 +772,7 @@ int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpns
 
        if (*iface_name)
                strncpy(ifr.ifr_name, iface_name, iface_name_len);
+       ifr.ifr_name[iface_name_len] = '\0';
 
        DBG("before init, ifindex : %d", ifr.ifr_ifindex);
 
@@ -792,9 +796,7 @@ int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpns
 
        handle_s->fd = 0;   /* server fd does not meaning */
        handle_s->index = get_interface_index(iface_name);
-       len = strlen(ifr.ifr_name);
-       strncpy(handle_s->name, ifr.ifr_name, len);
-       handle_s->name[len] = '\0';
+       g_strlcpy(handle_s->name, ifr.ifr_name, VPNSVC_VPN_IFACE_NAME_LEN);
 
        return VPNSVC_ERROR_NONE;
 }
@@ -802,18 +804,15 @@ int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpns
 int vpn_service_deinit(const char* dev_name)
 {
        char buf[100];
-       FILE *fp = NULL;
 
        snprintf(buf, sizeof(buf), "/usr/sbin/ip link del %s", dev_name);
-       DBG("link delete cmd : %s", buf);
 
-       fp = popen(buf, "r");
-       if (fp != NULL) {
-               pclose(fp);
-               return VPNSVC_ERROR_NONE;
-       } else {
+       if (netconfig_execute_cmd(buf)) {
+               ERR("Failed to execute command: %s", buf);
                return VPNSVC_ERROR_IO_ERROR;
        }
+
+       return VPNSVC_ERROR_NONE;
 }
 
 int vpn_service_protect(int socket_fd, const char* dev_name)
@@ -835,25 +834,20 @@ int vpn_service_protect(int socket_fd, const char* dev_name)
        return ret;
 }
 
-int vpn_service_up(int iface_index, const char* local_ip, const char* remote_ip,
-                                               char* routes[], int prefix[], size_t nr_routes,
-                                               char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt,
-                                               const char* dns_suffix, const unsigned int mtu) {
-
-       struct sockaddr_in local_addr;
-       struct sockaddr_in remote_addr;
+int vpn_service_up(const char *iface_name)
+{
        struct ifreq ifr_tun;
        int sk;
        int ret = VPNSVC_ERROR_NONE;
        char buf[BUF_SIZE_FOR_ERR] = { 0 };
 
        DBG("enter vpn_daemon_up");
+       DBG("iface_name : %s", iface_name);
 
-       DBG("iface_index : %d", iface_index);
-       DBG("local ip : %s", local_ip);
-       DBG("remote ip : %s", remote_ip);
-       DBG("route pointer : %p, nr_routes : %d, dns_server pointer : %p, nr_dns : %d, dns_suffix : %s, mtu : %d", routes, nr_routes, dns_servers, nr_dns, dns_suffix, mtu);
 
+       ret = check_interface_precondition(iface_name);
+       if (ret != VPNSVC_ERROR_NONE)
+               return ret;
 
        sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
        if (sk < 0) {
@@ -862,36 +856,7 @@ int vpn_service_up(int iface_index, const char* local_ip, const char* remote_ip,
        }
 
        memset(&ifr_tun, 0, sizeof(ifr_tun));
-       ifr_tun.ifr_ifindex = iface_index;
-
-       /* get an interface name by ifindex */
-       if (ioctl(sk, SIOCGIFNAME, &ifr_tun) < 0) {
-               ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               close(sk);
-               return VPNSVC_ERROR_IO_ERROR;
-       }
-
-       /* local ip setting */
-       memset(&local_addr, 0, sizeof(local_addr));
-       local_addr.sin_addr.s_addr = inet_addr(local_ip); /* network byte order */
-       local_addr.sin_family = AF_INET;
-       memcpy(&ifr_tun.ifr_addr, &local_addr, sizeof(ifr_tun.ifr_addr));
-       if (ioctl(sk, SIOCSIFADDR, &ifr_tun) < 0) {
-               ERR("ioctl SIOCSIFADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               close(sk);
-               return VPNSVC_ERROR_IO_ERROR;
-       }
-
-       /* remote ip setting */
-       memset(&remote_addr, 0, sizeof(remote_addr));
-       remote_addr.sin_addr.s_addr = inet_addr(remote_ip); /*network byte order*/
-       remote_addr.sin_family = AF_INET;
-       memcpy(&ifr_tun.ifr_dstaddr, &remote_addr, sizeof(ifr_tun.ifr_dstaddr));
-       if (ioctl(sk, SIOCSIFDSTADDR, &ifr_tun) < 0) {
-               ERR("ioctl SIOCSIFDSTADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               close(sk);
-               return VPNSVC_ERROR_IO_ERROR;
-       }
+       g_strlcpy((char *)ifr_tun.ifr_name, iface_name, sizeof(ifr_tun.ifr_name));
 
        /* set the flags for vpn up */
        if (ioctl(sk, SIOCGIFFLAGS, &ifr_tun) < 0) {
@@ -909,42 +874,8 @@ int vpn_service_up(int iface_index, const char* local_ip, const char* remote_ip,
                return VPNSVC_ERROR_IO_ERROR;
        }
 
-       /* mtu setting */
-       if (ioctl(sk, SIOCGIFMTU, &ifr_tun) < 0) {
-               ERR("ioctl SIOCGIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               close(sk);
-               return VPNSVC_ERROR_IO_ERROR;
-       }
-
-       if (mtu > 0 && ifr_tun.ifr_mtu != (int)mtu) {
-               ifr_tun.ifr_mtu = mtu;
-               if (ioctl(sk, SIOCSIFMTU, &ifr_tun) < 0) {
-                       ERR("ioctl SIOCSIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-                       close(sk);
-                       return VPNSVC_ERROR_IO_ERROR;
-               }
-       }
-
        close(sk);
 
-       /* add routes */
-       if (nr_routes > 0) {
-               ret = add_routes(ifr_tun.ifr_name, routes, prefix, nr_routes);
-               if (ret != VPNSVC_ERROR_NONE) {
-                       ERR("add_routes failed");
-                       return ret;
-               }
-       }
-
-       /* add DNS routes */
-       if (nr_dns > 0) {
-               ret = add_dns_routes(ifr_tun.ifr_name, dns_servers, nr_dns);
-               if (ret != VPNSVC_ERROR_NONE) {
-                       ERR("add_dns failed");
-                       return ret;
-               }
-       }
-
 #if 0
        /* add DNS servers */
        if (nr_dns > 0) {
@@ -973,10 +904,9 @@ int vpn_service_up(int iface_index, const char* local_ip, const char* remote_ip,
 
 
 
-int vpn_service_down(int iface_index)
+int vpn_service_down(const char *iface_name)
 {
-       struct ifreq ifr, addr_ifr;
-       struct sockaddr_in *addr = NULL;
+       struct ifreq ifr;
        int sk;
        char buf[BUF_SIZE_FOR_ERR] = { 0 };
 
@@ -987,13 +917,7 @@ int vpn_service_down(int iface_index)
        }
 
        memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = iface_index;
-
-       if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
-               ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-               close(sk);
-               return VPNSVC_ERROR_IO_ERROR;
-       }
+       g_strlcpy((char *)ifr.ifr_name, iface_name, sizeof(ifr.ifr_name));
 
        if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
                ERR("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
@@ -1001,13 +925,6 @@ int vpn_service_down(int iface_index)
                return VPNSVC_ERROR_IO_ERROR;
        }
 
-       memset(&addr_ifr, 0, sizeof(addr_ifr));
-       memcpy(&addr_ifr.ifr_name, &ifr.ifr_name, sizeof(ifr.ifr_name) - 1);
-       addr = (struct sockaddr_in *)&addr_ifr.ifr_addr;
-       addr->sin_family = AF_INET;
-       if (ioctl(sk, SIOCSIFADDR, &addr_ifr) < 0)
-               DBG("ioctl SIOCSIFADDR (could not clear IP address) failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-
        if (!(ifr.ifr_flags & IFF_UP)) {
                DBG("Interface already down");
                close(sk);
@@ -1063,3 +980,249 @@ int vpn_service_unblock_networks(void)
        return VPNSVC_ERROR_NONE;
 }
 
+int vpn_service_update_settings(int iface_index, const char *local_ip,
+               const char *remote_ip, const unsigned int mtu)
+{
+       int sk;
+       struct ifreq ifr_tun;
+       struct sockaddr_in local_addr;
+       struct sockaddr_in remote_addr;
+       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0) {
+               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       memset(&ifr_tun, 0, sizeof(ifr_tun));
+       ifr_tun.ifr_ifindex = iface_index;
+
+       /* get an interface name by ifindex */
+       if (ioctl(sk, SIOCGIFNAME, &ifr_tun) < 0) {
+               ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       /* local ip setting */
+       memset(&local_addr, 0, sizeof(local_addr));
+       local_addr.sin_addr.s_addr = inet_addr(local_ip); /* network byte order */
+       local_addr.sin_family = AF_INET;
+       memcpy(&ifr_tun.ifr_addr, &local_addr, sizeof(ifr_tun.ifr_addr));
+       if (ioctl(sk, SIOCSIFADDR, &ifr_tun) < 0) {
+               ERR("ioctl SIOCSIFADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       /* remote ip setting */
+       memset(&remote_addr, 0, sizeof(remote_addr));
+       remote_addr.sin_addr.s_addr = inet_addr(remote_ip); /*network byte order*/
+       remote_addr.sin_family = AF_INET;
+       memcpy(&ifr_tun.ifr_dstaddr, &remote_addr, sizeof(ifr_tun.ifr_dstaddr));
+       if (ioctl(sk, SIOCSIFDSTADDR, &ifr_tun) < 0) {
+               ERR("ioctl SIOCSIFDSTADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       /* mtu setting */
+       if (mtu > 0 && ifr_tun.ifr_mtu != (int)mtu) {
+               ifr_tun.ifr_mtu = mtu;
+               if (ioctl(sk, SIOCSIFMTU, &ifr_tun) < 0) {
+                       ERR("ioctl SIOCSIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+                       close(sk);
+                       return VPNSVC_ERROR_IO_ERROR;
+               }
+       }
+
+       close(sk);
+
+       return VPNSVC_ERROR_NONE;
+}
+
+int vpn_service_add_route(char *iface_name, const char *route, int prefix)
+{
+       struct rtentry rt;
+       struct sockaddr_in addr;
+       int sk;
+       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0) {
+               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       memset(&rt, 0, sizeof(rt));
+       rt.rt_flags = RTF_UP;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = inet_addr(route);
+       memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+       /* set mask using by prefix length */
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       addr.sin_addr.s_addr = host2net(make_mask(prefix));
+       memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+
+       rt.rt_dev = iface_name;
+
+       if (ioctl(sk, SIOCADDRT, &rt) < 0) {
+               ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       close(sk);
+
+       return VPNSVC_ERROR_NONE;
+}
+
+int vpn_service_remove_route(char *iface_name, const char *route, int prefix)
+{
+       struct rtentry rt;
+       struct sockaddr_in addr;
+       int sk;
+       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0) {
+               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       memset(&rt, 0, sizeof(rt));
+       rt.rt_flags = RTF_UP;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = inet_addr(route);
+       memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+       /* set mask using by prefix length */
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       addr.sin_addr.s_addr = host2net(make_mask(prefix));
+       memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+
+       rt.rt_dev = iface_name;
+
+       if (ioctl(sk, SIOCDELRT, &rt) < 0) {
+               ERR("ioctl SIOCDERLT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       close(sk);
+
+       return VPNSVC_ERROR_NONE;
+
+}
+
+int vpn_service_add_dns_server(char *iface_name, const char *dns_server)
+{
+       struct rtentry rt;
+       struct sockaddr_in addr;
+       int sk;
+       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0) {
+               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       memset(&rt, 0, sizeof(rt));
+       rt.rt_flags = RTF_UP;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = inet_addr(dns_server);
+       memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+       /* set mask using by prefix length */
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       addr.sin_addr.s_addr = host2net(make_mask(32));
+       memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+
+       rt.rt_dev = iface_name;
+
+       if (ioctl(sk, SIOCADDRT, &rt) < 0) {
+               ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       close(sk);
+
+       return VPNSVC_ERROR_NONE;
+}
+
+int vpn_service_remove_dns_server(char *iface_name, const char *dns_server)
+{
+       struct rtentry rt;
+       struct sockaddr_in addr;
+       int sk;
+       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0) {
+               ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       memset(&rt, 0, sizeof(rt));
+       rt.rt_flags = RTF_UP;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = inet_addr(dns_server);
+       memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+       /* set mask using by prefix length */
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
+       addr.sin_addr.s_addr = host2net(make_mask(32));
+       memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+
+       rt.rt_dev = iface_name;
+
+       if (ioctl(sk, SIOCDELRT, &rt) < 0) {
+               ERR("ioctl SIOCDELRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+               close(sk);
+               return VPNSVC_ERROR_IO_ERROR;
+       }
+
+       close(sk);
+
+       return VPNSVC_ERROR_NONE;
+}