mirror of https://github.com/M66B/NetGuard.git
Native refactoring
This commit is contained in:
parent
d90674ca16
commit
5630d71e27
|
@ -60,15 +60,17 @@ void *handle_events(void *);
|
||||||
|
|
||||||
void handle_tcp(JNIEnv *, jobject, const uint8_t *, const uint16_t);
|
void handle_tcp(JNIEnv *, jobject, const uint8_t *, const uint16_t);
|
||||||
|
|
||||||
void sendSYN(const struct connection *cur, int tun);
|
int openSocket(JNIEnv *, jobject, const struct sockaddr_in *);
|
||||||
|
|
||||||
void decode(JNIEnv *env, jobject, const uint8_t *, const uint16_t);
|
int sendSYN(const struct connection *, const int);
|
||||||
|
|
||||||
|
void decode(JNIEnv *, jobject, const uint8_t *, const uint16_t);
|
||||||
|
|
||||||
jint getUid(const int, const int, const void *, const uint16_t);
|
jint getUid(const int, const int, const void *, const uint16_t);
|
||||||
|
|
||||||
unsigned short checksum(unsigned short *, int);
|
unsigned short checksum(unsigned short *, int);
|
||||||
|
|
||||||
void nsleep(long);
|
void nsleep(const long);
|
||||||
|
|
||||||
char *hex(const u_int8_t *, const u_int16_t);
|
char *hex(const u_int8_t *, const u_int16_t);
|
||||||
|
|
||||||
|
@ -87,9 +89,7 @@ Java_eu_faircode_netguard_SinkholeService_jni_1start(JNIEnv *env, jobject instan
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Starting tun=%d", tun);
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Starting tun=%d", tun);
|
||||||
|
|
||||||
jint rs = (*env)->GetJavaVM(env, &jvm);
|
jint rs = (*env)->GetJavaVM(env, &jvm);
|
||||||
if (rs == JNI_OK)
|
if (rs != JNI_OK)
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "GetJavaVM OK");
|
|
||||||
else
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "GetJavaVM failed");
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "GetJavaVM failed");
|
||||||
|
|
||||||
running = 1;
|
running = 1;
|
||||||
|
@ -107,8 +107,9 @@ JNIEXPORT void JNICALL
|
||||||
Java_eu_faircode_netguard_SinkholeService_jni_1stop(JNIEnv *env, jobject instance, jint tun) {
|
Java_eu_faircode_netguard_SinkholeService_jni_1stop(JNIEnv *env, jobject instance, jint tun) {
|
||||||
running = 0;
|
running = 0;
|
||||||
while (!stopped) {
|
while (!stopped) {
|
||||||
|
// TODO interrupt thread
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopping");
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopping");
|
||||||
nsleep(100 * 1000L * 1000L);
|
nsleep(1000 * 1000L * 1000L);
|
||||||
}
|
}
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped");
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped");
|
||||||
}
|
}
|
||||||
|
@ -129,17 +130,13 @@ void *handle_events(void *a) {
|
||||||
|
|
||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
|
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
|
||||||
if (rs == JNI_OK)
|
if (rs != JNI_OK)
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "AttachCurrentThread OK");
|
|
||||||
else
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "AttachCurrentThread failed");
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "AttachCurrentThread failed");
|
||||||
|
|
||||||
int max;
|
int max;
|
||||||
int out;
|
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
fd_set wfds;
|
fd_set wfds;
|
||||||
fd_set efds;
|
fd_set efds;
|
||||||
fd_set swfds;
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char dest[20];
|
char dest[20];
|
||||||
|
|
||||||
|
@ -158,7 +155,6 @@ void *handle_events(void *a) {
|
||||||
|
|
||||||
max = args->tun;
|
max = args->tun;
|
||||||
|
|
||||||
out = 0;
|
|
||||||
struct connection *last = NULL;
|
struct connection *last = NULL;
|
||||||
struct connection *cur = connection;
|
struct connection *cur = connection;
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
|
@ -201,6 +197,7 @@ void *handle_events(void *a) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (cur->state == TCP_SYN_RECV) {
|
if (cur->state == TCP_SYN_RECV) {
|
||||||
|
// TODO check if tun writable?
|
||||||
FD_SET(cur->socket, &wfds);
|
FD_SET(cur->socket, &wfds);
|
||||||
if (cur->socket > max)
|
if (cur->socket > max)
|
||||||
max = cur->socket;
|
max = cur->socket;
|
||||||
|
@ -211,12 +208,6 @@ void *handle_events(void *a) {
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out) {
|
|
||||||
FD_SET(args->tun, &wfds);
|
|
||||||
if (args->tun > max)
|
|
||||||
max = args->tun;
|
|
||||||
}
|
|
||||||
|
|
||||||
tv.tv_sec = 10;
|
tv.tv_sec = 10;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
int ready = select(max + 1, &rfds, &wfds, &efds, &tv);
|
int ready = select(max + 1, &rfds, &wfds, &efds, &tv);
|
||||||
|
@ -252,10 +243,6 @@ void *handle_events(void *a) {
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "tun empty read");
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "tun empty read");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(args->tun, &wfds)) {
|
|
||||||
// TODO: send buffered packets
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check sockets
|
// Check sockets
|
||||||
struct connection *cur = connection;
|
struct connection *cur = connection;
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
|
@ -287,8 +274,10 @@ void *handle_events(void *a) {
|
||||||
inet_ntop(AF_INET, &(cur->daddr), dest, sizeof(dest));
|
inet_ntop(AF_INET, &(cur->daddr), dest, sizeof(dest));
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Established %s/%u lport=%u",
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Established %s/%u lport=%u",
|
||||||
dest, ntohs(cur->dest), cur->lport);
|
dest, ntohs(cur->dest), cur->lport);
|
||||||
sendSYN(cur, args->tun);
|
if (sendSYN(cur, args->tun) < 0)
|
||||||
cur->state = TCP_SYN_SENT;
|
cur->state = TCP_CLOSE;
|
||||||
|
else
|
||||||
|
cur->state = TCP_SYN_SENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
|
@ -298,9 +287,7 @@ void *handle_events(void *a) {
|
||||||
|
|
||||||
(*env)->DeleteGlobalRef(env, args->instance);
|
(*env)->DeleteGlobalRef(env, args->instance);
|
||||||
rs = (*jvm)->DetachCurrentThread(jvm);
|
rs = (*jvm)->DetachCurrentThread(jvm);
|
||||||
if (rs == JNI_OK)
|
if (rs != JNI_OK)
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "DetachCurrentThread OK");
|
|
||||||
else
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "DetachCurrentThread failed");
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "DetachCurrentThread failed");
|
||||||
free(args);
|
free(args);
|
||||||
|
|
||||||
|
@ -365,80 +352,30 @@ void handle_tcp(JNIEnv *env, jobject instance, const uint8_t *buffer, uint16_t l
|
||||||
syn->received = data;
|
syn->received = data;
|
||||||
syn->sent = NULL;
|
syn->sent = NULL;
|
||||||
syn->next = NULL;
|
syn->next = NULL;
|
||||||
|
// TODO handle data
|
||||||
|
|
||||||
|
// Build target address
|
||||||
|
struct sockaddr_in daddr;
|
||||||
|
memset(&daddr, 0, sizeof(struct sockaddr_in));
|
||||||
|
daddr.sin_family = AF_INET;
|
||||||
|
daddr.sin_port = tcphdr->dest;
|
||||||
|
daddr.sin_addr.s_addr = iphdr->daddr;
|
||||||
|
|
||||||
|
// Open socket
|
||||||
|
syn->socket = openSocket(env, instance, &daddr);
|
||||||
|
if (syn->socket < 0)
|
||||||
|
syn->state = TCP_CLOSE;
|
||||||
|
else {
|
||||||
|
syn->lport = getLocalPort(syn->socket);
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Connecting to %s/%u lport %u",
|
||||||
|
dest, ntohs(tcphdr->dest), syn->lport);
|
||||||
|
}
|
||||||
|
|
||||||
if (last == NULL)
|
if (last == NULL)
|
||||||
connection = syn;
|
connection = syn;
|
||||||
else
|
else
|
||||||
last->next = syn;
|
last->next = syn;
|
||||||
|
|
||||||
// Get TCP socket
|
|
||||||
if ((syn->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
||||||
// TODO
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "socket error %d: %s",
|
|
||||||
errno, strerror(errno));
|
|
||||||
syn->state = TCP_CLOSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set non blocking
|
|
||||||
uint8_t flags = fcntl(syn->socket, F_GETFL, 0);
|
|
||||||
if (flags < 0 || fcntl(syn->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
|
|
||||||
// TODO
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "fcntl error %d: %s",
|
|
||||||
errno, strerror(errno));
|
|
||||||
syn->state = TCP_CLOSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protect
|
|
||||||
jclass cls = (*env)->GetObjectClass(env, instance);
|
|
||||||
jmethodID mid = (*env)->GetMethodID(env, cls, "protect", "(I)Z");
|
|
||||||
if (mid == 0) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "protect not found");
|
|
||||||
syn->state = TCP_CLOSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jboolean isProtected = (*env)->CallBooleanMethod(env, instance, mid, syn->socket);
|
|
||||||
if (!isProtected)
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "protect failed");
|
|
||||||
|
|
||||||
jthrowable ex = (*env)->ExceptionOccurred(env);
|
|
||||||
if (ex) {
|
|
||||||
(*env)->ExceptionDescribe(env);
|
|
||||||
(*env)->ExceptionClear(env);
|
|
||||||
(*env)->DeleteLocalRef(env, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build target address
|
|
||||||
struct sockaddr_in a;
|
|
||||||
memset(&a, 0, sizeof(struct sockaddr_in));
|
|
||||||
a.sin_family = AF_INET;
|
|
||||||
a.sin_port = tcphdr->dest;
|
|
||||||
a.sin_addr.s_addr = iphdr->daddr;
|
|
||||||
|
|
||||||
// Initiate connect
|
|
||||||
int err = connect(syn->socket, &a, sizeof(struct sockaddr_in));
|
|
||||||
if (err < 0 && errno != EINPROGRESS) {
|
|
||||||
// TODO
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "connect error %d: %s",
|
|
||||||
errno, strerror(errno));
|
|
||||||
syn->state = TCP_CLOSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get local port
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
int sinlen = sizeof(sin);
|
|
||||||
if (getsockname(syn->socket, &sin, &sinlen) < 0)
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "getsockname error %d: %s",
|
|
||||||
errno, strerror(errno));
|
|
||||||
else
|
|
||||||
syn->lport = ntohs(sin.sin_port);
|
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Connecting to %s/%u lport %u",
|
|
||||||
dest, ntohs(tcphdr->dest), syn->lport);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -462,12 +399,70 @@ void handle_tcp(JNIEnv *env, jobject instance, const uint8_t *buffer, uint16_t l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdown(cur->socket, SHUT_RDWR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendSYN(const struct connection *cur, int tun) {
|
int openSocket(JNIEnv *env, jobject instance, const struct sockaddr_in *daddr) {
|
||||||
|
int sock = -1;
|
||||||
|
|
||||||
|
// Get TCP socket
|
||||||
|
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "socket error %d: %s",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set non blocking
|
||||||
|
uint8_t flags = fcntl(sock, F_GETFL, 0);
|
||||||
|
if (flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "fcntl error %d: %s",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protect
|
||||||
|
jclass cls = (*env)->GetObjectClass(env, instance);
|
||||||
|
jmethodID mid = (*env)->GetMethodID(env, cls, "protect", "(I)Z");
|
||||||
|
if (mid == 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "protect not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jboolean isProtected = (*env)->CallBooleanMethod(env, instance, mid, sock);
|
||||||
|
if (!isProtected)
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "protect failed");
|
||||||
|
|
||||||
|
jthrowable ex = (*env)->ExceptionOccurred(env);
|
||||||
|
if (ex) {
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
(*env)->ExceptionClear(env);
|
||||||
|
(*env)->DeleteLocalRef(env, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initiate connect
|
||||||
|
int err = connect(sock, daddr, sizeof(struct sockaddr_in));
|
||||||
|
if (err < 0 && errno != EINPROGRESS) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "connect error %d: %s",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLocalPort(const int sock) {
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
int len = sizeof(sin);
|
||||||
|
if (getsockname(sock, &sin, &len) < 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "getsockname error %d: %s",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
return ntohs(sin.sin_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sendSYN(const struct connection *cur, int tun) {
|
||||||
// Build packet
|
// Build packet
|
||||||
uint16_t len = sizeof(struct iphdr) + sizeof(struct tcphdr); // no data
|
uint16_t len = sizeof(struct iphdr) + sizeof(struct tcphdr); // no data
|
||||||
u_int8_t *buffer = calloc(len, 1);
|
u_int8_t *buffer = calloc(len, 1);
|
||||||
|
@ -520,13 +515,14 @@ void sendSYN(const struct connection *cur, int tun) {
|
||||||
"Sending SYN+ACK to tun %s/%u seq %u ack %u",
|
"Sending SYN+ACK to tun %s/%u seq %u ack %u",
|
||||||
to, ntohs(tcp->dest),
|
to, ntohs(tcp->dest),
|
||||||
ntohl(tcp->seq), ntohl(tcp->ack_seq));
|
ntohl(tcp->seq), ntohl(tcp->ack_seq));
|
||||||
if (write(tun, buffer, len) < 0) {
|
int res = write(tun, buffer, len);
|
||||||
// TODO
|
if (res < 0)
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "write error %d: %s",
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "write error %d: %s",
|
||||||
errno, strerror(errno));
|
errno, strerror(errno));
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode(JNIEnv *env, jobject instance, const uint8_t *buffer, const uint16_t length) {
|
void decode(JNIEnv *env, jobject instance, const uint8_t *buffer, const uint16_t length) {
|
||||||
|
@ -760,7 +756,7 @@ unsigned short checksum(unsigned short *addr, int len) {
|
||||||
return (answer);
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsleep(long ns) {
|
void nsleep(const long ns) {
|
||||||
struct timespec tim, tim2;
|
struct timespec tim, tim2;
|
||||||
tim.tv_sec = ns / 1000000000L;
|
tim.tv_sec = ns / 1000000000L;
|
||||||
tim.tv_nsec = ns % 1000000000L;
|
tim.tv_nsec = ns % 1000000000L;
|
||||||
|
|
Loading…
Reference in New Issue