mirror of https://github.com/M66B/NetGuard.git
parent
b1de77be1e
commit
af71ba803f
|
@ -25,10 +25,9 @@
|
||||||
// Global variables
|
// Global variables
|
||||||
|
|
||||||
JavaVM *jvm = NULL;
|
JavaVM *jvm = NULL;
|
||||||
|
int pipefds[2];
|
||||||
pthread_t thread_id = 0;
|
pthread_t thread_id = 0;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
jboolean stopping = 0;
|
|
||||||
jboolean signaled = 0;
|
|
||||||
int loglevel = ANDROID_LOG_WARN;
|
int loglevel = ANDROID_LOG_WARN;
|
||||||
|
|
||||||
extern int max_tun_msg;
|
extern int max_tun_msg;
|
||||||
|
@ -108,6 +107,17 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1init(JNIEnv *env, jobject instanc
|
||||||
|
|
||||||
if (pthread_mutex_init(&lock, NULL))
|
if (pthread_mutex_init(&lock, NULL))
|
||||||
log_android(ANDROID_LOG_ERROR, "pthread_mutex_init failed");
|
log_android(ANDROID_LOG_ERROR, "pthread_mutex_init failed");
|
||||||
|
|
||||||
|
// Create signal pipe
|
||||||
|
if (pipe(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)
|
||||||
|
log_android(ANDROID_LOG_ERROR, "fcntl pipefds[%d] O_NONBLOCK error %d: %s",
|
||||||
|
i, errno, strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
@ -155,14 +165,12 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1stop(
|
||||||
pthread_t t = thread_id;
|
pthread_t t = thread_id;
|
||||||
log_android(ANDROID_LOG_WARN, "Stop tun %d thread %x", tun, t);
|
log_android(ANDROID_LOG_WARN, "Stop tun %d thread %x", tun, t);
|
||||||
if (t && pthread_kill(t, 0) == 0) {
|
if (t && pthread_kill(t, 0) == 0) {
|
||||||
stopping = 1;
|
log_android(ANDROID_LOG_WARN, "Write pipe thread %x", t);
|
||||||
log_android(ANDROID_LOG_WARN, "Kill thread %x", t);
|
if (write(pipefds[1], "x", 1) < 0)
|
||||||
int err = pthread_kill(t, SIGUSR1);
|
log_android(ANDROID_LOG_WARN, "Write pipe error %d: %s", errno, strerror(errno));
|
||||||
if (err != 0)
|
|
||||||
log_android(ANDROID_LOG_WARN, "pthread_kill error %d: %s", err, strerror(err));
|
|
||||||
else {
|
else {
|
||||||
log_android(ANDROID_LOG_WARN, "Join thread %x", t);
|
log_android(ANDROID_LOG_WARN, "Join thread %x", t);
|
||||||
err = pthread_join(t, NULL);
|
int err = pthread_join(t, NULL);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
log_android(ANDROID_LOG_WARN, "pthread_join error %d: %s", err, strerror(err));
|
log_android(ANDROID_LOG_WARN, "pthread_join error %d: %s", err, strerror(err));
|
||||||
}
|
}
|
||||||
|
@ -295,6 +303,10 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1done(JNIEnv *env, jobject instanc
|
||||||
|
|
||||||
if (pthread_mutex_destroy(&lock))
|
if (pthread_mutex_destroy(&lock))
|
||||||
log_android(ANDROID_LOG_ERROR, "pthread_mutex_destroy failed");
|
log_android(ANDROID_LOG_ERROR, "pthread_mutex_destroy failed");
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
if (close(pipefds[i]))
|
||||||
|
log_android(ANDROID_LOG_ERROR, "Close pipe error %d: %s", errno, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
// JNI Util
|
// JNI Util
|
||||||
|
|
|
@ -20,10 +20,9 @@
|
||||||
#include "netguard.h"
|
#include "netguard.h"
|
||||||
|
|
||||||
extern JavaVM *jvm;
|
extern JavaVM *jvm;
|
||||||
|
extern int pipefds[2];
|
||||||
extern pthread_t thread_id;
|
extern pthread_t thread_id;
|
||||||
extern pthread_mutex_t lock;
|
extern pthread_mutex_t lock;
|
||||||
extern jboolean stopping;
|
|
||||||
extern jboolean signaled;
|
|
||||||
|
|
||||||
struct ng_session *ng_session = NULL;
|
struct ng_session *ng_session = NULL;
|
||||||
|
|
||||||
|
@ -46,18 +45,9 @@ void clear() {
|
||||||
ng_session = NULL;
|
ng_session = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_signal(int sig, siginfo_t *info, void *context) {
|
|
||||||
log_android(ANDROID_LOG_DEBUG, "Signal %d", sig);
|
|
||||||
signaled = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *handle_events(void *a) {
|
void *handle_events(void *a) {
|
||||||
int sdk;
|
|
||||||
int epoll_fd;
|
int epoll_fd;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
sigset_t blockset;
|
|
||||||
sigset_t emptyset;
|
|
||||||
struct sigaction sa;
|
|
||||||
|
|
||||||
struct arguments *args = (struct arguments *) a;
|
struct arguments *args = (struct arguments *) a;
|
||||||
log_android(ANDROID_LOG_WARN, "Start events tun=%d thread %x", args->tun, thread_id);
|
log_android(ANDROID_LOG_WARN, "Start events tun=%d thread %x", args->tun, thread_id);
|
||||||
|
@ -71,9 +61,7 @@ void *handle_events(void *a) {
|
||||||
}
|
}
|
||||||
args->env = env;
|
args->env = env;
|
||||||
|
|
||||||
// Get SDK version
|
// Get max sessions
|
||||||
sdk = sdk_int(env);
|
|
||||||
|
|
||||||
int maxsessions = 1024;
|
int maxsessions = 1024;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
if (getrlimit(RLIMIT_NOFILE, &rlim))
|
if (getrlimit(RLIMIT_NOFILE, &rlim))
|
||||||
|
@ -84,22 +72,10 @@ void *handle_events(void *a) {
|
||||||
rlim.rlim_cur, rlim.rlim_max, maxsessions);
|
rlim.rlim_cur, rlim.rlim_max, maxsessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block SIGUSR1
|
|
||||||
sigemptyset(&blockset);
|
|
||||||
sigaddset(&blockset, SIGUSR1);
|
|
||||||
sigprocmask(SIG_BLOCK, &blockset, NULL);
|
|
||||||
|
|
||||||
/// Handle SIGUSR1
|
|
||||||
sa.sa_sigaction = handle_signal;
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
sa.sa_flags = SA_RESTART;
|
|
||||||
sigaction(SIGUSR1, &sa, NULL);
|
|
||||||
|
|
||||||
// Terminate existing sessions not allowed anymore
|
// Terminate existing sessions not allowed anymore
|
||||||
check_allowed(args);
|
check_allowed(args);
|
||||||
|
|
||||||
stopping = 0;
|
int stopping = 0;
|
||||||
signaled = 0;
|
|
||||||
|
|
||||||
// Open epoll fd
|
// Open epoll fd
|
||||||
epoll_fd = epoll_create(1);
|
epoll_fd = epoll_create(1);
|
||||||
|
@ -109,6 +85,17 @@ void *handle_events(void *a) {
|
||||||
stopping = 1;
|
stopping = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Monitor stop events
|
||||||
|
struct epoll_event ev_pipe;
|
||||||
|
memset(&ev_pipe, 0, sizeof(struct epoll_event));
|
||||||
|
ev_pipe.events = EPOLLIN;
|
||||||
|
ev_pipe.data.ptr = &ev_pipe;
|
||||||
|
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 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;
|
||||||
|
}
|
||||||
|
|
||||||
// Monitor tun events
|
// Monitor tun events
|
||||||
struct epoll_event ev_tun;
|
struct epoll_event ev_tun;
|
||||||
memset(&ev_tun, 0, sizeof(struct epoll_event));
|
memset(&ev_tun, 0, sizeof(struct epoll_event));
|
||||||
|
@ -120,8 +107,6 @@ void *handle_events(void *a) {
|
||||||
stopping = 1;
|
stopping = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sigemptyset(&emptyset);
|
|
||||||
|
|
||||||
// Loop
|
// Loop
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
log_android(ANDROID_LOG_DEBUG, "Loop thread %x", thread_id);
|
log_android(ANDROID_LOG_DEBUG, "Loop thread %x", thread_id);
|
||||||
|
@ -178,36 +163,24 @@ void *handle_events(void *a) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1093893
|
log_android(ANDROID_LOG_DEBUG, "sessions ICMP %d UDP %d TCP %d max %d/%d",
|
||||||
int idle = (tsessions + usessions + tsessions == 0 && sdk >= 16);
|
isessions, usessions, tsessions, sessions, maxsessions);
|
||||||
log_android(ANDROID_LOG_DEBUG, "sessions ICMP %d UDP %d TCP %d max %d/%d idle %d sdk %d",
|
|
||||||
isessions, usessions, tsessions, sessions, maxsessions, idle, sdk);
|
|
||||||
|
|
||||||
// Next event time
|
// Next event time
|
||||||
ts.tv_sec = (sdk < 16 ? 5 : get_select_timeout(sessions, maxsessions));
|
ts.tv_sec = get_select_timeout(sessions, maxsessions);
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
|
|
||||||
// TODO: check if tun is writable?
|
// TODO: check if tun is writable?
|
||||||
|
|
||||||
// Poll
|
// Poll
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
sigset_t origmask;
|
|
||||||
pthread_sigmask(SIG_SETMASK, &emptyset, &origmask);
|
|
||||||
int ready = epoll_wait(epoll_fd, &ev, 1, ts.tv_sec * 1000);
|
int ready = epoll_wait(epoll_fd, &ev, 1, ts.tv_sec * 1000);
|
||||||
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
|
|
||||||
|
|
||||||
if (ready < 0) {
|
if (ready < 0) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
if (stopping && signaled) { ;
|
log_android(ANDROID_LOG_DEBUG,
|
||||||
log_android(ANDROID_LOG_WARN,
|
"epoll interrupted tun %d thread %x", args->tun, thread_id);
|
||||||
"epoll signaled tun %d thread %x", args->tun, thread_id);
|
continue;
|
||||||
report_exit(args, NULL);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
log_android(ANDROID_LOG_DEBUG,
|
|
||||||
"epoll interrupted tun %d thread %x", args->tun, thread_id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
log_android(ANDROID_LOG_ERROR,
|
log_android(ANDROID_LOG_ERROR,
|
||||||
"epoll tun %d thread %x error %d: %s",
|
"epoll tun %d thread %x error %d: %s",
|
||||||
|
@ -221,13 +194,23 @@ void *handle_events(void *a) {
|
||||||
if (ready == 0)
|
if (ready == 0)
|
||||||
log_android(ANDROID_LOG_DEBUG, "epoll timeout");
|
log_android(ANDROID_LOG_DEBUG, "epoll timeout");
|
||||||
else {
|
else {
|
||||||
log_android(ANDROID_LOG_DEBUG, "epoll ready %d in %d out %d err %d prot %d sock %d",
|
if (ev.data.ptr != &ev_pipe) {
|
||||||
ready,
|
if (ev.data.ptr == NULL)
|
||||||
(ev.events & EPOLLIN) != 0,
|
log_android(ANDROID_LOG_DEBUG, "epoll ready %d in %d out %d err %d",
|
||||||
(ev.events & EPOLLOUT) != 0,
|
ready,
|
||||||
(ev.events & EPOLLERR) != 0,
|
(ev.events & EPOLLIN) != 0,
|
||||||
(ev.data.ptr == NULL ? -1 : ((struct ng_session *) ev.data.ptr)->protocol),
|
(ev.events & EPOLLOUT) != 0,
|
||||||
(ev.data.ptr == NULL ? -1 : ((struct ng_session *) ev.data.ptr)->socket));
|
(ev.events & EPOLLERR) != 0);
|
||||||
|
else
|
||||||
|
log_android(ANDROID_LOG_DEBUG,
|
||||||
|
"epoll ready %d in %d out %d err %d prot %d sock %d",
|
||||||
|
ready,
|
||||||
|
(ev.events & EPOLLIN) != 0,
|
||||||
|
(ev.events & EPOLLOUT) != 0,
|
||||||
|
(ev.events & EPOLLERR) != 0,
|
||||||
|
((struct ng_session *) ev.data.ptr)->protocol,
|
||||||
|
((struct ng_session *) ev.data.ptr)->socket);
|
||||||
|
}
|
||||||
|
|
||||||
if (pthread_mutex_lock(&lock))
|
if (pthread_mutex_lock(&lock))
|
||||||
log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
|
log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
|
||||||
|
@ -240,9 +223,18 @@ void *handle_events(void *a) {
|
||||||
|
|
||||||
// Check upstream
|
// Check upstream
|
||||||
int error = 0;
|
int error = 0;
|
||||||
if (ev.data.ptr == NULL) {
|
if (ev.data.ptr == &ev_pipe) {
|
||||||
|
stopping = 1;
|
||||||
|
uint8_t buffer[1];
|
||||||
|
if (read(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");
|
||||||
|
|
||||||
|
} else if (ev.data.ptr == NULL) {
|
||||||
if (check_tun(args, &ev, epoll_fd, sessions, maxsessions) < 0)
|
if (check_tun(args, &ev, epoll_fd, sessions, maxsessions) < 0)
|
||||||
error = 1;
|
error = 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef PROFILE_EVENTS
|
#ifdef PROFILE_EVENTS
|
||||||
gettimeofday(&end, NULL);
|
gettimeofday(&end, NULL);
|
||||||
|
|
Loading…
Reference in New Issue