Remove unrechable codes
[platform/core/api/vpn-service.git] / src / capi_vpn_service.c
1 /*
2  * VPN Service 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 #include "capi_vpn_service_private.h"
21 #include <app.h>
22 #include <app_info.h>
23 #include <system_info.h>
24 #include <gio/gunixfdlist.h>
25
26 #ifdef LOG_TAG
27 #undef LOG_TAG
28 #endif
29 #define LOG_TAG "CAPI_VPNSVC"
30
31 #define DBUS_REPLY_TIMEOUT (120 * 1000)
32 #define BUF_SIZE_FOR_ERR 100
33 #define MAX_NUM_ROUTES 255
34
35 GVariant *op = NULL;
36
37 static __thread GSList *vpn_handle_list = NULL;
38 static __thread bool is_feature_checked = false;
39 static __thread bool feature_supported = false;
40
41 int _vpnsvc_check_feature_supported(const char *feature_name)
42 {
43         if (is_feature_checked) {
44                 if (!feature_supported) {
45                         LOGE("%s feature is disabled", feature_name);
46                         return VPNSVC_ERROR_NOT_SUPPORTED;
47                 }
48         } else {
49                 if (!system_info_get_platform_bool(feature_name, &feature_supported)) {
50                         is_feature_checked = true;
51                         if (!feature_supported) {
52                                 LOGE("%s feature is disabled", feature_name);
53                                 return VPNSVC_ERROR_NOT_SUPPORTED;
54                         }
55                 } else {
56                         LOGE("Error - Feature getting from System Info");
57                         return VPNSVC_ERROR_IO_ERROR;
58                 }
59         }
60
61         return VPNSVC_ERROR_NONE;
62 }
63
64 static bool _vpn_check_handle_validity(vpnsvc_h vpnsvc)
65 {
66         if (vpnsvc == NULL)
67                 return false;
68
69         if (g_slist_find(vpn_handle_list, vpnsvc) != NULL)
70                 return true;
71         else
72                 return false;
73 }
74
75 static bool _vpn_check_ip_address_validity(const char *addr)
76 {
77         if(strlen(addr) < VPNSVC_IP4_MIN_STRING_LEN
78                         || strlen(addr) > VPNSVC_IP4_MAX_STRING_LEN)
79                 return false;
80
81         return true;
82 }
83
84 static void _vpnsvc_init_vpnsvc_tun_s(vpnsvc_tun_s **s)
85 {
86         LOGD(" tun_s: %p", s);
87
88         if (s == NULL) return;
89         if (*s != NULL) {
90                 LOGE("Can't Initialize vpnsvc_tun_s: %p", *s);
91                 return;
92         }
93         *s = (vpnsvc_tun_s*)g_malloc0(sizeof(vpnsvc_tun_s));
94
95         if ((*s)->connection == NULL) {
96                 GDBusConnection *connection = NULL;
97                 GError* error = NULL;
98
99 #if !GLIB_CHECK_VERSION(2, 36, 0)
100                 g_type_init();
101 #endif
102
103                 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
104                 if (error != NULL) {
105                         LOGE("Error creating Connection: %s", error->message);
106                         g_error_free(error);
107                 } else {
108                         LOGD("Created Connection: %p", connection);
109                         (*s)->connection = connection;
110                 }
111         }
112
113         /* Setting Default User Settings */
114         (*s)->index = 0;
115         (*s)->mtu = _USER_SETTING_DEFAULT_MTU;
116         strncpy((*s)->session, _USER_SETTING_DEFAULT_SESSION, VPNSVC_SESSION_STRING_LEN);
117         (*s)->session[VPNSVC_SESSION_STRING_LEN-1] = '\0';
118         (*s)->dns_suffix = NULL;
119 }
120
121 static void _vpnsvc_deinit_vpnsvc_tun_s(vpnsvc_tun_s *s)
122 {
123         if (s == NULL) return;
124
125         if (s->connection)
126                 s->connection = NULL;
127
128         s->fd = 0;
129         s->index = 0;
130         s->mtu = 0;
131
132         memset(s->name, 0, VPNSVC_VPN_IFACE_NAME_LEN);
133         memset(s->session, 0, VPNSVC_SESSION_STRING_LEN);
134         memset(s->local_ip, 0, VPNSVC_IP4_STRING_LEN);
135         memset(s->remote_ip, 0, VPNSVC_IP4_STRING_LEN);
136
137         if (s->dns_suffix) {
138                 g_free(s->dns_suffix);
139                 s->dns_suffix = NULL;
140         }
141
142         if (s)
143                 g_free(s);
144 }
145
146 /*****************************************************************************
147 * Global Functions Definition
148 *****************************************************************************/
149 GVariant *_vpnsvc_invoke_dbus_method(GDBusConnection *connection,
150                 const char *dest, const char *path,
151                 const char *interface_name, const char *method,
152                 GVariant *params, int *dbus_error)
153 {
154         GError *error = NULL;
155         GVariant *reply = NULL;
156         *dbus_error = VPNSVC_ERROR_NONE;
157
158         LOGD("Method Call() dest=%s path=%s iface=%s method=%s", dest, path, interface_name, method);
159
160         if (connection == NULL) {
161                 LOGD("GDBusconnection is NULL");
162                 *dbus_error = VPNSVC_ERROR_IO_ERROR;
163                 return reply;
164         }
165
166         reply = g_dbus_connection_call_sync(connection,
167                                                                                 dest,
168                                                                                 path,
169                                                                                 interface_name,
170                                                                                 method,
171                                                                                 params,
172                                                                                 NULL,
173                                                                                 G_DBUS_CALL_FLAGS_NONE,
174                                                                                 DBUS_REPLY_TIMEOUT,
175                                                                                 NULL,
176                                                                                 &error);
177
178         if (reply == NULL) {
179                 if (error != NULL) {
180                         LOGE("g_dbus_connection_call_sync() failed "
181                                 "error [%d: %s]", error->code, error->message);
182                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED)
183                                 *dbus_error = VPNSVC_ERROR_PERMISSION_DENIED;
184                         else
185                                 *dbus_error = VPNSVC_ERROR_IO_ERROR;
186                         g_error_free(error);
187                 } else {
188                         LOGE("g_dbus_connection_call_sync() failed");
189                         *dbus_error = VPNSVC_ERROR_IPC_FAILED;
190                 }
191
192                 return NULL;
193         }
194
195         return reply;
196 }
197 GVariant *_vpnsvc_invoke_dbus_method_with_fd(GDBusConnection *connection,
198         const char *dest, const char *path,
199         const char *interface_name, const char *method,
200         GVariant *params, int fd, int *dbus_error)
201 {
202         GError *error = NULL;
203         GVariant *reply = NULL;
204         GUnixFDList *fd_list = NULL;
205         *dbus_error = VPNSVC_ERROR_NONE;
206
207         LOGD("Method Call() dest=%s path=%s iface=%s method=%s fd=%d", dest, path, interface_name, method, fd);
208
209         if (connection == NULL) {
210                 LOGD("GDBusconnection is NULL");
211                 *dbus_error = VPNSVC_ERROR_IO_ERROR;
212                 return reply;
213         }
214
215         /* Setting the fd_list */
216         fd_list = g_unix_fd_list_new();
217         if (fd_list == NULL) {
218                 LOGE("g_unix_fd_list_new() failed!");
219                 return NULL;
220         }
221
222         g_unix_fd_list_append(fd_list, fd, &error);
223         if (error != NULL) {
224                 LOGE("g_unix_fd_list_append() failed"
225                                 "error [%d: %s]", error->code, error->message);
226                 *dbus_error = VPNSVC_ERROR_IO_ERROR;
227                 g_error_free(error);
228                 return NULL;
229         }
230
231         reply = g_dbus_connection_call_with_unix_fd_list_sync(connection,
232                                                                                                                 dest,
233                                                                                                                 path,
234                                                                                                                 interface_name,
235                                                                                                                 method,
236                                                                                                                 params,
237                                                                                                                 NULL,
238                                                                                                                 G_DBUS_CALL_FLAGS_NONE,
239                                                                                                                 DBUS_REPLY_TIMEOUT,
240                                                                                                                 fd_list,
241                                                                                                                 NULL,
242                                                                                                                 NULL,
243                                                                                                                 &error);
244
245         if (reply == NULL) {
246                 if (error != NULL) {
247                         LOGE("g_dbus_connection_call_with_unix_fd_list_sync() failed "
248                                         "error [%d: %s]", error->code, error->message);
249                         if (error->code == G_DBUS_ERROR_ACCESS_DENIED)
250                                 *dbus_error = VPNSVC_ERROR_PERMISSION_DENIED;
251                         else
252                                 *dbus_error = VPNSVC_ERROR_IO_ERROR;
253                         g_error_free(error);
254                 } else {
255                         LOGE("g_dbus_connection_call_with_unix_fd_list_sync() failed");
256                         *dbus_error = VPNSVC_ERROR_IPC_FAILED;
257                 }
258
259                 return NULL;
260         }
261
262         return reply;
263 }
264
265 EXPORT_API int vpnsvc_create(vpnsvc_h *handle)
266 {
267         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
268
269         LOGD("enter vpnsvc_create");
270
271         /* parameter check */
272         if (handle == NULL) {
273                 LOGE("handle is a NULL");
274                 return VPNSVC_ERROR_INVALID_PARAMETER;
275         }
276
277         if (_vpn_check_handle_validity(*handle)) {
278                 LOGE("Invalid parameter");
279                 return VPNSVC_ERROR_INVALID_PARAMETER;
280         }
281
282         vpnsvc_tun_s *tmp_s = NULL;
283         _vpnsvc_init_vpnsvc_tun_s(&tmp_s);
284         *handle = tmp_s;
285         LOGD("handle : %p", (*handle));
286
287         return VPNSVC_ERROR_NONE;
288 }
289
290 EXPORT_API int vpnsvc_destroy(vpnsvc_h handle)
291 {
292         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
293
294         int result = VPNSVC_ERROR_NONE;
295         vpnsvc_tun_s *tun_s = NULL;
296
297         /* parameter check */
298         if (handle == NULL) {
299                 LOGE("handle is a NULL");
300                 return VPNSVC_ERROR_INVALID_PARAMETER;
301         }
302         tun_s = (vpnsvc_tun_s*)handle;
303
304         LOGD("enter vpnsvc_destroy");
305
306         _vpnsvc_deinit_vpnsvc_tun_s(tun_s);
307
308         return result;
309 }
310
311 EXPORT_API int vpnsvc_init(const char* iface_name, vpnsvc_h *handle)
312 {
313         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
314
315         int result = VPNSVC_ERROR_NONE;
316         int dbus_result;
317         int iface_fd = 0;
318
319         LOGD("enter vpnsvc_init, iface_name : %s", iface_name);
320
321         /* parameter check */
322         if (iface_name == NULL || strlen(iface_name) <= 0) {
323                 LOGE("iface_name is a NULL");
324                 return VPNSVC_ERROR_INVALID_PARAMETER;
325         } else if (handle == NULL || _vpn_check_handle_validity(*handle)) {
326                 LOGE("Invalid parameter");
327                 return VPNSVC_ERROR_INVALID_PARAMETER;
328         }
329
330         vpnsvc_tun_s *tmp_s = NULL;
331         _vpnsvc_init_vpnsvc_tun_s(&tmp_s);
332
333         if ((iface_fd = open("/dev/net/tun", O_RDWR)) < 0) {
334                 LOGE("tun device open fail\n");
335                 _vpnsvc_deinit_vpnsvc_tun_s(tmp_s);
336                 return VPNSVC_ERROR_IO_ERROR;
337         }
338
339         LOGD("client iface_fd : %d", iface_fd);
340
341         op = _vpnsvc_invoke_dbus_method(tmp_s->connection,
342                                                         NETCONFIG_SERVICE_NAME,
343                                                         NETCONFIG_NETWORK_PATH,
344                                                         NETCONFIG_NETWORK_INTERFACE,
345                                                         "CheckInternetPrivilege",
346                                                         NULL,
347                                                         &dbus_result);
348
349         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED) {
350                 close(iface_fd);
351                 _vpnsvc_deinit_vpnsvc_tun_s(tmp_s);
352                 return VPNSVC_ERROR_PERMISSION_DENIED;
353         }
354
355         op = _vpnsvc_invoke_dbus_method_with_fd(tmp_s->connection,
356                                                         NETCONFIG_SERVICE_NAME,
357                                                         NETCONFIG_VPNSVC_PATH,
358                                                         NETCONFIG_VPNSVC_INTERFACE_NAME,
359                                                         "vpn_init",
360                                                         g_variant_new("(su)", iface_name, strlen(iface_name)),
361                                                         iface_fd,
362                                                         &dbus_result);
363
364         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED) {
365                 close(iface_fd);
366                 _vpnsvc_deinit_vpnsvc_tun_s(tmp_s);
367                 return VPNSVC_ERROR_PERMISSION_DENIED;
368         }
369
370         if (op == NULL) {
371                 close(iface_fd);
372                 _vpnsvc_deinit_vpnsvc_tun_s(tmp_s);
373                 return VPNSVC_ERROR_IPC_FAILED;
374         } else {
375                 int tmp_index;
376                 char* tmp_name;
377
378                 g_variant_get(op, "(iis)", &result, &tmp_index, &tmp_name);
379                 if (result != VPNSVC_ERROR_NONE) {
380                         LOGE("vpnsvc_init() failed");
381                         close(iface_fd);
382                         _vpnsvc_deinit_vpnsvc_tun_s(tmp_s);
383                         result = VPNSVC_ERROR_PERMISSION_DENIED;
384                 } else {
385                         LOGD("vpnsvc_init() succeed");
386                         tmp_s->fd = iface_fd;   /* client fd must be set */
387                         tmp_s->index = tmp_index;
388                         strncpy(tmp_s->name, tmp_name, VPNSVC_VPN_IFACE_NAME_LEN);
389                         tmp_s->name[VPNSVC_VPN_IFACE_NAME_LEN-1] = '\0';
390                         *handle = tmp_s;
391                         vpn_handle_list = g_slist_prepend(vpn_handle_list, *handle);
392                         LOGD("handle : %p, handle->fd : %d, handle->index : %d, handle->name : %s",
393                                 (*handle), ((vpnsvc_tun_s*)*handle)->fd, ((vpnsvc_tun_s*)*handle)->index, ((vpnsvc_tun_s*)*handle)->name);
394                 }
395                 if (op) {
396                         g_variant_unref(op);
397                         op = NULL;
398                 }
399         }
400         return result;
401 }
402
403 EXPORT_API int vpnsvc_deinit(vpnsvc_h handle)
404 {
405         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
406
407         int result = VPNSVC_ERROR_NONE;
408         int dbus_result;
409         vpnsvc_tun_s *tun_s = NULL;
410         char buf[BUF_SIZE_FOR_ERR] = { 0 };
411
412         /* parameter check */
413         if (handle == NULL) {
414                 LOGE("handle is a NULL");
415                 return VPNSVC_ERROR_INVALID_PARAMETER;
416         }
417         tun_s = (vpnsvc_tun_s*)handle;
418
419         LOGD("enter vpnsvc_deinit, iface_fd : %d", tun_s->fd);
420
421         if (tun_s->fd > 0) {
422                 op = _vpnsvc_invoke_dbus_method(tun_s->connection,
423                                                                         NETCONFIG_SERVICE_NAME,
424                                                                         NETCONFIG_NETWORK_PATH,
425                                                                         NETCONFIG_NETWORK_INTERFACE,
426                                                                         "CheckInternetPrivilege",
427                                                                         NULL,
428                                                                         &dbus_result);
429
430                 if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
431                         return VPNSVC_ERROR_PERMISSION_DENIED;
432
433                 op = _vpnsvc_invoke_dbus_method(tun_s->connection,
434                                                                         NETCONFIG_SERVICE_NAME,
435                                                                         NETCONFIG_VPNSVC_PATH,
436                                                                         NETCONFIG_VPNSVC_INTERFACE_NAME,
437                                                                         "vpn_deinit",
438                                                                         g_variant_new("(s)", tun_s->name),
439                                                                         &dbus_result);
440
441                 if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
442                         return VPNSVC_ERROR_PERMISSION_DENIED;
443
444                 if (op == NULL) {
445                         return VPNSVC_ERROR_IPC_FAILED;
446                 } else {
447                         g_variant_get(op, "(i)", &result);
448                         if (result != VPNSVC_ERROR_NONE)
449                                 LOGE("vpn_deinit() failed");
450                         else
451                                 LOGD("vpn_deinit() succeed");
452                 }
453
454                 if (close(tun_s->fd) != 0) {
455                         LOGE("tun fd close : %s", strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
456                         return VPNSVC_ERROR_IO_ERROR;
457                 } else
458                         LOGD("tun fd close success");
459
460                 /* free allocared handle memory */
461                 vpn_handle_list = g_slist_remove(vpn_handle_list, tun_s);
462                 _vpnsvc_deinit_vpnsvc_tun_s(tun_s);
463         }
464
465         return result;
466 }
467
468 EXPORT_API int vpnsvc_protect(vpnsvc_h handle, int socket_fd, const char* iface_name)
469 {
470         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
471
472         int result = VPNSVC_ERROR_NONE;
473         int dbus_result;
474         vpnsvc_tun_s *tun_s = NULL;
475
476         /* parameter check */
477         if (handle == NULL || socket_fd < 0 || iface_name == NULL)
478                 return VPNSVC_ERROR_INVALID_PARAMETER;
479
480         tun_s = (vpnsvc_tun_s*)handle;
481
482         LOGD("enter vpnsvc_protect, socket : %d, dev_name : %s", socket_fd, iface_name);
483
484         if (tun_s->connection == NULL) {
485                 LOGE("Connection Object is NULL");
486                 return VPNSVC_ERROR_INVALID_PARAMETER;
487         }
488
489         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
490                                                 NETCONFIG_SERVICE_NAME,
491                                                 NETCONFIG_NETWORK_PATH,
492                                                 NETCONFIG_NETWORK_INTERFACE,
493                                                 "CheckInternetPrivilege",
494                                                 NULL,
495                                                 &dbus_result);
496
497         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
498                 return VPNSVC_ERROR_PERMISSION_DENIED;
499
500         /* call vpnsvc_protect */
501         op = _vpnsvc_invoke_dbus_method_with_fd(tun_s->connection,
502                                                 NETCONFIG_SERVICE_NAME,
503                                                 NETCONFIG_VPNSVC_PATH,
504                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
505                                                 "vpn_protect",
506                                                 g_variant_new("(s)", iface_name),
507                                                 socket_fd,
508                                                 &dbus_result);
509
510         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
511                 return VPNSVC_ERROR_PERMISSION_DENIED;
512
513         if (op == NULL) {
514                 return VPNSVC_ERROR_IPC_FAILED;
515         } else {
516                 g_variant_get(op, "(i)", &result);
517
518                 if (result != VPNSVC_ERROR_NONE)
519                         LOGE("vpn_protect() failed");
520                 else
521                         LOGD("vpn_protect() succeed");
522         }
523
524         return result;
525 }
526
527 EXPORT_API int vpnsvc_up(vpnsvc_h handle)
528 {
529         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
530
531         int result = VPNSVC_ERROR_NONE;
532         int dbus_result;
533         vpnsvc_tun_s *tun_s = NULL;
534
535         /* parameter check */
536         if (handle == NULL) {
537                 LOGE("handle is a NULL");
538                 return VPNSVC_ERROR_INVALID_PARAMETER;
539         }
540         tun_s = (vpnsvc_tun_s*)handle;
541
542         LOGD("enter vpnsvc_up");
543
544         if (tun_s->connection == NULL) {
545                 LOGE("Connection Object is NULL");
546                 return VPNSVC_ERROR_INVALID_PARAMETER;
547         } else if (tun_s->name[0] == 0) {
548                 LOGE("invalid handle");
549                 return VPNSVC_ERROR_INVALID_PARAMETER;
550         }
551
552         LOGD("iface_index %d, iface_name %s", tun_s->index, tun_s->name);
553
554         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
555                                                                 NETCONFIG_SERVICE_NAME,
556                                                                 NETCONFIG_NETWORK_PATH,
557                                                                 NETCONFIG_NETWORK_INTERFACE,
558                                                                 "CheckInternetPrivilege",
559                                                                 NULL,
560                                                                 &dbus_result);
561
562         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
563                 return VPNSVC_ERROR_PERMISSION_DENIED;
564
565         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
566                                                                 NETCONFIG_SERVICE_NAME,
567                                                                 NETCONFIG_VPNSVC_PATH,
568                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
569                                                                 "vpn_up",
570                                                                 g_variant_new("(s)", tun_s->name),
571                                                                 &dbus_result);
572
573         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
574                 return VPNSVC_ERROR_PERMISSION_DENIED;
575
576         if (op == NULL) {
577                 return VPNSVC_ERROR_IPC_FAILED;
578         } else {
579                 g_variant_get(op, "(i)", &result);
580                 if (result != VPNSVC_ERROR_NONE)
581                         LOGE("vpn_up() failed");
582                 else
583                         LOGD("vpn_up() succeed");
584         }
585
586         return result;
587 }
588
589 EXPORT_API int vpnsvc_down(vpnsvc_h handle)
590 {
591         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
592
593         int result = VPNSVC_ERROR_NONE;
594         int dbus_result;
595         vpnsvc_tun_s *tun_s = NULL;
596
597         /* parameter check */
598         if (handle == NULL) {
599                 LOGE("handle is a NULL");
600                 return VPNSVC_ERROR_INVALID_PARAMETER;
601         }
602         tun_s = (vpnsvc_tun_s*)handle;
603
604         LOGD("enter vpnsvc_down");
605
606         if (tun_s->connection == NULL) {
607                 LOGE("Connection Object is NULL");
608                 return VPNSVC_ERROR_INVALID_PARAMETER;
609         }
610
611         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
612                                                                 NETCONFIG_SERVICE_NAME,
613                                                                 NETCONFIG_NETWORK_PATH,
614                                                                 NETCONFIG_NETWORK_INTERFACE,
615                                                                 "CheckInternetPrivilege",
616                                                                 NULL,
617                                                                 &dbus_result);
618
619         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
620                 return VPNSVC_ERROR_PERMISSION_DENIED;
621
622         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
623                                                                 NETCONFIG_SERVICE_NAME,
624                                                                 NETCONFIG_VPNSVC_PATH,
625                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
626                                                                 "vpn_down",
627                                                                 g_variant_new("(s)", tun_s->name),
628                                                                 &dbus_result);
629
630         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
631                 return VPNSVC_ERROR_PERMISSION_DENIED;
632
633         if (op == NULL) {
634                 return VPNSVC_ERROR_IPC_FAILED;
635         } else {
636                 g_variant_get(op, "(i)", &result);
637                 if (result != VPNSVC_ERROR_NONE)
638                         LOGE("vpn_down() failed");
639                 else
640                         LOGD("vpn_down() succeed");
641         }
642
643         return result;
644
645 }
646
647 /* this API must not be use IPC */
648 EXPORT_API int vpnsvc_read(vpnsvc_h handle, int timeout_ms)
649 {
650         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
651
652         fd_set read_set;
653         struct timeval tv;
654         int ret, retVal;
655         vpnsvc_tun_s *tun_s = NULL;
656
657         /* parameter check */
658         if (handle == NULL) {
659                 LOGE("handle is a NULL");
660                 return VPNSVC_ERROR_INVALID_PARAMETER;
661         }
662
663         if (timeout_ms < 0) {
664                 LOGE("handle is a NULL");
665                 return VPNSVC_ERROR_INVALID_PARAMETER;
666         }
667
668         tun_s = (vpnsvc_tun_s*)handle;
669
670         if (tun_s->fd <= 0) {
671                 LOGE("invalid handle");
672                 return VPNSVC_ERROR_INVALID_PARAMETER;
673         }
674
675         /* listen for events */
676         FD_ZERO(&read_set);
677         FD_SET(tun_s->fd, &read_set);
678         tv.tv_sec = 0;
679         tv.tv_usec = timeout_ms*1000;
680         retVal = select(tun_s->fd +1, &read_set, NULL, NULL, &tv);
681
682         if (retVal > 0) {
683                 LOGD("Data is available now.\n");
684                 ret = VPNSVC_ERROR_NONE;
685         } else if (retVal == 0) {
686                 LOGD("No data within %d ms\n", timeout_ms);
687                 ret = VPNSVC_ERROR_TIMEOUT;
688         } else {
689                 LOGE("select failed\n");
690                 ret = VPNSVC_ERROR_IO_ERROR;
691         }
692
693         return ret;
694 }
695
696 /* this API must not be use IPC */
697 EXPORT_API int vpnsvc_write(vpnsvc_h handle, const char* data, size_t size)
698 {
699         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
700
701         vpnsvc_tun_s *tun_s = NULL;
702
703         /* parameter check */
704         if (handle == NULL) {
705                 LOGE("handle is a NULL");
706                 return VPNSVC_ERROR_INVALID_PARAMETER;
707         }
708
709         tun_s = (vpnsvc_tun_s*)handle;
710
711         if (tun_s->fd <= 0) {
712                 LOGE("invalid handle");
713                 return VPNSVC_ERROR_INVALID_PARAMETER;
714         }
715
716         return write(tun_s->fd, data, size);
717 }
718
719
720 EXPORT_API int vpnsvc_block_networks(vpnsvc_h handle,
721                 char* routes_dest_vpn_addr[],
722                 int routes_vpn_prefix[],
723                 size_t num_allow_routes_vpn,
724                 char* routes_dest_orig_addr[],
725                 int routes_orig_prefix[],
726                 size_t num_allow_routes_orig)
727
728 {
729         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
730
731         int result = VPNSVC_ERROR_NONE;
732         int dbus_result;
733         GVariantBuilder nets_builder;
734         size_t i = 0;
735         GVariant *nets_param_vpn;
736         GVariant *nets_param_orig;
737         vpnsvc_tun_s *tun_s = NULL;
738
739         /* parameter check */
740         if (handle == NULL) {
741                 LOGE("handle is a NULL");
742                 return VPNSVC_ERROR_INVALID_PARAMETER;
743         }
744
745         if (num_allow_routes_vpn > MAX_NUM_ROUTES || num_allow_routes_orig > MAX_NUM_ROUTES) {
746                 LOGE("too many routes");
747                 return VPNSVC_ERROR_INVALID_PARAMETER;
748         }
749
750         tun_s = (vpnsvc_tun_s*)handle;
751
752         LOGD("enter vpnsvc_block_networks");
753
754         if (tun_s->connection == NULL) {
755                 LOGE("Connection Object is NULL");
756                 return VPNSVC_ERROR_INVALID_PARAMETER;
757         }
758         /* make a route parameter for allowed VPN interface routes */
759         g_variant_builder_init(&nets_builder, G_VARIANT_TYPE("a{si}"));
760         for (i = 0 ;i < num_allow_routes_vpn ; i++) {
761                 g_variant_builder_add(&nets_builder, "{si}", routes_dest_vpn_addr[i], routes_vpn_prefix[i]);
762                 LOGD("dest_vpn[%d] : %s", i, routes_dest_vpn_addr[i]);
763                 LOGD("prefix_vpn[%d] : %d", i,  routes_vpn_prefix[i]);
764         }
765         nets_param_vpn = g_variant_builder_end(&nets_builder);
766
767         /* make a route parameter for allowed Original interface Routes */
768         g_variant_builder_init(&nets_builder, G_VARIANT_TYPE("a{si}"));
769         for (i = 0 ;i < num_allow_routes_orig ; i++) {
770                 g_variant_builder_add(&nets_builder, "{si}", routes_dest_orig_addr[i], routes_orig_prefix[i]);
771                 LOGD("dest_orig[%d] : %s", i, routes_dest_orig_addr[i]);
772                 LOGD("prefix_orig[%d] : %d", i,  routes_orig_prefix[i]);
773         }
774         nets_param_orig = g_variant_builder_end(&nets_builder);
775
776         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
777                                                                 NETCONFIG_SERVICE_NAME,
778                                                                 NETCONFIG_NETWORK_PATH,
779                                                                 NETCONFIG_NETWORK_INTERFACE,
780                                                                 "CheckInternetPrivilege",
781                                                                 NULL,
782                                                                 &dbus_result);
783
784         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
785                 return VPNSVC_ERROR_PERMISSION_DENIED;
786
787         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
788                                                                 NETCONFIG_SERVICE_NAME,
789                                                                 NETCONFIG_VPNSVC_PATH,
790                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
791                                                                 "vpn_block_networks",
792                                                                 g_variant_new("(vuvu)", nets_param_vpn, num_allow_routes_vpn,
793                                                                 nets_param_orig, num_allow_routes_orig),
794                                                                 &dbus_result);
795
796         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
797                 return VPNSVC_ERROR_PERMISSION_DENIED;
798
799         if (op == NULL) {
800                 return VPNSVC_ERROR_IPC_FAILED;
801         } else {
802                 g_variant_get(op, "(i)", &result);
803                 if (result != VPNSVC_ERROR_NONE)
804                         LOGE("vpn_block_networks() failed");
805                 else
806                         LOGD("vpn_block_networks() succeed");
807         }
808
809         return result;
810 }
811
812 EXPORT_API int vpnsvc_unblock_networks(vpnsvc_h handle)
813 {
814         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
815
816         int result = VPNSVC_ERROR_NONE;
817         int dbus_result;
818         vpnsvc_tun_s *tun_s = NULL;
819
820         /* parameter check */
821         if (handle == NULL) {
822                 LOGE("handle is a NULL");
823                 return VPNSVC_ERROR_INVALID_PARAMETER;
824         }
825         tun_s = (vpnsvc_tun_s*)handle;
826
827         LOGD("enter vpnsvc_unblock_networks");
828         if (tun_s->connection == NULL) {
829                 LOGE("Connection Object is NULL");
830                 return VPNSVC_ERROR_INVALID_PARAMETER;
831         }
832
833         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
834                                                                         NETCONFIG_SERVICE_NAME,
835                                                                         NETCONFIG_NETWORK_PATH,
836                                                                         NETCONFIG_NETWORK_INTERFACE,
837                                                                         "CheckInternetPrivilege",
838                                                                         NULL,
839                                                                         &dbus_result);
840
841         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
842                 return VPNSVC_ERROR_PERMISSION_DENIED;
843
844         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
845                                                                         NETCONFIG_SERVICE_NAME,
846                                                                         NETCONFIG_VPNSVC_PATH,
847                                                                         NETCONFIG_VPNSVC_INTERFACE_NAME,
848                                                                         "vpn_unblock_networks",
849                                                                         g_variant_new("()"),
850                                                                         &dbus_result);
851
852         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
853                 return VPNSVC_ERROR_PERMISSION_DENIED;
854
855         if (op == NULL) {
856                 return VPNSVC_ERROR_IPC_FAILED;
857         } else {
858                 g_variant_get(op, "(i)", &result);
859                 if (result != VPNSVC_ERROR_NONE)
860                         LOGE("vpn_unblock_networks() failed");
861                 else
862                         LOGD("vpn_unblock_networks() succeed");
863         }
864
865         return result;
866 }
867
868 EXPORT_API int vpnsvc_update_settings(vpnsvc_h handle)
869 {
870         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
871
872         int result = VPNSVC_ERROR_NONE;
873         int dbus_result;
874         vpnsvc_tun_s *tun_s = NULL;
875
876         /* parameter check */
877         if (handle == NULL) {
878                 LOGE("handle is a NULL");
879                 return VPNSVC_ERROR_INVALID_PARAMETER;
880         }
881
882         tun_s = (vpnsvc_tun_s*)handle;
883
884         if (!_vpn_check_ip_address_validity(tun_s->local_ip))
885                 return VPNSVC_ERROR_INVALID_PARAMETER;
886
887         if (!_vpn_check_ip_address_validity(tun_s->remote_ip))
888                 return VPNSVC_ERROR_INVALID_PARAMETER;
889
890         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
891                                                                 NETCONFIG_SERVICE_NAME,
892                                                                 NETCONFIG_VPNSVC_PATH,
893                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
894                                                                 "vpn_update_settings",
895                                                                 g_variant_new("(issu)", tun_s->index, tun_s->local_ip, tun_s->remote_ip, tun_s->mtu),
896                                                                 &dbus_result);
897         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
898                 return VPNSVC_ERROR_PERMISSION_DENIED;
899
900         if (op == NULL) {
901                 return VPNSVC_ERROR_IPC_FAILED;
902         } else {
903                 g_variant_get(op, "(i)", &result);
904                 if (result != VPNSVC_ERROR_NONE)
905                         LOGE("vpn_update_settings() failed");
906                 else
907                         LOGD("vpn_update_settings() succeed");
908         }
909
910         return result;
911 }
912
913 EXPORT_API int vpnsvc_get_iface_fd(vpnsvc_h handle, int* iface_fd)
914 {
915         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
916
917         vpnsvc_tun_s *tun_s = NULL;
918
919         /* parameter check */
920         if (handle == NULL || iface_fd == NULL) {
921                 LOGE("Invalid parameter");
922                 return VPNSVC_ERROR_INVALID_PARAMETER;
923         }
924         tun_s = (vpnsvc_tun_s*)handle;
925
926         if (tun_s->fd <= 0) {
927                 LOGE("invalid handle");
928                 return VPNSVC_ERROR_INVALID_PARAMETER;
929         }
930
931         *iface_fd = (int)(tun_s->fd);
932
933         return VPNSVC_ERROR_NONE;
934 }
935
936 EXPORT_API int vpnsvc_get_iface_index(vpnsvc_h handle, int* iface_index)
937 {
938         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
939
940         vpnsvc_tun_s *tun_s = NULL;
941
942         /* parameter check */
943         if (handle == NULL || iface_index == NULL) {
944                 LOGE("Invalid parameter");
945                 return VPNSVC_ERROR_INVALID_PARAMETER;
946         }
947
948         tun_s = (vpnsvc_tun_s*)handle;
949
950         if (tun_s->index <= 0) {
951                 LOGE("invalid handle");
952                 return VPNSVC_ERROR_INVALID_PARAMETER;
953         }
954
955         *iface_index = (int)(tun_s->index);
956
957         return VPNSVC_ERROR_NONE;
958 }
959
960 EXPORT_API int vpnsvc_get_iface_name(vpnsvc_h handle, char** iface_name)
961 {
962         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
963
964         vpnsvc_tun_s *tun_s = NULL;
965         char la_iface_name[VPNSVC_VPN_IFACE_NAME_LEN + 1] = { 0, };
966
967         /* parameter check */
968         if (handle == NULL || iface_name == NULL) {
969                 LOGE("handle is a NULL");
970                 return VPNSVC_ERROR_INVALID_PARAMETER;
971         }
972         tun_s = (vpnsvc_tun_s*)handle;
973
974         if (strlen(tun_s->name) <= 0) {
975                 LOGE("invalid handle");
976                 return VPNSVC_ERROR_INVALID_PARAMETER;
977         }
978
979         g_strlcpy(la_iface_name, tun_s->name, VPNSVC_VPN_IFACE_NAME_LEN + 1);
980         *iface_name = g_strdup(la_iface_name);
981
982         return VPNSVC_ERROR_NONE;
983 }
984
985 EXPORT_API int vpnsvc_set_iface_name(vpnsvc_h handle, const char *iface_name)
986 {
987         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
988
989         vpnsvc_tun_s *tun_s = NULL;
990
991         /* parameter check */
992         if (handle == NULL) {
993                 LOGE("handle is a NULL");
994                 return VPNSVC_ERROR_INVALID_PARAMETER;
995         }
996         tun_s = (vpnsvc_tun_s*)handle;
997
998         if (iface_name == NULL) {
999                 LOGE("Remote IP address is NULL");
1000                 return VPNSVC_ERROR_INVALID_PARAMETER;
1001         }
1002
1003         g_strlcpy(tun_s->name, iface_name, VPNSVC_VPN_IFACE_NAME_LEN);
1004
1005         return VPNSVC_ERROR_NONE;
1006 }
1007
1008
1009 EXPORT_API int vpnsvc_set_mtu(vpnsvc_h handle, int mtu)
1010 {
1011         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1012
1013         int result = VPNSVC_ERROR_NONE;
1014         vpnsvc_tun_s *tun_s = NULL;
1015
1016         /* parameter check */
1017         if (handle == NULL) {
1018                 LOGE("handle is a NULL");
1019                 return VPNSVC_ERROR_INVALID_PARAMETER;
1020         }
1021         tun_s = (vpnsvc_tun_s*)handle;
1022
1023         if (mtu <= 0) {
1024                 LOGE("Incorrect MTU Size = %d", mtu);
1025                 return VPNSVC_ERROR_INVALID_PARAMETER;
1026         }
1027
1028         tun_s->mtu = mtu;
1029
1030         return result;
1031 }
1032
1033 EXPORT_API int vpnsvc_set_blocking(vpnsvc_h handle, bool blocking)
1034 {
1035         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1036
1037         vpnsvc_tun_s *tun_s = NULL;
1038
1039         /* parameter check */
1040         if (handle == NULL) {
1041                 LOGE("handle is a NULL");
1042                 return VPNSVC_ERROR_INVALID_PARAMETER;
1043         }
1044         tun_s = (vpnsvc_tun_s*)handle;
1045
1046         int flags;
1047
1048         if (tun_s->fd <= 0) {
1049                 LOGE("The Tunnel File Descriptor fd = %d", tun_s->fd);
1050                 return VPNSVC_ERROR_INVALID_PARAMETER;
1051         }
1052
1053         flags = fcntl(tun_s->fd, F_GETFL);
1054         if (flags < 0) {
1055                 LOGD("File Descriptor Flags GET Failed fd = %d", tun_s->fd);
1056                 flags = 0;
1057         }
1058
1059         if (blocking == false)
1060                 flags = flags | O_NONBLOCK;
1061         else
1062                 flags = flags & (~O_NONBLOCK);
1063
1064         if (fcntl(tun_s->fd, F_SETFL, flags) < 0) {
1065                 LOGE("Failed fd = %d F_SETFL(flags) = %d", tun_s->fd, flags);
1066                 return VPNSVC_ERROR_IO_ERROR;
1067         }
1068         return VPNSVC_ERROR_NONE;
1069 }
1070
1071 EXPORT_API int vpnsvc_set_session(vpnsvc_h handle, const char* session)
1072 {
1073         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1074
1075         vpnsvc_tun_s *tun_s = NULL;
1076
1077         /* parameter check */
1078         if (handle == NULL) {
1079                 LOGE("handle is a NULL");
1080                 return VPNSVC_ERROR_INVALID_PARAMETER;
1081         }
1082         tun_s = (vpnsvc_tun_s*)handle;
1083
1084         if (session == NULL) {
1085                 LOGE("Session Name string is NULL");
1086                 return VPNSVC_ERROR_INVALID_PARAMETER;
1087         }
1088
1089         if (strlen(session) >= VPNSVC_SESSION_STRING_LEN) {
1090                 LOGE("Session name is longer than 32");
1091                 return VPNSVC_ERROR_INVALID_PARAMETER;
1092         }
1093
1094         strncpy(tun_s->session, session, VPNSVC_SESSION_STRING_LEN);
1095         tun_s->session[VPNSVC_SESSION_STRING_LEN - 1] = '\0';
1096
1097         return VPNSVC_ERROR_NONE;
1098 }
1099
1100 EXPORT_API int vpnsvc_get_session(vpnsvc_h handle, char** session)
1101 {
1102         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1103
1104         vpnsvc_tun_s *tun_s = NULL;
1105         char la_session[VPNSVC_SESSION_STRING_LEN + 1] = { 0, };
1106
1107         /* parameter check */
1108         if (handle == NULL) {
1109                 LOGE("handle is a NULL");
1110                 return VPNSVC_ERROR_INVALID_PARAMETER;
1111         }
1112         tun_s = (vpnsvc_tun_s*)handle;
1113
1114         if (session == NULL) {
1115                 LOGE("Session Name string is NULL");
1116                 return VPNSVC_ERROR_INVALID_PARAMETER;
1117         }
1118
1119         g_strlcpy(la_session, tun_s->session, VPNSVC_SESSION_STRING_LEN + 1);
1120         *session = g_strdup(la_session);
1121
1122         return VPNSVC_ERROR_NONE;
1123 }
1124
1125 EXPORT_API int vpnsvc_set_local_ip_address(vpnsvc_h handle, const char *local_ip)
1126 {
1127         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1128
1129         vpnsvc_tun_s *tun_s = NULL;
1130
1131         /* parameter check */
1132         if (handle == NULL) {
1133                 LOGE("handle is a NULL");
1134                 return VPNSVC_ERROR_INVALID_PARAMETER;
1135         }
1136         tun_s = (vpnsvc_tun_s*)handle;
1137
1138         if (local_ip == NULL) {
1139                 LOGE("Local IP address is NULL");
1140                 return VPNSVC_ERROR_INVALID_PARAMETER;
1141         }
1142
1143         g_strlcpy(tun_s->local_ip, local_ip, VPNSVC_IP4_STRING_LEN);
1144
1145         return VPNSVC_ERROR_NONE;
1146 }
1147
1148 EXPORT_API int vpnsvc_set_remote_ip_address(vpnsvc_h handle, const char *remote_ip)
1149 {
1150         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1151
1152         vpnsvc_tun_s *tun_s = NULL;
1153
1154         /* parameter check */
1155         if (handle == NULL) {
1156                 LOGE("handle is a NULL");
1157                 return VPNSVC_ERROR_INVALID_PARAMETER;
1158         }
1159         tun_s = (vpnsvc_tun_s*)handle;
1160
1161         if (remote_ip == NULL) {
1162                 LOGE("Remote IP address is NULL");
1163                 return VPNSVC_ERROR_INVALID_PARAMETER;
1164         }
1165
1166         g_strlcpy(tun_s->remote_ip, remote_ip, VPNSVC_IP4_STRING_LEN);
1167
1168         return VPNSVC_ERROR_NONE;
1169 }
1170
1171 EXPORT_API int vpnsvc_add_route(vpnsvc_h handle, const char *route_address, int prefix)
1172 {
1173         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1174
1175         int result = VPNSVC_ERROR_NONE;
1176         int dbus_result;
1177         vpnsvc_tun_s *tun_s = NULL;
1178
1179         /* parameter check */
1180         if (handle == NULL) {
1181                 LOGE("handle is a NULL");
1182                 return VPNSVC_ERROR_INVALID_PARAMETER;
1183         }
1184         tun_s = (vpnsvc_tun_s*)handle;
1185
1186         if (route_address == NULL) {
1187                 LOGE("remove_address is NULL");
1188                 return VPNSVC_ERROR_INVALID_PARAMETER;
1189         }
1190
1191         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
1192                                                                 NETCONFIG_SERVICE_NAME,
1193                                                                 NETCONFIG_VPNSVC_PATH,
1194                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
1195                                                                 "vpn_add_route",
1196                                                                 g_variant_new("(ssi)", tun_s->name, route_address, prefix),
1197                                                                 &dbus_result);
1198         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
1199                 return VPNSVC_ERROR_PERMISSION_DENIED;
1200
1201         if (op == NULL) {
1202                 return VPNSVC_ERROR_IPC_FAILED;
1203         } else {
1204                 g_variant_get(op, "(i)", &result);
1205                 if (result != VPNSVC_ERROR_NONE)
1206                         LOGE("vpn_add_route() failed");
1207                 else
1208                         LOGD("vpn_add_route() succeed");
1209         }
1210
1211         return result;
1212 }
1213
1214 EXPORT_API int vpnsvc_remove_route(vpnsvc_h handle, const char *route_address, int prefix)
1215 {
1216         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1217
1218         int result = VPNSVC_ERROR_NONE;
1219         int dbus_result;
1220         vpnsvc_tun_s *tun_s = NULL;
1221
1222         /* parameter check */
1223         if (handle == NULL) {
1224                 LOGE("handle is a NULL");
1225                 return VPNSVC_ERROR_INVALID_PARAMETER;
1226         }
1227         tun_s = (vpnsvc_tun_s*)handle;
1228
1229         if (route_address == NULL) {
1230                 LOGE("route_address is NULL");
1231                 return VPNSVC_ERROR_INVALID_PARAMETER;
1232         }
1233
1234         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
1235                                                                 NETCONFIG_SERVICE_NAME,
1236                                                                 NETCONFIG_VPNSVC_PATH,
1237                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
1238                                                                 "vpn_remove_route",
1239                                                                 g_variant_new("(ssi)", tun_s->name, route_address, prefix),
1240                                                                 &dbus_result);
1241         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
1242                 return VPNSVC_ERROR_PERMISSION_DENIED;
1243
1244         if (op == NULL) {
1245                 return VPNSVC_ERROR_IPC_FAILED;
1246         } else {
1247                 g_variant_get(op, "(i)", &result);
1248                 if (result != VPNSVC_ERROR_NONE)
1249                         LOGE("vpn_remove_route() failed");
1250                 else
1251                         LOGD("vpn_remove_route() succeed");
1252         }
1253
1254         return result;
1255 }
1256
1257 EXPORT_API int vpnsvc_add_dns_server(vpnsvc_h handle, const char *dns_server)
1258 {
1259         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1260
1261         int result = VPNSVC_ERROR_NONE;
1262         int dbus_result;
1263         vpnsvc_tun_s *tun_s = NULL;
1264
1265         /* parameter check */
1266         if (handle == NULL) {
1267                 LOGE("handle is a NULL");
1268                 return VPNSVC_ERROR_INVALID_PARAMETER;
1269         }
1270         tun_s = (vpnsvc_tun_s*)handle;
1271
1272         if (dns_server == NULL) {
1273                 LOGE("dns_server is NULL");
1274                 return VPNSVC_ERROR_INVALID_PARAMETER;
1275         }
1276
1277         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
1278                                                                 NETCONFIG_SERVICE_NAME,
1279                                                                 NETCONFIG_VPNSVC_PATH,
1280                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
1281                                                                 "vpn_add_dns_server",
1282                                                                 g_variant_new("(ss)", tun_s->name, dns_server),
1283                                                                 &dbus_result);
1284         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
1285                 return VPNSVC_ERROR_PERMISSION_DENIED;
1286
1287         if (op == NULL) {
1288                 return VPNSVC_ERROR_IPC_FAILED;
1289         } else {
1290                 g_variant_get(op, "(i)", &result);
1291                 if (result != VPNSVC_ERROR_NONE)
1292                         LOGE("vpn_add_dns_server() failed");
1293                 else
1294                         LOGD("vpn_add_dns_server() succeed");
1295         }
1296
1297         return result;
1298 }
1299
1300 EXPORT_API int vpnsvc_remove_dns_server(vpnsvc_h handle, const char *dns_server)
1301 {
1302         CHECK_FEATURE_SUPPORTED(VPN_SERVICE_FEATURE);
1303
1304         int result = VPNSVC_ERROR_NONE;
1305         int dbus_result;
1306         vpnsvc_tun_s *tun_s = NULL;
1307
1308         /* parameter check */
1309         if (handle == NULL) {
1310                 LOGE("handle is a NULL");
1311                 return VPNSVC_ERROR_INVALID_PARAMETER;
1312         }
1313         tun_s = (vpnsvc_tun_s*)handle;
1314
1315         if (dns_server == NULL) {
1316                 LOGE("dns_server is NULL");
1317                 return VPNSVC_ERROR_INVALID_PARAMETER;
1318         }
1319         op = _vpnsvc_invoke_dbus_method(tun_s->connection,
1320                                                                 NETCONFIG_SERVICE_NAME,
1321                                                                 NETCONFIG_VPNSVC_PATH,
1322                                                                 NETCONFIG_VPNSVC_INTERFACE_NAME,
1323                                                                 "vpn_remove_dns_server",
1324                                                                 g_variant_new("(ss)", tun_s->name, dns_server),
1325                                                                 &dbus_result);
1326         if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED)
1327                 return VPNSVC_ERROR_PERMISSION_DENIED;
1328
1329         if (op == NULL) {
1330                 return VPNSVC_ERROR_IPC_FAILED;
1331         } else {
1332                 g_variant_get(op, "(i)", &result);
1333                 if (result != VPNSVC_ERROR_NONE)
1334                         LOGE("vpn_remove_dns_server() failed");
1335                 else
1336                         LOGD("vpn_remove_dns_server() succeed");
1337         }
1338
1339         return result;
1340 }