Show fatal errors in the gui and terminate vpn

This commit is contained in:
emanuele-f 2021-02-17 17:27:53 +01:00
parent 6d47d75805
commit c78aba0dae
4 changed files with 76 additions and 7 deletions

View File

@ -28,6 +28,7 @@ import android.net.ConnectivityManager;
import android.net.VpnService;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
@ -42,6 +43,7 @@ public class CaptureService extends VpnService implements Runnable {
private static final String TAG = "CaptureService";
private static final String VpnSessionName = "PCAPdroid VPN";
private ParcelFileDescriptor mParcelFileDescriptor = null;
private Handler mHandler;
private Thread mThread;
private String vpn_ipv4;
private String vpn_dns;
@ -95,6 +97,8 @@ public class CaptureService extends VpnService implements Runnable {
public int onStartCommand(Intent intent, int flags, int startId) {
Context app_ctx = getApplicationContext();
mHandler = new Handler();
if (intent == null) {
Log.d(CaptureService.TAG, "NULL intent onStartCommand");
return super.onStartCommand(null, flags, startId);
@ -392,6 +396,12 @@ public class CaptureService extends VpnService implements Runnable {
mHttpServer.pushData(data);
}
public void reportError(String msg) {
mHandler.post(() -> {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
});
}
public static native void runPacketLoop(int fd, CaptureService vpn, int sdk);
public static native void stopPacketLoop();
public static native void askConnectionsDump();

View File

@ -161,6 +161,10 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
if (status.equals(CaptureService.SERVICE_STATUS_STARTED) && (mState == AppState.starting)) {
appStateRunning();
} else if (status.equals(CaptureService.SERVICE_STATUS_STOPPED)) {
// The service may still be active (on premature native termination)
if (CaptureService.isServiceActive())
CaptureService.stopService();
appStateReady();
}
}
@ -168,6 +172,14 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
}, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
}
@Override
public void onResume() {
super.onResume();
if(mMenu != null)
initAppState();
}
private void notifyAppState() {
for(AppStateListener listener: mStateListeners)
listener.appStateChanged(mState);

View File

@ -27,6 +27,33 @@
#include <malloc.h>
static int loglevel = 0;
static JNIEnv *cur_env = NULL;
static jclass vpnclass = 0;
static jclass vpn_inst = 0;
static jmethodID reportError = NULL;
jmethodID jniGetMethodID(JNIEnv *env, jclass cls, const char *name, const char *signature);
int jniCheckException(JNIEnv *env);
void DeleteLocalRef(JNIEnv *env, jobject *jresource);
/* ******************************************************* */
void init_log(int lvl, JNIEnv *env, jclass _vpnclass, jclass _vpn_inst) {
loglevel = lvl;
cur_env = env;
vpnclass = _vpnclass;
vpn_inst = _vpn_inst;
reportError = jniGetMethodID(cur_env, vpnclass, "reportError", "(Ljava/lang/String;)V");
}
/* ******************************************************* */
void finish_log() {
cur_env = NULL;
vpnclass = 0;
vpn_inst = 0;
reportError = 0;
}
/* ******************************************************* */
@ -37,8 +64,22 @@ void log_android(int prio, const char *fmt, ...) {
va_start(argptr, fmt);
vsnprintf(line, sizeof(line), fmt, argptr);
__android_log_print(prio, "VPNProxy", "%s", line);
va_end(argptr);
__android_log_print(prio, "VPNProxy", "%s", line);
if((prio >= ANDROID_LOG_FATAL) && (cur_env != NULL) && (reportError != NULL)) {
// This is a fatal error, report it to the gui
jobject info_string = (*cur_env)->NewStringUTF(cur_env, line);
if((jniCheckException(cur_env) != 0) || (info_string == NULL))
return;
(*cur_env)->CallVoidMethod(cur_env, vpn_inst, reportError, info_string);
jniCheckException(cur_env);
DeleteLocalRef(cur_env, info_string);
}
}
}

View File

@ -638,9 +638,11 @@ static int net2tap(zdtun_t *tun, char *pkt_buf, int pkt_size, const zdtun_conn_t
if(errno == EIO) {
log_android(ANDROID_LOG_INFO, "Got I/O error (terminating?)");
running = false;
} else
log_android(ANDROID_LOG_ERROR,
"tap write (%d) failed [%d]: %s", pkt_size, errno, strerror(errno));
} else {
log_android(ANDROID_LOG_FATAL,
"tap write (%d) failed [%d]: %s", pkt_size, errno, strerror(errno));
running = false;
}
} else if(rv != pkt_size)
log_android(ANDROID_LOG_WARN,
"partial tap write (%d / %d)", rv, pkt_size);
@ -830,7 +832,7 @@ static int connect_dumper(vpnproxy_data_t *proxy) {
dumper_socket = socket(AF_INET, proxy->pcap_dump.tcp_socket ? SOCK_STREAM : SOCK_DGRAM, 0);
if (!dumper_socket) {
log_android(ANDROID_LOG_ERROR,
log_android(ANDROID_LOG_FATAL,
"could not open UDP pcap dump socket [%d]: %s", errno,
strerror(errno));
return(-1);
@ -845,7 +847,7 @@ static int connect_dumper(vpnproxy_data_t *proxy) {
servaddr.sin_addr.s_addr = proxy->pcap_dump.collector_addr;
if(connect(dumper_socket, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
log_android(ANDROID_LOG_ERROR,
log_android(ANDROID_LOG_FATAL,
"connection to the PCAP receiver failed [%d]: %s", errno,
strerror(errno));
return(-2);
@ -867,6 +869,8 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
time_t last_connections_dump = (time(NULL) * 1000) - CONNECTION_DUMP_UPDATE_FREQUENCY_MS + 1000 /* update in a second */;
jclass vpn_class = (*env)->GetObjectClass(env, vpn);
init_log(ANDROID_LOG_DEBUG, env, vpn_class, vpn);
zdtun_parse_pkt(mitmproxy_pkt_buffer, sizeof(mitmproxy_pkt_buffer)-1, &mitm_pkt);
/* Classes */
@ -972,7 +976,7 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
proxy.java_dump.buffer_idx = 0;
if(!proxy.java_dump.buffer) {
log_android(ANDROID_LOG_ERROR, "malloc(java_dump.buffer) failed with code %d/%s",
log_android(ANDROID_LOG_FATAL, "malloc(java_dump.buffer) failed with code %d/%s",
errno, strerror(errno));
running = false;
}
@ -1099,6 +1103,8 @@ housekeeping:
}
notifyServiceStatus(&proxy, "stopped");
finish_log();
return(0);
}