ae8baee28346e0e111b7da4375348c411e85764d
[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 #include "util.h"
39
40 #define BUF_SIZE_FOR_CMD 1024
41 #define BUF_SIZE_FOR_ERR 100
42
43 #define CONNMAN_SERVICE "net.connman"
44 #define CONNMAN_INTERFACE_MANAGER "net.connman.Manager"
45 #define CONNMAN_INTERFACE_SERVICE "net.connman.Service"
46
47
48 /* for iptables */
49 static char iptables_cmd[] = "/usr/sbin/iptables";
50 static char iptables_filter_prefix[] = "CAPI_VPN_SERVICE_";
51 static char iptables_filter_out[] = "OUTPUT";
52 static char iptables_filter_in[] = "INPUT";
53 static char iptables_filter_interface_wlan[] = "wlan0";
54 static char iptables_nat_chain_name[] = "CAPI_VPN_SERVICE_NAT_OUTPUT";
55
56 #define IPTABLES_FMT_CREATE_CHAIN "%s -N %s%s -w"
57 #define IPTABLES_FMT_APPEND_DROP_RULE "%s -A %s%s -j DROP -w"
58 #define IPTABLES_FMT_APPEND_RETURN_RULE "%s -A %s%s -j RETURN -w"
59 #define IPTABLES_FMT_INSERT_RULE "%s -I %s -j %s%s -w"
60 #define IPTABLES_FMT_DEL_RULE "%s -D %s -j %s%s -w"
61 #define IPTABLES_FMT_FLUSH_CHAIN "%s -F %s%s -w"
62 #define IPTABLES_FMT_DEL_CHAIN "%s -X %s%s -w"
63 #define IPTABLES_FMT_APPEND_ACCEPT_RULE "%s -%c %s%s -%c %s/%d -j ACCEPT -w"
64 #define IPTABLES_FMT_APPEND_ACCEPT_RULE_WITH_INTF "%s -%c %s%s -%c %s -%c %s/%d -j ACCEPT -w"
65 #define IPTABLES_FMT_DEL_RULE_FROM_NAT "%s -t nat -D %s -j %s -w"
66 #define IPTABLES_FMT_FLUSH_CHAIN_FROM_NAT "%s -t nat -F %s -w"
67 #define IPTABLES_FMT_DEL_CHAIN_FROM_NAT "%s -t nat -X %s -w"
68
69 /*static char iptables_usage_fmt[] = "%s -L %s%s -n -v -w;";*/
70 /* iptables -t nat -A CAPI_VPN_SERVICE_OUTPUT -p udp -d <vpn dns address> --dport 53 -j DNAT --to <vpn defice address:53> */
71
72 typedef unsigned long int ipv4; /* Declare variable type for ipv4 net address. */
73
74 static GDBusConnection *global_connection = NULL;
75
76 static ipv4 make_mask(int prefix)
77 {
78         ipv4 mask = 0;
79         int i = 0;
80
81         for (i = prefix; i > 0; i--)
82                 mask += (ipv4) (1 << (32 - i));
83         return mask;
84 }
85
86 static in_addr_t host2net(ipv4 host)
87 {
88         in_addr_t net;
89
90         net = 0;
91
92         net |= (host & 0x000000FF) << 24;
93         net |= (host & 0x0000FF00) <<  8;
94         net |= (host & 0x00FF0000) >>  8;
95         net |= (host & 0xFF000000) >> 24;
96
97         return net;
98 }
99
100 static void connman_connection_open(void)
101 {
102         if (global_connection == NULL) {
103                 GError *error = NULL;
104 #if !GLIB_CHECK_VERSION(2, 36, 0)
105                 g_type_init();
106 #endif
107
108                 global_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
109                 if (global_connection == NULL) {
110                         if (error != NULL) {
111                                 ERR("Error connman connection open: %s", error->message);
112                                 g_error_free(error);
113                         }
114                 }
115         }
116 }
117
118 static void connman_connection_close(GDBusConnection *connection)
119 {
120         if (connection)
121                 g_object_unref(connection);
122 }
123
124 static GVariant *connman_method_call(
125         GDBusConnection *connection, char *service, char *path,
126         char *interface, char *method, GVariant *params)
127 {
128         GError *error = NULL;
129         GVariant *message = NULL;
130
131         message = g_dbus_connection_call_sync(
132                 connection, service, path, interface, method, params,
133                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
134
135         if (message == NULL) {
136                 if (error != NULL) {
137                         ERR("error: g_dbus_connection_call_sync [%d: %s]", error->code, error->message);
138                         g_error_free(error);
139                 } else {
140                         ERR("error: g_dbus_connection_call_sync\n");
141                 }
142         }
143
144         return message;
145 }
146
147 static char *connman_default_profile(GDBusConnection *connection)
148 {
149         gchar *key = NULL;
150         GVariantIter *value = NULL;
151         GVariant *message = NULL;
152         GVariantIter *iter = NULL;
153         char *profile = NULL;
154
155         message = connman_method_call(connection, CONNMAN_SERVICE, "/",
156                                                                   CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
157
158         if (message) {
159                 g_variant_get(message, "(a(oa{sv}))", &iter);
160                 while (g_variant_iter_loop(iter, "(oa{sv})", &key, &value)) {
161                         profile = strdup(key);
162                         break;
163                 }
164
165                 if (value)
166                         g_variant_iter_free(value);
167                 if (key)
168                         g_free(key);
169
170                 g_variant_iter_free(iter);
171                 g_variant_unref(message);
172         }
173
174         return profile;
175 }
176
177 #if 0
178 static char *connman_get_items(GDBusConnection *connection, char *profile, const char *keystr)
179 {
180         GVariant *message = NULL;
181         GVariantIter *iter = NULL;
182         GVariantIter *next = NULL;
183         gchar *obj = NULL;
184         char *items = NULL;
185
186         message = connman_method_call(connection, CONNMAN_SERVICE, "/",
187                                                                   CONNMAN_INTERFACE_MANAGER, "GetServices", NULL);
188
189         if (message) {
190                 g_variant_get(message, "(a(oa{sv}))", &iter);
191                 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
192                         if (strcmp(obj, profile) == 0) {
193                                 GVariant *var;
194                                 gchar *key;
195
196                                 while (g_variant_iter_loop(next, "{sv}", &key, &var)) {
197                                         if (g_strcmp0(key, keystr) == 0) {
198                                                 GVariantIter *iter_item;
199                                                 const gchar *value = NULL;
200
201                                                 g_variant_get(var, "as", &iter_item);
202                                                 while (g_variant_iter_loop(iter_item, "s", &value)) {
203                                                         if (items) {
204                                                                 char *tmp_items;
205
206                                                                 tmp_items = (char *) malloc(strlen(items) + 1 + strlen(value) + 1);
207                                                                 if (items) {
208                                                                         snprintf(tmp_items, strlen(tmp_items), "%s,%s", items, value);
209                                                                         free(items);
210                                                                         items = tmp_items;
211                                                                 }
212                                                         } else {
213                                                                 items = strdup(value);
214                                                         }
215                                                 }
216                                                 g_variant_iter_free(iter_item);
217                                                 break;
218                                         }
219                                 }
220                                 break;
221                         }
222                 }
223                 g_variant_iter_free(iter);
224                 g_variant_unref(message);
225         }
226
227         return items;
228 }
229 #endif
230
231 static void connman_set_items(GDBusConnection *connection, char *profile,
232                                                           const char *keystr, char *items)
233 {
234         GVariant *message = NULL;
235         GVariantBuilder *builder = NULL;
236         GVariant *params = NULL;
237         char *strings = strdup(items);
238         char *addr = NULL;
239         char *temp = NULL;
240
241         builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
242         if ((addr = strtok_r(strings, ", ", &temp)) != NULL) {
243                 do {
244                         g_variant_builder_add(builder, "s", addr);
245                 } while ((addr = strtok_r(NULL, ", ", &temp)) != NULL);
246         }
247         free(strings);
248         params = g_variant_new("(sv)", keystr,
249                                                    g_variant_builder_end(builder));
250         g_variant_builder_unref(builder);
251
252         message = connman_method_call(connection, CONNMAN_SERVICE, profile,
253                                                                   CONNMAN_INTERFACE_SERVICE, "SetProperty", params);
254         if (message)
255                 g_variant_unref(message);
256
257 }
258
259 #if 0
260 static char *connman_get_nameservers(GDBusConnection *connection, char *profile)
261 {
262         return connman_get_items(connection, profile, "Nameservers");
263 }
264
265 static char *connman_get_nameservers_conf(GDBusConnection *connection, char *profile)
266 {
267         return connman_get_items(connection, profile, "Nameservers.Configuration");
268 }
269 #endif
270
271 static void connman_set_nameservers(GDBusConnection *connection, char *profile,
272                                                                         char *nameservers)
273 {
274         return connman_set_items(connection, profile,
275                                                          "Nameservers.Configuration", nameservers);
276 }
277
278 #if 0
279 static char *connman_get_domains(GDBusConnection *connection, char *profile)
280 {
281         return connman_get_items(connection, profile, "Domains");
282 }
283
284 static char *connman_get_domains_conf(GDBusConnection *connection, char *profile)
285 {
286         return connman_get_items(connection, profile, "Domains.Configuration");
287 }
288 #endif
289
290 static void connman_set_domains(GDBusConnection *connection, char *profile,
291                                                                         char *domains)
292 {
293         return connman_set_items(connection, profile,
294                                                          "Domains.Configuration", domains);
295 }
296
297 #if 0
298 static int add_dns_servers(char** dns_servers, size_t nr_dns, size_t total_dns_string_cnt)
299 {
300         char *profile = NULL;
301         char *items = NULL;
302         char *org_items = NULL;
303         char *new_items = NULL;
304         unsigned int i = 0;
305
306         connman_connection_open();
307
308         profile = connman_default_profile(global_connection);
309         if (profile == NULL) {
310                 ERR("connman_default_profile failed");
311                 connman_connection_close(global_connection);
312                 return VPNSVC_ERROR_IPC_FAILED;
313         }
314
315         DBG("profile : %s\n", profile);
316
317         /* add name servers */
318         org_items = connman_get_nameservers(global_connection, profile);
319
320         if (org_items) {
321                 DBG("original DNS : %s\n", org_items);
322                 /* nr_dns = comma(,) count */
323                 items = (char *) calloc((total_dns_string_cnt + nr_dns + strlen(org_items) + 1), sizeof(char));
324                 if (items == NULL) {
325                         ERR("OOM while malloc\n");
326                         return VPNSVC_ERROR_OUT_OF_MEMORY;
327                 }
328                 strncpy(items, org_items, strlen(org_items));
329                 for (i = 0 ; i < nr_dns ; i++) {
330                         strncat(items, ",", 1);
331                         strncat(items, dns_servers[i], strlen(dns_servers[i]));
332                 }
333                 free(org_items);
334                 org_items = NULL;
335         } else {
336                 /* nr_dns = comma(,) count + end null char */
337                 items = (char *) calloc(total_dns_string_cnt + nr_dns, sizeof(char));
338                 if (items == NULL) {
339                         ERR("OOM while malloc\n");
340                         return VPNSVC_ERROR_OUT_OF_MEMORY;
341                 }
342                 for (i = 0 ; i < nr_dns ; i++) {
343                         strncat(items, dns_servers[i], strlen(dns_servers[i]));
344                         if (i != nr_dns - 1)
345                                 strncat(items, ",", 1);
346                 }
347         }
348
349         if (items) {
350                 DBG("adding DNS : %s\n", items);
351                 connman_set_nameservers(global_connection, profile, items);
352                 free(items);
353                 items = NULL;
354         }
355
356         /* print new DNSs */
357         new_items = connman_get_nameservers_conf(global_connection, profile);
358         DBG("new_dns : %s\n", new_items);
359
360         if (new_items)
361                 free(new_items);
362         free(profile);
363         return VPNSVC_ERROR_NONE;
364 }
365 #endif
366
367 static int del_dns_servers()
368 {
369         char *profile = NULL;
370
371         connman_connection_open();
372
373         profile = connman_default_profile(global_connection);
374         if (profile == NULL) {
375                 ERR("connman_default_profile failed");
376                 connman_connection_close(global_connection);
377                 return VPNSVC_ERROR_IPC_FAILED;
378         }
379
380         DBG("profile : %s", profile);
381
382         /* del name servers */
383         connman_set_nameservers(global_connection, profile, "");
384
385         if (profile)
386                 free(profile);
387
388         return VPNSVC_ERROR_NONE;
389 }
390
391 #if 0
392 static int add_dns_suffix(const char* dns_suffix, size_t dns_suffix_len)
393 {
394         char *profile = NULL;
395         char *items = NULL;
396         char *org_items = NULL;
397         char *new_items = NULL;
398
399         connman_connection_open();
400
401         profile = connman_default_profile(global_connection);
402         if (profile == NULL) {
403                 ERR("connman_default_profile failed");
404                 connman_connection_close(global_connection);
405                 return VPNSVC_ERROR_IPC_FAILED;
406         }
407
408         DBG("profile : %s", profile);
409
410         /* add name servers */
411         org_items = connman_get_domains(global_connection, profile);
412
413         if (org_items) {
414                 DBG("original DNS suffix : %s", org_items);
415                 /* comma(,) and end null character included */
416                 items = (char *) calloc((dns_suffix_len + strlen(org_items) + 2), sizeof(char));
417                 if (items == NULL) {
418                         ERR("OOM while malloc");
419                         return VPNSVC_ERROR_OUT_OF_MEMORY;
420                 }
421                 strncpy(items, org_items, strlen(org_items));
422                 strncat(items, ",", 1);
423                 strncat(items, dns_suffix, dns_suffix_len);
424                 free(org_items);
425                 org_items = NULL;
426         } else {
427                 /* nr_dns = comma(,) count + end null char */
428                 items = (char *) calloc((dns_suffix_len + 1), sizeof(char));
429                 if (items == NULL) {
430                         ERR("OOM while malloc");
431                         return VPNSVC_ERROR_OUT_OF_MEMORY;
432                 }
433                 strncat(items, dns_suffix, dns_suffix_len);
434         }
435
436         if (items) {
437                 DBG("adding DNS suffix : %s\n", items);
438                 connman_set_domains(global_connection, profile, items);
439                 free(items);
440                 items = NULL;
441         }
442
443         /* print new domains */
444         new_items = connman_get_domains_conf(global_connection, profile);
445         DBG("new DNS suffix : %s\n", new_items);
446
447         if (new_items)
448                 free(new_items);
449
450         if (profile)
451                 free(profile);
452
453         return VPNSVC_ERROR_NONE;
454 }
455 #endif
456
457 static int del_dns_suffix()
458 {
459         char *profile = NULL;
460
461         connman_connection_open();
462
463         profile = connman_default_profile(global_connection);
464         if (profile == NULL) {
465                 ERR("connman_default_profile failed");
466                 connman_connection_close(global_connection);
467                 return VPNSVC_ERROR_IPC_FAILED;
468         }
469
470         DBG("profile : %s", profile);
471
472         /* del DNS suffix */
473         connman_set_domains(global_connection, profile, "");
474
475         if (profile)
476                 free(profile);
477
478         return VPNSVC_ERROR_NONE;
479 }
480
481 #if 0
482 static void dns_nat_register(char **vpn_dns_address, size_t nr_dns, char *vpn_device_address)
483 {
484         int size = 0, i;
485         char buf[8192];
486
487         snprintf(buf + size, sizeof(buf) - size, iptables_nat_register_init_fmt,
488                         iptables_cmd, iptables_nat_chain_name,
489                         iptables_cmd, iptables_nat_chain_name,
490                         iptables_cmd, iptables_filter_out, iptables_nat_chain_name);
491         size = strlen(buf);
492
493         for (i = 0 ; i < nr_dns ; i++) {
494                 snprintf(buf + size, sizeof(buf) - size, iptables_nat_register_rule_fmt,
495                                 iptables_cmd, iptables_nat_chain_name, vpn_dns_address[i], vpn_device_address);
496                 size = strlen(buf);
497         }
498         DBG("iptable dns nat reg cmd : %s", buf);
499         iptables_exec(buf);
500 }
501 #endif
502
503 static void dns_nat_unregister(void)
504 {
505         char buf[BUF_SIZE_FOR_CMD];
506
507         snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_RULE_FROM_NAT,
508                         iptables_cmd, iptables_filter_out, iptables_nat_chain_name);
509         if (netconfig_execute_cmd(buf))
510                 ERR("Failed to execute command: %s", buf);
511
512         memset(buf, '0', sizeof(buf));
513         snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN_FROM_NAT,
514                         iptables_cmd, iptables_nat_chain_name);
515         if (netconfig_execute_cmd(buf))
516                 ERR("Failed to execute command: %s", buf);
517
518         memset(buf, '0', sizeof(buf));
519         snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_CHAIN_FROM_NAT,
520                         iptables_cmd, iptables_nat_chain_name);
521         if (netconfig_execute_cmd(buf))
522                 ERR("Failed to execute command: %s", buf);
523 }
524
525 static void iptables_register(void)
526 {
527         char buf[BUF_SIZE_FOR_CMD] = {0, };
528         char *filter;
529
530         filter = iptables_filter_out;
531
532         snprintf(buf, sizeof(buf), IPTABLES_FMT_CREATE_CHAIN,
533                         iptables_cmd, iptables_filter_prefix, filter);
534         if (netconfig_execute_cmd(buf))
535                 ERR("Failed to execute command: %s", buf);
536
537         memset(buf, '0', sizeof(buf));
538         snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
539                         iptables_cmd, iptables_filter_prefix, filter);
540         if (netconfig_execute_cmd(buf))
541                 ERR("Failed to execute command: %s", buf);
542
543         memset(buf, '0', sizeof(buf));
544         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_DROP_RULE,
545                         iptables_cmd, iptables_filter_prefix, filter);
546         if (netconfig_execute_cmd(buf))
547                 ERR("Failed to execute command: %s", buf);
548
549         memset(buf, '0', sizeof(buf));
550         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_RETURN_RULE,
551                         iptables_cmd, iptables_filter_prefix, filter);
552         if (netconfig_execute_cmd(buf))
553                 ERR("Failed to execute command: %s", buf);
554
555         memset(buf, '0', sizeof(buf));
556         snprintf(buf, sizeof(buf), IPTABLES_FMT_INSERT_RULE,
557                         iptables_cmd, filter, iptables_filter_prefix, filter);
558
559         filter = iptables_filter_in;
560
561         memset(buf, '0', sizeof(buf));
562         snprintf(buf, sizeof(buf), IPTABLES_FMT_CREATE_CHAIN,
563                         iptables_cmd, iptables_filter_prefix, filter);
564         if (netconfig_execute_cmd(buf))
565                 ERR("Failed to execute command: %s", buf);
566
567         memset(buf, '0', sizeof(buf));
568         snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
569                         iptables_cmd, iptables_filter_prefix, filter);
570         if (netconfig_execute_cmd(buf))
571                 ERR("Failed to execute command: %s", buf);
572
573         memset(buf, '0', sizeof(buf));
574         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_DROP_RULE,
575                         iptables_cmd, iptables_filter_prefix, filter);
576         if (netconfig_execute_cmd(buf))
577                 ERR("Failed to execute command: %s", buf);
578
579         memset(buf, '0', sizeof(buf));
580         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_RETURN_RULE,
581                         iptables_cmd, iptables_filter_prefix, filter);
582         if (netconfig_execute_cmd(buf))
583                 ERR("Failed to execute command: %s", buf);
584
585         memset(buf, '0', sizeof(buf));
586         snprintf(buf, sizeof(buf), IPTABLES_FMT_INSERT_RULE,
587                         iptables_cmd, filter, iptables_filter_prefix, filter);
588 }
589
590 static void iptables_unregister(void)
591 {
592         char buf[BUF_SIZE_FOR_CMD] = {0, };
593         char *filter;
594
595         filter = iptables_filter_out;
596
597         snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_RULE,
598                         iptables_cmd, filter, iptables_filter_prefix, filter);
599         if (netconfig_execute_cmd(buf))
600                 ERR("Failed to execute command: %s", buf);
601
602         memset(buf, '0', sizeof(buf));
603         snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
604                         iptables_cmd, iptables_filter_prefix, filter);
605         if (netconfig_execute_cmd(buf))
606                 ERR("Failed to execute command: %s", buf);
607
608         memset(buf, '0', sizeof(buf));
609         snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_CHAIN,
610                         iptables_cmd, iptables_filter_prefix, filter);
611         if (netconfig_execute_cmd(buf))
612                 ERR("Failed to execute command: %s", buf);
613
614         filter = iptables_filter_in;
615
616         memset(buf, '0', sizeof(buf));
617         snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_RULE,
618                         iptables_cmd, filter, iptables_filter_prefix, filter);
619         if (netconfig_execute_cmd(buf))
620                 ERR("Failed to execute command: %s", buf);
621
622         memset(buf, '0', sizeof(buf));
623         snprintf(buf, sizeof(buf), IPTABLES_FMT_FLUSH_CHAIN,
624                         iptables_cmd, iptables_filter_prefix, filter);
625         if (netconfig_execute_cmd(buf))
626                 ERR("Failed to execute command: %s", buf);
627
628         memset(buf, '0', sizeof(buf));
629         snprintf(buf, sizeof(buf), IPTABLES_FMT_DEL_CHAIN,
630                         iptables_cmd, iptables_filter_prefix, filter);
631         if (netconfig_execute_cmd(buf))
632                 ERR("Failed to execute command: %s", buf);
633 }
634
635 static void iptables_rule(const char c, const char *addr, const int mask)
636 {
637         char buf[BUF_SIZE_FOR_CMD];
638
639         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE,
640                         iptables_cmd, c, iptables_filter_prefix,
641                         iptables_filter_out, 'd', addr, mask);
642         if (netconfig_execute_cmd(buf))
643                 ERR("Failed to execute command: %s", buf);
644
645         memset(buf, '0', sizeof(buf));
646         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE,
647                         iptables_cmd, c,  iptables_filter_prefix,
648                         iptables_filter_in, 's', addr, mask);
649         if (netconfig_execute_cmd(buf))
650                 ERR("Failed to execute command: %s", buf);
651 }
652
653 static void iptables_rule_interface(const char c, const char *addr, const int mask, const char *interface)
654 {
655         char buf[BUF_SIZE_FOR_CMD];
656
657         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE_WITH_INTF,
658                         iptables_cmd, c, iptables_filter_prefix, iptables_filter_out,
659                         'o', interface, 'd', addr, mask);
660         if (netconfig_execute_cmd(buf))
661                 ERR("Failed to execute command: %s", buf);
662
663         memset(buf, '0', sizeof(buf));
664         snprintf(buf, sizeof(buf), IPTABLES_FMT_APPEND_ACCEPT_RULE_WITH_INTF,
665                         iptables_cmd, c, iptables_filter_prefix, iptables_filter_in,
666                         'i', interface, 's', addr, mask);
667         if (netconfig_execute_cmd(buf))
668                 ERR("Failed to execute command: %s", buf);
669 }
670
671 void iptables_add_orig(const char *addr, const int mask)
672 {
673         iptables_rule_interface('I', addr, mask, iptables_filter_interface_wlan);
674 }
675
676 void iptables_delete_orig(const char *addr, const int mask)
677 {
678         iptables_rule_interface('D', addr, mask, iptables_filter_interface_wlan);
679 }
680
681 void iptables_add(const char *addr, const int mask)
682 {
683         iptables_rule('I', addr, mask);
684 }
685
686 void iptables_delete(const char *addr, const int mask)
687 {
688         iptables_rule('D', addr, mask);
689 }
690
691 static int get_interface_index(const char *iface_name)
692 {
693         struct ifreq ifr;
694         int sk = 0;
695         char buf[BUF_SIZE_FOR_ERR] = { 0 };
696
697         DBG("enter get_interface_index, iface_name : %s", iface_name);
698
699         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
700         if (sk < 0) {
701                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
702                 return VPNSVC_ERROR_IO_ERROR;
703         }
704
705         memset(&ifr, 0, sizeof(ifr));
706
707         if (*iface_name)
708                 strncpy(ifr.ifr_name, iface_name, IFNAMSIZ);
709
710         /* get an interface name by ifindex */
711         if (ioctl(sk, SIOCGIFINDEX, &ifr) < 0) {
712                 ERR("ioctl SIOCGIFINDEX failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
713                 close(sk);
714                 return VPNSVC_ERROR_IO_ERROR;
715         }
716
717         close(sk);
718
719         return ifr.ifr_ifindex;
720 }
721
722 static int check_interface_precondition(const char *iface_name)
723 {
724
725         int sk;
726         struct ifreq ifr_tun;
727         char buf[BUF_SIZE_FOR_ERR] = { 0 };
728
729         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
730         if (sk < 0) {
731                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
732                 return VPNSVC_ERROR_IO_ERROR;
733         }
734
735         memset(&ifr_tun, 0, sizeof(ifr_tun));
736         g_strlcpy((char *)ifr_tun.ifr_name, iface_name, sizeof(ifr_tun.ifr_name));
737
738         /* local ip */
739         if (ioctl(sk, SIOCGIFADDR, &ifr_tun) < 0) {
740                 ERR("Fail to get local IP address: %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
741                 close(sk);
742                 return VPNSVC_ERROR_INVALID_PARAMETER;
743         }
744
745         /* remote ip */
746         if (ioctl(sk, SIOCGIFDSTADDR, &ifr_tun) < 0) {
747                 ERR("Fail to get remote IP address: %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
748                 close(sk);
749                 return VPNSVC_ERROR_INVALID_PARAMETER;
750         }
751
752         close(sk);
753
754         return VPNSVC_ERROR_NONE;
755 }
756
757
758 int vpn_service_init(const char* iface_name, size_t iface_name_len, int fd, vpnsvc_tun_s *handle_s)
759 {
760         struct ifreq ifr;
761         size_t len = 0;
762         char buf[BUF_SIZE_FOR_ERR] = { 0 };
763
764         DBG("enter vpn_daemon_init, iface_name : %s, iface_name_len : %d, fd : %d\n", iface_name, iface_name_len, fd);
765
766         memset(&ifr, 0, sizeof(ifr));
767
768         /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
769         *               IFF_TAP   - TAP device
770         *
771         *               IFF_NO_PI - Do not provide packet information
772         */
773
774         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
775
776         if (*iface_name)
777                 strncpy(ifr.ifr_name, iface_name, iface_name_len);
778
779         DBG("before init, ifindex : %d", ifr.ifr_ifindex);
780
781         if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
782                 ERR("TUNSETIFF 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, TUNSETOWNER, 5000) < 0) {
788                 ERR("TUNSETOWNER Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
789                 close(fd);
790                 return VPNSVC_ERROR_IO_ERROR;
791         }
792
793         if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
794                 ERR("TUNSETPERSIST Failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
795                 close(fd);
796                 return VPNSVC_ERROR_IO_ERROR;
797         }
798
799         handle_s->fd = 0;   /* server fd does not meaning */
800         handle_s->index = get_interface_index(iface_name);
801         len = strlen(ifr.ifr_name);
802         strncpy(handle_s->name, ifr.ifr_name, len);
803         handle_s->name[len] = '\0';
804
805         return VPNSVC_ERROR_NONE;
806 }
807
808 int vpn_service_deinit(const char* dev_name)
809 {
810         char buf[100];
811
812         snprintf(buf, sizeof(buf), "/usr/sbin/ip link del %s", dev_name);
813
814         if (netconfig_execute_cmd(buf)) {
815                 ERR("Failed to execute command: %s", buf);
816                 return VPNSVC_ERROR_IO_ERROR;
817         }
818
819         return VPNSVC_ERROR_NONE;
820 }
821
822 int vpn_service_protect(int socket_fd, const char* dev_name)
823 {
824         int ret = VPNSVC_ERROR_NONE;
825         char buf[BUF_SIZE_FOR_ERR] = { 0 };
826         DBG("enter vpn_daemon_protect, socket : %d, dev_name : %s\n", socket_fd, dev_name);
827
828         ret = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE,
829                                         dev_name, strlen(dev_name));
830
831         if (ret < 0) {
832                 DBG("setsockopt failed : %d, %s", ret, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
833                 ret = VPNSVC_ERROR_IO_ERROR;
834         } else {
835                 ret = VPNSVC_ERROR_NONE;
836         }
837
838         return ret;
839 }
840
841 int vpn_service_up(const char *iface_name)
842 {
843         struct ifreq ifr_tun;
844         int sk;
845         int ret = VPNSVC_ERROR_NONE;
846         char buf[BUF_SIZE_FOR_ERR] = { 0 };
847
848         DBG("enter vpn_daemon_up");
849         DBG("iface_name : %s", iface_name);
850
851
852         ret = check_interface_precondition(iface_name);
853         if (ret != VPNSVC_ERROR_NONE)
854                 return ret;
855
856         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
857         if (sk < 0) {
858                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
859                 return VPNSVC_ERROR_IO_ERROR;
860         }
861
862         memset(&ifr_tun, 0, sizeof(ifr_tun));
863         g_strlcpy((char *)ifr_tun.ifr_name, iface_name, sizeof(ifr_tun.ifr_name));
864
865         /* set the flags for vpn up */
866         if (ioctl(sk, SIOCGIFFLAGS, &ifr_tun) < 0) {
867                 ERR("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
868                 close(sk);
869                 return VPNSVC_ERROR_IO_ERROR;
870         }
871
872         ifr_tun.ifr_flags |= IFF_UP;
873         ifr_tun.ifr_flags |= IFF_RUNNING;
874
875         if (ioctl(sk, SIOCSIFFLAGS, &ifr_tun) < 0)  {
876                 ERR("ioctl SIOCSIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
877                 close(sk);
878                 return VPNSVC_ERROR_IO_ERROR;
879         }
880
881         close(sk);
882
883 #if 0
884         /* add DNS servers */
885         if (nr_dns > 0) {
886                 ret = add_dns_servers(dns_servers, nr_dns, total_dns_string_cnt);
887                 if (ret != VPNSVC_ERROR_NONE) {
888                         ERR("add_dns failed");
889                         return ret;
890                 }
891         }
892
893         /* add_dns_suffix */
894         if (dns_suffix) {
895                 ret = add_dns_suffix(dns_suffix, strlen(dns_suffix));
896                 if (ret != VPNSVC_ERROR_NONE) {
897                         ERR("add_dns_suffix failed");
898                         return ret;
899                 }
900         }
901
902         if (nr_dns > 0)
903                 dns_nat_register(dns_servers, nr_dns, local_ip);
904 #endif
905
906         return ret;
907 }
908
909
910
911 int vpn_service_down(const char *iface_name)
912 {
913         struct ifreq ifr;
914         int sk;
915         char buf[BUF_SIZE_FOR_ERR] = { 0 };
916
917         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
918         if (sk < 0) {
919                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
920                 return VPNSVC_ERROR_IO_ERROR;
921         }
922
923         memset(&ifr, 0, sizeof(ifr));
924         g_strlcpy((char *)ifr.ifr_name, iface_name, sizeof(ifr.ifr_name));
925
926         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
927                 ERR("ioctl SIOCGIFFLAGS failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
928                 close(sk);
929                 return VPNSVC_ERROR_IO_ERROR;
930         }
931
932         if (!(ifr.ifr_flags & IFF_UP)) {
933                 DBG("Interface already down");
934                 close(sk);
935                 return VPNSVC_ERROR_NONE;
936         }
937
938         ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
939         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
940                 ERR("ioctl SIOCSIFFLAGS (interface down) failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
941                 close(sk);
942                 return VPNSVC_ERROR_IO_ERROR;
943         }
944
945         close(sk);
946
947         /* routes are will be removed  automatically while down interfaces */
948         /* remove dns servers */
949         del_dns_servers();
950
951         /* remove dns suffix */
952         del_dns_suffix();
953
954         /* remove dns filter */
955         dns_nat_unregister();
956
957         return VPNSVC_ERROR_NONE;
958 }
959
960 int vpn_service_block_networks(char* nets_vpn[], int prefix_vpn[], size_t nr_nets_vpn,
961                 char* nets_orig[], int prefix_orig[], size_t nr_nets_orig) {
962         unsigned int i;
963
964         /* iptable chain regist */
965         iptables_register();
966
967         for (i = 0; i < nr_nets_vpn; i++) {
968                 DBG("block[%d] ip/mask : %s/%d", i, nets_vpn[i], prefix_vpn[i]);
969                 iptables_add(nets_vpn[i], prefix_vpn[i]);
970         }
971
972         for (i = 0; i < nr_nets_orig; i++) {
973                 DBG("allow[%d] ip/mask : %s/%d", i, nets_orig[i], prefix_orig[i]);
974                 iptables_add_orig(nets_orig[i], prefix_orig[i]);
975         }
976
977         return VPNSVC_ERROR_NONE;
978 }
979
980 int vpn_service_unblock_networks(void)
981 {
982         iptables_unregister();
983
984         return VPNSVC_ERROR_NONE;
985 }
986
987 int vpn_service_update_settings(int iface_index, const char *local_ip,
988                 const char *remote_ip, const unsigned int mtu)
989 {
990         int sk;
991         struct ifreq ifr_tun;
992         struct sockaddr_in local_addr;
993         struct sockaddr_in remote_addr;
994         char buf[BUF_SIZE_FOR_ERR] = { 0 };
995
996         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
997         if (sk < 0) {
998                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
999                 return VPNSVC_ERROR_IO_ERROR;
1000         }
1001
1002         memset(&ifr_tun, 0, sizeof(ifr_tun));
1003         ifr_tun.ifr_ifindex = iface_index;
1004
1005         /* get an interface name by ifindex */
1006         if (ioctl(sk, SIOCGIFNAME, &ifr_tun) < 0) {
1007                 ERR("ioctl SIOCGIFNAME failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1008                 close(sk);
1009                 return VPNSVC_ERROR_IO_ERROR;
1010         }
1011
1012         /* local ip setting */
1013         memset(&local_addr, 0, sizeof(local_addr));
1014         local_addr.sin_addr.s_addr = inet_addr(local_ip); /* network byte order */
1015         local_addr.sin_family = AF_INET;
1016         memcpy(&ifr_tun.ifr_addr, &local_addr, sizeof(ifr_tun.ifr_addr));
1017         if (ioctl(sk, SIOCSIFADDR, &ifr_tun) < 0) {
1018                 ERR("ioctl SIOCSIFADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1019                 close(sk);
1020                 return VPNSVC_ERROR_IO_ERROR;
1021         }
1022
1023         /* remote ip setting */
1024         memset(&remote_addr, 0, sizeof(remote_addr));
1025         remote_addr.sin_addr.s_addr = inet_addr(remote_ip); /*network byte order*/
1026         remote_addr.sin_family = AF_INET;
1027         memcpy(&ifr_tun.ifr_dstaddr, &remote_addr, sizeof(ifr_tun.ifr_dstaddr));
1028         if (ioctl(sk, SIOCSIFDSTADDR, &ifr_tun) < 0) {
1029                 ERR("ioctl SIOCSIFDSTADDR failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1030                 close(sk);
1031                 return VPNSVC_ERROR_IO_ERROR;
1032         }
1033
1034         /* mtu setting */
1035         if (mtu > 0 && ifr_tun.ifr_mtu != (int)mtu) {
1036                 ifr_tun.ifr_mtu = mtu;
1037                 if (ioctl(sk, SIOCSIFMTU, &ifr_tun) < 0) {
1038                         ERR("ioctl SIOCSIFMTU failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1039                         close(sk);
1040                         return VPNSVC_ERROR_IO_ERROR;
1041                 }
1042         }
1043
1044         close(sk);
1045
1046         return VPNSVC_ERROR_NONE;
1047 }
1048
1049 int vpn_service_add_route(char *iface_name, const char *route, int prefix)
1050 {
1051         struct rtentry rt;
1052         struct sockaddr_in addr;
1053         int sk;
1054         char buf[BUF_SIZE_FOR_ERR] = { 0 };
1055
1056         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1057         if (sk < 0) {
1058                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1059                 return VPNSVC_ERROR_IO_ERROR;
1060         }
1061
1062         memset(&rt, 0, sizeof(rt));
1063         rt.rt_flags = RTF_UP;
1064
1065         memset(&addr, 0, sizeof(addr));
1066         addr.sin_family = AF_INET;
1067         addr.sin_addr.s_addr = inet_addr(route);
1068         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1069
1070         memset(&addr, 0, sizeof(addr));
1071         addr.sin_family = AF_INET;
1072         addr.sin_addr.s_addr = INADDR_ANY;
1073         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1074
1075         /* set mask using by prefix length */
1076         memset(&addr, 0, sizeof(addr));
1077         addr.sin_family = AF_INET;
1078         addr.sin_addr.s_addr = INADDR_ANY;
1079         addr.sin_addr.s_addr = host2net(make_mask(prefix));
1080         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1081
1082         rt.rt_dev = iface_name;
1083
1084         if (ioctl(sk, SIOCADDRT, &rt) < 0) {
1085                 ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1086                 close(sk);
1087                 return VPNSVC_ERROR_IO_ERROR;
1088         }
1089
1090         close(sk);
1091
1092         return VPNSVC_ERROR_NONE;
1093 }
1094
1095 int vpn_service_remove_route(char *iface_name, const char *route, int prefix)
1096 {
1097         struct rtentry rt;
1098         struct sockaddr_in addr;
1099         int sk;
1100         char buf[BUF_SIZE_FOR_ERR] = { 0 };
1101
1102         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1103         if (sk < 0) {
1104                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1105                 return VPNSVC_ERROR_IO_ERROR;
1106         }
1107
1108         memset(&rt, 0, sizeof(rt));
1109         rt.rt_flags = RTF_UP;
1110
1111         memset(&addr, 0, sizeof(addr));
1112         addr.sin_family = AF_INET;
1113         addr.sin_addr.s_addr = inet_addr(route);
1114         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1115
1116         memset(&addr, 0, sizeof(addr));
1117         addr.sin_family = AF_INET;
1118         addr.sin_addr.s_addr = INADDR_ANY;
1119         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1120
1121         /* set mask using by prefix length */
1122         memset(&addr, 0, sizeof(addr));
1123         addr.sin_family = AF_INET;
1124         addr.sin_addr.s_addr = INADDR_ANY;
1125         addr.sin_addr.s_addr = host2net(make_mask(prefix));
1126         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1127
1128         rt.rt_dev = iface_name;
1129
1130         if (ioctl(sk, SIOCDELRT, &rt) < 0) {
1131                 ERR("ioctl SIOCDERLT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1132                 close(sk);
1133                 return VPNSVC_ERROR_IO_ERROR;
1134         }
1135
1136         close(sk);
1137
1138         return VPNSVC_ERROR_NONE;
1139
1140 }
1141
1142 int vpn_service_add_dns_server(char *iface_name, const char *dns_server)
1143 {
1144         struct rtentry rt;
1145         struct sockaddr_in addr;
1146         int sk;
1147         char buf[BUF_SIZE_FOR_ERR] = { 0 };
1148
1149         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1150         if (sk < 0) {
1151                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1152                 return VPNSVC_ERROR_IO_ERROR;
1153         }
1154
1155         memset(&rt, 0, sizeof(rt));
1156         rt.rt_flags = RTF_UP;
1157
1158         memset(&addr, 0, sizeof(addr));
1159         addr.sin_family = AF_INET;
1160         addr.sin_addr.s_addr = inet_addr(dns_server);
1161         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1162
1163         memset(&addr, 0, sizeof(addr));
1164         addr.sin_family = AF_INET;
1165         addr.sin_addr.s_addr = INADDR_ANY;
1166         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1167
1168         /* set mask using by prefix length */
1169         memset(&addr, 0, sizeof(addr));
1170         addr.sin_family = AF_INET;
1171         addr.sin_addr.s_addr = INADDR_ANY;
1172         addr.sin_addr.s_addr = host2net(make_mask(32));
1173         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1174
1175         rt.rt_dev = iface_name;
1176
1177         if (ioctl(sk, SIOCADDRT, &rt) < 0) {
1178                 ERR("ioctl SIOCADDRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1179                 close(sk);
1180                 return VPNSVC_ERROR_IO_ERROR;
1181         }
1182
1183         close(sk);
1184
1185         return VPNSVC_ERROR_NONE;
1186 }
1187
1188 int vpn_service_remove_dns_server(char *iface_name, const char *dns_server)
1189 {
1190         struct rtentry rt;
1191         struct sockaddr_in addr;
1192         int sk;
1193         char buf[BUF_SIZE_FOR_ERR] = { 0 };
1194
1195         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1196         if (sk < 0) {
1197                 ERR("socket failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1198                 return VPNSVC_ERROR_IO_ERROR;
1199         }
1200
1201         memset(&rt, 0, sizeof(rt));
1202         rt.rt_flags = RTF_UP;
1203
1204         memset(&addr, 0, sizeof(addr));
1205         addr.sin_family = AF_INET;
1206         addr.sin_addr.s_addr = inet_addr(dns_server);
1207         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
1208
1209         memset(&addr, 0, sizeof(addr));
1210         addr.sin_family = AF_INET;
1211         addr.sin_addr.s_addr = INADDR_ANY;
1212         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
1213
1214         /* set mask using by prefix length */
1215         memset(&addr, 0, sizeof(addr));
1216         addr.sin_family = AF_INET;
1217         addr.sin_addr.s_addr = INADDR_ANY;
1218         addr.sin_addr.s_addr = host2net(make_mask(32));
1219         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
1220
1221         rt.rt_dev = iface_name;
1222
1223         if (ioctl(sk, SIOCDELRT, &rt) < 0) {
1224                 ERR("ioctl SIOCDELRT failed : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
1225                 close(sk);
1226                 return VPNSVC_ERROR_IO_ERROR;
1227         }
1228
1229         close(sk);
1230
1231         return VPNSVC_ERROR_NONE;
1232 }