From: Tobias Brunner Date: Fri, 17 Feb 2012 16:16:07 +0000 (+0100) Subject: Added android.net.VpnService wrapper around charon (loaded via JNI). X-Git-Tag: 5.0.1~211^2~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a2081430056cebc760638bd96eb685e184835cb;p=thirdparty%2Fstrongswan.git Added android.net.VpnService wrapper around charon (loaded via JNI). --- diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml index 702a15d21b..63464e712a 100644 --- a/src/frontends/android/AndroidManifest.xml +++ b/src/frontends/android/AndroidManifest.xml @@ -5,6 +5,7 @@ android:versionName="1.0" > + + + + + + \ No newline at end of file diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index 74c6c6a427..e5659a4df2 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -56,6 +56,7 @@ strongswan_CFLAGS += \ include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ vstr \ openssl \ + libandroidbridge \ strongswan/src/libcharon \ strongswan/src/libhydra \ strongswan/src/libstrongswan \ diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk new file mode 100644 index 0000000000..7f25a540a3 --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/Android.mk @@ -0,0 +1,33 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# copy-n-paste from Makefile.am +LOCAL_SRC_FILES := \ +charonservice.c + +# build libandroidbridge ------------------------------------------------------- + +LOCAL_C_INCLUDES += \ + $(libvstr_PATH) \ + $(strongswan_PATH)/src/libhydra \ + $(strongswan_PATH)/src/libcharon \ + $(strongswan_PATH)/src/libstrongswan + +LOCAL_CFLAGS := $(strongswan_CFLAGS) \ + -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"' + +LOCAL_MODULE := libandroidbridge + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_PRELINK_MODULE := false + +LOCAL_LDLIBS := -llog + +LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libcharon + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c new file mode 100644 index 0000000000..ecc2434811 --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include + +#include +#include +#include + +#define JNI_PACKAGE org_strongswan_android + +#define JNI_METHOD_PP(pack, klass, name, ret, ...) \ + ret Java_##pack##_##klass##_##name(JNIEnv *env, jobject this, ##__VA_ARGS__) + +#define JNI_METHOD_P(pack, klass, name, ret, ...) \ + JNI_METHOD_PP(pack, klass, name, ret, ##__VA_ARGS__) + +#define JNI_METHOD(klass, name, ret, ...) \ + JNI_METHOD_P(JNI_PACKAGE, klass, name, ret, ##__VA_ARGS__) + +/** + * hook in library for debugging messages + */ +extern void (*dbg) (debug_t group, level_t level, char *fmt, ...); + +/** + * Logging hook for library logs, using android specific logging + */ +static void dbg_android(debug_t group, level_t level, char *fmt, ...) +{ + va_list args; + + if (level <= 4) + { + char sgroup[16], buffer[8192]; + char *current = buffer, *next; + snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group); + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + while (current) + { /* log each line separately */ + next = strchr(current, '\n'); + if (next) + { + *(next++) = '\0'; + } + __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n", + sgroup, current); + current = next; + } + } +} + +/** + * Initialize charon and the libraries via JNI + */ +JNI_METHOD(CharonVpnService, initializeCharon, void) +{ + /* logging for library during initialization, as we have no bus yet */ + dbg = dbg_android; + + /* initialize library */ + if (!library_init(NULL)) + { + library_deinit(); + return; + } + + if (!libhydra_init("charon")) + { + libhydra_deinit(); + library_deinit(); + return; + } + + if (!libcharon_init("charon") || + !charon->initialize(charon, PLUGINS)) + { + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); + return; + } + + /* start daemon (i.e. the threads in the thread-pool) */ + charon->start(charon); +} + +/** + * Initialize charon and the libraries via JNI + */ +JNI_METHOD(CharonVpnService, deinitializeCharon, void) +{ + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); +} + diff --git a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java new file mode 100644 index 0000000000..596372f9d6 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java @@ -0,0 +1,50 @@ +package org.strongswan.android; + +import android.content.Intent; +import android.net.VpnService; + +public class CharonVpnService extends VpnService { + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // called whenever the service is started with startService + // create our own thread because we are running in the calling processes main thread + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onCreate() { + // onCreate is only called once + initializeCharon(); + super.onCreate(); + } + + @Override + public void onDestroy() { + // called once the service is to be destroyed + deinitializeCharon(); + super.onDestroy(); + } + + /** + * Initialization of charon, provided by libandroidbridge.so + */ + public native void initializeCharon(); + + /** + * Deinitialize charon, provided by libandroidbridge.so + */ + public native void deinitializeCharon(); + + /* + * The libraries are extracted to /data/data/org.strongswan.android/... + * during installation. + */ + static { + System.loadLibrary("crypto"); + System.loadLibrary("strongswan"); + System.loadLibrary("hydra"); + System.loadLibrary("charon"); + System.loadLibrary("androidbridge"); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java index 16d4a09734..b4fb6f398d 100644 --- a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java +++ b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java @@ -1,13 +1,32 @@ package org.strongswan.android; import android.app.Activity; +import android.content.Intent; +import android.net.VpnService; import android.os.Bundle; public class strongSwanActivity extends Activity { - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + startVpnService(); + } + + private void startVpnService() { + Intent intent = VpnService.prepare(this); + if (intent != null) { + startActivityForResult(intent, 0); + } else { + onActivityResult(0, RESULT_OK, null); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK) { + Intent intent = new Intent(this, CharonVpnService.class); + startService(intent); + } + } } \ No newline at end of file