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