mirror of
https://github.com/M66B/NetGuard.git
synced 2025-02-22 22:31:17 +00:00
Native select
This commit is contained in:
parent
28c0bf2dad
commit
d90674ca16
4 changed files with 232 additions and 191 deletions
|
@ -98,7 +98,6 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/objectFiles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-rules" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
|
|
4
app/proguard-rules.pro
vendored
4
app/proguard-rules.pro
vendored
|
@ -23,9 +23,9 @@
|
|||
#NetGuard
|
||||
-keepnames class eu.faircode.netguard.** { *; }
|
||||
|
||||
# logPacket(int version, String saddr, int sport, String daddr, int dport, int protocol, String flags, int uid)
|
||||
#JNI callback
|
||||
-keep class eu.faircode.netguard.SinkholeService {
|
||||
void logPacket(int, java.lang.String, int, java.lang.String, int, int, java.lang.String, int);
|
||||
void logPacket(int, java.lang.String, int, java.lang.String, int, int, java.lang.String, int, boolean);
|
||||
}
|
||||
|
||||
#Support library
|
||||
|
|
|
@ -84,8 +84,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
private boolean phone_state = false;
|
||||
private Object subscriptionsChangedListener = null;
|
||||
private ParcelFileDescriptor vpn = null;
|
||||
private Thread receiveThread = null;
|
||||
private Thread pollThread = null;
|
||||
|
||||
private volatile Looper mServiceLooper;
|
||||
private volatile ServiceHandler mServiceHandler;
|
||||
|
@ -115,13 +113,11 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
|
||||
private static final String ACTION_SCREEN_OFF_DELAYED = "eu.faircode.netguard.SCREEN_OFF_DELAYED";
|
||||
|
||||
private native void jni_init();
|
||||
private native void jni_start(int tun);
|
||||
|
||||
private native void jni_tun(int fd);
|
||||
private native void jni_stop(int tun);
|
||||
|
||||
private native void jni_decode(byte[] buffer, int length);
|
||||
|
||||
private native void jni_poll();
|
||||
private native void jni_reload(int tun);
|
||||
|
||||
static {
|
||||
System.loadLibrary("netguard");
|
||||
|
@ -250,7 +246,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
if (vpn == null)
|
||||
throw new IllegalStateException("VPN start failed");
|
||||
if (prefs.getBoolean("log", false))
|
||||
startReceiving(vpn);
|
||||
jni_start(vpn.getFd());
|
||||
removeDisabledNotification();
|
||||
}
|
||||
break;
|
||||
|
@ -277,16 +273,14 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
if (vpn == null)
|
||||
throw new IllegalStateException("Handover failed");
|
||||
}
|
||||
stopReceiving();
|
||||
if (prefs.getBoolean("log", false))
|
||||
startReceiving(vpn);
|
||||
jni_reload(vpn.getFd());
|
||||
if (prev != null)
|
||||
stopVPN(prev);
|
||||
break;
|
||||
|
||||
case stop:
|
||||
if (vpn != null) {
|
||||
stopReceiving();
|
||||
jni_stop(vpn.getFd());
|
||||
stopVPN(vpn);
|
||||
vpn = null;
|
||||
}
|
||||
|
@ -671,8 +665,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setConfigureIntent(pi);
|
||||
|
||||
builder.setBlocking(true);
|
||||
|
||||
// Start VPN service
|
||||
try {
|
||||
return builder.establish();
|
||||
|
@ -692,64 +684,13 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
}
|
||||
|
||||
private void startReceiving(final ParcelFileDescriptor pfd) {
|
||||
receiveThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(pfd.getFileDescriptor());
|
||||
jni_tun(pfd.getFd());
|
||||
|
||||
// TODO read native
|
||||
Log.i(TAG, "Start receiving");
|
||||
byte[] bytes = new byte[32768];
|
||||
while (!Thread.currentThread().isInterrupted() &&
|
||||
pfd.getFileDescriptor() != null &&
|
||||
pfd.getFileDescriptor().valid())
|
||||
try {
|
||||
int length = in.read(bytes);
|
||||
if (length > 0)
|
||||
jni_decode(bytes, length);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
Log.i(TAG, "End receiving");
|
||||
} catch (Throwable ex) {
|
||||
if (!Thread.currentThread().isInterrupted() &&
|
||||
pfd.getFileDescriptor() != null &&
|
||||
pfd.getFileDescriptor().valid()) {
|
||||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
Util.sendCrashReport(ex, SinkholeService.this);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (in != null)
|
||||
in.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, getString(R.string.app_name) + " receive");
|
||||
receiveThread.start();
|
||||
|
||||
pollThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.currentThread().isInterrupted())
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
jni_poll();
|
||||
} catch (InterruptedException ignore) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, getString(R.string.app_name) + " poll");
|
||||
pollThread.start();
|
||||
}
|
||||
|
||||
// Called from native code
|
||||
private void logPacket(int version, String saddr, int sport, String daddr, int dport, int protocol, String flags, int uid) {
|
||||
private void logPacket(
|
||||
int version,
|
||||
String saddr, int sport,
|
||||
String daddr, int dport,
|
||||
int protocol, String flags,
|
||||
int uid, boolean allowed) {
|
||||
new DatabaseHelper(SinkholeService.this).insertLog(
|
||||
version,
|
||||
daddr,
|
||||
|
@ -761,13 +702,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
last_interactive).close();
|
||||
}
|
||||
|
||||
private void stopReceiving() {
|
||||
if (receiveThread != null)
|
||||
receiveThread.interrupt();
|
||||
if (pollThread != null)
|
||||
pollThread.interrupt();
|
||||
}
|
||||
|
||||
private BroadcastReceiver interactiveStateReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
@ -956,9 +890,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
ifPackage.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
ifPackage.addDataScheme("package");
|
||||
registerReceiver(packageAddedReceiver, ifPackage);
|
||||
|
||||
// Native
|
||||
jni_init();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1055,7 +986,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
if (vpn != null) {
|
||||
stopReceiving();
|
||||
jni_stop(vpn.getFd());
|
||||
stopVPN(vpn);
|
||||
vpn = null;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <android/log.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// 3 way handshake
|
||||
// -> SYN seq=x
|
||||
|
@ -23,9 +25,15 @@
|
|||
// TODO header file
|
||||
|
||||
#define TAG "NetGuard.JNI"
|
||||
#define MAXPKT 32678
|
||||
#define TIMEOUTPKT 30
|
||||
#define TTL 64
|
||||
|
||||
struct arguments {
|
||||
jobject instance;
|
||||
int tun;
|
||||
};
|
||||
|
||||
struct data {
|
||||
uint32_t seq; // host notation
|
||||
jbyte *data;
|
||||
|
@ -48,131 +56,211 @@ struct connection {
|
|||
struct connection *next;
|
||||
};
|
||||
|
||||
void poll();
|
||||
void *handle_events(void *);
|
||||
|
||||
void handle_tcp(JNIEnv *, jobject, const uint8_t *, const uint16_t);
|
||||
|
||||
void sendSYN(const struct connection *cur);
|
||||
void sendSYN(const struct connection *cur, int tun);
|
||||
|
||||
void decode(JNIEnv *env, jobject instance, const uint8_t *, const uint16_t);
|
||||
void decode(JNIEnv *env, jobject, const uint8_t *, const uint16_t);
|
||||
|
||||
jint getUid(const int, const int, const void *, const uint16_t);
|
||||
|
||||
unsigned short checksum(unsigned short *, int);
|
||||
|
||||
void nsleep(long);
|
||||
|
||||
char *hex(const u_int8_t *, const u_int16_t);
|
||||
|
||||
// Global variables
|
||||
|
||||
jint tun;
|
||||
static JavaVM *jvm;
|
||||
int running = 0;
|
||||
int stopped = 1;
|
||||
pthread_t thread_id;
|
||||
struct connection *connection = NULL;
|
||||
pthread_mutex_t poll_lock;
|
||||
|
||||
// JNI interface
|
||||
// JNI
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1init(JNIEnv *env, jobject instance) {
|
||||
__android_log_print(ANDROID_LOG_INFO, TAG, "Init");
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1start(JNIEnv *env, jobject instance, jint tun) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Starting tun=%d", tun);
|
||||
|
||||
if (pthread_mutex_init(&poll_lock, NULL) != 0)
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Mutex init error %d: %s",
|
||||
jint rs = (*env)->GetJavaVM(env, &jvm);
|
||||
if (rs == JNI_OK)
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "GetJavaVM OK");
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "GetJavaVM failed");
|
||||
|
||||
running = 1;
|
||||
struct arguments *args = malloc(sizeof(struct arguments));
|
||||
args->instance = (*env)->NewGlobalRef(env, instance);
|
||||
args->tun = tun;
|
||||
if (pthread_create(&thread_id, NULL, handle_events, args) != 0) {
|
||||
running = 0;
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "pthread_create error %d: %s",
|
||||
errno, strerror(errno));
|
||||
// TODO pthread_mutex_destroy
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1tun(JNIEnv *env, jobject instance, jint fd) {
|
||||
__android_log_print(ANDROID_LOG_INFO, TAG, "tun");
|
||||
tun = fd;
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1stop(JNIEnv *env, jobject instance, jint tun) {
|
||||
running = 0;
|
||||
while (!stopped) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopping");
|
||||
nsleep(100 * 1000L * 1000L);
|
||||
}
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1decode(JNIEnv *env, jobject instance,
|
||||
jbyteArray buffer_, jint length) {
|
||||
jbyte *buffer = (*env)->GetByteArrayElements(env, buffer_, NULL);
|
||||
decode(env, instance, buffer, length);
|
||||
(*env)->ReleaseByteArrayElements(env, buffer_, buffer, 0);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1poll(JNIEnv *env, jobject instance) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Poll");
|
||||
poll();
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1reload(JNIEnv *env, jobject instance, jint tun) {
|
||||
// TODO seamless handover
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Reload tun=%d", tun);
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1stop(env, instance, tun);
|
||||
Java_eu_faircode_netguard_SinkholeService_jni_1start(env, instance, tun);
|
||||
}
|
||||
|
||||
// Private functions
|
||||
|
||||
void poll() {
|
||||
// TODO timers
|
||||
if (pthread_mutex_lock(&poll_lock) != 0)
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Mutex lock error %d: %s",
|
||||
errno, strerror(errno));
|
||||
void *handle_events(void *a) {
|
||||
struct arguments *args = (struct arguments *) a;
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Start events tun=%d", args->tun);
|
||||
|
||||
time_t now = time(NULL);
|
||||
JNIEnv *env;
|
||||
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
|
||||
if (rs == JNI_OK)
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "AttachCurrentThread OK");
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "AttachCurrentThread failed");
|
||||
|
||||
struct connection *last = NULL;
|
||||
struct connection *cur = connection;
|
||||
while (cur != NULL) {
|
||||
// Log
|
||||
char dest[20];
|
||||
inet_ntop(AF_INET, &(cur->daddr), dest, sizeof(dest));
|
||||
int max;
|
||||
int out;
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
fd_set efds;
|
||||
fd_set swfds;
|
||||
struct timeval tv;
|
||||
char dest[20];
|
||||
|
||||
if (cur->state == TCP_CLOSE || cur->time + TIMEOUTPKT < now) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Close/timeout %s/%u lport=%u",
|
||||
dest, ntohs(cur->dest), cur->lport);
|
||||
stopped = 0;
|
||||
while (running) {
|
||||
time_t now = time(NULL);
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Select");
|
||||
|
||||
shutdown(cur->socket, SHUT_RDWR);
|
||||
// Select
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_ZERO(&efds);
|
||||
|
||||
if (last == NULL)
|
||||
connection = cur->next;
|
||||
else
|
||||
last->next = cur->next;
|
||||
FD_SET(args->tun, &rfds);
|
||||
FD_SET(args->tun, &efds);
|
||||
|
||||
struct data *prev;
|
||||
struct data *received = cur->received;
|
||||
while (received != NULL) {
|
||||
prev = received;
|
||||
received = received->next;
|
||||
if (prev->data != NULL)
|
||||
free(prev->data);
|
||||
free(prev);
|
||||
}
|
||||
max = args->tun;
|
||||
|
||||
struct data *sent = cur->sent;
|
||||
while (sent != NULL) {
|
||||
prev = sent;
|
||||
sent = sent->next;
|
||||
if (prev->data != NULL)
|
||||
free(prev->data);
|
||||
free(prev);
|
||||
}
|
||||
|
||||
free(cur);
|
||||
|
||||
} else {
|
||||
if (cur->state == TCP_SYN_RECV) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Poll %s/%u lport=%u",
|
||||
out = 0;
|
||||
struct connection *last = NULL;
|
||||
struct connection *cur = connection;
|
||||
while (cur != NULL) {
|
||||
if (cur->time + TIMEOUTPKT < now) {
|
||||
// Log
|
||||
inet_ntop(AF_INET, &(cur->daddr), dest, sizeof(dest));
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Idle %s/%u lport=%u",
|
||||
dest, ntohs(cur->dest), cur->lport);
|
||||
|
||||
// Check connection state
|
||||
fd_set wfds;
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(cur->socket, &wfds);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
int ready = select(cur->socket + 1, NULL, &wfds, NULL, &tv);
|
||||
if (ready < 0) {
|
||||
// TODO
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "select error %d: %s",
|
||||
errno, strerror(errno));
|
||||
continue;
|
||||
// TODO check if open
|
||||
shutdown(cur->socket, SHUT_RDWR);
|
||||
// TODO check for errors
|
||||
|
||||
if (last == NULL)
|
||||
connection = cur->next;
|
||||
else
|
||||
last->next = cur->next;
|
||||
|
||||
struct data *prev;
|
||||
|
||||
struct data *received = cur->received;
|
||||
while (received != NULL) {
|
||||
prev = received;
|
||||
received = received->next;
|
||||
if (prev->data != NULL)
|
||||
free(prev->data);
|
||||
free(prev);
|
||||
}
|
||||
|
||||
// Connected
|
||||
if (ready == 1) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Established ready=%d", ready);
|
||||
struct data *sent = cur->sent;
|
||||
while (sent != NULL) {
|
||||
prev = sent;
|
||||
sent = sent->next;
|
||||
if (prev->data != NULL)
|
||||
free(prev->data);
|
||||
free(prev);
|
||||
}
|
||||
|
||||
free(cur);
|
||||
|
||||
} else {
|
||||
if (cur->state == TCP_SYN_RECV) {
|
||||
FD_SET(cur->socket, &wfds);
|
||||
if (cur->socket > max)
|
||||
max = cur->socket;
|
||||
}
|
||||
}
|
||||
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
FD_SET(args->tun, &wfds);
|
||||
if (args->tun > max)
|
||||
max = args->tun;
|
||||
}
|
||||
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
int ready = select(max + 1, &rfds, &wfds, &efds, &tv);
|
||||
if (ready < 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "select error %d: %s",
|
||||
errno, strerror(errno));
|
||||
nsleep(1000 * 1000L * 1000L);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ready == 0)
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Yield");
|
||||
else {
|
||||
// Check tun
|
||||
if (FD_ISSET(args->tun, &efds)) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "tun exception");
|
||||
running = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET(args->tun, &rfds)) {
|
||||
uint8_t buffer[MAXPKT];
|
||||
ssize_t length = read(args->tun, buffer, MAXPKT);
|
||||
if (length < 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "tun read error %d: %s",
|
||||
errno, strerror(errno));
|
||||
running = 0;
|
||||
break;
|
||||
}
|
||||
if (length > 0)
|
||||
decode(env, args->instance, buffer, length);
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "tun empty read");
|
||||
}
|
||||
|
||||
if (FD_ISSET(args->tun, &wfds)) {
|
||||
// TODO: send buffered packets
|
||||
}
|
||||
|
||||
// Check sockets
|
||||
struct connection *cur = connection;
|
||||
while (cur != NULL) {
|
||||
// Check exceptions
|
||||
if (FD_ISSET(cur->socket, &efds)) {
|
||||
int serr;
|
||||
socklen_t optlen = sizeof(serr);
|
||||
if (getsockopt(cur->socket, SOL_SOCKET, SO_ERROR, &serr, &optlen) < 0) {
|
||||
|
@ -189,23 +277,35 @@ void poll() {
|
|||
cur->state = TCP_CLOSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
sendSYN(cur);
|
||||
|
||||
cur->state = TCP_SYN_SENT;
|
||||
} else {
|
||||
// TODO
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Connecting ready=%d", ready);
|
||||
}
|
||||
|
||||
// Check connects
|
||||
if (cur->state == TCP_SYN_RECV) {
|
||||
if (FD_ISSET(cur->socket, &wfds)) {
|
||||
// Log
|
||||
char dest[20];
|
||||
inet_ntop(AF_INET, &(cur->daddr), dest, sizeof(dest));
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Established %s/%u lport=%u",
|
||||
dest, ntohs(cur->dest), cur->lport);
|
||||
sendSYN(cur, args->tun);
|
||||
cur->state = TCP_SYN_SENT;
|
||||
}
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock(&poll_lock) != 0)
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Mutex unlock error %d: %s",
|
||||
errno, strerror(errno));
|
||||
(*env)->DeleteGlobalRef(env, args->instance);
|
||||
rs = (*jvm)->DetachCurrentThread(jvm);
|
||||
if (rs == JNI_OK)
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "DetachCurrentThread OK");
|
||||
else
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "DetachCurrentThread failed");
|
||||
free(args);
|
||||
|
||||
stopped = 1;
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped events tun=%d", args->tun);
|
||||
}
|
||||
|
||||
void handle_tcp(JNIEnv *env, jobject instance, const uint8_t *buffer, uint16_t length) {
|
||||
|
@ -344,10 +444,9 @@ void handle_tcp(JNIEnv *env, jobject instance, const uint8_t *buffer, uint16_t l
|
|||
else {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Existing connection lport %u", cur->lport);
|
||||
|
||||
if (tcphdr->syn) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Repeated SYN");
|
||||
sendSYN(cur);
|
||||
}
|
||||
if (tcphdr->syn)
|
||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Ignoring repeated SYN");
|
||||
|
||||
else if (tcphdr->ack) {
|
||||
cur->time = time(NULL);
|
||||
|
||||
|
@ -368,7 +467,7 @@ void handle_tcp(JNIEnv *env, jobject instance, const uint8_t *buffer, uint16_t l
|
|||
}
|
||||
}
|
||||
|
||||
void sendSYN(const struct connection *cur) {
|
||||
void sendSYN(const struct connection *cur, int tun) {
|
||||
// Build packet
|
||||
uint16_t len = sizeof(struct iphdr) + sizeof(struct tcphdr); // no data
|
||||
u_int8_t *buffer = calloc(len, 1);
|
||||
|
@ -535,22 +634,27 @@ void decode(JNIEnv *env, jobject instance, const uint8_t *buffer, const uint16_t
|
|||
__android_log_print(ANDROID_LOG_DEBUG, TAG,
|
||||
"Packet v%d %s/%u -> %s/%u proto %d flags %s uid %d",
|
||||
version, source, sport, dest, dport, protocol, flags, uid);
|
||||
poll();
|
||||
|
||||
if (protocol == IPPROTO_TCP)
|
||||
handle_tcp(env, instance, buffer, length);
|
||||
|
||||
// Call back
|
||||
jclass cls = (*env)->GetObjectClass(env, instance);
|
||||
jmethodID mid = (*env)->GetMethodID(env, cls, "logPacket",
|
||||
"(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;I)V");
|
||||
"(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;IZ)V");
|
||||
if (mid == 0)
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "logPacket not found");
|
||||
else {
|
||||
jboolean allowed = 0;
|
||||
jstring jsource = (*env)->NewStringUTF(env, source);
|
||||
jstring jdest = (*env)->NewStringUTF(env, dest);
|
||||
jstring jflags = (*env)->NewStringUTF(env, flags);
|
||||
(*env)->CallVoidMethod(env, instance, mid,
|
||||
version, jsource, sport, jdest, dport, protocol, jflags, uid);
|
||||
version,
|
||||
jsource, sport,
|
||||
jdest, dport,
|
||||
protocol, jflags,
|
||||
uid, allowed);
|
||||
(*env)->DeleteLocalRef(env, jsource);
|
||||
(*env)->DeleteLocalRef(env, jdest);
|
||||
(*env)->DeleteLocalRef(env, jflags);
|
||||
|
@ -656,6 +760,13 @@ unsigned short checksum(unsigned short *addr, int len) {
|
|||
return (answer);
|
||||
}
|
||||
|
||||
void nsleep(long ns) {
|
||||
struct timespec tim, tim2;
|
||||
tim.tv_sec = ns / 1000000000L;
|
||||
tim.tv_nsec = ns % 1000000000L;
|
||||
nanosleep(&tim, &tim2);
|
||||
}
|
||||
|
||||
char *hex(const u_int8_t *data, const u_int16_t len) {
|
||||
char hex_str[] = "0123456789ABCDEF";
|
||||
|
||||
|
|
Loading…
Reference in a new issue