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>
33 #include "vpn_service_daemon.h"
38 #define LOG_TAG "VPNSVC_DAEMON"
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";
60 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;";
61 static char iptables_nat_register_rule_fmt[] = "%s -t nat -A %s -p udp -d %s --dport 53 -j DNAT --to %s:53 -w;";
62 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;";
64 typedef unsigned long int ipv4; /* Declare variable type for ipv4 net address. */
66 static GDBusConnection *global_connection = NULL;
68 static ipv4 make_mask(int prefix)
73 for (i = prefix; i > 0; i--)
74 mask += (ipv4) (1 << (32 - i));
78 static in_addr_t host2net(ipv4 host)
84 net |= (host & 0x000000FF) << 24;
85 net |= (host & 0x0000FF00) << 8;
86 net |= (host & 0x00FF0000) >> 8;
87 net |= (host & 0xFF000000) >> 24;
92 static int add_routes(char* iface_name, char* routes[], int prefix[], size_t nr_routes)
95 struct sockaddr_in addr;
98 char buf[BUF_SIZE_FOR_ERR] = { 0 };
100 LOGD("Enter add_routes");
102 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
104 LOGE("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
105 return VPNSVC_ERROR_IO_ERROR;
108 for (i = 0; i < nr_routes; i++) {
109 memset(&rt, 0, sizeof(rt));
110 rt.rt_flags = RTF_UP;
112 memset(&addr, 0, sizeof(addr));
113 addr.sin_family = AF_INET;
114 addr.sin_addr.s_addr = inet_addr(routes[i]);
115 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
117 memset(&addr, 0, sizeof(addr));
118 addr.sin_family = AF_INET;
119 addr.sin_addr.s_addr = INADDR_ANY;
120 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
122 /* set mask using by prefix length */
123 memset(&addr, 0, sizeof(addr));
124 addr.sin_family = AF_INET;
125 addr.sin_addr.s_addr = INADDR_ANY;
126 addr.sin_addr.s_addr = host2net(make_mask(prefix[i]));
127 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
129 rt.rt_dev = iface_name;
131 if (ioctl(sk, SIOCADDRT, &rt) < 0) {
132 LOGE("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
134 return VPNSVC_ERROR_IO_ERROR;
140 return VPNSVC_ERROR_NONE;
143 static int add_dns_routes(char* if_name, char** dns_servers, size_t nr_dns)
146 struct sockaddr_in addr;
150 LOGD("Enter add_routes");
152 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
154 LOGE("socket failed : %s", strerror(errno));
155 return VPNSVC_ERROR_IO_ERROR;
158 for (i = 0; i < nr_dns; i++) {
159 memset(&rt, 0, sizeof(rt));
160 rt.rt_flags = RTF_UP;
162 memset(&addr, 0, sizeof(addr));
163 addr.sin_family = AF_INET;
164 addr.sin_addr.s_addr = inet_addr(dns_servers[i]);
165 memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
167 memset(&addr, 0, sizeof(addr));
168 addr.sin_family = AF_INET;
169 addr.sin_addr.s_addr = INADDR_ANY;
170 memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
172 /* set mask using by prefix length */
173 memset(&addr, 0, sizeof(addr));
174 addr.sin_family = AF_INET;
175 addr.sin_addr.s_addr = INADDR_ANY;
176 addr.sin_addr.s_addr = host2net(make_mask(32));
177 memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
181 if (ioctl(sk, SIOCADDRT, &rt) < 0) {
182 LOGE("ioctl SIOCADDRT failed : %s", strerror(errno));
184 return VPNSVC_ERROR_IO_ERROR;
190 return VPNSVC_ERROR_NONE;
193 static void connman_connection_open(void)
195 if (global_connection == NULL) {
196 GError *error = NULL;
197 #if !GLIB_CHECK_VERSION(2, 36, 0)
201 global_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
202 if (global_connection == NULL) {
204 LOGE("Error connman connection open: %s", error->message);
211 static void connman_connection_close(GDBusConnection *connection)
214 g_object_unref(connection);
217 static GVariant *connman_method_call(
218 GDBusConnection *connection, char *service, char *path,
219 char *interface, char *method, GVariant *params)
221 GError *error = NULL;
222 GVariant *message = NULL;
224 message = g_dbus_connection_call_sync(
225 connection, service, path, interface, method, params,
226 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
228 if (message == NULL) {
230 LOGE("error: g_dbus_connection_call_sync [%d: %s]", error->code, error->message);
233 LOGE("error: g_dbus_connection_call_sync\n");
240 static char *connman_default_profile(GDBusConnection *connection)
243 GVariantIter *value = NULL;
244 GVariant *message = NULL;
245 GVariantIter *iter = NULL;
246 char *profile = NULL;
248 message = connman_method_call(connection, CONNMAN_SERVICE, "/",
249 CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
252 g_variant_get(message, "(a(oa{sv}))", &iter);
253 while (g_variant_iter_loop(iter, "(oa{sv})", &key, &value)) {
254 profile = strdup(key);
259 g_variant_iter_free(value);
263 g_variant_iter_free(iter);
264 g_variant_unref(message);
270 static char *connman_get_items(GDBusConnection *connection, char *profile, const char *keystr)
272 GVariant *message = NULL;
273 GVariantIter *iter = NULL;
274 GVariantIter *next = NULL;
278 message = connman_method_call(connection, CONNMAN_SERVICE, "/",
279 CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
282 g_variant_get(message, "(a(oa{sv}))", &iter);
283 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
284 if (strcmp(obj, profile) == 0) {
288 while (g_variant_iter_loop(next, "{sv}", &key, &var)) {
289 if (g_strcmp0(key, keystr) == 0) {
290 GVariantIter *iter_item;
291 const gchar *value = NULL;
293 g_variant_get(var, "as", &iter_item);
294 while (g_variant_iter_loop(iter_item, "s", &value)) {
298 tmp_items = (char *) malloc(strlen(items) + 1 + strlen(value) + 1);
300 snprintf(tmp_items, strlen(tmp_items), "%s,%s", items, value);
305 items = strdup(value);
308 g_variant_iter_free(iter_item);
315 g_variant_iter_free(iter);
316 g_variant_unref(message);
322 static void connman_set_items(GDBusConnection *connection, char *profile,
323 const char *keystr, char *items)
325 GVariant *message = NULL;
326 GVariantBuilder *builder = NULL;
327 GVariant *params = NULL;
328 char *strings = strdup(items);
332 builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
333 if ((addr = strtok_r(strings, ", ", &temp)) != NULL) {
335 g_variant_builder_add(builder, "s", addr);
336 } while ((addr = strtok_r(NULL, ", ", &temp)) != NULL);
339 params = g_variant_new("(sv)", keystr,
340 g_variant_builder_end(builder));
341 g_variant_builder_unref(builder);
343 message = connman_method_call(connection, CONNMAN_SERVICE, profile,
344 CONNMAN_INTERFACE_SERVICE, "SetProperty", params);
346 g_variant_unref(message);
350 static char *connman_get_nameservers(GDBusConnection *connection, char *profile)
352 return connman_get_items(connection, profile, "Nameservers");
355 static char *connman_get_nameservers_conf(GDBusConnection *connection, char *profile)
357 return connman_get_items(connection, profile, "Nameservers.Configuration");
360 static void connman_set_nameservers(GDBusConnection *connection, char *profile,
363 return connman_set_items(connection, profile,
364 "Nameservers.Configuration", nameservers);
367 static char *connman_get_domains(GDBusConnection *connection, char *profile)
369 return connman_get_items(connection, profile, "Domains");
372 static char *connman_get_domains_conf(GDBusConnection *connection, char *profile)
374 return connman_get_items(connection, profile, "Domains.Configuration");
377 static void connman_set_domains(GDBusConnection *connection, char *profile,
380 return connman_set_items(connection, profile,
381 "Domains.Configuration", domains);
384 static int add_dns_servers(char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt)
386 char *profile = NULL;
388 char *org_items = NULL;
389 char *new_items = NULL;
392 connman_connection_open();
394 profile = connman_default_profile(global_connection);
395 if (profile == NULL) {
396 LOGE("connman_default_profile failed");
397 connman_connection_close(global_connection);
398 return VPNSVC_ERROR_IPC_FAILED;
401 LOGD("profile : %s\n", profile);
403 /* add name servers */
404 org_items = connman_get_nameservers(global_connection, profile);
407 LOGD("original DNS : %s\n", org_items);
408 /* nr_dns = comma(,) count */
409 items = (char *) calloc((total_dns_string_cnt + nr_dns + strlen(org_items) + 1), sizeof(char));
411 LOGE("OOM while malloc\n");
412 return VPNSVC_ERROR_OUT_OF_MEMORY;
414 strncpy(items, org_items, strlen(org_items));
415 for (i = 0 ; i < nr_dns ; i++) {
416 strncat(items, ",", 1);
417 strncat(items, dns_servers[i], strlen(dns_servers[i]));
422 /* nr_dns = comma(,) count + end null char */
423 items = (char *) calloc(total_dns_string_cnt + nr_dns, sizeof(char));
425 LOGE("OOM while malloc\n");
426 return VPNSVC_ERROR_OUT_OF_MEMORY;
428 for (i = 0 ; i < nr_dns ; i++) {
429 strncat(items, dns_servers[i], strlen(dns_servers[i]));
431 strncat(items, ",", 1);
436 LOGD("adding DNS : %s\n", items);
437 connman_set_nameservers(global_connection, profile, items);
443 new_items = connman_get_nameservers_conf(global_connection, profile);
444 LOGD("new_dns : %s\n", new_items);
449 return VPNSVC_ERROR_NONE;
452 static int del_dns_servers()
454 char *profile = NULL;
456 connman_connection_open();
458 profile = connman_default_profile(global_connection);
459 if (profile == NULL) {
460 LOGE("connman_default_profile failed");
461 connman_connection_close(global_connection);
462 return VPNSVC_ERROR_IPC_FAILED;
465 LOGD("profile : %s", profile);
467 /* del name servers */
468 connman_set_nameservers(global_connection, profile, "");
473 return VPNSVC_ERROR_NONE;
476 static int add_dns_suffix(const char* dns_suffix, size_t dns_suffix_len)
478 char *profile = NULL;
480 char *org_items = NULL;
481 char *new_items = NULL;
483 connman_connection_open();
485 profile = connman_default_profile(global_connection);
486 if (profile == NULL) {
487 LOGE("connman_default_profile failed");
488 connman_connection_close(global_connection);
489 return VPNSVC_ERROR_IPC_FAILED;
492 LOGD("profile : %s", profile);
494 /* add name servers */
495 org_items = connman_get_domains(global_connection, profile);
498 LOGD("original DNS suffix : %s", org_items);
499 /* comma(,) and end null character included */
500 items = (char *) calloc((dns_suffix_len + strlen(org_items) + 2), sizeof(char));
502 LOGE("OOM while malloc");
503 return VPNSVC_ERROR_OUT_OF_MEMORY;
505 strncpy(items, org_items, strlen(org_items));
506 strncat(items, ",", 1);
507 strncat(items, dns_suffix, dns_suffix_len);
511 /* nr_dns = comma(,) count + end null char */
512 items = (char *) calloc((dns_suffix_len + 1), sizeof(char));
514 LOGE("OOM while malloc");
515 return VPNSVC_ERROR_OUT_OF_MEMORY;
517 strncat(items, dns_suffix, dns_suffix_len);
521 LOGD("adding DNS suffix : %s\n", items);
522 connman_set_domains(global_connection, profile, items);
527 /* print new domains */
528 new_items = connman_get_domains_conf(global_connection, profile);
529 LOGD("new DNS suffix : %s\n", new_items);
537 return VPNSVC_ERROR_NONE;
540 static int del_dns_suffix()
542 char *profile = NULL;
544 connman_connection_open();
546 profile = connman_default_profile(global_connection);
547 if (profile == NULL) {
548 LOGE("connman_default_profile failed");
549 connman_connection_close(global_connection);
550 return VPNSVC_ERROR_IPC_FAILED;
553 LOGD("profile : %s", profile);
556 connman_set_domains(global_connection, profile, "");
561 return VPNSVC_ERROR_NONE;
565 static void iptables_exec(char *cmdline)
569 fp = popen(cmdline, "r");
575 static void dns_nat_register(char **vpn_dns_address, size_t nr_dns, char *vpn_device_address)
580 snprintf(buf + size, sizeof(buf) - size, iptables_nat_register_init_fmt,
581 iptables_cmd, iptables_nat_chain_name,
582 iptables_cmd, iptables_nat_chain_name,
583 iptables_cmd, iptables_filter_out, iptables_nat_chain_name);
586 for (i = 0 ; i < nr_dns ; i++) {
587 snprintf(buf + size, sizeof(buf) - size, iptables_nat_register_rule_fmt,
588 iptables_cmd, iptables_nat_chain_name, vpn_dns_address[i], vpn_device_address);
591 LOGD("iptable dns nat reg cmd : %s", buf);
595 static void dns_nat_unregister(void)
600 snprintf(buf + size, sizeof(buf) - size, iptables_nat_unregister_fmt,
601 iptables_cmd, iptables_filter_out, iptables_nat_chain_name,
602 iptables_cmd, iptables_nat_chain_name,
603 iptables_cmd, iptables_nat_chain_name);
605 LOGD("iptable dns nat unreg cmd : %s", buf);
609 static void iptables_register(void)
612 char buf[8192], *filter;
614 filter = iptables_filter_out;
615 snprintf(buf + size, sizeof(buf) - size, iptables_register_fmt,
616 iptables_cmd, iptables_filter_prefix, filter,
617 iptables_cmd, iptables_filter_prefix, filter,
618 iptables_cmd, iptables_filter_prefix, filter,
619 iptables_cmd, iptables_filter_prefix, filter,
620 iptables_cmd, filter, iptables_filter_prefix, filter);
622 filter = iptables_filter_in;
623 snprintf(buf + size, sizeof(buf) - size, iptables_register_fmt,
624 iptables_cmd, iptables_filter_prefix, filter,
625 iptables_cmd, iptables_filter_prefix, filter,
626 iptables_cmd, iptables_filter_prefix, filter,
627 iptables_cmd, iptables_filter_prefix, filter,
628 iptables_cmd, filter, iptables_filter_prefix, filter);
629 LOGD("iptable reg cmd : %s", buf);
633 static void iptables_unregister(void)
636 char buf[8192], *filter;
638 filter = iptables_filter_out;
639 snprintf(buf + size, sizeof(buf) - size, iptables_unregister_fmt,
640 iptables_cmd, filter, iptables_filter_prefix, filter,
641 iptables_cmd, iptables_filter_prefix, filter,
642 iptables_cmd, iptables_filter_prefix, filter);
644 filter = iptables_filter_in;
645 snprintf(buf + size, sizeof(buf) - size, iptables_unregister_fmt,
646 iptables_cmd, filter, iptables_filter_prefix, filter,
647 iptables_cmd, iptables_filter_prefix, filter,
648 iptables_cmd, iptables_filter_prefix, filter);
649 LOGD("iptable unreg cmd : %s", buf);
653 static void iptables_rule(const char c, const char *addr, const int mask)
658 snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
659 iptables_filter_prefix, iptables_filter_out, 'd', addr, mask);
661 snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
662 iptables_filter_prefix, iptables_filter_in, 's', addr, mask);
663 LOGD("iptable cmd : %s", buf);
667 static void iptables_rule_interface(const char c, const char *addr, const int mask, const char *interface)
672 snprintf(buf + size, sizeof(buf) - size,
673 iptables_rule_with_interface_fmt, iptables_cmd,
674 c, iptables_filter_prefix, iptables_filter_out,
675 'o', interface, 'd', addr, mask);
677 snprintf(buf + size, sizeof(buf) - size,
678 iptables_rule_with_interface_fmt, iptables_cmd,
679 c, iptables_filter_prefix, iptables_filter_in,
680 'i', interface, 's', addr, mask);
681 LOGD("iptable cmd : %s", buf);
685 void iptables_add_orig(const char *addr, const int mask)
687 iptables_rule_interface('I', addr, mask, iptables_filter_interface_wlan);
690 void iptables_delete_orig(const char *addr, const int mask)
692 iptables_rule_interface('D', addr, mask, iptables_filter_interface_wlan);
695 void iptables_add(const char *addr, const int mask)
697 iptables_rule('I', addr, mask);
700 void iptables_delete(const char *addr, const int mask)
702 iptables_rule('D', addr, mask);
705 static int get_interface_index(const char *iface_name)
709 char buf[BUF_SIZE_FOR_ERR] = { 0 };
711 LOGD("enter get_interface_index, iface_name : %s", iface_name);
713 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
715 LOGE("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
716 return VPNSVC_ERROR_IO_ERROR;
719 memset(&ifr, 0, sizeof(ifr));
722 strncpy(ifr.ifr_name, iface_name, strlen(iface_name));
724 /* get an interface name by ifindex */
725 if (ioctl(sk, SIOCGIFINDEX, &ifr) < 0) {
726 LOGE("ioctl SIOCGIFINDEX failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
728 return VPNSVC_ERROR_IO_ERROR;
733 return ifr.ifr_ifindex;
737 int vpn_daemon_init(const char* iface_name, size_t iface_name_len, int fd, vpnsvc_tun_s *handle_s)
741 char buf[BUF_SIZE_FOR_ERR] = { 0 };
743 LOGD("enter vpn_daemon_init, iface_name : %s, iface_name_len : %d, fd : %d\n", iface_name, iface_name_len, fd);
745 memset(&ifr, 0, sizeof(ifr));
747 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
748 * IFF_TAP - TAP device
750 * IFF_NO_PI - Do not provide packet information
753 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
756 strncpy(ifr.ifr_name, iface_name, iface_name_len);
758 LOGD("before init, ifindex : %d", ifr.ifr_ifindex);
760 if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
761 LOGE("TUNSETIFF Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
763 return VPNSVC_ERROR_IO_ERROR;
766 if (ioctl(fd, TUNSETOWNER, 5000) < 0) {
767 LOGE("TUNSETOWNER Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
769 return VPNSVC_ERROR_IO_ERROR;
772 if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
773 LOGE("TUNSETPERSIST Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
775 return VPNSVC_ERROR_IO_ERROR;
778 handle_s->fd = 0; /* server fd does not meaning */
779 handle_s->index = get_interface_index(iface_name);
780 len = strlen(ifr.ifr_name);
781 strncpy(handle_s->name, ifr.ifr_name, len);
782 handle_s->name[len] = '\0';
784 return VPNSVC_ERROR_NONE;
787 int vpn_daemon_deinit(const char* dev_name)
792 snprintf(buf, sizeof(buf), "/usr/sbin/ip link del %s", dev_name);
793 LOGD("link delete cmd : %s", buf);
795 fp = popen(buf, "r");
798 return VPNSVC_ERROR_NONE;
800 return VPNSVC_ERROR_IO_ERROR;
804 int vpn_daemon_protect(int socket_fd, const char* dev_name)
806 int ret = VPNSVC_ERROR_NONE;
807 char buf[BUF_SIZE_FOR_ERR] = { 0 };
808 LOGD("enter vpn_daemon_protect, socket : %d, dev_name : %s\n", socket_fd, dev_name);
810 ret = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE,
811 dev_name, strlen(dev_name));
814 LOGD("setsockopt failed : %d, %s", ret, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
815 ret = VPNSVC_ERROR_IO_ERROR;
817 ret = VPNSVC_ERROR_NONE;
823 int vpn_daemon_up(int iface_index, const char* local_ip, const char* remote_ip,
824 char* routes[], int prefix[], size_t nr_routes,
825 char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt,
826 const char* dns_suffix, const unsigned int mtu) {
828 struct sockaddr_in local_addr;
829 struct sockaddr_in remote_addr;
830 struct ifreq ifr_tun;
832 int ret = VPNSVC_ERROR_NONE;
833 char buf[BUF_SIZE_FOR_ERR] = { 0 };
835 LOGD("enter vpn_daemon_up");
837 LOGD("iface_index : %d", iface_index);
838 LOGD("local ip : %s", local_ip);
839 LOGD("remote ip : %s", remote_ip);
840 LOGD("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);
843 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
845 LOGE("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
846 return VPNSVC_ERROR_IO_ERROR;
849 memset(&ifr_tun, 0, sizeof(ifr_tun));
850 ifr_tun.ifr_ifindex = iface_index;
852 /* get an interface name by ifindex */
853 if (ioctl(sk, SIOCGIFNAME, &ifr_tun) < 0) {
854 LOGE("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
856 return VPNSVC_ERROR_IO_ERROR;
859 /* local ip setting */
860 memset(&local_addr, 0, sizeof(local_addr));
861 local_addr.sin_addr.s_addr = inet_addr(local_ip); /* network byte order */
862 local_addr.sin_family = AF_INET;
863 memcpy(&ifr_tun.ifr_addr, &local_addr, sizeof(ifr_tun.ifr_addr));
864 if (ioctl(sk, SIOCSIFADDR, &ifr_tun) < 0) {
865 LOGE("ioctl SIOCSIFADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
867 return VPNSVC_ERROR_IO_ERROR;
870 /* remote ip setting */
871 memset(&remote_addr, 0, sizeof(remote_addr));
872 remote_addr.sin_addr.s_addr = inet_addr(remote_ip); /*network byte order*/
873 remote_addr.sin_family = AF_INET;
874 memcpy(&ifr_tun.ifr_dstaddr, &remote_addr, sizeof(ifr_tun.ifr_dstaddr));
875 if (ioctl(sk, SIOCSIFDSTADDR, &ifr_tun) < 0) {
876 LOGE("ioctl SIOCSIFDSTADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
878 return VPNSVC_ERROR_IO_ERROR;
881 /* set the flags for vpn up */
882 if (ioctl(sk, SIOCGIFFLAGS, &ifr_tun) < 0) {
883 LOGE("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
885 return VPNSVC_ERROR_IO_ERROR;
888 ifr_tun.ifr_flags |= IFF_UP;
889 ifr_tun.ifr_flags |= IFF_RUNNING;
891 if (ioctl(sk, SIOCSIFFLAGS, &ifr_tun) < 0) {
892 LOGE("ioctl SIOCSIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
894 return VPNSVC_ERROR_IO_ERROR;
898 if (ioctl(sk, SIOCGIFMTU, &ifr_tun) < 0) {
899 LOGE("ioctl SIOCGIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
901 return VPNSVC_ERROR_IO_ERROR;
904 if (mtu > 0 && ifr_tun.ifr_mtu != (int)mtu) {
905 ifr_tun.ifr_mtu = mtu;
906 if (ioctl(sk, SIOCSIFMTU, &ifr_tun) < 0) {
907 LOGE("ioctl SIOCSIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
909 return VPNSVC_ERROR_IO_ERROR;
917 ret = add_routes(ifr_tun.ifr_name, routes, prefix, nr_routes);
918 if (ret != VPNSVC_ERROR_NONE) {
919 LOGE("add_routes failed");
926 ret = add_dns_routes(ifr_tun.ifr_name, dns_servers, nr_dns);
927 if (ret != VPNSVC_ERROR_NONE) {
928 LOGE("add_dns failed");
934 /* add DNS servers */
936 ret = add_dns_servers(dns_servers, nr_dns, total_dns_string_cnt);
937 if (ret != VPNSVC_ERROR_NONE) {
938 LOGE("add_dns failed");
945 ret = add_dns_suffix(dns_suffix, strlen(dns_suffix));
946 if (ret != VPNSVC_ERROR_NONE) {
947 LOGE("add_dns_suffix failed");
953 dns_nat_register(dns_servers, nr_dns, local_ip);
962 int vpn_daemon_down(int iface_index)
964 struct ifreq ifr, addr_ifr;
965 struct sockaddr_in *addr = NULL;
967 char buf[BUF_SIZE_FOR_ERR] = { 0 };
969 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
971 LOGE("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
972 return VPNSVC_ERROR_IO_ERROR;
975 memset(&ifr, 0, sizeof(ifr));
976 ifr.ifr_ifindex = iface_index;
978 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
979 LOGE("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
981 return VPNSVC_ERROR_IO_ERROR;
984 if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
985 LOGE("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
987 return VPNSVC_ERROR_IO_ERROR;
990 memset(&addr_ifr, 0, sizeof(addr_ifr));
991 memcpy(&addr_ifr.ifr_name, &ifr.ifr_name, sizeof(ifr.ifr_name) - 1);
992 addr = (struct sockaddr_in *)&addr_ifr.ifr_addr;
993 addr->sin_family = AF_INET;
994 if (ioctl(sk, SIOCSIFADDR, &addr_ifr) < 0)
995 LOGD("ioctl SIOCSIFADDR (could not clear IP address) failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
997 if (!(ifr.ifr_flags & IFF_UP)) {
998 LOGD("Interface already down");
1000 return VPNSVC_ERROR_NONE;
1003 ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
1004 if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
1005 LOGE("ioctl SIOCSIFFLAGS (interface down) failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1007 return VPNSVC_ERROR_IO_ERROR;
1012 /* routes are will be removed automatically while down interfaces */
1013 /* remove dns servers */
1016 /* remove dns suffix */
1019 /* remove dns filter */
1020 dns_nat_unregister();
1022 return VPNSVC_ERROR_NONE;
1025 int vpn_daemon_block_networks(char* nets_vpn[], int prefix_vpn[], size_t nr_nets_vpn,
1026 char* nets_orig[], int prefix_orig[], size_t nr_nets_orig) {
1029 /* iptable chain regist */
1030 iptables_register();
1032 for (i = 0; i < nr_nets_vpn; i++) {
1033 LOGD("block[%d] ip/mask : %s/%d", i, nets_vpn[i], prefix_vpn[i]);
1034 iptables_add(nets_vpn[i], prefix_vpn[i]);
1037 for (i = 0; i < nr_nets_orig; i++) {
1038 LOGD("allow[%d] ip/mask : %s/%d", i, nets_orig[i], prefix_orig[i]);
1039 iptables_add_orig(nets_orig[i], prefix_orig[i]);
1042 return VPNSVC_ERROR_NONE;
1045 int vpn_daemon_unblock_networks(void)
1047 iptables_unregister();
1049 return VPNSVC_ERROR_NONE;