]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c
android: Use the default scheduler for short-term events
[thirdparty/strongswan.git] / src / frontends / android / app / src / main / jni / libandroidbridge / charonservice.c
CommitLineData
4a208143 1/*
664389eb 2 * Copyright (C) 2012-2020 Tobias Brunner
cb887af4
TB
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
7b417757 5 * HSR Hochschule fuer Technik Rapperswil
4a208143
TB
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
a3048743 18#include <signal.h>
4a208143 19#include <string.h>
6db742e7 20#include <sys/utsname.h>
4a208143 21#include <android/log.h>
fe05f1f0 22#include <errno.h>
4a208143 23
6f11e941 24#include "charonservice.h"
cb887af4 25#include "android_jni.h"
3a05756b 26#include "backend/android_attr.h"
8430e54d 27#include "backend/android_creds.h"
7b417757 28#include "backend/android_fetcher.h"
406d680e 29#include "backend/android_private_key.h"
1b4c4123 30#include "backend/android_scheduler.h"
c6c39c78 31#include "backend/android_service.h"
17508851 32#include "kernel/android_ipsec.h"
24447cf4 33#include "kernel/android_net.h"
cb887af4 34
96658d72
TB
35#ifdef USE_BYOD
36#include "byod/imc_android.h"
37#endif
38
cb887af4 39#include <daemon.h>
06ed785e 40#include <ipsec.h>
4a208143 41#include <library.h>
a3048743 42#include <threading/thread.h>
4a208143 43
d2007494 44#define ANDROID_DEBUG_LEVEL 1
76e55491 45#define ANDROID_RETRASNMIT_TRIES 3
901f6ac4 46#define ANDROID_RETRANSMIT_TIMEOUT 2.0
76e55491 47#define ANDROID_RETRANSMIT_BASE 1.4
73a6bec3 48#define ANDROID_KEEPALIVE_INTERVAL 45
664389eb 49#define ANDROID_KEEPALIVE_DPD_MARGIN 20
d2007494 50
6f11e941
TB
51typedef struct private_charonservice_t private_charonservice_t;
52
53/**
54 * private data of charonservice
55 */
56struct private_charonservice_t {
57
58 /**
59 * public interface
60 */
61 charonservice_t public;
529c8c88 62
3a05756b
TB
63 /**
64 * android_attr instance
65 */
66 android_attr_t *attr;
67
8430e54d
TB
68 /**
69 * android_creds instance
70 */
71 android_creds_t *creds;
72
c6c39c78
TB
73 /**
74 * android_service instance
75 */
76 android_service_t *service;
77
ae4f1ea1
TB
78 /**
79 * VpnService builder (accessed via JNI)
80 */
81 vpnservice_builder_t *builder;
82
38bbca58
TB
83 /**
84 * NetworkManager instance (accessed via JNI)
85 */
86 network_manager_t *network_manager;
87
529c8c88
TB
88 /**
89 * CharonVpnService reference
90 */
91 jobject vpn_service;
45885ca6
TB
92
93 /**
94 * Sockets that were bypassed and we keep track for
95 */
96 linked_list_t *sockets;
6f11e941
TB
97};
98
99/**
100 * Single instance of charonservice_t.
101 */
102charonservice_t *charonservice;
4a208143
TB
103
104/**
105 * hook in library for debugging messages
106 */
cb887af4 107extern void (*dbg)(debug_t group, level_t level, char *fmt, ...);
4a208143
TB
108
109/**
110 * Logging hook for library logs, using android specific logging
111 */
112static void dbg_android(debug_t group, level_t level, char *fmt, ...)
113{
114 va_list args;
115
d2007494 116 if (level <= ANDROID_DEBUG_LEVEL)
4a208143
TB
117 {
118 char sgroup[16], buffer[8192];
119 char *current = buffer, *next;
d2007494 120
4a208143
TB
121 snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
122 va_start(args, fmt);
123 vsnprintf(buffer, sizeof(buffer), fmt, args);
124 va_end(args);
125 while (current)
126 { /* log each line separately */
127 next = strchr(current, '\n');
128 if (next)
129 {
130 *(next++) = '\0';
131 }
132 __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n",
133 sgroup, current);
134 current = next;
135 }
136 }
137}
138
8c2af60c
TB
139METHOD(charonservice_t, update_status, bool,
140 private_charonservice_t *this, android_vpn_state_t code)
141{
142 JNIEnv *env;
143 jmethodID method_id;
144 bool success = FALSE;
145
146 androidjni_attach_thread(&env);
147
148 method_id = (*env)->GetMethodID(env, android_charonvpnservice_class,
149 "updateStatus", "(I)V");
150 if (!method_id)
151 {
152 goto failed;
153 }
154 (*env)->CallVoidMethod(env, this->vpn_service, method_id, (jint)code);
155 success = !androidjni_exception_occurred(env);
156
157failed:
158 androidjni_exception_occurred(env);
159 androidjni_detach_thread();
160 return success;
161}
162
dc52cfab
TB
163METHOD(charonservice_t, update_imc_state, bool,
164 private_charonservice_t *this, android_imc_state_t state)
165{
166 JNIEnv *env;
167 jmethodID method_id;
168 bool success = FALSE;
169
170 androidjni_attach_thread(&env);
171
172 method_id = (*env)->GetMethodID(env, android_charonvpnservice_class,
173 "updateImcState", "(I)V");
174 if (!method_id)
175 {
176 goto failed;
177 }
178 (*env)->CallVoidMethod(env, this->vpn_service, method_id, (jint)state);
179 success = !androidjni_exception_occurred(env);
180
181failed:
182 androidjni_exception_occurred(env);
183 androidjni_detach_thread();
184 return success;
185}
186
a05acd76
TB
187METHOD(charonservice_t, add_remediation_instr, bool,
188 private_charonservice_t *this, char *instr)
189{
190 JNIEnv *env;
191 jmethodID method_id;
192 jstring jinstr;
193 bool success = FALSE;
194
195 androidjni_attach_thread(&env);
196
197 method_id = (*env)->GetMethodID(env, android_charonvpnservice_class,
198 "addRemediationInstruction",
199 "(Ljava/lang/String;)V");
200 if (!method_id)
201 {
202 goto failed;
203 }
204 jinstr = (*env)->NewStringUTF(env, instr);
205 if (!jinstr)
206 {
207 goto failed;
208 }
209 (*env)->CallVoidMethod(env, this->vpn_service, method_id, jinstr);
210 success = !androidjni_exception_occurred(env);
211
212failed:
213 androidjni_exception_occurred(env);
214 androidjni_detach_thread();
215 return success;
216}
217
45885ca6
TB
218/**
219 * Bypass a single socket
220 */
8a2e4d4a 221static bool bypass_single_socket(private_charonservice_t *this, int fd)
d4f76751
TB
222{
223 JNIEnv *env;
224 jmethodID method_id;
225
226 androidjni_attach_thread(&env);
227
228 method_id = (*env)->GetMethodID(env, android_charonvpnservice_class,
229 "protect", "(I)Z");
230 if (!method_id)
231 {
232 goto failed;
233 }
234 if (!(*env)->CallBooleanMethod(env, this->vpn_service, method_id, fd))
235 {
45885ca6 236 DBG2(DBG_KNL, "VpnService.protect() failed");
d4f76751
TB
237 goto failed;
238 }
239 androidjni_detach_thread();
240 return TRUE;
241
242failed:
243 androidjni_exception_occurred(env);
244 androidjni_detach_thread();
245 return FALSE;
246}
247
8a2e4d4a
TB
248CALLBACK(bypass_single_socket_cb, void,
249 intptr_t fd, va_list args)
250{
251 private_charonservice_t *this;
252
253 VA_ARGS_VGET(args, this);
254 bypass_single_socket(this, fd);
255}
256
45885ca6
TB
257METHOD(charonservice_t, bypass_socket, bool,
258 private_charonservice_t *this, int fd, int family)
259{
260 if (fd >= 0)
261 {
262 this->sockets->insert_last(this->sockets, (void*)(intptr_t)fd);
8a2e4d4a 263 return bypass_single_socket(this, fd);
45885ca6 264 }
8a2e4d4a 265 this->sockets->invoke_function(this->sockets, bypass_single_socket_cb, this);
45885ca6
TB
266 return TRUE;
267}
268
3aba3386
TB
269/**
270 * Converts the given Java array of byte arrays (byte[][]) to a linked list
271 * of chunk_t objects.
272 */
273static linked_list_t *convert_array_of_byte_arrays(JNIEnv *env,
274 jobjectArray jarray)
275{
276 linked_list_t *list;
277 jsize i;
278
279 list = linked_list_create();
280 for (i = 0; i < (*env)->GetArrayLength(env, jarray); ++i)
281 {
282 chunk_t *chunk;
283 jbyteArray jbytearray;
284
285 chunk = malloc_thing(chunk_t);
286 list->insert_last(list, chunk);
287
288 jbytearray = (*env)->GetObjectArrayElement(env, jarray, i);
289 *chunk = chunk_alloc((*env)->GetArrayLength(env, jbytearray));
290 (*env)->GetByteArrayRegion(env, jbytearray, 0, chunk->len, chunk->ptr);
291 (*env)->DeleteLocalRef(env, jbytearray);
292 }
293 return list;
294}
295
2bec193a
TB
296METHOD(charonservice_t, get_trusted_certificates, linked_list_t*,
297 private_charonservice_t *this)
298{
299 JNIEnv *env;
300 jmethodID method_id;
301 jobjectArray jcerts;
302 linked_list_t *list;
2bec193a
TB
303
304 androidjni_attach_thread(&env);
305
306 method_id = (*env)->GetMethodID(env,
307 android_charonvpnservice_class,
9d994ba5 308 "getTrustedCertificates", "()[[B");
2bec193a
TB
309 if (!method_id)
310 {
311 goto failed;
312 }
9d994ba5 313 jcerts = (*env)->CallObjectMethod(env, this->vpn_service, method_id);
37d42a76 314 if (!jcerts || androidjni_exception_occurred(env))
2bec193a
TB
315 {
316 goto failed;
317 }
3aba3386
TB
318 list = convert_array_of_byte_arrays(env, jcerts);
319 androidjni_detach_thread();
320 return list;
321
322failed:
323 androidjni_exception_occurred(env);
324 androidjni_detach_thread();
325 return NULL;
326}
327
328METHOD(charonservice_t, get_user_certificate, linked_list_t*,
329 private_charonservice_t *this)
330{
331 JNIEnv *env;
332 jmethodID method_id;
333 jobjectArray jencodings;
334 linked_list_t *list;
2bec193a 335
3aba3386 336 androidjni_attach_thread(&env);
2bec193a 337
3aba3386
TB
338 method_id = (*env)->GetMethodID(env,
339 android_charonvpnservice_class,
340 "getUserCertificate", "()[[B");
341 if (!method_id)
342 {
343 goto failed;
344 }
406d680e 345 jencodings = (*env)->CallObjectMethod(env, this->vpn_service, method_id);
37d42a76 346 if (!jencodings || androidjni_exception_occurred(env))
3aba3386
TB
347 {
348 goto failed;
2bec193a 349 }
3aba3386 350 list = convert_array_of_byte_arrays(env, jencodings);
2bec193a
TB
351 androidjni_detach_thread();
352 return list;
353
354failed:
355 androidjni_exception_occurred(env);
356 androidjni_detach_thread();
357 return NULL;
358}
359
406d680e
TB
360METHOD(charonservice_t, get_user_key, private_key_t*,
361 private_charonservice_t *this, public_key_t *pubkey)
362{
363 JNIEnv *env;
364 jmethodID method_id;
365 private_key_t *key;
366 jobject jkey;
367
368 androidjni_attach_thread(&env);
369
370 method_id = (*env)->GetMethodID(env,
371 android_charonvpnservice_class,
372 "getUserKey", "()Ljava/security/PrivateKey;");
373 if (!method_id)
374 {
375 goto failed;
376 }
377 jkey = (*env)->CallObjectMethod(env, this->vpn_service, method_id);
37d42a76 378 if (!jkey || androidjni_exception_occurred(env))
406d680e
TB
379 {
380 goto failed;
381 }
382 key = android_private_key_create(jkey, pubkey);
383 androidjni_detach_thread();
384 return key;
385
386failed:
387 DESTROY_IF(pubkey);
388 androidjni_exception_occurred(env);
389 androidjni_detach_thread();
390 return NULL;
391}
392
ae4f1ea1
TB
393METHOD(charonservice_t, get_vpnservice_builder, vpnservice_builder_t*,
394 private_charonservice_t *this)
395{
396 return this->builder;
397}
398
38bbca58
TB
399METHOD(charonservice_t, get_network_manager, network_manager_t*,
400 private_charonservice_t *this)
401{
402 return this->network_manager;
403}
404
c6c39c78
TB
405/**
406 * Initiate a new connection
407 *
79af70c6 408 * @param settings configuration settings (gets owned)
c6c39c78 409 */
79af70c6 410static void initiate(settings_t *settings)
c6c39c78
TB
411{
412 private_charonservice_t *this = (private_charonservice_t*)charonservice;
413
6830cb1c
TB
414 lib->settings->set_str(lib->settings,
415 "charon.plugins.tnc-imc.preferred_language",
416 settings->get_str(settings, "global.language", "en"));
a7060581
TB
417 lib->settings->set_bool(lib->settings,
418 "charon.plugins.revocation.enable_crl",
419 settings->get_bool(settings, "global.crl", TRUE));
420 lib->settings->set_bool(lib->settings,
421 "charon.plugins.revocation.enable_ocsp",
422 settings->get_bool(settings, "global.ocsp", TRUE));
205ec47d
TB
423 lib->settings->set_bool(lib->settings,
424 "charon.rsa_pss",
425 settings->get_bool(settings, "global.rsa_pss", FALSE));
4d02c49e
TB
426 /* this is actually the size of the complete IKE/IP packet, so if the MTU
427 * for the TUN devices has to be reduced to pass traffic the IKE packets
428 * will be a bit smaller than necessary as there is no IPsec overhead like
429 * for the tunneled traffic (but compensating that seems like overkill) */
430 lib->settings->set_int(lib->settings,
431 "charon.fragment_size",
432 settings->get_int(settings, "global.mtu",
433 ANDROID_DEFAULT_MTU));
db599d6b
TB
434 /* use configured interval, or an increased default to save battery power */
435 lib->settings->set_int(lib->settings,
436 "charon.keep_alive",
437 settings->get_int(settings, "global.nat_keepalive",
438 ANDROID_KEEPALIVE_INTERVAL));
664389eb
TB
439 /* send DPDs if above interval is exceeded, use a static value for now */
440 lib->settings->set_int(lib->settings,
441 "charon.keep_alive_dpd_margin",
442 ANDROID_KEEPALIVE_DPD_MARGIN);
6830cb1c 443
a7060581
TB
444 /* reload plugins after changing settings */
445 lib->plugins->reload(lib->plugins, NULL);
446
c6c39c78 447 this->creds->clear(this->creds);
c6c39c78 448 DESTROY_IF(this->service);
79af70c6 449 this->service = android_service_create(this->creds, settings);
c6c39c78
TB
450}
451
8430e54d
TB
452/**
453 * Initialize/deinitialize Android backend
454 */
96658d72 455static bool charonservice_register(plugin_t *plugin, plugin_feature_t *feature,
8430e54d
TB
456 bool reg, void *data)
457{
458 private_charonservice_t *this = (private_charonservice_t*)charonservice;
459 if (reg)
460 {
461 lib->credmgr->add_set(lib->credmgr, &this->creds->set);
75136327
MW
462 charon->attributes->add_handler(charon->attributes,
463 &this->attr->handler);
8430e54d
TB
464 }
465 else
466 {
467 lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
75136327
MW
468 charon->attributes->remove_handler(charon->attributes,
469 &this->attr->handler);
c6c39c78
TB
470 if (this->service)
471 {
472 this->service->destroy(this->service);
473 this->service = NULL;
474 }
8430e54d
TB
475 }
476 return TRUE;
477}
478
67332b4e
TB
479/**
480 * Set strongswan.conf options
481 */
482static void set_options(char *logfile)
483{
484 lib->settings->set_int(lib->settings,
485 "charon.plugins.android_log.loglevel", ANDROID_DEBUG_LEVEL);
486 /* setup file logger */
487 lib->settings->set_str(lib->settings,
948c42ab
TB
488 "charon.filelog.android.path", logfile);
489 lib->settings->set_str(lib->settings,
490 "charon.filelog.android.time_format", "%b %e %T");
67332b4e 491 lib->settings->set_bool(lib->settings,
948c42ab 492 "charon.filelog.android.append", TRUE);
67332b4e 493 lib->settings->set_bool(lib->settings,
948c42ab 494 "charon.filelog.android.flush_line", TRUE);
67332b4e 495 lib->settings->set_int(lib->settings,
948c42ab 496 "charon.filelog.android.default", ANDROID_DEBUG_LEVEL);
67332b4e
TB
497
498 lib->settings->set_int(lib->settings,
499 "charon.retransmit_tries", ANDROID_RETRASNMIT_TRIES);
500 lib->settings->set_double(lib->settings,
501 "charon.retransmit_timeout", ANDROID_RETRANSMIT_TIMEOUT);
502 lib->settings->set_double(lib->settings,
503 "charon.retransmit_base", ANDROID_RETRANSMIT_BASE);
9d957bac
TB
504 lib->settings->set_bool(lib->settings,
505 "charon.initiator_only", TRUE);
67332b4e
TB
506 lib->settings->set_bool(lib->settings,
507 "charon.close_ike_on_child_failure", TRUE);
070cd12d
TB
508 lib->settings->set_bool(lib->settings,
509 "charon.check_current_path", TRUE);
67332b4e
TB
510 /* setting the source address breaks the VpnService.protect() function which
511 * uses SO_BINDTODEVICE internally. the addresses provided to the kernel as
512 * auxiliary data have precedence over this option causing a routing loop if
513 * the gateway is contained in the VPN routes. alternatively, providing an
514 * explicit device (in addition or instead of the source address) in the
515 * auxiliary data would also work, but we currently don't have that
516 * information */
517 lib->settings->set_bool(lib->settings,
518 "charon.plugins.socket-default.set_source", FALSE);
0015727e
TB
519 /* the Linux kernel does currently not support UDP encaspulation for IPv6
520 * so lets disable IPv6 for now to avoid issues with dual-stack gateways */
521 lib->settings->set_bool(lib->settings,
522 "charon.plugins.socket-default.use_ipv6", FALSE);
96658d72
TB
523
524#ifdef USE_BYOD
525 lib->settings->set_str(lib->settings,
526 "charon.plugins.eap-tnc.protocol", "tnccs-2.0");
65ee857a
TB
527 lib->settings->set_int(lib->settings,
528 "charon.plugins.eap-ttls.max_message_count", 0);
96658d72
TB
529 lib->settings->set_bool(lib->settings,
530 "android.imc.send_os_info", TRUE);
753035f6
TB
531 lib->settings->set_str(lib->settings,
532 "libtnccs.tnc_config", "");
96658d72 533#endif
67332b4e
TB
534}
535
6f11e941
TB
536/**
537 * Initialize the charonservice object
538 */
2ecda342 539static void charonservice_init(JNIEnv *env, jobject service, jobject builder,
3fe9a436 540 char *appdir, jboolean byod)
6f11e941
TB
541{
542 private_charonservice_t *this;
24447cf4 543 static plugin_feature_t features[] = {
17508851
TB
544 PLUGIN_CALLBACK(kernel_ipsec_register, kernel_android_ipsec_create),
545 PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
10823724
TB
546 PLUGIN_CALLBACK(kernel_net_register, kernel_android_net_create),
547 PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
96658d72
TB
548 PLUGIN_CALLBACK(charonservice_register, NULL),
549 PLUGIN_PROVIDE(CUSTOM, "android-backend"),
8430e54d 550 PLUGIN_DEPENDS(CUSTOM, "libcharon"),
0bebbae9 551 PLUGIN_DEPENDS(CERT_DECODE, CERT_X509_CRL),
7b417757
TB
552 PLUGIN_REGISTER(FETCHER, android_fetcher_create),
553 PLUGIN_PROVIDE(FETCHER, "http://"),
554 PLUGIN_PROVIDE(FETCHER, "https://"),
24447cf4 555 };
6f11e941
TB
556
557 INIT(this,
558 .public = {
8c2af60c 559 .update_status = _update_status,
dc52cfab 560 .update_imc_state = _update_imc_state,
a05acd76 561 .add_remediation_instr = _add_remediation_instr,
d4f76751 562 .bypass_socket = _bypass_socket,
2bec193a 563 .get_trusted_certificates = _get_trusted_certificates,
3aba3386 564 .get_user_certificate = _get_user_certificate,
406d680e 565 .get_user_key = _get_user_key,
ae4f1ea1 566 .get_vpnservice_builder = _get_vpnservice_builder,
38bbca58 567 .get_network_manager = _get_network_manager,
6f11e941 568 },
3a05756b 569 .attr = android_attr_create(),
0bebbae9 570 .creds = android_creds_create(appdir),
ae4f1ea1 571 .builder = vpnservice_builder_create(builder),
ef3d1a1b 572 .network_manager = network_manager_create(service),
45885ca6 573 .sockets = linked_list_create(),
529c8c88 574 .vpn_service = (*env)->NewGlobalRef(env, service),
6f11e941
TB
575 );
576 charonservice = &this->public;
d2007494 577
24447cf4 578 lib->plugins->add_static_features(lib->plugins, "androidbridge", features,
5421092b 579 countof(features), TRUE, NULL, NULL);
96658d72
TB
580
581#ifdef USE_BYOD
2ecda342 582 if (byod)
aa4ff3b2
TB
583 {
584 plugin_feature_t byod_features[] = {
585 PLUGIN_CALLBACK(imc_android_register, this->vpn_service),
586 PLUGIN_PROVIDE(CUSTOM, "android-imc"),
587 PLUGIN_DEPENDS(CUSTOM, "android-backend"),
588 PLUGIN_DEPENDS(CUSTOM, "imc-manager"),
589 };
590
591 lib->plugins->add_static_features(lib->plugins, "android-byod",
5421092b 592 byod_features, countof(byod_features), TRUE, NULL, NULL);
aa4ff3b2 593 }
96658d72 594#endif
6f11e941
TB
595}
596
597/**
598 * Deinitialize the charonservice object
599 */
529c8c88 600static void charonservice_deinit(JNIEnv *env)
6f11e941
TB
601{
602 private_charonservice_t *this = (private_charonservice_t*)charonservice;
603
38bbca58 604 this->network_manager->destroy(this->network_manager);
45885ca6 605 this->sockets->destroy(this->sockets);
ae4f1ea1 606 this->builder->destroy(this->builder);
8430e54d 607 this->creds->destroy(this->creds);
3a05756b 608 this->attr->destroy(this->attr);
529c8c88 609 (*env)->DeleteGlobalRef(env, this->vpn_service);
6f11e941
TB
610 free(this);
611 charonservice = NULL;
612}
613
a3048743
TB
614/**
615 * Handle SIGSEGV/SIGILL signals raised by threads
616 */
617static void segv_handler(int signal)
618{
619 dbg_android(DBG_DMN, 1, "thread %u received %d", thread_current_id(),
620 signal);
621 exit(1);
622}
623
f3695d08
TB
624/**
625 * Register this logger as default before we have the bus available
626 */
627static void __attribute__ ((constructor))register_logger()
628{
629 dbg = dbg_android;
630}
631
4a208143
TB
632/**
633 * Initialize charon and the libraries via JNI
634 */
c3ee829e 635JNI_METHOD(CharonVpnService, initializeCharon, jboolean,
3fe9a436 636 jobject builder, jstring jlogfile, jstring jappdir, jboolean byod)
4a208143 637{
a3048743 638 struct sigaction action;
6db742e7 639 struct utsname utsname;
3fe9a436 640 char *logfile, *appdir, *plugins;
a3048743 641
4a208143 642 /* initialize library */
34d3bfcf 643 if (!library_init(NULL, "charon"))
4a208143
TB
644 {
645 library_deinit();
c3ee829e 646 return FALSE;
4a208143
TB
647 }
648
d67a5b0c
TB
649 if (android_sdk_version >= ANDROID_MARSHMALLOW)
650 {
651 /* use a custom scheduler so the app is woken when jobs have to run */
652 lib->scheduler = android_scheduler_create(this, lib->scheduler);
653 }
654
67332b4e
TB
655 /* set options before initializing other libraries that might read them */
656 logfile = androidjni_convert_jstring(env, jlogfile);
19c95c9b 657
67332b4e
TB
658 set_options(logfile);
659 free(logfile);
660
06ed785e
TB
661 if (!libipsec_init())
662 {
663 libipsec_deinit();
06ed785e 664 library_deinit();
c3ee829e 665 return FALSE;
06ed785e
TB
666 }
667
1c306c0e 668 if (!libcharon_init())
6db742e7
TB
669 {
670 libcharon_deinit();
671 libipsec_deinit();
6db742e7 672 library_deinit();
c3ee829e 673 return FALSE;
6db742e7
TB
674 }
675
9665686b 676 charon->load_loggers(charon);
6f11e941 677
3fe9a436
TB
678 appdir = androidjni_convert_jstring(env, jappdir);
679 charonservice_init(env, this, builder, appdir, byod);
680 free(appdir);
67332b4e 681
6db742e7
TB
682 if (uname(&utsname) != 0)
683 {
684 memset(&utsname, 0, sizeof(utsname));
685 }
19c95c9b
TB
686 DBG1(DBG_DMN, "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
687 DBG1(DBG_DMN, "Starting IKE service (strongSwan "VERSION", %s, %s, "
c5ba3817 688 "%s %s, %s)", android_version_string, android_device_string,
6db742e7
TB
689 utsname.sysname, utsname.release, utsname.machine);
690
2ecda342
TB
691#ifdef PLUGINS_BYOD
692 if (byod)
693 {
694 plugins = PLUGINS " " PLUGINS_BYOD;
695 }
696 else
697#endif
698 {
699 plugins = PLUGINS;
700 }
701
702 if (!charon->initialize(charon, plugins))
4a208143
TB
703 {
704 libcharon_deinit();
529c8c88 705 charonservice_deinit(env);
06ed785e 706 libipsec_deinit();
4a208143 707 library_deinit();
c3ee829e 708 return FALSE;
4a208143 709 }
607f8e99 710 lib->plugins->status(lib->plugins, LEVEL_CTRL);
4a208143 711
a3048743
TB
712 /* add handler for SEGV and ILL etc. */
713 action.sa_handler = segv_handler;
714 action.sa_flags = 0;
715 sigemptyset(&action.sa_mask);
716 sigaction(SIGSEGV, &action, NULL);
717 sigaction(SIGILL, &action, NULL);
718 sigaction(SIGBUS, &action, NULL);
719 action.sa_handler = SIG_IGN;
720 sigaction(SIGPIPE, &action, NULL);
721
4a208143
TB
722 /* start daemon (i.e. the threads in the thread-pool) */
723 charon->start(charon);
c3ee829e 724 return TRUE;
4a208143
TB
725}
726
727/**
6f11e941 728 * Deinitialize charon and all libraries
4a208143
TB
729 */
730JNI_METHOD(CharonVpnService, deinitializeCharon, void)
731{
6db742e7 732 /* deinitialize charon before we destroy our own objects */
4a208143 733 libcharon_deinit();
529c8c88 734 charonservice_deinit(env);
06ed785e 735 libipsec_deinit();
4a208143
TB
736 library_deinit();
737}
738
c6c39c78
TB
739/**
740 * Initiate SA
741 */
742JNI_METHOD(CharonVpnService, initiate, void,
79af70c6 743 jstring jconfig)
c6c39c78 744{
79af70c6
TB
745 settings_t *settings;
746 char *config;
c6c39c78 747
79af70c6
TB
748 config = androidjni_convert_jstring(env, jconfig);
749 settings = settings_create_string(config);
8b6c2334
TB
750 free(config);
751
79af70c6 752 initiate(settings);
c6c39c78 753}
836a9438
TB
754
755/**
756 * Utility function to verify proposal strings (static, so `this` is the class)
757 */
758JNI_METHOD_P(org_strongswan_android_utils, Utils, isProposalValid, jboolean,
759 jboolean ike, jstring proposal)
760{
761 proposal_t *prop;
762 char *str;
763 bool valid;
764
836a9438
TB
765 if (!library_init(NULL, "charon"))
766 {
767 library_deinit();
768 return FALSE;
769 }
770 str = androidjni_convert_jstring(env, proposal);
771 prop = proposal_create_from_string(ike ? PROTO_IKE : PROTO_ESP, str);
772 valid = prop != NULL;
773 DESTROY_IF(prop);
774 free(str);
775 library_deinit();
776 return valid;
777}
7028e9d3
TB
778
779/**
780 * Utility function to parse an IP address from a string (static, so `this` is the class)
781 */
782JNI_METHOD_P(org_strongswan_android_utils, Utils, parseInetAddressBytes, jbyteArray,
783 jstring address)
784{
785 jbyteArray bytes;
786 host_t *host;
787 char *str;
788
7028e9d3
TB
789 if (!library_init(NULL, "charon"))
790 {
791 library_deinit();
792 return NULL;
793 }
794 str = androidjni_convert_jstring(env, address);
795 host = host_create_from_string(str, 0);
796 if (!host)
797 {
798 free(str);
799 return NULL;
800 }
801 bytes = byte_array_from_chunk(env, host->get_address(host));
802 host->destroy(host);
803 free(str);
804 library_deinit();
805 return bytes;
806}