Add the vpn service
[platform/core/connectivity/net-config.git] / src / vpnsvc-internal.c
1 /*
2  * Network Configuration - VPN Service Internal Module
3  *
4  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20
21 #include <errno.h>
22 #include <net/route.h>
23 #include <glib.h>
24 #include <gio/gio.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/ioctl.h>
29 #include <sys/un.h>
30 #include <arpa/inet.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <linux/if.h>
34 #include <linux/if_tun.h>
35
36 #include "vpnsvc-internal.h"
37 #include "log.h"
38
39 #define BUF_SIZE_FOR_ERR 100
40
41 #define CONNMAN_SERVICE "net.connman"
42 #define CONNMAN_INTERFACE_MANAGER "net.connman.Manager"
43 #define CONNMAN_INTERFACE_SERVICE "net.connman.Service"
44
45
46 /* for iptables */
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 #if 0
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;";
63 #endif
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;";
65
66 typedef unsigned long int ipv4; /* Declare variable type for ipv4 net address. */
67
68 static GDBusConnection *global_connection = NULL;
69
70 static ipv4 make_mask(int prefix)
71 {
72         ipv4 mask = 0;
73         int i = 0;
74
75         for (i = prefix; i > 0; i--)
76                 mask += (ipv4) (1 << (32 - i));
77         return mask;
78 }
79
80 static in_addr_t host2net(ipv4 host)
81 {
82         in_addr_t net;
83
84         net = 0;
85
86         net |= (host & 0x000000FF) << 24;
87         net |= (host & 0x0000FF00) <<  8;
88         net |= (host & 0x00FF0000) >>  8;
89         net |= (host & 0xFF000000) >> 24;
90
91         return net;
92 }
93
94 static int add_routes(char* iface_name, char* routes[], int prefix[], size_t nr_routes)
95 {
96         struct rtentry rt;
97         struct sockaddr_in addr;
98         int sk;
99         unsigned int i = 0;
100         char buf[BUF_SIZE_FOR_ERR] = { 0 };
101
102         DBG("Enter add_routes");
103
104         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
105         if (sk < 0) {
106                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
107                 return VPNSVC_ERROR_IO_ERROR;
108         }
109
110         for (i = 0; i < nr_routes; i++) {
111                 memset(&rt, 0, sizeof(rt));
112                 rt.rt_flags = RTF_UP;
113
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));
118
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));
123
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));
130
131                 rt.rt_dev = iface_name;
132
133                 if (ioctl(sk, SIOCADDRT, &rt) < 0) {
134                         ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
135                         close(sk);
136                         return VPNSVC_ERROR_IO_ERROR;
137                 }
138         }
139
140         close(sk);
141
142         return VPNSVC_ERROR_NONE;
143 }
144
145 static int add_dns_routes(char* if_name, char** dns_servers, size_t nr_dns)
146 {
147         struct rtentry rt;
148         struct sockaddr_in addr;
149         int sk;
150         unsigned int i = 0;
151         char buf[BUF_SIZE_FOR_ERR] = { 0 };
152
153         DBG("Enter add_routes");
154
155         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
156         if (sk < 0) {
157                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
158                 return VPNSVC_ERROR_IO_ERROR;
159         }
160
161         for (i = 0; i < nr_dns; i++) {
162                 memset(&rt, 0, sizeof(rt));
163                 rt.rt_flags = RTF_UP;
164
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));
169
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));
174
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));
181
182                 rt.rt_dev = if_name;
183
184                 if (ioctl(sk, SIOCADDRT, &rt) < 0) {
185                         ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
186                         close(sk);
187                         return VPNSVC_ERROR_IO_ERROR;
188                 }
189         }
190
191         close(sk);
192
193         return VPNSVC_ERROR_NONE;
194 }
195
196 static void connman_connection_open(void)
197 {
198         if (global_connection == NULL) {
199                 GError *error = NULL;
200 #if !GLIB_CHECK_VERSION(2, 36, 0)
201                 g_type_init();
202 #endif
203
204                 global_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
205                 if (global_connection == NULL) {
206                         if (error != NULL) {
207                                 ERR("Error connman connection open: %s", error->message);
208                                 g_error_free(error);
209                         }
210                 }
211         }
212 }
213
214 static void connman_connection_close(GDBusConnection *connection)
215 {
216         if (connection)
217                 g_object_unref(connection);
218 }
219
220 static GVariant *connman_method_call(
221         GDBusConnection *connection, char *service, char *path,
222         char *interface, char *method, GVariant *params)
223 {
224         GError *error = NULL;
225         GVariant *message = NULL;
226
227         message = g_dbus_connection_call_sync(
228                 connection, service, path, interface, method, params,
229                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
230
231         if (message == NULL) {
232                 if (error != NULL) {
233                         ERR("error: g_dbus_connection_call_sync [%d: %s]", error->code, error->message);
234                         g_error_free(error);
235                 } else {
236                         ERR("error: g_dbus_connection_call_sync\n");
237                 }
238         }
239
240         return message;
241 }
242
243 static char *connman_default_profile(GDBusConnection *connection)
244 {
245         gchar *key = NULL;
246         GVariantIter *value = NULL;
247         GVariant *message = NULL;
248         GVariantIter *iter = NULL;
249         char *profile = NULL;
250
251         message = connman_method_call(connection, CONNMAN_SERVICE, "/",
252                                                                   CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
253
254         if (message) {
255                 g_variant_get(message, "(a(oa{sv}))", &iter);
256                 while (g_variant_iter_loop(iter, "(oa{sv})", &key, &value)) {
257                         profile = strdup(key);
258                         break;
259                 }
260
261                 if (value)
262                         g_variant_iter_free(value);
263                 if (key)
264                         g_free(key);
265
266                 g_variant_iter_free(iter);
267                 g_variant_unref(message);
268         }
269
270         return profile;
271 }
272
273 #if 0
274 static char *connman_get_items(GDBusConnection *connection, char *profile, const char *keystr)
275 {
276         GVariant *message = NULL;
277         GVariantIter *iter = NULL;
278         GVariantIter *next = NULL;
279         gchar *obj = NULL;
280         char *items = NULL;
281
282         message = connman_method_call(connection, CONNMAN_SERVICE, "/",
283                                                                   CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
284
285         if (message) {
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) {
289                                 GVariant *var;
290                                 gchar *key;
291
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;
296
297                                                 g_variant_get(var, "as", &iter_item);
298                                                 while (g_variant_iter_loop(iter_item, "s", &value)) {
299                                                         if (items) {
300                                                                 char *tmp_items;
301
302                                                                 tmp_items = (char *) malloc(strlen(items) + 1 + strlen(value) + 1);
303                                                                 if (items) {
304                                                                         snprintf(tmp_items, strlen(tmp_items), "%s,%s", items, value);
305                                                                         free(items);
306                                                                         items = tmp_items;
307                                                                 }
308                                                         } else {
309                                                                 items = strdup(value);
310                                                         }
311                                                 }
312                                                 g_variant_iter_free(iter_item);
313                                                 break;
314                                         }
315                                 }
316                                 break;
317                         }
318                 }
319                 g_variant_iter_free(iter);
320                 g_variant_unref(message);
321         }
322
323         return items;
324 }
325 #endif
326
327 static void connman_set_items(GDBusConnection *connection, char *profile,
328                                                           const char *keystr, char *items)
329 {
330         GVariant *message = NULL;
331         GVariantBuilder *builder = NULL;
332         GVariant *params = NULL;
333         char *strings = strdup(items);
334         char *addr = NULL;
335         char *temp = NULL;
336
337         builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
338         if ((addr = strtok_r(strings, ", ", &temp)) != NULL) {
339                 do {
340                         g_variant_builder_add(builder, "s", addr);
341                 } while ((addr = strtok_r(NULL, ", ", &temp)) != NULL);
342         }
343         free(strings);
344         params = g_variant_new("(sv)", keystr,
345                                                    g_variant_builder_end(builder));
346         g_variant_builder_unref(builder);
347
348         message = connman_method_call(connection, CONNMAN_SERVICE, profile,
349                                                                   CONNMAN_INTERFACE_SERVICE, "SetProperty", params);
350         if (message)
351                 g_variant_unref(message);
352
353 }
354
355 #if 0
356 static char *connman_get_nameservers(GDBusConnection *connection, char *profile)
357 {
358         return connman_get_items(connection, profile, "Nameservers");
359 }
360
361 static char *connman_get_nameservers_conf(GDBusConnection *connection, char *profile)
362 {
363         return connman_get_items(connection, profile, "Nameservers.Configuration");
364 }
365 #endif
366
367 static void connman_set_nameservers(GDBusConnection *connection, char *profile,
368                                                                         char *nameservers)
369 {
370         return connman_set_items(connection, profile,
371                                                          "Nameservers.Configuration", nameservers);
372 }
373
374 #if 0
375 static char *connman_get_domains(GDBusConnection *connection, char *profile)
376 {
377         return connman_get_items(connection, profile, "Domains");
378 }
379
380 static char *connman_get_domains_conf(GDBusConnection *connection, char *profile)
381 {
382         return connman_get_items(connection, profile, "Domains.Configuration");
383 }
384 #endif
385
386 static void connman_set_domains(GDBusConnection *connection, char *profile,
387                                                                         char *domains)
388 {
389         return connman_set_items(connection, profile,
390                                                          "Domains.Configuration", domains);
391 }
392
393 #if 0
394 static int add_dns_servers(char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt)
395 {
396         char *profile = NULL;
397         char *items = NULL;
398         char *org_items = NULL;
399         char *new_items = NULL;
400         unsigned int i = 0;
401
402         connman_connection_open();
403
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;
409         }
410
411         DBG("profile : %s\n", profile);
412
413         /* add name servers */
414         org_items = connman_get_nameservers(global_connection, profile);
415
416         if (org_items) {
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));
420                 if (items == NULL) {
421                         ERR("OOM while malloc\n");
422                         return VPNSVC_ERROR_OUT_OF_MEMORY;
423                 }
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]));
428                 }
429                 free(org_items);
430                 org_items = NULL;
431         } else {
432                 /* nr_dns = comma(,) count + end null char */
433                 items = (char *) calloc(total_dns_string_cnt + nr_dns, sizeof(char));
434                 if (items == NULL) {
435                         ERR("OOM while malloc\n");
436                         return VPNSVC_ERROR_OUT_OF_MEMORY;
437                 }
438                 for (i = 0 ; i < nr_dns ; i++) {
439                         strncat(items, dns_servers[i], strlen(dns_servers[i]));
440                         if (i != nr_dns - 1)
441                                 strncat(items, ",", 1);
442                 }
443         }
444
445         if (items) {
446                 DBG("adding DNS : %s\n", items);
447                 connman_set_nameservers(global_connection, profile, items);
448                 free(items);
449                 items = NULL;
450         }
451
452         /* print new DNSs */
453         new_items = connman_get_nameservers_conf(global_connection, profile);
454         DBG("new_dns : %s\n", new_items);
455
456         if (new_items)
457                 free(new_items);
458         free(profile);
459         return VPNSVC_ERROR_NONE;
460 }
461 #endif
462
463 static int del_dns_servers()
464 {
465         char *profile = NULL;
466
467         connman_connection_open();
468
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;
474         }
475
476         DBG("profile : %s", profile);
477
478         /* del name servers */
479         connman_set_nameservers(global_connection, profile, "");
480
481         if (profile)
482                 free(profile);
483
484         return VPNSVC_ERROR_NONE;
485 }
486
487 #if 0
488 static int add_dns_suffix(const char* dns_suffix, size_t dns_suffix_len)
489 {
490         char *profile = NULL;
491         char *items = NULL;
492         char *org_items = NULL;
493         char *new_items = NULL;
494
495         connman_connection_open();
496
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;
502         }
503
504         DBG("profile : %s", profile);
505
506         /* add name servers */
507         org_items = connman_get_domains(global_connection, profile);
508
509         if (org_items) {
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));
513                 if (items == NULL) {
514                         ERR("OOM while malloc");
515                         return VPNSVC_ERROR_OUT_OF_MEMORY;
516                 }
517                 strncpy(items, org_items, strlen(org_items));
518                 strncat(items, ",", 1);
519                 strncat(items, dns_suffix, dns_suffix_len);
520                 free(org_items);
521                 org_items = NULL;
522         } else {
523                 /* nr_dns = comma(,) count + end null char */
524                 items = (char *) calloc((dns_suffix_len + 1), sizeof(char));
525                 if (items == NULL) {
526                         ERR("OOM while malloc");
527                         return VPNSVC_ERROR_OUT_OF_MEMORY;
528                 }
529                 strncat(items, dns_suffix, dns_suffix_len);
530         }
531
532         if (items) {
533                 DBG("adding DNS suffix : %s\n", items);
534                 connman_set_domains(global_connection, profile, items);
535                 free(items);
536                 items = NULL;
537         }
538
539         /* print new domains */
540         new_items = connman_get_domains_conf(global_connection, profile);
541         DBG("new DNS suffix : %s\n", new_items);
542
543         if (new_items)
544                 free(new_items);
545
546         if (profile)
547                 free(profile);
548
549         return VPNSVC_ERROR_NONE;
550 }
551 #endif
552
553 static int del_dns_suffix()
554 {
555         char *profile = NULL;
556
557         connman_connection_open();
558
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;
564         }
565
566         DBG("profile : %s", profile);
567
568         /* del DNS suffix */
569         connman_set_domains(global_connection, profile, "");
570
571         if (profile)
572                 free(profile);
573
574         return VPNSVC_ERROR_NONE;
575 }
576
577
578 static void iptables_exec(char *cmdline)
579 {
580         FILE *fp = NULL;
581
582         fp = popen(cmdline, "r");
583
584         if (fp != NULL)
585                 pclose(fp);
586 }
587
588 #if 0
589 static void dns_nat_register(char **vpn_dns_address, size_t nr_dns, char *vpn_device_address)
590 {
591         int size = 0, i;
592         char buf[8192];
593
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);
598         size = strlen(buf);
599
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);
603                 size = strlen(buf);
604         }
605         DBG("iptable dns nat reg cmd : %s", buf);
606         iptables_exec(buf);
607 }
608 #endif
609
610 static void dns_nat_unregister(void)
611 {
612         int size = 0;
613         char buf[8192];
614
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);
619         size = strlen(buf);
620         DBG("iptable dns nat unreg cmd : %s", buf);
621         iptables_exec(buf);
622 }
623
624 static void iptables_register(void)
625 {
626         int size = 0;
627         char buf[8192], *filter;
628
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);
636         size = strlen(buf);
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);
645         iptables_exec(buf);
646 }
647
648 static void iptables_unregister(void)
649 {
650         int size = 0;
651         char buf[8192], *filter;
652
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);
658         size = strlen(buf);
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);
665         iptables_exec(buf);
666 }
667
668 static void iptables_rule(const char c, const char *addr, const int mask)
669 {
670         int size = 0;
671         char buf[4096];
672
673         snprintf(buf + size, sizeof(buf) - size, iptables_rule_fmt, iptables_cmd, c,
674                          iptables_filter_prefix, iptables_filter_out, 'd', addr, mask);
675         size = strlen(buf);
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);
679         iptables_exec(buf);
680 }
681
682 static void iptables_rule_interface(const char c, const char *addr, const int mask, const char *interface)
683 {
684         int size = 0;
685         char buf[4096];
686
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);
691         size = strlen(buf);
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);
697         iptables_exec(buf);
698 }
699
700 void iptables_add_orig(const char *addr, const int mask)
701 {
702         iptables_rule_interface('I', addr, mask, iptables_filter_interface_wlan);
703 }
704
705 void iptables_delete_orig(const char *addr, const int mask)
706 {
707         iptables_rule_interface('D', addr, mask, iptables_filter_interface_wlan);
708 }
709
710 void iptables_add(const char *addr, const int mask)
711 {
712         iptables_rule('I', addr, mask);
713 }
714
715 void iptables_delete(const char *addr, const int mask)
716 {
717         iptables_rule('D', addr, mask);
718 }
719
720 static int get_interface_index(const char *iface_name)
721 {
722         struct ifreq ifr;
723         int sk = 0;
724         char buf[BUF_SIZE_FOR_ERR] = { 0 };
725
726         DBG("enter get_interface_index, iface_name : %s", iface_name);
727
728         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
729         if (sk < 0) {
730                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
731                 return VPNSVC_ERROR_IO_ERROR;
732         }
733
734         memset(&ifr, 0, sizeof(ifr));
735
736         if (*iface_name)
737         strncpy(ifr.ifr_name, iface_name, strlen(iface_name));
738
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));
742                 close(sk);
743                 return VPNSVC_ERROR_IO_ERROR;
744         }
745
746         close(sk);
747
748         return ifr.ifr_ifindex;
749 }
750
751
752 int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpnsvc_tun_s *handle_s)
753 {
754         struct ifreq ifr;
755         size_t len = 0;
756         char buf[BUF_SIZE_FOR_ERR] = { 0 };
757
758         DBG("enter vpn_daemon_init, iface_name : %s, iface_name_len : %d, fd : %d\n", iface_name, iface_name_len, fd);
759
760         memset(&ifr, 0, sizeof(ifr));
761
762         /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
763         *               IFF_TAP   - TAP device
764         *
765         *               IFF_NO_PI - Do not provide packet information
766         */
767
768         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
769
770         if (*iface_name)
771                 strncpy(ifr.ifr_name, iface_name, iface_name_len);
772
773         DBG("before init, ifindex : %d", ifr.ifr_ifindex);
774
775         if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
776                 ERR("TUNSETIFF Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
777                 close(fd);
778                 return VPNSVC_ERROR_IO_ERROR;
779         }
780
781         if (ioctl(fd, TUNSETOWNER, 5000) < 0) {
782                 ERR("TUNSETOWNER Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
783                 close(fd);
784                 return VPNSVC_ERROR_IO_ERROR;
785         }
786
787         if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
788                 ERR("TUNSETPERSIST Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
789                 close(fd);
790                 return VPNSVC_ERROR_IO_ERROR;
791         }
792
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';
798
799         return VPNSVC_ERROR_NONE;
800 }
801
802 int vpn_service_deinit(const char* dev_name)
803 {
804         char buf[100];
805         FILE *fp = NULL;
806
807         snprintf(buf, sizeof(buf), "/usr/sbin/ip link del %s", dev_name);
808         DBG("link delete cmd : %s", buf);
809
810         fp = popen(buf, "r");
811         if (fp != NULL) {
812                 pclose(fp);
813                 return VPNSVC_ERROR_NONE;
814         } else {
815                 return VPNSVC_ERROR_IO_ERROR;
816         }
817 }
818
819 int vpn_service_protect(int socket_fd, const char* dev_name)
820 {
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);
824
825         ret = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE,
826                                         dev_name, strlen(dev_name));
827
828         if (ret < 0) {
829                 DBG("setsockopt failed : %d, %s", ret, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
830                 ret = VPNSVC_ERROR_IO_ERROR;
831         } else {
832                 ret = VPNSVC_ERROR_NONE;
833         }
834
835         return ret;
836 }
837
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) {
842
843         struct sockaddr_in local_addr;
844         struct sockaddr_in remote_addr;
845         struct ifreq ifr_tun;
846         int sk;
847         int ret = VPNSVC_ERROR_NONE;
848         char buf[BUF_SIZE_FOR_ERR] = { 0 };
849
850         DBG("enter vpn_daemon_up");
851
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);
856
857
858         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
859         if (sk < 0) {
860                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
861                 return VPNSVC_ERROR_IO_ERROR;
862         }
863
864         memset(&ifr_tun, 0, sizeof(ifr_tun));
865         ifr_tun.ifr_ifindex = iface_index;
866
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));
870                 close(sk);
871                 return VPNSVC_ERROR_IO_ERROR;
872         }
873
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));
881                 close(sk);
882                 return VPNSVC_ERROR_IO_ERROR;
883         }
884
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));
892                 close(sk);
893                 return VPNSVC_ERROR_IO_ERROR;
894         }
895
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));
899                 close(sk);
900                 return VPNSVC_ERROR_IO_ERROR;
901         }
902
903         ifr_tun.ifr_flags |= IFF_UP;
904         ifr_tun.ifr_flags |= IFF_RUNNING;
905
906         if (ioctl(sk, SIOCSIFFLAGS, &ifr_tun) < 0)  {
907                 ERR("ioctl SIOCSIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
908                 close(sk);
909                 return VPNSVC_ERROR_IO_ERROR;
910         }
911
912         /* mtu setting */
913         if (ioctl(sk, SIOCGIFMTU, &ifr_tun) < 0) {
914                 ERR("ioctl SIOCGIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
915                 close(sk);
916                 return VPNSVC_ERROR_IO_ERROR;
917         }
918
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));
923                         close(sk);
924                         return VPNSVC_ERROR_IO_ERROR;
925                 }
926         }
927
928         close(sk);
929
930         /* add routes */
931         if (nr_routes > 0) {
932                 ret = add_routes(ifr_tun.ifr_name, routes, prefix, nr_routes);
933                 if (ret != VPNSVC_ERROR_NONE) {
934                         ERR("add_routes failed");
935                         return ret;
936                 }
937         }
938
939         /* add DNS routes */
940         if (nr_dns > 0) {
941                 ret = add_dns_routes(ifr_tun.ifr_name, dns_servers, nr_dns);
942                 if (ret != VPNSVC_ERROR_NONE) {
943                         ERR("add_dns failed");
944                         return ret;
945                 }
946         }
947
948 #if 0
949         /* add DNS servers */
950         if (nr_dns > 0) {
951                 ret = add_dns_servers(dns_servers, nr_dns, total_dns_string_cnt);
952                 if (ret != VPNSVC_ERROR_NONE) {
953                         ERR("add_dns failed");
954                         return ret;
955                 }
956         }
957
958         /* add_dns_suffix */
959         if (dns_suffix) {
960                 ret = add_dns_suffix(dns_suffix, strlen(dns_suffix));
961                 if (ret != VPNSVC_ERROR_NONE) {
962                         ERR("add_dns_suffix failed");
963                         return ret;
964                 }
965         }
966
967         if (nr_dns > 0)
968                 dns_nat_register(dns_servers, nr_dns, local_ip);
969 #endif
970
971         return ret;
972 }
973
974
975
976 int vpn_service_down(int iface_index)
977 {
978         struct ifreq ifr, addr_ifr;
979         struct sockaddr_in *addr = NULL;
980         int sk;
981         char buf[BUF_SIZE_FOR_ERR] = { 0 };
982
983         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
984         if (sk < 0) {
985                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
986                 return VPNSVC_ERROR_IO_ERROR;
987         }
988
989         memset(&ifr, 0, sizeof(ifr));
990         ifr.ifr_ifindex = iface_index;
991
992         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
993                 ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
994                 close(sk);
995                 return VPNSVC_ERROR_IO_ERROR;
996         }
997
998         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
999                 ERR("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1000                 close(sk);
1001                 return VPNSVC_ERROR_IO_ERROR;
1002         }
1003
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));
1010
1011         if (!(ifr.ifr_flags & IFF_UP)) {
1012                 DBG("Interface already down");
1013                 close(sk);
1014                 return VPNSVC_ERROR_NONE;
1015         }
1016
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));
1020                 close(sk);
1021                 return VPNSVC_ERROR_IO_ERROR;
1022         }
1023
1024         close(sk);
1025
1026         /* routes are will be removed  automatically while down interfaces */
1027         /* remove dns servers */
1028         del_dns_servers();
1029
1030         /* remove dns suffix */
1031         del_dns_suffix();
1032
1033         /* remove dns filter */
1034         dns_nat_unregister();
1035
1036         return VPNSVC_ERROR_NONE;
1037 }
1038
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) {
1041         unsigned int i;
1042
1043         /* iptable chain regist */
1044         iptables_register();
1045
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]);
1049         }
1050
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]);
1054         }
1055
1056         return VPNSVC_ERROR_NONE;
1057 }
1058
1059 int vpn_service_unblock_networks(void)
1060 {
1061         iptables_unregister();
1062
1063         return VPNSVC_ERROR_NONE;
1064 }
1065