android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
+ <uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/ic_launcher"
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <service android:name=".CharonVpnService" android:permission="android.permission.BIND_VPN_SERVICE">
+ <intent-filter>
+ <action android:name="android.net.VpnService"/>
+ </intent-filter>
+ </service>
</application>
</manifest>
\ No newline at end of file
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
vstr \
openssl \
+ libandroidbridge \
strongswan/src/libcharon \
strongswan/src/libhydra \
strongswan/src/libstrongswan \
--- /dev/null
+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)
+
+
--- /dev/null
+/*
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <string.h>
+#include <android/log.h>
+#include <jni.h>
+
+#include <hydra.h>
+#include <daemon.h>
+#include <library.h>
+
+#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();
+}
+
--- /dev/null
+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");
+ }
+}
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