2 * Copyright (C) 2012 Giuliano Grassi
3 * Copyright (C) 2012 Ralf Sager
4 * Copyright (C) 2012 Tobias Brunner
5 * Hochschule fuer Technik Rapperswil
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>.
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
20 #include <android/log.h>
22 #include "charonservice.h"
23 #include "android_jni.h"
24 #include "kernel/android_ipsec.h"
25 #include "kernel/android_net.h"
31 #include <threading/thread.h>
33 #define ANDROID_DEBUG_LEVEL 1
35 typedef struct private_charonservice_t private_charonservice_t
;
38 * private data of charonservice
40 struct private_charonservice_t
{
45 charonservice_t
public;
48 * CharonVpnService reference
54 * Single instance of charonservice_t.
56 charonservice_t
*charonservice
;
59 * hook in library for debugging messages
61 extern void (*dbg
)(debug_t group
, level_t level
, char *fmt
, ...);
64 * Logging hook for library logs, using android specific logging
66 static void dbg_android(debug_t group
, level_t level
, char *fmt
, ...)
70 if (level
<= ANDROID_DEBUG_LEVEL
)
72 char sgroup
[16], buffer
[8192];
73 char *current
= buffer
, *next
;
75 snprintf(sgroup
, sizeof(sgroup
), "%N", debug_names
, group
);
77 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
80 { /* log each line separately */
81 next
= strchr(current
, '\n');
86 __android_log_print(ANDROID_LOG_INFO
, "charon", "00[%s] %s\n",
93 METHOD(charonservice_t
, update_status
, bool,
94 private_charonservice_t
*this, android_vpn_state_t code
)
100 androidjni_attach_thread(&env
);
102 method_id
= (*env
)->GetMethodID(env
, android_charonvpnservice_class
,
103 "updateStatus", "(I)V");
108 (*env
)->CallVoidMethod(env
, this->vpn_service
, method_id
, (jint
)code
);
109 success
= !androidjni_exception_occurred(env
);
112 androidjni_exception_occurred(env
);
113 androidjni_detach_thread();
117 METHOD(charonservice_t
, bypass_socket
, bool,
118 private_charonservice_t
*this, int fd
, int family
)
123 androidjni_attach_thread(&env
);
125 method_id
= (*env
)->GetMethodID(env
, android_charonvpnservice_class
,
131 if (!(*env
)->CallBooleanMethod(env
, this->vpn_service
, method_id
, fd
))
133 DBG1(DBG_CFG
, "VpnService.protect() failed");
136 androidjni_detach_thread();
140 androidjni_exception_occurred(env
);
141 androidjni_detach_thread();
146 * Initialize the charonservice object
148 static void charonservice_init(JNIEnv
*env
, jobject service
)
150 private_charonservice_t
*this;
151 static plugin_feature_t features
[] = {
152 PLUGIN_CALLBACK(kernel_net_register
, kernel_android_net_create
),
153 PLUGIN_PROVIDE(CUSTOM
, "kernel-net"),
154 PLUGIN_CALLBACK(kernel_ipsec_register
, kernel_android_ipsec_create
),
155 PLUGIN_PROVIDE(CUSTOM
, "kernel-ipsec"),
160 .update_status
= _update_status
,
161 .bypass_socket
= _bypass_socket
,
163 .vpn_service
= (*env
)->NewGlobalRef(env
, service
),
165 charonservice
= &this->public;
167 lib
->plugins
->add_static_features(lib
->plugins
, "androidbridge", features
,
168 countof(features
), TRUE
);
170 lib
->settings
->set_int(lib
->settings
,
171 "charon.plugins.android_log.loglevel", ANDROID_DEBUG_LEVEL
);
175 * Deinitialize the charonservice object
177 static void charonservice_deinit(JNIEnv
*env
)
179 private_charonservice_t
*this = (private_charonservice_t
*)charonservice
;
181 (*env
)->DeleteGlobalRef(env
, this->vpn_service
);
183 charonservice
= NULL
;
187 * Handle SIGSEGV/SIGILL signals raised by threads
189 static void segv_handler(int signal
)
191 dbg_android(DBG_DMN
, 1, "thread %u received %d", thread_current_id(),
197 * Initialize charon and the libraries via JNI
199 JNI_METHOD(CharonVpnService
, initializeCharon
, void)
201 struct sigaction action
;
203 /* logging for library during initialization, as we have no bus yet */
206 /* initialize library */
207 if (!library_init(NULL
))
213 if (!libhydra_init("charon"))
220 if (!libipsec_init())
228 charonservice_init(env
, this);
230 if (!libcharon_init("charon") ||
231 !charon
->initialize(charon
, PLUGINS
))
234 charonservice_deinit(env
);
241 /* add handler for SEGV and ILL etc. */
242 action
.sa_handler
= segv_handler
;
244 sigemptyset(&action
.sa_mask
);
245 sigaction(SIGSEGV
, &action
, NULL
);
246 sigaction(SIGILL
, &action
, NULL
);
247 sigaction(SIGBUS
, &action
, NULL
);
248 action
.sa_handler
= SIG_IGN
;
249 sigaction(SIGPIPE
, &action
, NULL
);
251 /* start daemon (i.e. the threads in the thread-pool) */
252 charon
->start(charon
);
256 * Deinitialize charon and all libraries
258 JNI_METHOD(CharonVpnService
, deinitializeCharon
, void)
261 charonservice_deinit(env
);