#include "imc_android_state.h"
#include "../android_jni.h"
+#include "../charonservice.h"
#include <tnc/tnc.h>
#include <libpts.h>
return TNC_RESULT_SUCCESS;
}
+/**
+ * Update the state in the GUI.
+ */
+static void update_imc_state(TNC_ConnectionState state)
+{
+ android_imc_state_t imc_state = ANDROID_IMC_STATE_UNKNOWN;
+
+ switch (state)
+ { /* map connection states to the values used by the GUI */
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ imc_state = ANDROID_IMC_STATE_ALLOW;
+ break;
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ imc_state = ANDROID_IMC_STATE_ISOLATE;
+ break;
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ imc_state = ANDROID_IMC_STATE_BLOCK;
+ break;
+ }
+
+ charonservice->update_imc_state(charonservice, imc_state);
+}
+
/**
* see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
*/
return TNC_RESULT_SUCCESS;
case TNC_CONNECTION_STATE_DELETE:
return imc_android->delete_state(imc_android, connection_id);
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ update_imc_state(new_state);
+ /* fall-through */
default:
return imc_android->change_state(imc_android, connection_id,
new_state, NULL);
return success;
}
+METHOD(charonservice_t, update_imc_state, bool,
+ private_charonservice_t *this, android_imc_state_t state)
+{
+ JNIEnv *env;
+ jmethodID method_id;
+ bool success = FALSE;
+
+ androidjni_attach_thread(&env);
+
+ method_id = (*env)->GetMethodID(env, android_charonvpnservice_class,
+ "updateImcState", "(I)V");
+ if (!method_id)
+ {
+ goto failed;
+ }
+ (*env)->CallVoidMethod(env, this->vpn_service, method_id, (jint)state);
+ success = !androidjni_exception_occurred(env);
+
+failed:
+ androidjni_exception_occurred(env);
+ androidjni_detach_thread();
+ return success;
+}
+
/**
* Bypass a single socket
*/
INIT(this,
.public = {
.update_status = _update_status,
+ .update_imc_state = _update_imc_state,
.bypass_socket = _bypass_socket,
.get_trusted_certificates = _get_trusted_certificates,
.get_user_certificate = _get_user_certificate,
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil
#include <collections/linked_list.h>
typedef enum android_vpn_state_t android_vpn_state_t;
+typedef enum android_imc_state_t android_imc_state_t;
typedef struct charonservice_t charonservice_t;
/**
CHARONSERVICE_GENERIC_ERROR,
};
+/**
+ * Final IMC state as defined in ImcState.java
+ */
+enum android_imc_state_t {
+ ANDROID_IMC_STATE_UNKNOWN = 0,
+ ANDROID_IMC_STATE_ALLOW = 1,
+ ANDROID_IMC_STATE_BLOCK = 2,
+ ANDROID_IMC_STATE_ISOLATE = 3,
+};
+
/**
* Public interface of charonservice.
*
*/
bool (*update_status)(charonservice_t *this, android_vpn_state_t code);
+ /**
+ * Update final IMC state in the Java domain (UI)
+ *
+ * @param state IMC state
+ * @return TRUE on success
+ */
+ bool (*update_imc_state)(charonservice_t *this, android_imc_state_t state);
+
/**
* Install a bypass policy for the given socket using the protect() Method
* of the Android VpnService interface.
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil
import org.strongswan.android.data.VpnProfileDataSource;
import org.strongswan.android.logic.VpnStateService.ErrorState;
import org.strongswan.android.logic.VpnStateService.State;
+import org.strongswan.android.logic.imc.ImcState;
import org.strongswan.android.ui.MainActivity;
import android.app.PendingIntent;
setProfile(mCurrentProfile);
setError(ErrorState.NO_ERROR);
setState(State.CONNECTING);
+ setImcState(ImcState.UNKNOWN);
mIsDisconnecting = false;
BuilderAdapter builder = new BuilderAdapter(mCurrentProfile.getName());
}
}
+ /**
+ * Set the IMC state on the state service. Called by the handler thread and
+ * any of charon's threads.
+ *
+ * @param state IMC state
+ */
+ private void setImcState(ImcState state)
+ {
+ synchronized (mServiceLock)
+ {
+ if (mService != null)
+ {
+ mService.setImcState(state);
+ }
+ }
+ }
+
/**
* Set an error on the state service and disconnect the current connection.
* This is not done by calling stopCurrentConnection() above, but instead
}
}
+ /**
+ * Updates the IMC state of the current connection.
+ * Called via JNI by different threads (but not concurrently).
+ *
+ * @param value new state
+ */
+ public void updateImcState(int value)
+ {
+ ImcState state = ImcState.fromValue(value);
+ if (state != null)
+ {
+ setImcState(state);
+ }
+ }
+
/**
* Function called via JNI to generate a list of DER encoded CA certificates
* as byte array.
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
import java.util.concurrent.Callable;
import org.strongswan.android.data.VpnProfile;
+import org.strongswan.android.logic.imc.ImcState;
import android.app.Service;
import android.content.Context;
private VpnProfile mProfile;
private State mState = State.DISABLED;
private ErrorState mError = ErrorState.NO_ERROR;
+ private ImcState mImcState = ImcState.UNKNOWN;
public enum State
{
return mError;
}
+ /**
+ * Get the current IMC state, if any.
+ *
+ * @return imc state
+ */
+ public ImcState getImcState()
+ { /* only updated from the main thread so no synchronization needed */
+ return mImcState;
+ }
+
/**
* Disconnect any existing connection and shutdown the daemon, the
* VpnService is not stopped but it is reset so new connections can be
}
});
}
+
+ /**
+ * Set the current IMC state and notify all listeners, if changed.
+ *
+ * May be called from threads other than the main thread.
+ *
+ * @param error error state
+ */
+ public void setImcState(final ImcState state)
+ {
+ notifyListeners(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception
+ {
+ if (VpnStateService.this.mImcState != state)
+ {
+ VpnStateService.this.mImcState = state;
+ return true;
+ }
+ return false;
+ }
+ });
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package org.strongswan.android.logic.imc;
+
+public enum ImcState
+{
+ UNKNOWN(0),
+ ALLOW(1),
+ BLOCK(2),
+ ISOLATE(3);
+
+ private final int mValue;
+
+ private ImcState(int value)
+ {
+ mValue = value;
+ }
+
+ /**
+ * Get the numeric value of the IMC state.
+ * @return numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Get the enum entry from a numeric value, if defined
+ *
+ * @param value numeric value
+ * @return the enum entry or null
+ */
+ public static ImcState fromValue(int value)
+ {
+ for (ImcState state : ImcState.values())
+ {
+ if (state.mValue == value)
+ {
+ return state;
+ }
+ }
+ return null;
+ }
+}