diff --git a/app/src/main/jni/core/CMakeLists.txt b/app/src/main/jni/core/CMakeLists.txt index 56364764..cfb9a1db 100644 --- a/app/src/main/jni/core/CMakeLists.txt +++ b/app/src/main/jni/core/CMakeLists.txt @@ -3,7 +3,7 @@ project(core) add_library(capture SHARED pcapdroid.c capture_vpn.c - capture_root.c + capture_libpcap.c ip_lru.c ndpi_config.c crc32.c diff --git a/app/src/main/jni/core/capture_root.c b/app/src/main/jni/core/capture_libpcap.c similarity index 94% rename from app/src/main/jni/core/capture_root.c rename to app/src/main/jni/core/capture_libpcap.c index 408e181e..8fe648ef 100644 --- a/app/src/main/jni/core/capture_root.c +++ b/app/src/main/jni/core/capture_libpcap.c @@ -102,7 +102,7 @@ static int connectPcapd(pcapdroid_t *pd) { int sock; int client = -1; char pcapd[PATH_MAX]; - char *bpf = pd->root.bpf ? pd->root.bpf : ""; + char *bpf = pd->pcap.bpf ? pd->pcap.bpf : ""; if(pd->cb.get_libprog_path) pd->cb.get_libprog_path(pd, "pcapd", pcapd, sizeof(pcapd)); @@ -155,7 +155,7 @@ static int connectPcapd(pcapdroid_t *pd) { #ifdef ANDROID // File paths are currently disallowed // NOTE: interface validation is currently skipped when running local tests (files are used) - if(!valid_ifname(pd->root.capture_interface)) { + if(!valid_ifname(pd->pcap.capture_interface)) { log_e("Invalid capture_interface"); goto cleanup; } @@ -163,8 +163,8 @@ static int connectPcapd(pcapdroid_t *pd) { // Start the daemon char args[256]; - snprintf(args, sizeof(args), "-l pcapd.log -i '%s' -d -u %d -t -b '%s'", pd->root.capture_interface, pd->tls_decryption.enabled ? -1 : pd->app_filter, bpf); - if(run_shell_cmd(pcapd, args, pd->root.as_root, true) != 0) + snprintf(args, sizeof(args), "-l pcapd.log -i '%s' -d -u %d -t -b '%s'", pd->pcap.capture_interface, pd->tls_decryption.enabled ? -1 : pd->app_filter, bpf); + if(run_shell_cmd(pcapd, args, pd->pcap.as_root, true) != 0) goto cleanup; // Wait for pcapd to start @@ -222,7 +222,7 @@ static void remove_connection(pcapdroid_t *pd, pcap_conn_t *conn) { break; } - HASH_DEL(pd->root.connections, conn); + HASH_DEL(pd->pcap.connections, conn); pd_free(conn); } @@ -339,13 +339,13 @@ static bool handle_packet(pcapdroid_t *pd, pcapd_hdr_t *hdr, const char *buffer, tupleSwapPeers(&pkt.tuple); } - HASH_FIND(hh, pd->root.connections, &pkt.tuple, sizeof(zdtun_5tuple_t), conn); + HASH_FIND(hh, pd->pcap.connections, &pkt.tuple, sizeof(zdtun_5tuple_t), conn); if(!conn) { // is_tx may be wrong, search in the other direction is_tx = !is_tx; tupleSwapPeers(&pkt.tuple); - HASH_FIND(hh, pd->root.connections, &pkt.tuple, sizeof(zdtun_5tuple_t), conn); + HASH_FIND(hh, pd->pcap.connections, &pkt.tuple, sizeof(zdtun_5tuple_t), conn); if(!conn) { if((pkt.flags & ZDTUN_PKT_IS_FRAGMENT) && !(pkt.flags & ZDTUN_PKT_IS_FIRST_FRAGMENT)) { @@ -372,11 +372,11 @@ static bool handle_packet(pcapdroid_t *pd, pcapd_hdr_t *hdr, const char *buffer, } if(hdr->linktype == PCAPD_DLT_LINUX_SLL2) - data->root.ifidx = ntohl(*(uint32_t*)(buffer + 4)); // sll2_header->sll2_if_index + data->pcap.ifidx = ntohl(*(uint32_t*)(buffer + 4)); // sll2_header->sll2_if_index conn->tuple = pkt.tuple; conn->data = data; - HASH_ADD(hh, pd->root.connections, tuple, sizeof(zdtun_5tuple_t), conn); + HASH_ADD(hh, pd->pcap.connections, tuple, sizeof(zdtun_5tuple_t), conn); switch (conn->tuple.ipproto) { case IPPROTO_TCP: @@ -399,7 +399,7 @@ static bool handle_packet(pcapdroid_t *pd, pcapd_hdr_t *hdr, const char *buffer, } // like last_seen but monotonic - conn->data->root.last_update_ms = pd->now_ms; + conn->data->pcap.last_update_ms = pd->now_ms; // make a copy before passing it to pd_process_packet since conn may // be freed in update_connection_status, while the pkt_context_t is still @@ -422,7 +422,7 @@ static bool handle_packet(pcapdroid_t *pd, pcapd_hdr_t *hdr, const char *buffer, static void purge_expired_connections(pcapdroid_t *pd, uint8_t purge_all) { pcap_conn_t *conn, *tmp; - HASH_ITER(hh, pd->root.connections, conn, tmp) { + HASH_ITER(hh, pd->pcap.connections, conn, tmp) { uint64_t timeout = 0; switch(conn->tuple.ipproto) { @@ -437,7 +437,7 @@ static void purge_expired_connections(pcapdroid_t *pd, uint8_t purge_all) { break; } - if(purge_all || (pd->now_ms >= (conn->data->root.last_update_ms + timeout))) { + if(purge_all || (pd->now_ms >= (conn->data->pcap.last_update_ms + timeout))) { //log_d("IDLE (type=%d)", conn->tuple.ipproto); conn->data->to_purge = true; @@ -461,10 +461,10 @@ static void purge_expired_connections(pcapdroid_t *pd, uint8_t purge_all) { /* ******************************************************* */ -void root_iter_connections(pcapdroid_t *pd, conn_cb cb) { +void libpcap_iter_connections(pcapdroid_t *pd, conn_cb cb) { pcap_conn_t *conn, *tmp; - HASH_ITER(hh, pd->root.connections, conn, tmp) { + HASH_ITER(hh, pd->pcap.connections, conn, tmp) { if(cb(pd, &conn->tuple, conn->data) != 0) return; } @@ -472,7 +472,7 @@ void root_iter_connections(pcapdroid_t *pd, conn_cb cb) { /* ******************************************************* */ -int run_root(pcapdroid_t *pd) { +int run_libpcap(pcapdroid_t *pd) { int sock = -1; int rv = -1; char buffer[PCAPD_SNAPLEN]; @@ -485,9 +485,9 @@ int run_root(pcapdroid_t *pd) { char bpf[256]; bpf[0] = '\0'; - pd->root.as_root = true; // TODO support read from PCAP file - pd->root.bpf = getStringPref(pd, "getPcapDumperBpf", bpf, sizeof(bpf)); - pd->root.capture_interface = getStringPref(pd, "getCaptureInterface", capture_interface, sizeof(capture_interface)); + pd->pcap.as_root = true; // TODO support read from PCAP file + pd->pcap.bpf = getStringPref(pd, "getPcapDumperBpf", bpf, sizeof(bpf)); + pd->pcap.capture_interface = getStringPref(pd, "getCaptureInterface", capture_interface, sizeof(capture_interface)); #endif if((pd->zdt = zdtun_init(&callbacks, NULL)) == NULL) diff --git a/app/src/main/jni/core/capture_vpn.c b/app/src/main/jni/core/capture_vpn.c index 3d95256f..ac193ed6 100644 --- a/app/src/main/jni/core/capture_vpn.c +++ b/app/src/main/jni/core/capture_vpn.c @@ -48,7 +48,7 @@ static void protectSocketCallback(zdtun_t *zdt, socket_t sock) { pcapdroid_t *pd = ((pcapdroid_t*)zdtun_userdata(zdt)); JNIEnv *env = pd->env; - if(pd->root_capture) + if(!pd->vpn_capture) return; /* Call VpnService protect */ diff --git a/app/src/main/jni/core/jni_impl.c b/app/src/main/jni/core/jni_impl.c index 2cd700f3..ee771f47 100644 --- a/app/src/main/jni/core/jni_impl.c +++ b/app/src/main/jni/core/jni_impl.c @@ -162,7 +162,7 @@ static jobject getConnUpdate(pcapdroid_t *pd, const conn_and_tuple_t *conn) { } if(data->update_type & CONN_UPDATE_STATS) { - bool blocked = data->to_block && !pd->root_capture; // currently can only block connections in non-root mode + bool blocked = data->to_block && pd->vpn_capture; // currently can only block connections in non-root mode (*env)->CallVoidMethod(env, update, mids.connUpdateSetStats, data->last_seen, data->payload_length, data->sent_bytes, data->rcvd_bytes, data->sent_pkts, data->rcvd_pkts, data->blocked_pkts, @@ -232,8 +232,8 @@ static int dumpNewConnection(pcapdroid_t *pd, const conn_and_tuple_t *conn, jobj jobject src_string = (*env)->NewStringUTF(env, srcip); jobject dst_string = (*env)->NewStringUTF(env, dstip); - u_int ifidx = (pd->root_capture ? data->root.ifidx : 0); - u_int local_port = (!pd->root_capture ? data->vpn.local_port : conn_info->src_port); + u_int ifidx = (pd->vpn_capture ? 0 : data->pcap.ifidx); + u_int local_port = (pd->vpn_capture ? data->vpn.local_port : conn_info->src_port); bool mitm_decrypt = (pd->tls_decryption.enabled && data->proxied); jobject conn_descriptor = (*env)->NewObject(env, cls.conn, mids.connInit, data->incr_id, conn_info->ipver, conn_info->ipproto, @@ -586,7 +586,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl }, .app_filter = getIntPref(env, vpn, "getAppFilterUid"), .mitm_addon_uid = getIntPref(env, vpn, "getMitmAddonUid"), - .root_capture = (bool) getIntPref(env, vpn, "isRootCapture"), + .vpn_capture = (bool) !getIntPref(env, vpn, "isRootCapture"), .payload_mode = (payload_mode_t) getIntPref(env, vpn, "getPayloadMode"), .pcap_dump = { .enabled = (bool) getIntPref(env, vpn, "pcapDumpEnabled"), @@ -615,7 +615,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl if(pd.socks5.enabled) getSocks5ProxyAuth(&pd); - if(!pd.root_capture) + if(pd.vpn_capture) pd.vpn.tunfd = tunfd; getStringPref(&pd, "getWorkingDir", pd.cachedir, sizeof(pd.cachedir)); @@ -805,7 +805,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_reloadBlocklist(JNIEnv *env, j return false; } - if(pd->root_capture) { + if(!pd->vpn_capture) { log_e("firewall in root mode not implemented"); return false; } @@ -846,7 +846,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_reloadFirewallWhitelist(JNIEnv return false; } - if(pd->root_capture) { + if(!pd->vpn_capture) { log_e("firewall in root mode not implemented"); return false; } diff --git a/app/src/main/jni/core/pcapdroid.c b/app/src/main/jni/core/pcapdroid.c index 8e2b7b02..b9cd564b 100644 --- a/app/src/main/jni/core/pcapdroid.c +++ b/app/src/main/jni/core/pcapdroid.c @@ -27,8 +27,8 @@ #include "ndpi_protocol_ids.h" extern int run_vpn(pcapdroid_t *pd); -extern int run_root(pcapdroid_t *pd); -extern void root_iter_connections(pcapdroid_t *pd, conn_cb cb); +extern int run_libpcap(pcapdroid_t *pd); +extern void libpcap_iter_connections(pcapdroid_t *pd, conn_cb cb); extern void vpn_process_ndpi(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_conn_t *data); /* ******************************************************* */ @@ -531,7 +531,7 @@ static void process_ndpi_data(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_c data->update_type |= CONN_UPDATE_INFO; } - if(!pd->root_capture) + if(pd->vpn_capture) vpn_process_ndpi(pd, tuple, data); } @@ -883,8 +883,8 @@ static int zdtun_iter_adapter(zdtun_t *zdt, const zdtun_conn_t *conn_info, void } static void iter_active_connections(pcapdroid_t *pd, conn_cb cb) { - if(pd->root_capture) - root_iter_connections(pd, cb); + if(!pd->vpn_capture) + libpcap_iter_connections(pd, cb); else { struct iter_conn_data idata = { .pd = pd, @@ -975,7 +975,7 @@ void pd_housekeeping(pcapdroid_t *pd) { dump_capture_stats_now = false; //log_d("Send stats"); - if(!pd->root_capture) + if(pd->vpn_capture) zdtun_get_stats(pd->zdt, &pd->stats); if(pd->cb.send_stats_dump) @@ -1164,7 +1164,7 @@ int pd_run(pcapdroid_t *pd) { } if(pd->pcap_dump.enabled) { - int max_snaplen = pd->root_capture ? PCAPD_SNAPLEN : VPN_BUFFER_SIZE; + int max_snaplen = !pd->vpn_capture ? PCAPD_SNAPLEN : VPN_BUFFER_SIZE; // use the snaplen provided by the API if((pd->pcap_dump.snaplen <= 0) || (pd->pcap_dump.snaplen > max_snaplen)) @@ -1200,7 +1200,7 @@ int pd_run(pcapdroid_t *pd) { pd->cb.notify_service_status(pd, "started"); // Run the capture - int rv = pd->root_capture ? run_root(pd) : run_vpn(pd); + int rv = pd->vpn_capture ? run_vpn(pd) : run_libpcap(pd); log_i("Stopped packet loop"); diff --git a/app/src/main/jni/core/pcapdroid.h b/app/src/main/jni/core/pcapdroid.h index b2e43206..08e8a808 100644 --- a/app/src/main/jni/core/pcapdroid.h +++ b/app/src/main/jni/core/pcapdroid.h @@ -78,7 +78,7 @@ typedef struct { struct { uint64_t last_update_ms; // like last_seen but monotonic u_int ifidx; // the 1-based interface index - } root; + } pcap; struct { struct pkt_context *fw_pctx; // context for the forwarded packet uint16_t local_port; // local port, from zdtun to the Internet @@ -189,7 +189,7 @@ typedef struct pcapdroid { // config jint app_filter; jint mitm_addon_uid; - bool root_capture; + bool vpn_capture; payload_mode_t payload_mode; // stats @@ -222,7 +222,7 @@ typedef struct pcapdroid { bool as_root; char *bpf; char *capture_interface; - } root; // TODO rename: it can run without root to read a PCAP file + } pcap; }; struct { diff --git a/app/src/main/jni/tests/fuzz/fuzz_capture.c b/app/src/main/jni/tests/fuzz/fuzz_capture.c index 125b16ed..7dba00e3 100644 --- a/app/src/main/jni/tests/fuzz/fuzz_capture.c +++ b/app/src/main/jni/tests/fuzz/fuzz_capture.c @@ -29,7 +29,7 @@ static char errbuf[PCAP_ERRBUF_SIZE]; /* ******************************************************* */ int openPcap(pcapdroid_t *pd) { - char *pcap_path = pd->root.capture_interface; + char *pcap_path = pd->pcap.capture_interface; if(!pcap_path) { log_e("NULL pcap path"); diff --git a/app/src/main/jni/tests/test_utils.c b/app/src/main/jni/tests/test_utils.c index 01d8168c..6ec4725c 100644 --- a/app/src/main/jni/tests/test_utils.c +++ b/app/src/main/jni/tests/test_utils.c @@ -85,9 +85,9 @@ pcapdroid_t* pd_init_test(const char *ifname) { pcapdroid_t *pd = calloc(1, sizeof(pcapdroid_t)); assert(pd != NULL); - pd->root_capture = true; - pd->root.capture_interface = (char*) ifname; - pd->root.as_root = false; // don't run as root + pd->vpn_capture = false; + pd->pcap.capture_interface = (char*) ifname; + pd->pcap.as_root = false; // don't run as root pd->app_filter = -1; // don't filter pd->cb.get_libprog_path = getPcapdPath; pd->payload_mode = PAYLOAD_MODE_FULL;