Added JNI context

This commit is contained in:
M66B 2017-11-09 19:07:08 +01:00
parent 605b0fb756
commit b64887dbfa
7 changed files with 97 additions and 98 deletions

View File

@ -137,6 +137,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
private int last_blocked = -1;
private int last_hosts = -1;
private long jni_context = 0;
private Thread tunnelThread = null;
private ServiceSinkhole.Builder last_builder = null;
private ParcelFileDescriptor vpn = null;
@ -196,25 +197,25 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
private static final String ACTION_SCREEN_OFF_DELAYED = "eu.faircode.netguard.SCREEN_OFF_DELAYED";
private static final String ACTION_WATCHDOG = "eu.faircode.netguard.WATCHDOG";
private native void jni_init(int sdk);
private native long jni_init(int sdk);
private native void jni_start(int loglevel);
private native void jni_start(long context, int loglevel);
private native void jni_run(int tun, boolean fwd53, int rcode);
private native void jni_run(long context, int tun, boolean fwd53, int rcode);
private native void jni_stop();
private native void jni_stop(long context);
private native void jni_clear();
private native void jni_clear(long context);
private native int jni_get_mtu();
private native int[] jni_get_stats();
private native int[] jni_get_stats(long context);
private static native void jni_pcap(String name, int record_size, int file_size);
private native void jni_socks5(String addr, int port, String username, String password);
private native void jni_done();
private native void jni_done(long context);
public static void setPcap(boolean enabled, Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@ -1022,7 +1023,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
// Show session/file count
if (filter && loglevel <= Log.WARN) {
int[] count = jni_get_stats();
int[] count = jni_get_stats(jni_context);
remoteViews.setTextViewText(R.id.tvSessions, count[0] + "/" + count[1] + "/" + count[2]);
remoteViews.setTextViewText(R.id.tvFiles, count[3] + "/" + count[4]);
} else {
@ -1423,13 +1424,13 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
if (tunnelThread == null) {
Log.i(TAG, "Starting tunnel thread");
jni_start(prio);
jni_start(jni_context, prio);
tunnelThread = new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "Running tunnel");
jni_run(vpn.getFd(), mapForward.containsKey(53), rcode);
jni_run(jni_context, vpn.getFd(), mapForward.containsKey(53), rcode);
Log.i(TAG, "Tunnel exited");
tunnelThread = null;
}
@ -1448,7 +1449,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
if (tunnelThread != null) {
Log.i(TAG, "Stopping tunnel thread");
jni_stop();
jni_stop(jni_context);
Thread thread = tunnelThread;
while (thread != null)
@ -1460,7 +1461,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
tunnelThread = null;
if (clear)
jni_clear();
jni_clear(jni_context);
Log.i(TAG, "Stopped tunnel thread");
}
@ -2304,7 +2305,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Native init
jni_init(Build.VERSION.SDK_INT);
jni_context = jni_init(Build.VERSION.SDK_INT);
boolean pcap = prefs.getBoolean("pcap", false);
setPcap(pcap, this);
@ -2643,7 +2644,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
jni_done();
jni_done(jni_context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.unregisterOnSharedPreferenceChangeListener(this);

View File

@ -19,7 +19,6 @@
#include "netguard.h"
extern struct ng_session *ng_session;
extern FILE *pcap_file;
int get_icmp_timeout(const struct icmp_session *u, int sessions, int maxsessions) {
@ -171,7 +170,7 @@ jboolean handle_icmp(const struct arguments *args,
}
// Search session
struct ng_session *cur = ng_session;
struct ng_session *cur = args->ctx->ng_session;
while (cur != NULL &&
!((cur->protocol == IPPROTO_ICMP || cur->protocol == IPPROTO_ICMPV6) &&
!cur->icmp.stop && cur->icmp.version == version &&
@ -222,8 +221,8 @@ jboolean handle_icmp(const struct arguments *args,
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s->socket, &s->ev))
log_android(ANDROID_LOG_ERROR, "epoll add icmp error %d: %s", errno, strerror(errno));
s->next = ng_session;
ng_session = s;
s->next = args->ctx->ng_session;
args->ctx->ng_session = s;
cur = s;
}

View File

@ -24,9 +24,6 @@
// Global variables
int pipefds[2];
int stopping = 0;
pthread_mutex_t lock;
char socks5_addr[INET6_ADDRSTRLEN + 1];
int socks5_port = 0;
char socks5_username[127 + 1];
@ -34,7 +31,7 @@ char socks5_password[127 + 1];
int loglevel = ANDROID_LOG_WARN;
extern int max_tun_msg;
extern struct ng_session *ng_session;
extern FILE *pcap_file;
extern size_t pcap_record_size;
extern long pcap_file_size;
@ -86,8 +83,6 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
void JNI_OnUnload(JavaVM *vm, void *reserved) {
log_android(ANDROID_LOG_INFO, "JNI unload");
clear();
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK)
log_android(ANDROID_LOG_INFO, "JNI load GetEnv failed");
@ -99,15 +94,12 @@ void JNI_OnUnload(JavaVM *vm, void *reserved) {
// JNI ServiceSinkhole
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1init(JNIEnv *env, jobject instance, jint sdk) {
loglevel = ANDROID_LOG_WARN;
JNIEXPORT jlong JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1init(
JNIEnv *env, jobject instance, jint sdk) {
struct context *ctx = calloc(1, sizeof(struct context));
struct arguments args;
args.env = env;
args.instance = instance;
args.sdk = sdk;
init(&args);
loglevel = ANDROID_LOG_WARN;
*socks5_addr = 0;
socks5_port = 0;
@ -115,28 +107,31 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1init(JNIEnv *env, jobject instanc
*socks5_password = 0;
pcap_file = NULL;
if (pthread_mutex_init(&lock, NULL))
if (pthread_mutex_init(&ctx->lock, NULL))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_init failed");
// Create signal pipe
if (pipe(pipefds))
if (pipe(ctx->pipefds))
log_android(ANDROID_LOG_ERROR, "Create pipe error %d: %s", errno, strerror(errno));
else
for (int i = 0; i < 2; i++) {
int flags = fcntl(pipefds[i], F_GETFL, 0);
if (flags < 0 || fcntl(pipefds[i], F_SETFL, flags | O_NONBLOCK) < 0)
int flags = fcntl(ctx->pipefds[i], F_GETFL, 0);
if (flags < 0 || fcntl(ctx->pipefds[i], F_SETFL, flags | O_NONBLOCK) < 0)
log_android(ANDROID_LOG_ERROR, "fcntl pipefds[%d] O_NONBLOCK error %d: %s",
i, errno, strerror(errno));
}
return (jlong) ctx;
}
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1start(
JNIEnv *env, jobject instance, jint loglevel_) {
JNIEnv *env, jobject instance, jlong context, jint loglevel_) {
struct context *ctx = (struct context *) context;
loglevel = loglevel_;
max_tun_msg = 0;
stopping = 0;
ctx->stopping = 0;
log_android(ANDROID_LOG_WARN, "Starting level %d", loglevel);
@ -144,7 +139,8 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1start(
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1run(
JNIEnv *env, jobject instance, jint tun, jboolean fwd53, jint rcode) {
JNIEnv *env, jobject instance, jlong context, jint tun, jboolean fwd53, jint rcode) {
struct context *ctx = (struct context *) context;
log_android(ANDROID_LOG_WARN, "Running tun %d fwd53 %d level %d", tun, fwd53, loglevel);
@ -161,23 +157,26 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1run(
args->tun = tun;
args->fwd53 = fwd53;
args->rcode = rcode;
args->ctx = ctx;
handle_events(args);
}
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1stop(
JNIEnv *env, jobject instance) {
stopping = 1;
JNIEnv *env, jobject instance, jlong context) {
struct context *ctx = (struct context *) context;
ctx->stopping = 1;
log_android(ANDROID_LOG_WARN, "Write pipe wakeup");
if (write(pipefds[1], "w", 1) < 0)
if (write(ctx->pipefds[1], "w", 1) < 0)
log_android(ANDROID_LOG_WARN, "Write pipe error %d: %s", errno, strerror(errno));
}
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1clear(
JNIEnv *env, jobject instance) {
clear();
JNIEnv *env, jobject instance, jlong context) {
struct context *ctx = (struct context *) context;
clear(ctx);
}
JNIEXPORT jint JNICALL
@ -186,15 +185,17 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1mtu(JNIEnv *env, jobject ins
}
JNIEXPORT jintArray JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1stats(JNIEnv *env, jobject instance) {
if (pthread_mutex_lock(&lock))
Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1stats(
JNIEnv *env, jobject instance, jlong context) {
struct context *ctx = (struct context *) context;
if (pthread_mutex_lock(&ctx->lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
jintArray jarray = (*env)->NewIntArray(env, 5);
jint *jcount = (*env)->GetIntArrayElements(env, jarray, NULL);
struct ng_session *s = ng_session;
struct ng_session *s = ctx->ng_session;
while (s != NULL) {
if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
if (!s->icmp.stop)
@ -209,7 +210,7 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1stats(JNIEnv *env, jobject i
s = s->next;
}
if (pthread_mutex_unlock(&lock))
if (pthread_mutex_unlock(&ctx->lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
jcount[3] = 0;
@ -239,8 +240,8 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1pcap(
pcap_record_size = (size_t) record_size;
pcap_file_size = file_size;
if (pthread_mutex_lock(&lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
//if (pthread_mutex_lock(&lock))
// log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
if (name_ == NULL) {
if (pcap_file != NULL) {
@ -283,8 +284,8 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1pcap(
(*env)->ReleaseStringUTFChars(env, name_, name);
}
if (pthread_mutex_unlock(&lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
//if (pthread_mutex_unlock(&lock))
// log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
}
JNIEXPORT void JNICALL
@ -309,17 +310,21 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1socks5(JNIEnv *env, jobject insta
}
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1done(JNIEnv *env, jobject instance) {
Java_eu_faircode_netguard_ServiceSinkhole_jni_1done(
JNIEnv *env, jobject instance, jlong context) {
struct context *ctx = (struct context *) context;
log_android(ANDROID_LOG_INFO, "Done");
clear();
clear(ctx);
if (pthread_mutex_destroy(&lock))
if (pthread_mutex_destroy(&ctx->lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_destroy failed");
for (int i = 0; i < 2; i++)
if (close(pipefds[i]))
if (close(ctx->pipefds[i]))
log_android(ANDROID_LOG_ERROR, "Close pipe error %d: %s", errno, strerror(errno));
free(ctx);
}
// JNI Util

View File

@ -68,6 +68,14 @@
#define SOCKS5_CONNECT 4
#define SOCKS5_CONNECTED 5
struct context {
pthread_mutex_t lock;
int pipefds[2];
int stopping;
int tun;
struct ng_session *ng_session;
};
struct arguments {
JNIEnv *env;
jobject instance;
@ -75,6 +83,7 @@ struct arguments {
int tun;
jboolean fwd53;
jint rcode;
struct context *ctx;
};
struct allowed {
@ -326,9 +335,7 @@ void report_error(const struct arguments *args, jint error, const char *fmt, ...
void check_allowed(const struct arguments *args);
void init(const struct arguments *args);
void clear();
void clear(struct context *ctx);
int check_icmp_session(const struct arguments *args,
struct ng_session *s,

View File

@ -19,18 +19,8 @@
#include "netguard.h"
extern int pipefds[2];
extern int stopping;
extern pthread_mutex_t lock;
struct ng_session *ng_session = NULL;
void init(const struct arguments *args) {
ng_session = NULL;
}
void clear() {
struct ng_session *s = ng_session;
void clear(struct context *ctx) {
struct ng_session *s = ctx->ng_session;
while (s != NULL) {
if (s->socket >= 0 && close(s->socket))
log_android(ANDROID_LOG_ERROR, "close %d error %d: %s",
@ -41,7 +31,7 @@ void clear() {
s = s->next;
free(p);
}
ng_session = NULL;
ctx->ng_session = NULL;
}
void *handle_events(void *a) {
@ -69,7 +59,7 @@ void *handle_events(void *a) {
if (epoll_fd < 0) {
log_android(ANDROID_LOG_ERROR, "epoll create error %d: %s", errno, strerror(errno));
report_exit(args, "epoll create error %d: %s", errno, strerror(errno));
stopping = 1;
args->ctx->stopping = 1;
}
// Monitor stop events
@ -77,10 +67,10 @@ void *handle_events(void *a) {
memset(&ev_pipe, 0, sizeof(struct epoll_event));
ev_pipe.events = EPOLLIN | EPOLLERR;
ev_pipe.data.ptr = &ev_pipe;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipefds[0], &ev_pipe)) {
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->ctx->pipefds[0], &ev_pipe)) {
log_android(ANDROID_LOG_ERROR, "epoll add pipe error %d: %s", errno, strerror(errno));
report_exit(args, "epoll add pipe error %d: %s", errno, strerror(errno));
stopping = 1;
args->ctx->stopping = 1;
}
// Monitor tun events
@ -91,12 +81,12 @@ void *handle_events(void *a) {
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->tun, &ev_tun)) {
log_android(ANDROID_LOG_ERROR, "epoll add tun error %d: %s", errno, strerror(errno));
report_exit(args, "epoll add tun error %d: %s", errno, strerror(errno));
stopping = 1;
args->ctx->stopping = 1;
}
// Loop
long long last_check = 0;
while (!stopping) {
while (!args->ctx->stopping) {
log_android(ANDROID_LOG_DEBUG, "Loop");
int recheck = 0;
@ -106,7 +96,7 @@ void *handle_events(void *a) {
int isessions = 0;
int usessions = 0;
int tsessions = 0;
struct ng_session *s = ng_session;
struct ng_session *s = args->ctx->ng_session;
while (s != NULL) {
if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
if (!s->icmp.stop)
@ -131,7 +121,7 @@ void *handle_events(void *a) {
time_t now = time(NULL);
struct ng_session *sl = NULL;
s = ng_session;
s = args->ctx->ng_session;
while (s != NULL) {
int del = 0;
if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
@ -162,7 +152,7 @@ void *handle_events(void *a) {
if (del) {
if (sl == NULL)
ng_session = s->next;
args->ctx->ng_session = s->next;
else
sl->next = s->next;
@ -208,7 +198,7 @@ void *handle_events(void *a) {
log_android(ANDROID_LOG_DEBUG, "epoll timeout");
else {
if (pthread_mutex_lock(&lock))
if (pthread_mutex_lock(&args->ctx->lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
int error = 0;
@ -217,12 +207,11 @@ void *handle_events(void *a) {
if (ev[i].data.ptr == &ev_pipe) {
// Check pipe
uint8_t buffer[1];
if (read(pipefds[0], buffer, 1) < 0)
if (read(args->ctx->pipefds[0], buffer, 1) < 0)
log_android(ANDROID_LOG_WARN, "Read pipe error %d: %s",
errno, strerror(errno));
else
log_android(ANDROID_LOG_WARN, "Read pipe");
break;
} else if (ev[i].data.ptr == NULL) {
// Check upstream
@ -265,7 +254,7 @@ void *handle_events(void *a) {
break;
}
if (pthread_mutex_unlock(&lock))
if (pthread_mutex_unlock(&args->ctx->lock))
log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
if (error)
@ -290,7 +279,7 @@ void check_allowed(const struct arguments *args) {
char dest[INET6_ADDRSTRLEN + 1];
struct ng_session *l = NULL;
struct ng_session *s = ng_session;
struct ng_session *s = args->ctx->ng_session;
while (s != NULL) {
if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
if (!s->icmp.stop) {
@ -334,7 +323,7 @@ void check_allowed(const struct arguments *args) {
log_android(ANDROID_LOG_WARN, "UDP remove blocked session uid %d", s->udp.uid);
if (l == NULL)
ng_session = s->next;
args->ctx->ng_session = s->next;
else
l->next = s->next;

View File

@ -19,7 +19,6 @@
#include "netguard.h"
extern struct ng_session *ng_session;
extern char socks5_addr[INET6_ADDRSTRLEN + 1];
extern int socks5_port;
extern char socks5_username[127 + 1];
@ -611,7 +610,7 @@ jboolean handle_tcp(const struct arguments *args,
const uint16_t datalen = (const uint16_t) (length - (data - pkt));
// Search session
struct ng_session *cur = ng_session;
struct ng_session *cur = args->ctx->ng_session;
while (cur != NULL &&
!(cur->protocol == IPPROTO_TCP &&
cur->tcp.version == version &&
@ -765,8 +764,8 @@ jboolean handle_tcp(const struct arguments *args,
log_android(ANDROID_LOG_ERROR, "epoll add tcp error %d: %s",
errno, strerror(errno));
s->next = ng_session;
ng_session = s;
s->next = args->ctx->ng_session;
args->ctx->ng_session = s;
if (!allowed) {
log_android(ANDROID_LOG_WARN, "%s resetting blocked session", packet);

View File

@ -19,7 +19,6 @@
#include "netguard.h"
extern struct ng_session *ng_session;
extern FILE *pcap_file;
int get_udp_timeout(const struct udp_session *u, int sessions, int maxsessions) {
@ -159,7 +158,7 @@ int has_udp_session(const struct arguments *args, const uint8_t *pkt, const uint
return 1;
// Search session
struct ng_session *cur = ng_session;
struct ng_session *cur = args->ctx->ng_session;
while (cur != NULL &&
!(cur->protocol == IPPROTO_UDP &&
cur->udp.version == version &&
@ -217,8 +216,8 @@ void block_udp(const struct arguments *args,
s->udp.state = UDP_BLOCKED;
s->socket = -1;
s->next = ng_session;
ng_session = s;
s->next = args->ctx->ng_session;
args->ctx->ng_session = s;
}
jboolean handle_udp(const struct arguments *args,
@ -235,7 +234,7 @@ jboolean handle_udp(const struct arguments *args,
const size_t datalen = length - (data - pkt);
// Search session
struct ng_session *cur = ng_session;
struct ng_session *cur = args->ctx->ng_session;
while (cur != NULL &&
!(cur->protocol == IPPROTO_UDP &&
cur->udp.version == version &&
@ -314,8 +313,8 @@ jboolean handle_udp(const struct arguments *args,
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s->socket, &s->ev))
log_android(ANDROID_LOG_ERROR, "epoll add udp error %d: %s", errno, strerror(errno));
s->next = ng_session;
ng_session = s;
s->next = args->ctx->ng_session;
args->ctx->ng_session = s;
cur = s;
}