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
, bypass_socket
, bool,
94 private_charonservice_t
*this, int fd
, int family
)
99 androidjni_attach_thread(&env
);
101 method_id
= (*env
)->GetMethodID(env
, android_charonvpnservice_class
,
107 if (!(*env
)->CallBooleanMethod(env
, this->vpn_service
, method_id
, fd
))
109 DBG1(DBG_CFG
, "VpnService.protect() failed");
112 androidjni_detach_thread();
116 androidjni_exception_occurred(env
);
117 androidjni_detach_thread();
122 * Initialize the charonservice object
124 static void charonservice_init(JNIEnv
*env
, jobject service
)
126 private_charonservice_t
*this;
127 static plugin_feature_t features
[] = {
128 PLUGIN_CALLBACK(kernel_net_register
, kernel_android_net_create
),
129 PLUGIN_PROVIDE(CUSTOM
, "kernel-net"),
130 PLUGIN_CALLBACK(kernel_ipsec_register
, kernel_android_ipsec_create
),
131 PLUGIN_PROVIDE(CUSTOM
, "kernel-ipsec"),
136 .bypass_socket
= _bypass_socket
,
138 .vpn_service
= (*env
)->NewGlobalRef(env
, service
),
140 charonservice
= &this->public;
142 lib
->plugins
->add_static_features(lib
->plugins
, "androidbridge", features
,
143 countof(features
), TRUE
);
145 lib
->settings
->set_int(lib
->settings
,
146 "charon.plugins.android_log.loglevel", ANDROID_DEBUG_LEVEL
);
150 * Deinitialize the charonservice object
152 static void charonservice_deinit(JNIEnv
*env
)
154 private_charonservice_t
*this = (private_charonservice_t
*)charonservice
;
156 (*env
)->DeleteGlobalRef(env
, this->vpn_service
);
158 charonservice
= NULL
;
162 * Handle SIGSEGV/SIGILL signals raised by threads
164 static void segv_handler(int signal
)
166 dbg_android(DBG_DMN
, 1, "thread %u received %d", thread_current_id(),
172 * Initialize charon and the libraries via JNI
174 JNI_METHOD(CharonVpnService
, initializeCharon
, void)
176 struct sigaction action
;
178 /* logging for library during initialization, as we have no bus yet */
181 /* initialize library */
182 if (!library_init(NULL
))
188 if (!libhydra_init("charon"))
195 if (!libipsec_init())
203 charonservice_init(env
, this);
205 if (!libcharon_init("charon") ||
206 !charon
->initialize(charon
, PLUGINS
))
209 charonservice_deinit(env
);
216 /* add handler for SEGV and ILL etc. */
217 action
.sa_handler
= segv_handler
;
219 sigemptyset(&action
.sa_mask
);
220 sigaction(SIGSEGV
, &action
, NULL
);
221 sigaction(SIGILL
, &action
, NULL
);
222 sigaction(SIGBUS
, &action
, NULL
);
223 action
.sa_handler
= SIG_IGN
;
224 sigaction(SIGPIPE
, &action
, NULL
);
226 /* start daemon (i.e. the threads in the thread-pool) */
227 charon
->start(charon
);
231 * Deinitialize charon and all libraries
233 JNI_METHOD(CharonVpnService
, deinitializeCharon
, void)
236 charonservice_deinit(env
);