Add wireguard related changes and test cases
[platform/core/api/vpn-setting.git] / src / vpn-internal.c
1 /*
2 * Network VPN library
3 *
4 * Copyright (c) 2014-2015 Samsung Electronics. 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 <stdio.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <glib.h>
24
25 #include <dvpnlib-vpn.h>
26 #include <dvpnlib-vpn-manager.h>
27 #include <dvpnlib-vpn-connection.h>
28
29 #include "vpn-internal.h"
30
31 struct _vpn_cb_s {
32         vpn_created_cb create_cb;
33         void *create_user_data;
34         vpn_removed_cb remove_cb;
35         void *remove_user_data;
36         vpn_connect_cb connect_cb;
37         void *connect_user_data;
38         vpn_disconnect_cb disconnect_cb;
39         void *disconnect_user_data;
40         GHashTable *state_cb_datas;
41 };
42
43 static struct _vpn_cb_s vpn_callbacks = {0,};
44 static GHashTable *settings_hash;
45
46 //LCOV_EXCL_START
47 /*
48  * Utility Functions
49  */
50
51 static void print_key_value_string(gpointer key,
52                                 gpointer value, gpointer user_data)
53 {
54         if (user_data) {
55                 VPN_LOG(VPN_INFO, " %s[%s]=%s",
56                         (gchar *)user_data, (gchar *)key, (gchar *)value);
57                 return;
58         }
59         VPN_LOG(VPN_INFO, " %s=%s", (gchar *)key, (gchar *)value);
60 }
61
62 vpn_error_e _dvpnlib_error2vpn_error(enum dvpnlib_err err_type)
63 {
64         switch (err_type) {
65         case DVPNLIB_ERR_NONE:
66                 return VPN_ERROR_NONE;
67         case DVPNLIB_ERR_ALREADY_EXISTS:
68                 return VPN_ERROR_INVALID_OPERATION;
69         case DVPNLIB_ERR_NOT_REGISTERED:
70                 return VPN_ERROR_INVALID_OPERATION;
71         case DVPNLIB_ERR_NOT_CONNECTED:
72                 return VPN_ERROR_NO_CONNECTION;
73         case DVPNLIB_ERR_ALREADY_CONNECTED:
74                 return VPN_ERROR_ALREADY_EXISTS;
75         case DVPNLIB_ERR_IN_PROGRESS:
76                 return VPN_ERROR_NOW_IN_PROGRESS;
77         case DVPNLIB_ERR_OPERATION_ABORTED:
78                 return VPN_ERROR_OPERATION_ABORTED;
79         case DVPNLIB_ERR_OPERATION_TIMEOUT:
80         case DVPNLIB_ERR_TIMEOUT:
81                 return VPN_ERROR_NO_REPLY;
82         default:
83                 return VPN_ERROR_OPERATION_FAILED;
84         }
85 }
86 //LCOV_EXCL_STOP
87
88 /*
89  *Functions Actually use Default VPN Library
90  */
91
92 bool _vpn_init(void)
93 {
94         int rv;
95
96         rv = dvpnlib_vpn_init();
97
98         if (rv != 0)
99                 return false;
100
101         vpn_callbacks.state_cb_datas = g_hash_table_new_full(g_direct_hash,
102                                                              g_direct_equal,
103                                                              NULL,
104                                                              NULL);
105         return true;
106 }
107
108 bool _vpn_deinit(void)
109 {
110         dvpnlib_vpn_deinit();
111
112         g_hash_table_remove_all(vpn_callbacks.state_cb_datas);
113
114         return true;
115 }
116
117 int _vpn_settings_init()
118 {
119         if (settings_hash != NULL) {
120                 VPN_LOG(VPN_INFO, "Settings Hash: %p Already present!", settings_hash); //LCOV_EXCL_LINE
121                 return VPN_ERROR_INVALID_OPERATION; //LCOV_EXCL_LINE
122         }
123
124         settings_hash = g_hash_table_new_full(
125                                 g_str_hash, g_str_equal,
126                                 g_free, g_free);
127         VPN_LOG(VPN_INFO, "Settings Hash: %p", settings_hash);
128
129         return VPN_ERROR_NONE;
130 }
131
132 int _vpn_settings_deinit()
133 {
134         if (settings_hash == NULL)
135                 return VPN_ERROR_INVALID_OPERATION;
136
137         VPN_LOG(VPN_INFO, "Settings Hash: %p Destroyed", settings_hash);
138         g_hash_table_destroy(settings_hash);
139         settings_hash = NULL;
140
141         return VPN_ERROR_NONE;
142 }
143
144 int _vpn_settings_set_specific(const char *key, const char *value)
145 {
146         VPN_LOG(VPN_INFO,
147                 "Settings Hash: %p {%s=%s}", settings_hash, key, value);
148
149         if (key == NULL)
150                 return VPN_ERROR_INVALID_PARAMETER;
151
152         if (settings_hash == NULL)
153                 return VPN_ERROR_INVALID_OPERATION;
154
155         if (g_hash_table_contains(settings_hash, key)) {
156 //LCOV_EXCL_START
157                 if (value == NULL) {
158                         VPN_LOG(VPN_INFO, "Settings Hash: %p {%s=%s} (Removed)",
159                                 settings_hash, key,
160                                 (gchar *)g_hash_table_lookup(
161                                         settings_hash, key));
162                         g_hash_table_remove(settings_hash, key);
163                         return VPN_ERROR_NONE;
164                 }
165 //LCOV_EXCL_STOP
166         }
167
168         g_hash_table_replace(settings_hash,
169                         (gpointer)g_strdup(key),
170                         (gpointer)g_strdup(value));
171
172         return VPN_ERROR_NONE;
173 }
174
175 //LCOV_EXCL_START
176 /*
177  *Callbacks
178  */
179 static void __vpn_create_cb(vpn_error_e result)
180 {
181         if (vpn_callbacks.create_cb)
182                 vpn_callbacks.create_cb(result,
183                                 vpn_callbacks.create_user_data);
184
185         vpn_callbacks.create_cb = NULL;
186         vpn_callbacks.create_user_data = NULL;
187 }
188
189 static void vpn_manager_create_cb(enum dvpnlib_err result,
190                                                         void *user_data)
191 {
192         VPN_LOG(VPN_INFO, "callback: %d Settings: %p\n", result, user_data);
193
194         __vpn_create_cb(_dvpnlib_error2vpn_error(result));
195 }
196
197 static void __vpn_remove_cb(vpn_error_e result)
198 {
199         if (vpn_callbacks.create_cb)
200                 vpn_callbacks.create_cb(result,
201                                 vpn_callbacks.create_user_data);
202
203         vpn_callbacks.remove_cb = NULL;
204         vpn_callbacks.remove_user_data = NULL;
205 }
206
207 static void vpn_manager_remove_cb(enum dvpnlib_err result,
208                                                         void *user_data)
209 {
210         VPN_LOG(VPN_INFO, "callback: %d Settings: %p\n", result, user_data);
211
212         __vpn_remove_cb(_dvpnlib_error2vpn_error(result));
213 }
214 //LCOV_EXCL_STOP
215
216 int _vpn_create(vpn_created_cb callback, void *user_data)
217 {
218         enum dvpnlib_err err = DVPNLIB_ERR_NONE;
219         if (!settings_hash)
220                 return VPN_ERROR_INVALID_OPERATION;
221
222 //LCOV_EXCL_START
223         VPN_LOG(VPN_INFO, "");
224
225         vpn_callbacks.create_cb = callback;
226         vpn_callbacks.create_user_data = user_data;
227
228         g_hash_table_foreach(settings_hash,
229                 print_key_value_string, "VPNSettings");
230
231         err = dvpnlib_vpn_manager_create(settings_hash,
232                 vpn_manager_create_cb, NULL);
233         if (err != DVPNLIB_ERR_NONE)
234                 return _dvpnlib_error2vpn_error(err);
235
236         return VPN_ERROR_NONE;
237 //LCOV_EXCL_STOP
238
239 }
240
241 int _vpn_remove(vpn_h handle, vpn_removed_cb callback, void *user_data)
242 {
243         enum dvpnlib_err err = DVPNLIB_ERR_NONE;
244
245         VPN_LOG(VPN_INFO, "");
246
247         vpn_callbacks.remove_cb = callback;
248         vpn_callbacks.remove_user_data = user_data;
249
250         GList *connections = vpn_get_connections();
251         if (NULL == g_list_find(connections, handle)) {
252                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
253                 return VPN_ERROR_INVALID_PARAMETER;
254         }
255
256         const char *path = vpn_connection_get_path(handle); //LCOV_EXCL_LINE
257         err = dvpnlib_vpn_manager_remove(path, vpn_manager_remove_cb, NULL); //LCOV_EXCL_LINE
258         if (err != DVPNLIB_ERR_NONE) //LCOV_EXCL_LINE
259                 return _dvpnlib_error2vpn_error(err); //LCOV_EXCL_LINE
260
261         return VPN_ERROR_NONE;
262 }
263
264 //LCOV_EXCL_START
265 /*
266  *Connect Disconnect Callbacks
267  */
268
269 static void __vpn_connect_cb(vpn_error_e result)
270 {
271         if (vpn_callbacks.connect_cb)
272                 vpn_callbacks.connect_cb(result,
273                                 vpn_callbacks.connect_user_data);
274
275         vpn_callbacks.connect_cb = NULL;
276         vpn_callbacks.connect_user_data = NULL;
277 }
278
279 static void vpn_manager_connect_cb(enum dvpnlib_err result,
280                                                         void *user_data)
281 {
282         VPN_LOG(VPN_INFO, "callback: %d Settings: %p\n", result, user_data);
283
284         __vpn_connect_cb(_dvpnlib_error2vpn_error(result));
285 }
286 //LCOV_EXCL_STOP
287
288 /*
289  *Connect to VPN Profile
290  */
291
292 int _vpn_connect(vpn_h handle, vpn_removed_cb callback, void *user_data)
293 {
294         enum dvpnlib_err err = DVPNLIB_ERR_NONE;
295
296         VPN_LOG(VPN_INFO, "");
297
298         vpn_callbacks.connect_cb = callback;
299         vpn_callbacks.connect_user_data = user_data;
300
301         GList *connections = vpn_get_connections();
302         if (NULL == g_list_find(connections, handle)) {
303                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
304                 return VPN_ERROR_INVALID_PARAMETER;
305         }
306
307         enum vpn_connection_state state = vpn_connection_get_state(handle); //LCOV_EXCL_LINE
308         if (state == VPN_CONN_STATE_READY) //LCOV_EXCL_LINE
309                 return VPN_ERROR_ALREADY_EXISTS; //LCOV_EXCL_LINE
310
311         err = vpn_connection_connect(handle, vpn_manager_connect_cb, NULL); //LCOV_EXCL_LINE
312         if (err != DVPNLIB_ERR_NONE) //LCOV_EXCL_LINE
313                 return _dvpnlib_error2vpn_error(err); //LCOV_EXCL_LINE
314
315         return VPN_ERROR_NONE;
316 }
317
318 /*
319  *Disconnect from VPN Profile
320  */
321
322 int _vpn_disconnect(vpn_h handle)
323 {
324         enum dvpnlib_err err = DVPNLIB_ERR_NONE;
325
326         VPN_LOG(VPN_INFO, "");
327
328         GList *connections = vpn_get_connections();
329         if (NULL == g_list_find(connections, handle)) {
330                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
331                 return VPN_ERROR_INVALID_PARAMETER;
332         }
333
334         enum vpn_connection_state state = vpn_connection_get_state(handle); //LCOV_EXCL_LINE
335         if (state != VPN_CONN_STATE_READY) //LCOV_EXCL_LINE
336                 return VPN_ERROR_NO_CONNECTION; //LCOV_EXCL_LINE
337
338         err = vpn_connection_disconnect(handle); //LCOV_EXCL_LINE
339         if (err != DVPNLIB_ERR_NONE) //LCOV_EXCL_LINE
340                 return _dvpnlib_error2vpn_error(err); //LCOV_EXCL_LINE
341
342         return VPN_ERROR_NONE;
343 }
344
345 /*
346  *Gets the VPN Handles List from VPN Profile
347  */
348 GList *_vpn_get_vpn_handle_list(void)
349 {
350         return vpn_get_connections();
351 }
352
353 /*
354  * Get a specific VPN Handle based on name, host & domain parameters
355  */
356 int _vpn_get_vpn_handle(const char *name, const char *host, const char *domain, vpn_h *handle)
357 {
358         VPN_LOG(VPN_INFO, "");
359
360         struct vpn_connection *connection = vpn_get_connection(name, host, domain);
361
362         if (connection == NULL) {
363                 VPN_LOG(VPN_ERROR, "name=%s host=%s domain=%s", name, host, domain ? domain : "NULL");
364                 return VPN_ERROR_INVALID_PARAMETER;
365         }
366
367         *handle = connection; //LCOV_EXCL_LINE
368         return VPN_ERROR_NONE; //LCOV_EXCL_LINE
369 }
370
371 /*
372  * Get VPN Info (Name) from VPN Handle
373  */
374 int _vpn_get_vpn_info_name(vpn_h handle, const char **name)
375 {
376         VPN_LOG(VPN_INFO, "");
377
378         GList *connections = vpn_get_connections();
379         if (NULL == g_list_find(connections, handle)) {
380                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
381                 return VPN_ERROR_INVALID_PARAMETER;
382         }
383
384         *name = vpn_connection_get_name(handle); //LCOV_EXCL_LINE
385         return VPN_ERROR_NONE; //LCOV_EXCL_LINE
386 }
387
388 /*
389  * Get VPN Info (Type) from VPN Handle
390  */
391 int _vpn_get_vpn_info_type(vpn_h handle, const char **type)
392 {
393         VPN_LOG(VPN_INFO, "");
394
395         GList *connections = vpn_get_connections();
396         if (NULL == g_list_find(connections, handle)) {
397                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
398                 return VPN_ERROR_INVALID_PARAMETER;
399         }
400
401         *type = vpn_connection_get_type(handle); //LCOV_EXCL_LINE
402         return VPN_ERROR_NONE; //LCOV_EXCL_LINE
403 }
404
405 /*
406  * Get VPN Info (Host) from VPN Handle
407  */
408 int _vpn_get_vpn_info_host(vpn_h handle, const char **host)
409 {
410         VPN_LOG(VPN_INFO, "");
411
412         GList *connections = vpn_get_connections();
413         if (NULL == g_list_find(connections, handle)) {
414                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
415                 return VPN_ERROR_INVALID_PARAMETER;
416         }
417
418         *host = vpn_connection_get_host(handle); //LCOV_EXCL_LINE
419         return VPN_ERROR_NONE; //LCOV_EXCL_LINE
420 }
421
422 /*
423  * Get VPN Info (Domain) from VPN Handle
424  */
425 int _vpn_get_vpn_info_domain(vpn_h handle, const char **domain)
426 {
427         VPN_LOG(VPN_INFO, "");
428
429         GList *connections = vpn_get_connections();
430         if (NULL == g_list_find(connections, handle)) {
431                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
432                 return VPN_ERROR_INVALID_PARAMETER;
433         }
434
435         *domain = vpn_connection_get_domain(handle); //LCOV_EXCL_LINE
436         return VPN_ERROR_NONE; //LCOV_EXCL_LINE
437 }
438
439 //LCOV_EXCL_START
440 /*
441  *State Callbacks
442  */
443
444 static void __vpn_state_cb(struct vpn_connection *connection, void *user_data)
445 {
446         vpn_state_cb cb = NULL;
447         cb = (vpn_state_cb)g_hash_table_lookup(vpn_callbacks.state_cb_datas, connection);
448         if (cb)
449                 cb(connection, vpn_connection_get_state(connection), user_data);
450 }
451
452 static void vpn_manager_state_cb(struct vpn_connection *connection, void *user_data)
453 {
454         VPN_LOG(VPN_INFO, "connection: %p user_data: %p\n", connection, user_data);
455
456         __vpn_state_cb(connection, user_data);
457 }
458 //LCOV_EXCL_STOP
459
460 /*
461  *Set state changed callback to VPN handle
462  */
463
464 int _vpn_set_state_callback(const vpn_h handle, vpn_state_cb cb, void *user_data)
465 {
466         enum dvpnlib_err err = DVPNLIB_ERR_NONE;
467
468         VPN_LOG(VPN_INFO, "");
469
470         GList *connections = vpn_get_connections();
471         if (NULL == g_list_find(connections, handle)) {
472                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
473                 return VPN_ERROR_INVALID_PARAMETER;
474         }
475
476         g_hash_table_replace(vpn_callbacks.state_cb_datas, handle, cb); //LCOV_EXCL_LINE
477         err = vpn_connection_set_property_changed_cb(handle, VPN_CONN_PROP_STATE, vpn_manager_state_cb, (void *)user_data); //LCOV_EXCL_LINE
478         if (err != DVPNLIB_ERR_NONE) //LCOV_EXCL_LINE
479                 return _dvpnlib_error2vpn_error(err); //LCOV_EXCL_LINE
480
481         return VPN_ERROR_NONE;
482 }
483
484 /*
485  *Unset state changed callback to VPN handle
486  */
487
488 int _vpn_unset_state_callback(const vpn_h handle)
489 {
490         enum dvpnlib_err err = DVPNLIB_ERR_NONE;
491
492         VPN_LOG(VPN_INFO, "");
493
494         GList *connections = vpn_get_connections();
495         if (NULL == g_list_find(connections, handle)) {
496                 VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle);
497                 return VPN_ERROR_INVALID_PARAMETER;
498         }
499
500         err = vpn_connection_unset_property_changed_cb(handle, VPN_CONN_PROP_STATE); //LCOV_EXCL_LINE
501         if (err != DVPNLIB_ERR_NONE) //LCOV_EXCL_LINE
502                 return _dvpnlib_error2vpn_error(err); //LCOV_EXCL_LINE
503
504         return VPN_ERROR_NONE;
505 }