mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-16 21:10:57 +08:00
Merge branch 'master' into dev
This commit is contained in:
commit
8d508b7cd1
@ -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;
|
||||
@ -46,6 +47,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;
|
||||
@ -103,6 +105,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);
|
||||
@ -289,10 +293,12 @@ public class CaptureService extends VpnService implements Runnable {
|
||||
public void run() {
|
||||
if(mParcelFileDescriptor != null) {
|
||||
int fd = mParcelFileDescriptor.getFd();
|
||||
int fd_setsize = getFdSetSize();
|
||||
|
||||
if(fd > 0)
|
||||
if((fd > 0) && (fd < fd_setsize)) {
|
||||
Log.d(TAG, "VPN fd: " + fd + " - FD_SETSIZE: " + fd_setsize);
|
||||
runPacketLoop(fd, this, Build.VERSION.SDK_INT);
|
||||
else
|
||||
} else
|
||||
Log.e(TAG, "Invalid VPN fd: " + fd);
|
||||
}
|
||||
}
|
||||
@ -401,7 +407,14 @@ 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 askStatsDump();
|
||||
public static native int getFdSetSize();
|
||||
}
|
||||
|
||||
@ -175,6 +175,9 @@ public class Utils {
|
||||
if(connInfo != null) {
|
||||
int ipAddress = connInfo.getIpAddress();
|
||||
|
||||
if(ipAddress == 0)
|
||||
return(null);
|
||||
|
||||
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
|
||||
ipAddress = Integer.reverseBytes(ipAddress);
|
||||
}
|
||||
@ -206,7 +209,7 @@ public class Utils {
|
||||
// try to get the WiFi IP address first
|
||||
String wifi_ip = getLocalWifiIpAddress(context);
|
||||
|
||||
if(wifi_ip != null) {
|
||||
if((wifi_ip != null) && (!wifi_ip.equals("0.0.0.0"))) {
|
||||
Log.d("getLocalIPAddress", "Using WiFi IP: " + wifi_ip);
|
||||
return wifi_ip;
|
||||
}
|
||||
@ -223,9 +226,8 @@ public class Utils {
|
||||
&& addr.isSiteLocalAddress() /* Exclude public IPs */
|
||||
&& !addr.equals(vpn_ip)) {
|
||||
String sAddr = addr.getHostAddress();
|
||||
boolean isIPv4 = sAddr.indexOf(':') < 0;
|
||||
|
||||
if (isIPv4) {
|
||||
if ((addr instanceof Inet4Address) && !sAddr.equals("0.0.0.0")) {
|
||||
Log.d("getLocalIPAddress", "Using interface '" + intf.getName() + "' IP: " + sAddr);
|
||||
return sAddr;
|
||||
}
|
||||
|
||||
@ -184,6 +184,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();
|
||||
}
|
||||
}
|
||||
@ -191,6 +195,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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -110,6 +110,25 @@ static bool send_header;
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static char* tuple2str(const zdtun_5tuple_t *tuple, char *buf, size_t bufsize) {
|
||||
char srcip[64], dstip[64];
|
||||
struct in_addr addr;
|
||||
|
||||
addr.s_addr = tuple->src_ip;
|
||||
strncpy(srcip, inet_ntoa(addr), sizeof(srcip));
|
||||
addr.s_addr = tuple->dst_ip;
|
||||
strncpy(dstip, inet_ntoa(addr), sizeof(dstip));
|
||||
|
||||
snprintf(buf, bufsize, "[proto %d]: %s:%u -> %s:%u",
|
||||
tuple->ipproto,
|
||||
srcip, ntohs(tuple->src_port),
|
||||
dstip, ntohs(tuple->dst_port));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
void free_ndpi(conn_data_t *data) {
|
||||
if(data->ndpi_flow) {
|
||||
ndpi_free_flow(data->ndpi_flow);
|
||||
@ -484,9 +503,8 @@ static int resolve_uid(vpnproxy_data_t *proxy, const zdtun_5tuple_t *conn_info)
|
||||
|
||||
if(uid >= 0) {
|
||||
#if 1
|
||||
char appbuf[256];
|
||||
char srcip[64], dstip[64];
|
||||
struct in_addr addr;
|
||||
char buf[256];
|
||||
char appbuf[128];
|
||||
|
||||
if(uid == 0)
|
||||
strncpy(appbuf, "ROOT", sizeof(appbuf));
|
||||
@ -495,16 +513,8 @@ static int resolve_uid(vpnproxy_data_t *proxy, const zdtun_5tuple_t *conn_info)
|
||||
else
|
||||
getApplicationByUid(proxy, uid, appbuf, sizeof(appbuf));
|
||||
|
||||
addr.s_addr = conn_info->src_ip;
|
||||
strncpy(srcip, inet_ntoa(addr), sizeof(srcip));
|
||||
addr.s_addr = conn_info->dst_ip;
|
||||
strncpy(dstip, inet_ntoa(addr), sizeof(dstip));
|
||||
|
||||
log_android(ANDROID_LOG_INFO, "[proto=%d]: %s:%u -> %s:%u [%d/%s]",
|
||||
conn_info->ipproto,
|
||||
srcip, ntohs(conn_info->src_port),
|
||||
dstip, ntohs(conn_info->dst_port),
|
||||
uid, appbuf);
|
||||
log_android(ANDROID_LOG_INFO, "%s [%d/%s]",
|
||||
tuple2str(conn_info, buf, sizeof(buf)), uid, appbuf);
|
||||
#endif
|
||||
} else
|
||||
uid = -1;
|
||||
@ -676,16 +686,24 @@ static int net2tap(zdtun_t *tun, char *pkt_buf, int pkt_size, const zdtun_conn_t
|
||||
int rv = write(proxy->tapfd, pkt_buf, pkt_size);
|
||||
|
||||
if(rv < 0) {
|
||||
if(errno == EIO) {
|
||||
if(errno == ENOBUFS) {
|
||||
char buf[256];
|
||||
|
||||
// Do not abort, the connection will be terminated
|
||||
log_android(ANDROID_LOG_ERROR, "Got ENOBUFS %s", tuple2str(zdtun_conn_get_5tuple(conn_info), buf, sizeof(buf)));
|
||||
} else 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 if(rv != pkt_size)
|
||||
log_android(ANDROID_LOG_WARN,
|
||||
} 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_FATAL,
|
||||
"partial tap write (%d / %d)", rv, pkt_size);
|
||||
else
|
||||
rv = -1;
|
||||
} else
|
||||
rv = 0;
|
||||
|
||||
return rv;
|
||||
@ -859,7 +877,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);
|
||||
@ -874,7 +892,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);
|
||||
@ -896,6 +914,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 */
|
||||
@ -984,8 +1004,8 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
|
||||
|
||||
// Limit the segments size for two reasons:
|
||||
// 1. to be able to encapsulate the packets for the UDP export
|
||||
// 2. to avoid ENOBUFS while writing to the tapfd (for big packets).
|
||||
zdtun_set_max_window_size(tun, 32768);
|
||||
// 2. to avoid ENOBUFS while writing to the tapfd (for big packets, e.g. speedtest).
|
||||
zdtun_set_max_window_size(tun, 8192);
|
||||
|
||||
log_android(ANDROID_LOG_DEBUG, "Starting packet loop [tapfd=%d]", tapfd);
|
||||
|
||||
@ -1001,7 +1021,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;
|
||||
}
|
||||
@ -1063,7 +1083,7 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
|
||||
check_tls_mitm(tun, &proxy, &pkt, conn);
|
||||
|
||||
if ((rc = zdtun_forward(tun, &pkt, conn)) != 0) {
|
||||
log_android(ANDROID_LOG_ERROR, "zdtun_forward failed with code %d", rc);
|
||||
log_android(ANDROID_LOG_ERROR, "zdtun_forward (proto=%d) failed with code %d", pkt.tuple.ipproto, rc);
|
||||
proxy.num_dropped_connections++;
|
||||
|
||||
zdtun_destroy_conn(tun, conn);
|
||||
@ -1120,6 +1140,8 @@ housekeeping:
|
||||
}
|
||||
|
||||
notifyServiceStatus(&proxy, "stopped");
|
||||
|
||||
finish_log();
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -1145,4 +1167,9 @@ Java_com_emanuelef_remote_1capture_CaptureService_askStatsDump(JNIEnv *env, jcla
|
||||
dump_vpn_stats_now = true;
|
||||
dump_capture_stats_now = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_emanuelef_remote_1capture_CaptureService_getFdSetSize(JNIEnv *env, jclass clazz) {
|
||||
return FD_SETSIZE;
|
||||
}
|
||||
|
||||
@ -79,5 +79,6 @@
|
||||
<string name="packets_sent">发送数据包</string>
|
||||
<string name="packets_rcvd">接收数据包</string>
|
||||
<string name="dns_queries">DNS 查询</string>
|
||||
<string name="dns_server">DNS 服务器</string>
|
||||
</resources>
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit b5fa5c3ffaae5746aa9c9434ac7198c818ecede4
|
||||
Subproject commit 220344447ec72773e90245324999af976c5568cd
|
||||
Loading…
Reference in New Issue
Block a user