a9a3fe4a6fb651b75272d8ad406dd3aa561d13f0
[strongswan.git] / src / frontends / android / jni / libandroidbridge / charonservice.c
1 /*
2 * Copyright (C) 2012 Giuliano Grassi
3 * Copyright (C) 2012 Ralf Sager
4 * Copyright (C) 2012 Tobias Brunner
5 * Hochschule fuer Technik Rapperswil
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
18 #include <signal.h>
19 #include <string.h>
20 #include <android/log.h>
21
22 #include "charonservice.h"
23 #include "android_jni.h"
24 #include "kernel/android_ipsec.h"
25 #include "kernel/android_net.h"
26
27 #include <daemon.h>
28 #include <hydra.h>
29 #include <ipsec.h>
30 #include <library.h>
31 #include <threading/thread.h>
32
33 #define ANDROID_DEBUG_LEVEL 1
34
35 typedef struct private_charonservice_t private_charonservice_t;
36
37 /**
38 * private data of charonservice
39 */
40 struct private_charonservice_t {
41
42 /**
43 * public interface
44 */
45 charonservice_t public;
46
47 /**
48 * CharonVpnService reference
49 */
50 jobject vpn_service;
51 };
52
53 /**
54 * Single instance of charonservice_t.
55 */
56 charonservice_t *charonservice;
57
58 /**
59 * hook in library for debugging messages
60 */
61 extern void (*dbg)(debug_t group, level_t level, char *fmt, ...);
62
63 /**
64 * Logging hook for library logs, using android specific logging
65 */
66 static void dbg_android(debug_t group, level_t level, char *fmt, ...)
67 {
68 va_list args;
69
70 if (level <= ANDROID_DEBUG_LEVEL)
71 {
72 char sgroup[16], buffer[8192];
73 char *current = buffer, *next;
74
75 snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
76 va_start(args, fmt);
77 vsnprintf(buffer, sizeof(buffer), fmt, args);
78 va_end(args);
79 while (current)
80 { /* log each line separately */
81 next = strchr(current, '\n');
82 if (next)
83 {
84 *(next++) = '\0';
85 }
86 __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n",
87 sgroup, current);
88 current = next;
89 }
90 }
91 }
92
93 /**
94 * Initialize the charonservice object
95 */
96 static void charonservice_init(JNIEnv *env, jobject service)
97 {
98 private_charonservice_t *this;
99 static plugin_feature_t features[] = {
100 PLUGIN_CALLBACK(kernel_net_register, kernel_android_net_create),
101 PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
102 PLUGIN_CALLBACK(kernel_ipsec_register, kernel_android_ipsec_create),
103 PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
104 };
105
106 INIT(this,
107 .public = {
108 },
109 .vpn_service = (*env)->NewGlobalRef(env, service),
110 );
111 charonservice = &this->public;
112
113 lib->plugins->add_static_features(lib->plugins, "androidbridge", features,
114 countof(features), TRUE);
115
116 lib->settings->set_int(lib->settings,
117 "charon.plugins.android_log.loglevel", ANDROID_DEBUG_LEVEL);
118 }
119
120 /**
121 * Deinitialize the charonservice object
122 */
123 static void charonservice_deinit(JNIEnv *env)
124 {
125 private_charonservice_t *this = (private_charonservice_t*)charonservice;
126
127 (*env)->DeleteGlobalRef(env, this->vpn_service);
128 free(this);
129 charonservice = NULL;
130 }
131
132 /**
133 * Handle SIGSEGV/SIGILL signals raised by threads
134 */
135 static void segv_handler(int signal)
136 {
137 dbg_android(DBG_DMN, 1, "thread %u received %d", thread_current_id(),
138 signal);
139 exit(1);
140 }
141
142 /**
143 * Initialize charon and the libraries via JNI
144 */
145 JNI_METHOD(CharonVpnService, initializeCharon, void)
146 {
147 struct sigaction action;
148
149 /* logging for library during initialization, as we have no bus yet */
150 dbg = dbg_android;
151
152 /* initialize library */
153 if (!library_init(NULL))
154 {
155 library_deinit();
156 return;
157 }
158
159 if (!libhydra_init("charon"))
160 {
161 libhydra_deinit();
162 library_deinit();
163 return;
164 }
165
166 if (!libipsec_init())
167 {
168 libipsec_deinit();
169 libhydra_deinit();
170 library_deinit();
171 return;
172 }
173
174 charonservice_init(env, this);
175
176 if (!libcharon_init("charon") ||
177 !charon->initialize(charon, PLUGINS))
178 {
179 libcharon_deinit();
180 charonservice_deinit(env);
181 libipsec_deinit();
182 libhydra_deinit();
183 library_deinit();
184 return;
185 }
186
187 /* add handler for SEGV and ILL etc. */
188 action.sa_handler = segv_handler;
189 action.sa_flags = 0;
190 sigemptyset(&action.sa_mask);
191 sigaction(SIGSEGV, &action, NULL);
192 sigaction(SIGILL, &action, NULL);
193 sigaction(SIGBUS, &action, NULL);
194 action.sa_handler = SIG_IGN;
195 sigaction(SIGPIPE, &action, NULL);
196
197 /* start daemon (i.e. the threads in the thread-pool) */
198 charon->start(charon);
199 }
200
201 /**
202 * Deinitialize charon and all libraries
203 */
204 JNI_METHOD(CharonVpnService, deinitializeCharon, void)
205 {
206 libcharon_deinit();
207 charonservice_deinit(env);
208 libipsec_deinit();
209 libhydra_deinit();
210 library_deinit();
211 }
212