2 * Network Configuration - VPN Service Internal Module
4 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <net/route.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
28 #include <sys/ioctl.h>
30 #include <arpa/inet.h>
34 #include <linux/if_tun.h>
36 #include "vpnsvc-internal.h"
39 #define BUF_SIZE_FOR_ERR 100
41 #define CONNMAN_SERVICE "net.connman"
42 #define CONNMAN_INTERFACE_MANAGER "net.connman.Manager"
43 #define CONNMAN_INTERFACE_SERVICE "net.connman.Service"
47 static char iptables_cmd[] = "/usr/sbin/iptables";
48 static char iptables_filter_prefix[] = "CAPI_VPN_SERVICE_";
49 static char iptables_filter_out[] = "OUTPUT";
50 static char iptables_filter_in[] = "INPUT";
51 static char iptables_filter_interface_wlan[] = "wlan0";
52 /* 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;"; */
53 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;";
54 static char iptables_unregister_fmt[] = "%s -D %s -j %s%s -w;" "%s -F %s%s -w;" "%s -X %s%s -w;";
55 static char iptables_rule_fmt[] = "%s -%c %s%s -%c %s/%d -j ACCEPT -w;";
56 static char iptables_rule_with_interface_fmt[] = "%s -%c %s%s -%c %s -%c %s/%d -j ACCEPT -w;";
57 /*static char iptables_usage_fmt[] = "%s -L %s%s -n -v -w;";*/
58 /* iptables -t nat -A CAPI_VPN_SERVICE_OUTPUT -p udp -d <vpn dns address> --dport 53 -j DNAT --to <vpn defice address:53> */
59 static char iptables_nat_chain_name[] = "CAPI_VPN_SERVICE_NAT_OUTPUT";
61 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;";
62 static char iptables_nat_register_rule_fmt[] = "%s -t nat -A %s -p udp -d %s --dport 53 -j DNAT --to %s:53 -w;";
64 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;";
66 typedef unsigned long int ipv4; /* Declare variable type for ipv4 net address. */
68 static GDBusConnection *global_connection = NULL;
70 static ipv4 make_mask(int prefix)
75 for (i = prefix; i > 0; i--)
76 mask += (ipv4) (1 << (32 - i));
80 static in_addr_t host2net(ipv4 host)
86 net |= (host & 0x000000FF) << 24;
87 net |= (host & 0x0000FF00) << 8;
88 net |= (host & 0x00FF0000) >> 8;
89 net |= (host & 0xFF000000) >> 24;
94 static int add_routes(char* iface_name, char* routes[], int prefix[], size_t nr_routes)
97 struct sockaddr_in addr;
100 char buf[BUF_SIZE_FOR_ERR] = { 0 };
102 DBG("Enter add_routes");
104 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
106 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
107 return VPNSVC_ERROR_IO_ERROR;
110 for (i = 0; i < nr_routes; i++) {
111 memset(&rt, 0, sizeof(rt));
112 rt.rt_flags = RTF_UP;
114 memset(&addr, 0, sizeof(addr));
115 addr.sin_family = AF_INET;
116 addr.sin_addr.s_addr = inet_addr(routes[i]);
117 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
119 memset(&addr, 0, sizeof(addr));
120 addr.sin_family = AF_INET;
121 addr.sin_addr.s_addr = INADDR_ANY;
122 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
124 /* set mask using by prefix length */
125 memset(&addr, 0, sizeof(addr));
126 addr.sin_family = AF_INET;
127 addr.sin_addr.s_addr = INADDR_ANY;
128 addr.sin_addr.s_addr = host2net(make_mask(prefix[i]));
129 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
131 rt.rt_dev = iface_name;
133 if (ioctl(sk, SIOCADDRT, &rt) < 0) {
134 ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
136 return VPNSVC_ERROR_IO_ERROR;
142 return VPNSVC_ERROR_NONE;
145 static int add_dns_routes(char* if_name, char** dns_servers, size_t nr_dns)
148 struct sockaddr_in addr;
151 char buf[BUF_SIZE_FOR_ERR] = { 0 };
153 DBG("Enter add_routes");
155 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
157 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
158 return VPNSVC_ERROR_IO_ERROR;
161 for (i = 0; i < nr_dns; i++) {
162 memset(&rt, 0, sizeof(rt));
163 rt.rt_flags = RTF_UP;
165 memset(&addr, 0, sizeof(addr));
166 addr.sin_family = AF_INET;
167 addr.sin_addr.s_addr = inet_addr(dns_servers[i]);
168 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
170 memset(&addr, 0, sizeof(addr));
171 addr.sin_family = AF_INET;
172 addr.sin_addr.s_addr = INADDR_ANY;
173 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
175 /* set mask using by prefix length */
176 memset(&addr, 0, sizeof(addr));
177 addr.sin_family = AF_INET;
178 addr.sin_addr.s_addr = INADDR_ANY;
179 addr.sin_addr.s_addr = host2net(make_mask(32));
180 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
184 if (ioctl(sk, SIOCADDRT, &rt) < 0) {
185 ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
187 return VPNSVC_ERROR_IO_ERROR;
193 return VPNSVC_ERROR_NONE;
196 static void connman_connection_open(void)
198 if (global_connection == NULL) {
199 GError *error = NULL;
200 #if !GLIB_CHECK_VERSION(2, 36, 0)
204 global_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
205 if (global_connection == NULL) {
207 ERR("Error connman connection open: %s", error->message);
214 static void connman_connection_close(GDBusConnection *connection)
217 g_object_unref(connection);
220 static GVariant *connman_method_call(
221 GDBusConnection *connection, char *service, char *path,
222 char *interface, char *method, GVariant *params)
224 GError *error = NULL;
225 GVariant *message = NULL;
227 message = g_dbus_connection_call_sync(
228 connection, service, path, interface, method, params,
229 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
231 if (message == NULL) {
233 ERR("error: g_dbus_connection_call_sync [%d: %s]", error->code, error->message);
236 ERR("error: g_dbus_connection_call_sync\n");
243 static char *connman_default_profile(GDBusConnection *connection)
246 GVariantIter *value = NULL;
247 GVariant *message = NULL;
248 GVariantIter *iter = NULL;
249 char *profile = NULL;
251 message = connman_method_call(connection, CONNMAN_SERVICE, "/",
252 CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
255 g_variant_get(message, "(a(oa{sv}))", &iter);
256 while (g_variant_iter_loop(iter, "(oa{sv})", &key, &value)) {
257 profile = strdup(key);
262 g_variant_iter_free(value);
266 g_variant_iter_free(iter);
267 g_variant_unref(message);
274 static char *connman_get_items(GDBusConnection *connection, char *profile, const char *keystr)
276 GVariant *message = NULL;
277 GVariantIter *iter = NULL;
278 GVariantIter *next = NULL;
282 message = connman_method_call(connection, CONNMAN_SERVICE, "/",
283 CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
286 g_variant_get(message, "(a(oa{sv}))", &iter);
287 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
288 if (strcmp(obj, profile) == 0) {
292 while (g_variant_iter_loop(next, "{sv}", &key, &var)) {
293 if (g_strcmp0(key, keystr) == 0) {
294 GVariantIter *iter_item;
295 const gchar *value = NULL;
297 g_variant_get(var, "as", &iter_item);
298 while (g_variant_iter_loop(iter_item, "s", &value)) {
302 tmp_items = (char *) malloc(strlen(items) + 1 + strlen(value) + 1);
304 snprintf(tmp_items, strlen(tmp_items), "%s,%s", items, value);
309 items = strdup(value);
312 g_variant_iter_free(iter_item);
319 g_variant_iter_free(iter);
320 g_variant_unref(message);
327 static void connman_set_items(GDBusConnection *connection, char *profile,
328 const char *keystr, char *items)
330 GVariant *message = NULL;
331 GVariantBuilder *builder = NULL;
332 GVariant *params = NULL;
333 char *strings = strdup(items);
337 builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
338 if ((addr = strtok_r(strings, ", ", &temp)) != NULL) {
340 g_variant_builder_add(builder, "s", addr);
341 } while ((addr = strtok_r(NULL, ", ", &temp)) != NULL);
344 params = g_variant_new("(sv)", keystr,
345 g_variant_builder_end(builder));
346 g_variant_builder_unref(builder);
348 message = connman_method_call(connection, CONNMAN_SERVICE, profile,
349 CONNMAN_INTERFACE_SERVICE, "SetProperty", params);
351 g_variant_unref(message);
356 static char *connman_get_nameservers(GDBusConnection *connection, char *profile)
358 return connman_get_items(connection, profile, "Nameservers");
361 static char *connman_get_nameservers_conf(GDBusConnection *connection, char *profile)
363 return connman_get_items(connection, profile, "Nameservers.Configuration");
367 static void connman_set_nameservers(GDBusConnection *connection, char *profile,
370 return connman_set_items(connection, profile,
371 "Nameservers.Configuration", nameservers);
375 static char *connman_get_domains(GDBusConnection *connection, char *profile)
377 return connman_get_items(connection, profile, "Domains");
380 static char *connman_get_domains_conf(GDBusConnection *connection, char *profile)
382 return connman_get_items(connection, profile, "Domains.Configuration");
386 static void connman_set_domains(GDBusConnection *connection, char *profile,
389 return connman_set_items(connection, profile,
390 "Domains.Configuration", domains);
394 static int add_dns_servers(char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt)
396 char *profile = NULL;
398 char *org_items = NULL;
399 char *new_items = NULL;
402 connman_connection_open();
404 profile = connman_default_profile(global_connection);
405 if (profile == NULL) {
406 ERR("connman_default_profile failed");
407 connman_connection_close(global_connection);
408 return VPNSVC_ERROR_IPC_FAILED;
411 DBG("profile : %s\n", profile);
413 /* add name servers */
414 org_items = connman_get_nameservers(global_connection, profile);
417 DBG("original DNS : %s\n", org_items);
418 /* nr_dns = comma(,) count */
419 items = (char *) calloc((total_dns_string_cnt + nr_dns + strlen(org_items) + 1), sizeof(char));
421 ERR("OOM while malloc\n");
422 return VPNSVC_ERROR_OUT_OF_MEMORY;
424 strncpy(items, org_items, strlen(org_items));
425 for (i = 0 ; i < nr_dns ; i++) {
426 strncat(items, ",", 1);
427 strncat(items, dns_servers[i], strlen(dns_servers[i]));
432 /* nr_dns = comma(,) count + end null char */
433 items = (char *) calloc(total_dns_string_cnt + nr_dns, sizeof(char));
435 ERR("OOM while malloc\n");
436 return VPNSVC_ERROR_OUT_OF_MEMORY;
438 for (i = 0 ; i < nr_dns ; i++) {
439 strncat(items, dns_servers[i], strlen(dns_servers[i]));
441 strncat(items, ",", 1);
446 DBG("adding DNS : %s\n", items);
447 connman_set_nameservers(global_connection, profile, items);
453 new_items = connman_get_nameservers_conf(global_connection, profile);
454 DBG("new_dns : %s\n", new_items);
459 return VPNSVC_ERROR_NONE;
463 static int del_dns_servers()
465 char *profile = NULL;
467 connman_connection_open();
469 profile = connman_default_profile(global_connection);
470 if (profile == NULL) {
471 ERR("connman_default_profile failed");
472 connman_connection_close(global_connection);
473 return VPNSVC_ERROR_IPC_FAILED;
476 DBG("profile : %s", profile);
478 /* del name servers */
479 connman_set_nameservers(global_connection, profile, "");
484 return VPNSVC_ERROR_NONE;
488 static int add_dns_suffix(const char* dns_suffix, size_t dns_suffix_len)
490 char *profile = NULL;
492 char *org_items = NULL;
493 char *new_items = NULL;
495 connman_connection_open();
497 profile = connman_default_profile(global_connection);
498 if (profile == NULL) {
499 ERR("connman_default_profile failed");
500 connman_connection_close(global_connection);
501 return VPNSVC_ERROR_IPC_FAILED;
504 DBG("profile : %s", profile);
506 /* add name servers */
507 org_items = connman_get_domains(global_connection, profile);
510 DBG("original DNS suffix : %s", org_items);
511 /* comma(,) and end null character included */
512 items = (char *) calloc((dns_suffix_len + strlen(org_items) + 2), sizeof(char));
514 ERR("OOM while malloc");
515 return VPNSVC_ERROR_OUT_OF_MEMORY;
517 strncpy(items, org_items, strlen(org_items));
518 strncat(items, ",", 1);
519 strncat(items, dns_suffix, dns_suffix_len);
523 /* nr_dns = comma(,) count + end null char */
524 items = (char *) calloc((dns_suffix_len + 1), sizeof(char));
526 ERR("OOM while malloc");
527 return VPNSVC_ERROR_OUT_OF_MEMORY;
529 strncat(items, dns_suffix, dns_suffix_len);
533 DBG("adding DNS suffix : %s\n", items);
534 connman_set_domains(global_connection, profile, items);
539 /* print new domains */
540 new_items = connman_get_domains_conf(global_connection, profile);
541 DBG("new DNS suffix : %s\n", new_items);
549 return VPNSVC_ERROR_NONE;
553 static int del_dns_suffix()
555 char *profile = NULL;
557 connman_connection_open();
559 profile = connman_default_profile(global_connection);
560 if (profile == NULL) {
561 ERR("connman_default_profile failed");
562 connman_connection_close(global_connection);
563 return VPNSVC_ERROR_IPC_FAILED;
566 DBG("profile : %s", profile);
569 connman_set_domains(global_connection, profile, "");
574 return VPNSVC_ERROR_NONE;
578 static void iptables_exec(char *cmdline)
582 fp = popen(cmdline, "r");
589 static void dns_nat_register(char **vpn_dns_address, size_t nr_dns, char *vpn_device_address)
594 snprintf(buf + size, sizeof(buf) - size, iptables_nat_register_init_fmt,
595 iptables_cmd, iptables_nat_chain_name,
596 iptables_cmd, iptables_nat_chain_name,
597 iptables_cmd, iptables_filter_out, iptables_nat_chain_name);
600 for (i = 0 ; i < nr_dns ; i++) {
601 snprintf(buf + size, sizeof(buf) - size, iptables_nat_register_rule_fmt,
602 iptables_cmd, iptables_nat_chain_name, vpn_dns_address[i], vpn_device_address);
605 DBG("iptable dns nat reg cmd : %s", buf);
610 static void dns_nat_unregister(void)
615 snprintf(buf + size, sizeof(buf) - size, iptables_nat_unregister_fmt,
616 iptables_cmd, iptables_filter_out, iptables_nat_chain_name,
617 iptables_cmd, iptables_nat_chain_name,
618 iptables_cmd, iptables_nat_chain_name);
620 DBG("iptable dns nat unreg cmd : %s", buf);
624 static void iptables_register(void)
627 char buf[8192], *filter;
629 filter = iptables_filter_out;
630 snprintf(buf + size, sizeof(buf) - size, iptables_register_fmt,
631 iptables_cmd, iptables_filter_prefix, filter,
632 iptables_cmd, iptables_filter_prefix, filter,
633 iptables_cmd, iptables_filter_prefix, filter,
634 iptables_cmd, iptables_filter_prefix, filter,
635 iptables_cmd, filter, iptables_filter_prefix, filter);
637 filter = iptables_filter_in;
638 snprintf(buf + size, sizeof(buf) - size, iptables_register_fmt,
639 iptables_cmd, iptables_filter_prefix, filter,
640 iptables_cmd, iptables_filter_prefix, filter,
641 iptables_cmd, iptables_filter_prefix, filter,
642 iptables_cmd, iptables_filter_prefix, filter,
643 iptables_cmd, filter, iptables_filter_prefix, filter);
644 DBG("iptable reg cmd : %s", buf);
648 static void iptables_unregister(void)
651 char buf[8192], *filter;
653 filter = iptables_filter_out;
654 snprintf(buf + size, sizeof(buf) - size, iptables_unregister_fmt,
655 iptables_cmd, filter, iptables_filter_prefix, filter,
656 iptables_cmd, iptables_filter_prefix, filter,
657 iptables_cmd, iptables_filter_prefix, filter);
659 filter = iptables_filter_in;
660 snprintf(buf + size, sizeof(buf) - size, iptables_unregister_fmt,
661 iptables_cmd, filter, iptables_filter_prefix, filter,
662 iptables_cmd, iptables_filter_prefix, filter,
663 iptables_cmd, iptables_filter_prefix, filter);
664 DBG("iptable unreg cmd : %s", buf);
668 static void iptables_rule(const char c, const char *addr, const int mask)
673 snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
674 iptables_filter_prefix, iptables_filter_out, 'd', addr, mask);
676 snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
677 iptables_filter_prefix, iptables_filter_in, 's', addr, mask);
678 DBG("iptable cmd : %s", buf);
682 static void iptables_rule_interface(const char c, const char *addr, const int mask, const char *interface)
687 snprintf(buf + size, sizeof(buf) - size,
688 iptables_rule_with_interface_fmt, iptables_cmd,
689 c, iptables_filter_prefix, iptables_filter_out,
690 'o', interface, 'd', addr, mask);
692 snprintf(buf + size, sizeof(buf) - size,
693 iptables_rule_with_interface_fmt, iptables_cmd,
694 c, iptables_filter_prefix, iptables_filter_in,
695 'i', interface, 's', addr, mask);
696 DBG("iptable cmd : %s", buf);
700 void iptables_add_orig(const char *addr, const int mask)
702 iptables_rule_interface('I', addr, mask, iptables_filter_interface_wlan);
705 void iptables_delete_orig(const char *addr, const int mask)
707 iptables_rule_interface('D', addr, mask, iptables_filter_interface_wlan);
710 void iptables_add(const char *addr, const int mask)
712 iptables_rule('I', addr, mask);
715 void iptables_delete(const char *addr, const int mask)
717 iptables_rule('D', addr, mask);
720 static int get_interface_index(const char *iface_name)
724 char buf[BUF_SIZE_FOR_ERR] = { 0 };
726 DBG("enter get_interface_index, iface_name : %s", iface_name);
728 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
730 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
731 return VPNSVC_ERROR_IO_ERROR;
734 memset(&ifr, 0, sizeof(ifr));
737 strncpy(ifr.ifr_name, iface_name, strlen(iface_name));
739 /* get an interface name by ifindex */
740 if (ioctl(sk, SIOCGIFINDEX, &ifr) < 0) {
741 ERR("ioctl SIOCGIFINDEX failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
743 return VPNSVC_ERROR_IO_ERROR;
748 return ifr.ifr_ifindex;
752 int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpnsvc_tun_s *handle_s)
756 char buf[BUF_SIZE_FOR_ERR] = { 0 };
758 DBG("enter vpn_daemon_init, iface_name : %s, iface_name_len : %d, fd : %d\n", iface_name, iface_name_len, fd);
760 memset(&ifr, 0, sizeof(ifr));
762 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
763 * IFF_TAP - TAP device
765 * IFF_NO_PI - Do not provide packet information
768 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
771 strncpy(ifr.ifr_name, iface_name, iface_name_len);
773 DBG("before init, ifindex : %d", ifr.ifr_ifindex);
775 if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
776 ERR("TUNSETIFF Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
778 return VPNSVC_ERROR_IO_ERROR;
781 if (ioctl(fd, TUNSETOWNER, 5000) < 0) {
782 ERR("TUNSETOWNER Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
784 return VPNSVC_ERROR_IO_ERROR;
787 if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
788 ERR("TUNSETPERSIST Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
790 return VPNSVC_ERROR_IO_ERROR;
793 handle_s->fd = 0; /* server fd does not meaning */
794 handle_s->index = get_interface_index(iface_name);
795 len = strlen(ifr.ifr_name);
796 strncpy(handle_s->name, ifr.ifr_name, len);
797 handle_s->name[len] = '\0';
799 return VPNSVC_ERROR_NONE;
802 int vpn_service_deinit(const char* dev_name)
807 snprintf(buf, sizeof(buf), "/usr/sbin/ip link del %s", dev_name);
808 DBG("link delete cmd : %s", buf);
810 fp = popen(buf, "r");
813 return VPNSVC_ERROR_NONE;
815 return VPNSVC_ERROR_IO_ERROR;
819 int vpn_service_protect(int socket_fd, const char* dev_name)
821 int ret = VPNSVC_ERROR_NONE;
822 char buf[BUF_SIZE_FOR_ERR] = { 0 };
823 DBG("enter vpn_daemon_protect, socket : %d, dev_name : %s\n", socket_fd, dev_name);
825 ret = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE,
826 dev_name, strlen(dev_name));
829 DBG("setsockopt failed : %d, %s", ret, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
830 ret = VPNSVC_ERROR_IO_ERROR;
832 ret = VPNSVC_ERROR_NONE;
838 int vpn_service_up(int iface_index, const char* local_ip, const char* remote_ip,
839 char* routes[], int prefix[], size_t nr_routes,
840 char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt,
841 const char* dns_suffix, const unsigned int mtu) {
843 struct sockaddr_in local_addr;
844 struct sockaddr_in remote_addr;
845 struct ifreq ifr_tun;
847 int ret = VPNSVC_ERROR_NONE;
848 char buf[BUF_SIZE_FOR_ERR] = { 0 };
850 DBG("enter vpn_daemon_up");
852 DBG("iface_index : %d", iface_index);
853 DBG("local ip : %s", local_ip);
854 DBG("remote ip : %s", remote_ip);
855 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);
858 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
860 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
861 return VPNSVC_ERROR_IO_ERROR;
864 memset(&ifr_tun, 0, sizeof(ifr_tun));
865 ifr_tun.ifr_ifindex = iface_index;
867 /* get an interface name by ifindex */
868 if (ioctl(sk, SIOCGIFNAME, &ifr_tun) < 0) {
869 ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
871 return VPNSVC_ERROR_IO_ERROR;
874 /* local ip setting */
875 memset(&local_addr, 0, sizeof(local_addr));
876 local_addr.sin_addr.s_addr = inet_addr(local_ip); /* network byte order */
877 local_addr.sin_family = AF_INET;
878 memcpy(&ifr_tun.ifr_addr, &local_addr, sizeof(ifr_tun.ifr_addr));
879 if (ioctl(sk, SIOCSIFADDR, &ifr_tun) < 0) {
880 ERR("ioctl SIOCSIFADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
882 return VPNSVC_ERROR_IO_ERROR;
885 /* remote ip setting */
886 memset(&remote_addr, 0, sizeof(remote_addr));
887 remote_addr.sin_addr.s_addr = inet_addr(remote_ip); /*network byte order*/
888 remote_addr.sin_family = AF_INET;
889 memcpy(&ifr_tun.ifr_dstaddr, &remote_addr, sizeof(ifr_tun.ifr_dstaddr));
890 if (ioctl(sk, SIOCSIFDSTADDR, &ifr_tun) < 0) {
891 ERR("ioctl SIOCSIFDSTADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
893 return VPNSVC_ERROR_IO_ERROR;
896 /* set the flags for vpn up */
897 if (ioctl(sk, SIOCGIFFLAGS, &ifr_tun) < 0) {
898 ERR("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
900 return VPNSVC_ERROR_IO_ERROR;
903 ifr_tun.ifr_flags |= IFF_UP;
904 ifr_tun.ifr_flags |= IFF_RUNNING;
906 if (ioctl(sk, SIOCSIFFLAGS, &ifr_tun) < 0) {
907 ERR("ioctl SIOCSIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
909 return VPNSVC_ERROR_IO_ERROR;
913 if (ioctl(sk, SIOCGIFMTU, &ifr_tun) < 0) {
914 ERR("ioctl SIOCGIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
916 return VPNSVC_ERROR_IO_ERROR;
919 if (mtu > 0 && ifr_tun.ifr_mtu != (int)mtu) {
920 ifr_tun.ifr_mtu = mtu;
921 if (ioctl(sk, SIOCSIFMTU, &ifr_tun) < 0) {
922 ERR("ioctl SIOCSIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
924 return VPNSVC_ERROR_IO_ERROR;
932 ret = add_routes(ifr_tun.ifr_name, routes, prefix, nr_routes);
933 if (ret != VPNSVC_ERROR_NONE) {
934 ERR("add_routes failed");
941 ret = add_dns_routes(ifr_tun.ifr_name, dns_servers, nr_dns);
942 if (ret != VPNSVC_ERROR_NONE) {
943 ERR("add_dns failed");
949 /* add DNS servers */
951 ret = add_dns_servers(dns_servers, nr_dns, total_dns_string_cnt);
952 if (ret != VPNSVC_ERROR_NONE) {
953 ERR("add_dns failed");
960 ret = add_dns_suffix(dns_suffix, strlen(dns_suffix));
961 if (ret != VPNSVC_ERROR_NONE) {
962 ERR("add_dns_suffix failed");
968 dns_nat_register(dns_servers, nr_dns, local_ip);
976 int vpn_service_down(int iface_index)
978 struct ifreq ifr, addr_ifr;
979 struct sockaddr_in *addr = NULL;
981 char buf[BUF_SIZE_FOR_ERR] = { 0 };
983 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
985 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
986 return VPNSVC_ERROR_IO_ERROR;
989 memset(&ifr, 0, sizeof(ifr));
990 ifr.ifr_ifindex = iface_index;
992 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
993 ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
995 return VPNSVC_ERROR_IO_ERROR;
998 if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
999 ERR("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1001 return VPNSVC_ERROR_IO_ERROR;
1004 memset(&addr_ifr, 0, sizeof(addr_ifr));
1005 memcpy(&addr_ifr.ifr_name, &ifr.ifr_name, sizeof(ifr.ifr_name) - 1);
1006 addr = (struct sockaddr_in *)&addr_ifr.ifr_addr;
1007 addr->sin_family = AF_INET;
1008 if (ioctl(sk, SIOCSIFADDR, &addr_ifr) < 0)
1009 DBG("ioctl SIOCSIFADDR (could not clear IP address) failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1011 if (!(ifr.ifr_flags & IFF_UP)) {
1012 DBG("Interface already down");
1014 return VPNSVC_ERROR_NONE;
1017 ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
1018 if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
1019 ERR("ioctl SIOCSIFFLAGS (interface down) failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1021 return VPNSVC_ERROR_IO_ERROR;
1026 /* routes are will be removed automatically while down interfaces */
1027 /* remove dns servers */
1030 /* remove dns suffix */
1033 /* remove dns filter */
1034 dns_nat_unregister();
1036 return VPNSVC_ERROR_NONE;
1039 int vpn_service_block_networks(char* nets_vpn[], int prefix_vpn[], size_t nr_nets_vpn,
1040 char* nets_orig[], int prefix_orig[], size_t nr_nets_orig) {
1043 /* iptable chain regist */
1044 iptables_register();
1046 for (i = 0; i < nr_nets_vpn; i++) {
1047 DBG("block[%d] ip/mask : %s/%d", i, nets_vpn[i], prefix_vpn[i]);
1048 iptables_add(nets_vpn[i], prefix_vpn[i]);
1051 for (i = 0; i < nr_nets_orig; i++) {
1052 DBG("allow[%d] ip/mask : %s/%d", i, nets_orig[i], prefix_orig[i]);
1053 iptables_add_orig(nets_orig[i], prefix_orig[i]);
1056 return VPNSVC_ERROR_NONE;
1059 int vpn_service_unblock_networks(void)
1061 iptables_unregister();
1063 return VPNSVC_ERROR_NONE;