mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-16 21:10:57 +08:00
Add pcap_reader and blacklist tests
The pcap_reader can be used to test the native PCAPdroid implementation. Native tests can be run with run_tests.sh
This commit is contained in:
parent
32da035db9
commit
2ea1229938
@ -13,6 +13,10 @@ set(ZDTUN_ROOT ${ROOTDIR}/submodules/zdtun)
|
||||
include_directories(${ZDTUN_ROOT})
|
||||
add_subdirectory(${ZDTUN_ROOT} zdtun_build)
|
||||
|
||||
# nDPI
|
||||
set(NDPI_ROOT ${ROOTDIR}/submodules/nDPI)
|
||||
include_directories(${NDPI_ROOT}/src/include ${NDPI_ROOT}/src/lib/third_party/include)
|
||||
|
||||
# base
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
||||
@ -108,6 +108,7 @@ ssize_t xwrite(int fd, const void *buf, size_t count) {
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
// returns < 0 on error, 0 if fd is closed
|
||||
ssize_t xread(int fd, void *buf, size_t count) {
|
||||
size_t sofar = 0;
|
||||
ssize_t rv;
|
||||
@ -125,9 +126,9 @@ ssize_t xread(int fd, void *buf, size_t count) {
|
||||
} while((sofar != count) && (rv != 0));
|
||||
|
||||
if(sofar != count)
|
||||
return -1;
|
||||
return (rv == 0) ? 0 : -1;
|
||||
|
||||
return 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
@ -12,9 +12,7 @@ add_library(capture SHARED
|
||||
jni_impl.c)
|
||||
|
||||
# nDPI
|
||||
set(NDPI_ROOT ${ROOTDIR}/submodules/nDPI)
|
||||
add_definitions(-DNDPI_LIB_COMPILATION)
|
||||
include_directories(${NDPI_ROOT}/src/include ${NDPI_ROOT}/src/lib/third_party/include)
|
||||
AUX_SOURCE_DIRECTORY(${NDPI_ROOT}/src/lib ndpiSources)
|
||||
AUX_SOURCE_DIRECTORY(${NDPI_ROOT}/src/lib/third_party/src ndpiSources)
|
||||
AUX_SOURCE_DIRECTORY(${NDPI_ROOT}/src/lib/protocols ndpiSources)
|
||||
|
||||
@ -253,6 +253,23 @@ bool blacklist_match_ip(blacklist_t *bl, const zdtun_ip_t *ip, int ipver) {
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
bool blacklist_match_ipstr(blacklist_t *bl, const char *ip_str) {
|
||||
ndpi_ip_addr_t addr;
|
||||
int ipver = ndpi_parse_ip_string(ip_str, &addr);
|
||||
zdtun_ip_t ip;
|
||||
|
||||
if(ipver == 4)
|
||||
ip.ip4 = addr.ipv4;
|
||||
else if(ipver == 6)
|
||||
memcpy(&ip.ip6, &addr.ipv6, 16);
|
||||
else
|
||||
return false;
|
||||
|
||||
return blacklist_match_ip(bl, &ip, ipver);
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
bool blacklist_match_domain(blacklist_t *bl, const char *domain) {
|
||||
string_entry_t *entry = NULL;
|
||||
|
||||
@ -337,4 +354,4 @@ int blacklist_load_list_descriptor(blacklist_t *bl, JNIEnv *env, jobject ld) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
||||
#endif // ANDROID
|
||||
|
||||
@ -76,6 +76,7 @@ int blacklist_load_file(blacklist_t *bl, const char *path, blacklist_type btype,
|
||||
int blacklist_load_list_descriptor(blacklist_t *bl, JNIEnv *env, jobject ld);
|
||||
#endif
|
||||
bool blacklist_match_ip(blacklist_t *bl, const zdtun_ip_t *ip, int ipver);
|
||||
bool blacklist_match_ipstr(blacklist_t *bl, const char *ip);
|
||||
bool blacklist_match_domain(blacklist_t *bl, const char *domain);
|
||||
bool blacklist_match_uid(blacklist_t *bl, int uid);
|
||||
void blacklist_get_stats(const blacklist_t *bl, blacklists_stats_t *stats);
|
||||
|
||||
@ -45,7 +45,7 @@ struct pcap_conn {
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static int su_cmd(const char *prog, const char *args, bool check_error) {
|
||||
static int run_cmd(const char *prog, const char *args, bool as_root, bool check_error) {
|
||||
int in_p[2], out_p[2];
|
||||
int rv = -1;
|
||||
pid_t pid;
|
||||
@ -57,7 +57,7 @@ static int su_cmd(const char *prog, const char *args, bool check_error) {
|
||||
|
||||
if((pid = fork()) == 0) {
|
||||
// child
|
||||
char *argp[] = {"sh", "-c", "su", NULL};
|
||||
char *argp[] = {"sh", "-c", as_root ? "su" : "sh", NULL};
|
||||
|
||||
close(in_p[1]);
|
||||
close(out_p[0]);
|
||||
@ -76,7 +76,7 @@ static int su_cmd(const char *prog, const char *args, bool check_error) {
|
||||
close(out_p[1]);
|
||||
|
||||
// write "su" command input
|
||||
log_d("su_cmd[%d]: %s %s", pid, prog, args);
|
||||
log_d("run_cmd[%d]: %s %s", pid, prog, args);
|
||||
write(in_p[1], prog, strlen(prog));
|
||||
write(in_p[1], " ", 1);
|
||||
write(in_p[1], args, strlen(args));
|
||||
@ -133,7 +133,7 @@ static void kill_pcapd(pcapdroid_t *nc) {
|
||||
|
||||
if(pid != 0) {
|
||||
log_d("Killing old pcapd with pid %d", pid);
|
||||
su_cmd("kill", pid_s, false);
|
||||
run_cmd("kill", pid_s, true, false);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
@ -144,15 +144,8 @@ static void kill_pcapd(pcapdroid_t *nc) {
|
||||
static int connectPcapd(pcapdroid_t *pd) {
|
||||
int sock;
|
||||
int client = -1;
|
||||
char bpf[256];
|
||||
char pcapd[PATH_MAX];
|
||||
char capture_interface[16] = "@inet";
|
||||
bpf[0] = '\0';
|
||||
|
||||
#if ANDROID
|
||||
getStringPref(pd, "getPcapDumperBpf", bpf, sizeof(bpf));
|
||||
getStringPref(pd, "getCaptureInterface", capture_interface, sizeof(capture_interface));
|
||||
#endif
|
||||
char *bpf = pd->root.bpf ? pd->root.bpf : "";
|
||||
|
||||
if(pd->cb.get_libprog_path)
|
||||
pd->cb.get_libprog_path(pd, "pcapd", pcapd, sizeof(pcapd));
|
||||
@ -198,8 +191,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\"", capture_interface, pd->app_filter, bpf);
|
||||
if(su_cmd(pcapd, args, true) != 0)
|
||||
snprintf(args, sizeof(args), "-l pcapd.log -i %s -d -u %d -t -b \"%s\"", pd->root.capture_interface, pd->app_filter, bpf);
|
||||
if(run_cmd(pcapd, args, pd->root.as_root, true) != 0)
|
||||
goto cleanup;
|
||||
|
||||
// Wait for pcapd to start
|
||||
@ -497,6 +490,16 @@ int run_root(pcapdroid_t *pd) {
|
||||
u_int64_t next_purge_ms;
|
||||
zdtun_callbacks_t callbacks = {.send_client = (void*)1};
|
||||
|
||||
#if ANDROID
|
||||
char capture_interface[16] = "@inet";
|
||||
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));
|
||||
#endif
|
||||
|
||||
if((pd->zdt = zdtun_init(&callbacks, NULL)) == NULL)
|
||||
return(-1);
|
||||
|
||||
@ -531,15 +534,17 @@ int run_root(pcapdroid_t *pd) {
|
||||
if(!FD_ISSET(sock, &fdset))
|
||||
goto housekeeping;
|
||||
|
||||
if(xread(sock, &hdr, sizeof(hdr)) < 0) {
|
||||
log_e("read hdr from pcapd failed[%d]: %s", errno, strerror(errno));
|
||||
ssize_t xrv = xread(sock, &hdr, sizeof(hdr));
|
||||
if(xrv != sizeof(hdr)) {
|
||||
if(xrv < 0)
|
||||
log_e("read hdr from pcapd failed[%d]: %s", errno, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
if(hdr.len > sizeof(buffer)) {
|
||||
log_e("packet too big (%d B)", hdr.len);
|
||||
goto cleanup;
|
||||
}
|
||||
if(xread(sock, buffer, hdr.len) < 0) {
|
||||
if(xread(sock, buffer, hdr.len) != hdr.len) {
|
||||
log_e("read %d B packet from pcapd failed[%d]: %s", hdr.len, errno, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -473,10 +473,8 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl
|
||||
.notify_service_status = notifyServiceStatus,
|
||||
.notify_blacklists_loaded = notifyBlacklistsLoaded,
|
||||
},
|
||||
.ip_to_host = ip_lru_init(MAX_HOST_LRU_SIZE),
|
||||
.app_filter = getIntPref(env, vpn, "getAppFilterUid"),
|
||||
.root_capture = (bool) getIntPref(env, vpn, "isRootCapture"),
|
||||
.new_conn_id = 0,
|
||||
.pcap_dump = {
|
||||
.enabled = (bool) getIntPref(env, vpn, "pcapDumpEnabled"),
|
||||
},
|
||||
@ -792,4 +790,4 @@ void getApplicationByUid(pcapdroid_t *pd, jint uid, char *buf, int bufsize) {
|
||||
if(obj) (*env)->DeleteLocalRef(env, obj);
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
||||
#endif // ANDROID
|
||||
|
||||
@ -1039,6 +1039,8 @@ int pd_run(pcapdroid_t *pd) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pd->ip_to_host = ip_lru_init(MAX_HOST_LRU_SIZE);
|
||||
|
||||
if(pd->malware_detection.enabled && pd->cb.load_blacklists_info)
|
||||
pd->cb.load_blacklists_info(pd);
|
||||
|
||||
@ -1075,6 +1077,10 @@ int pd_run(pcapdroid_t *pd) {
|
||||
|
||||
log_d("Stopped packet loop");
|
||||
|
||||
// send last dump
|
||||
if(pd->cb.send_connections_dump)
|
||||
pd->cb.send_connections_dump(pd);
|
||||
|
||||
conns_clear(&pd->new_conns, true);
|
||||
conns_clear(&pd->conns_updates, true);
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ struct pcapdroid;
|
||||
// Used to decouple pcapdroid.c from the JNI calls
|
||||
typedef struct {
|
||||
void (*get_libprog_path)(struct pcapdroid *pd, const char *prog_name, char *buf, int bufsize);
|
||||
int (*load_blacklists_info)(struct pcapdroid *pd);
|
||||
int (*load_blacklists_info)(struct pcapdroid *pd);
|
||||
void (*send_stats_dump)(struct pcapdroid *pd);
|
||||
void (*send_connections_dump)(struct pcapdroid *pd);
|
||||
void (*send_pcap_dump)(struct pcapdroid *pd);
|
||||
@ -193,7 +193,10 @@ typedef struct pcapdroid {
|
||||
} vpn;
|
||||
struct {
|
||||
pcap_conn_t *connections;
|
||||
} root;
|
||||
bool as_root;
|
||||
char *bpf;
|
||||
char *capture_interface;
|
||||
} root; // TODO rename: it can run without root to read a PCAP file
|
||||
};
|
||||
|
||||
struct {
|
||||
|
||||
@ -73,6 +73,7 @@ typedef struct {
|
||||
char name[IFNAMSIZ];
|
||||
int ifidx;
|
||||
uint8_t ifid; // positional interface index
|
||||
uint8_t is_file;
|
||||
pcap_t *pd;
|
||||
int pf;
|
||||
int dlink;
|
||||
@ -395,22 +396,28 @@ static void init_interface(pcapd_iface_t *iface) {
|
||||
|
||||
static int open_interface(pcapd_iface_t *iface, pcapd_runtime_t *rt, const char *ifname, int ifid) {
|
||||
#ifndef READ_FROM_PCAP
|
||||
int is_file = 0;
|
||||
int mtu = get_iface_mtu(ifname);
|
||||
|
||||
if(mtu < 0) {
|
||||
mtu = 1500;
|
||||
log_w("Could not get \"%s\" interface MTU, assuming %d", ifname, mtu);
|
||||
}
|
||||
|
||||
/* The snaplen includes the datalink overhead. Max datalink overhead (SLL2): 20 B */
|
||||
int snaplen = mtu + SLL2_HDR_LEN;
|
||||
log_d("Using a %d snaplen (MTU %d)", snaplen, mtu);
|
||||
|
||||
pcap_t *pd = pcap_open_live(ifname, snaplen, 0, 1, errbuf);
|
||||
|
||||
if(!pd) {
|
||||
log_i("pcap_open_live(%s) failed: %s", ifname, errbuf);
|
||||
return -1;
|
||||
// try to open as file
|
||||
pd = pcap_open_offline(ifname, errbuf);
|
||||
|
||||
if(!pd) {
|
||||
log_i("pcap_open(%s) failed: %s", ifname, errbuf);
|
||||
return -1;
|
||||
}
|
||||
is_file = 1;
|
||||
} else {
|
||||
if(mtu < 0) {
|
||||
mtu = 1500;
|
||||
log_w("Could not get \"%s\" interface MTU, assuming %d", ifname, mtu);
|
||||
}
|
||||
log_d("Using a %d snaplen (MTU %d)", snaplen, mtu);
|
||||
}
|
||||
|
||||
// Fixes pcap_next_ex sometimes hanging on interface down
|
||||
@ -479,20 +486,21 @@ static int open_interface(pcapd_iface_t *iface, pcapd_runtime_t *rt, const char
|
||||
|
||||
// Success
|
||||
iface->pd = pd;
|
||||
iface->is_file = is_file;
|
||||
iface->mac = 0;
|
||||
iface->ifid = ifid;
|
||||
iface->ifidx = if_nametoindex(ifname);
|
||||
|
||||
errno = 0;
|
||||
if((dlink == DLT_EN10MB) && (get_iface_mac(ifname, &iface->mac) < 0))
|
||||
if(!is_file && (dlink == DLT_EN10MB) && (get_iface_mac(ifname, &iface->mac) < 0))
|
||||
log_i("Could not get interface \"%s\" MAC[%d]: %s", ifname, errno, strerror(errno));
|
||||
|
||||
uint32_t netmask;
|
||||
iface->ip = 0;
|
||||
if(get_iface_ip(ifname, &iface->ip, &netmask) < 0)
|
||||
if(!is_file && get_iface_ip(ifname, &iface->ip, &netmask) < 0)
|
||||
log_i("Could not get interface \"%s\" IP[%d]: %s", ifname, errno, strerror(errno));
|
||||
|
||||
if(get_iface_ip6(ifname, &iface->ip6) < 0) {
|
||||
if(!is_file && get_iface_ip6(ifname, &iface->ip6) < 0) {
|
||||
log_i("Could not get interface \"%s\" IPv6[%d]: %s", ifname, errno, strerror(errno));
|
||||
memset(&iface->ip6, 0, sizeof(iface->ip6));
|
||||
}
|
||||
@ -744,9 +752,12 @@ static int read_pkt(pcapd_runtime_t *rt, pcapd_iface_t *iface, time_t now) {
|
||||
|
||||
// abort, resuming other interfaces is not supported yet
|
||||
return -1;
|
||||
} else if(rv != 1) {
|
||||
// TODO handle EOF without error
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((rv == 1) && (hdr->caplen >= to_skip)) {
|
||||
if(hdr->caplen >= to_skip) {
|
||||
pcapd_hdr_t phdr;
|
||||
zdtun_pkt_t zpkt;
|
||||
int len = hdr->caplen;
|
||||
@ -764,11 +775,15 @@ static int read_pkt(pcapd_runtime_t *rt, pcapd_iface_t *iface, time_t now) {
|
||||
tupleSwapPeers(&zpkt.tuple);
|
||||
}
|
||||
|
||||
int uid = uid_lru_find(rt->lru, &zpkt.tuple);
|
||||
int uid = UID_UNKNOWN;
|
||||
|
||||
if(uid == -2) {
|
||||
uid = get_uid(rt->resolver, &zpkt.tuple);
|
||||
uid_lru_add(rt->lru, &zpkt.tuple, uid);
|
||||
if(!iface->is_file) {
|
||||
uid = uid_lru_find(rt->lru, &zpkt.tuple);
|
||||
|
||||
if(uid == -2) {
|
||||
uid = get_uid(rt->resolver, &zpkt.tuple);
|
||||
uid_lru_add(rt->lru, &zpkt.tuple, uid);
|
||||
}
|
||||
}
|
||||
|
||||
if((rt->conf->uid_filter == -1) || (rt->conf->uid_filter == uid)) {
|
||||
@ -1011,6 +1026,9 @@ int main(int argc, char *argv[]) {
|
||||
rv = run_pcap_dump(&conf);
|
||||
unlink(PCAPD_PID);
|
||||
|
||||
for(int i=0; i<conf.num_interfaces; i++)
|
||||
free(conf.ifnames[i]);
|
||||
|
||||
if(conf.bpf)
|
||||
free(conf.bpf);
|
||||
if(conf.log_file)
|
||||
|
||||
32
app/src/main/jni/tests/CMakeLists.txt
Normal file
32
app/src/main/jni/tests/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
project(test)
|
||||
cmake_minimum_required(VERSION 3.18.1)
|
||||
|
||||
set(ROOTDIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/main)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
include_directories(${ROOTDIR}/submodules/zdtun)
|
||||
include_directories(${ROOTDIR}/submodules/nDPI/src/include)
|
||||
|
||||
include(CTest)
|
||||
list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
|
||||
|
||||
# Target to run tests and build them if necessary
|
||||
add_custom_target(run_tests COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
|
||||
# build_tests(target)
|
||||
macro(build_tests)
|
||||
ADD_EXECUTABLE(${ARGV0} ${ARGV0}.c test_utils.c)
|
||||
add_dependencies(${ARGV0} libpcapd.so)
|
||||
add_dependencies(run_tests ${ARGV0})
|
||||
|
||||
target_link_libraries(${ARGV0}
|
||||
capture
|
||||
pthread
|
||||
m)
|
||||
endmacro()
|
||||
|
||||
build_tests(pcap_reader)
|
||||
|
||||
add_test(NAME blacklist_match COMMAND ./blacklist match)
|
||||
build_tests(blacklist)
|
||||
59
app/src/main/jni/tests/blacklist.c
Normal file
59
app/src/main/jni/tests/blacklist.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of PCAPdroid.
|
||||
*
|
||||
* PCAPdroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PCAPdroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2022 - Emanuele Faranda
|
||||
*/
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static void test_match() {
|
||||
blacklist_t *bl = blacklist_init();
|
||||
assert(bl != NULL);
|
||||
|
||||
// Load blacklist
|
||||
assert0(blacklist_add_domain(bl, "example.org"));
|
||||
assert0(blacklist_add_ipstr(bl, "1.2.3.4"));
|
||||
assert0(blacklist_add_ipstr(bl, "::2"));
|
||||
assert0(blacklist_add_uid(bl, 777));
|
||||
assert0(blacklist_add_uid(bl, 888));
|
||||
|
||||
// Use blacklist
|
||||
assert1(blacklist_match_domain(bl, "www.example.org"));
|
||||
//assert1(blacklist_match_domain(bl, "some.example.org")); // TODO support subdomains matching
|
||||
|
||||
assert0(blacklist_match_ipstr(bl, "1.2.3.0"));
|
||||
assert1(blacklist_match_ipstr(bl, "1.2.3.4"));
|
||||
|
||||
assert0(blacklist_match_ipstr(bl, "::1"));
|
||||
assert1(blacklist_match_ipstr(bl, "::2"));
|
||||
|
||||
assert0(blacklist_match_uid(bl, 0));
|
||||
assert0(blacklist_match_uid(bl, 999));
|
||||
assert1(blacklist_match_uid(bl, 777));
|
||||
|
||||
blacklist_destroy(bl);
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
add_test("match", test_match);
|
||||
run_test(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
104
app/src/main/jni/tests/pcap_reader.c
Normal file
104
app/src/main/jni/tests/pcap_reader.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is part of PCAPdroid.
|
||||
*
|
||||
* PCAPdroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PCAPdroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2022 - Emanuele Faranda
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include "test_utils.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "pcap_reader - test for PCAPdroid\n"
|
||||
"Copyright 2022 Emanuele Faranda <black.silver@hotmail.it>\n\n"
|
||||
"Usage: pcap_reader -i ifname\n"
|
||||
" -i [ifname] capture packets on the specified interface or PCAP file.\n"
|
||||
" The '@inet' keyword can be used to capture from the internet\n"
|
||||
" interface\n"
|
||||
);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static void sig_handler(int signo) {
|
||||
if(running) {
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "exit now");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static void dump_connections(pcapdroid_t *pd) {
|
||||
char buf[256];
|
||||
|
||||
for(int i=0; i < pd->new_conns.cur_items; i++) {
|
||||
conn_and_tuple_t *conn = &pd->new_conns.items[i];
|
||||
|
||||
zdtun_5tuple2str(&conn->tuple, buf, sizeof(buf));
|
||||
printf("%s [%s]\n", buf,
|
||||
//pd_get_proto_name(pd, conn->data->l7proto, conn->tuple.ipproto),
|
||||
conn->data->info ? conn->data->info : "");
|
||||
}
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int c;
|
||||
char *ifname = NULL;
|
||||
uint8_t verbose = 0;
|
||||
|
||||
while((c = getopt(argc, argv, "hi:v")) != -1) {
|
||||
switch(c) {
|
||||
case 'i':
|
||||
ifname = strdup(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if(ifname == NULL)
|
||||
usage();
|
||||
|
||||
loglevel = verbose ? ANDROID_LOG_DEBUG : ANDROID_LOG_INFO;
|
||||
|
||||
pcapdroid_t *pd = pd_init(ifname);
|
||||
pd->cb.send_connections_dump = dump_connections;
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGHUP, sig_handler);
|
||||
|
||||
log_i("Capturing packets from %s", ifname);
|
||||
pd_run(pd);
|
||||
|
||||
log_i("Terminated");
|
||||
pd_free(pd);
|
||||
free(ifname);
|
||||
}
|
||||
4
app/src/main/jni/tests/run_tests.sh
Executable file
4
app/src/main/jni/tests/run_tests.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p build
|
||||
cd build && cmake .. && make -j$(nproc) run_tests
|
||||
90
app/src/main/jni/tests/test_utils.c
Normal file
90
app/src/main/jni/tests/test_utils.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of PCAPdroid.
|
||||
*
|
||||
* PCAPdroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PCAPdroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2022 - Emanuele Faranda
|
||||
*/
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
#define TEST_NAME_MAX_LENGTH 32
|
||||
#define MAX_TESTS 32
|
||||
|
||||
typedef struct {
|
||||
char name[TEST_NAME_MAX_LENGTH];
|
||||
void (*cb)();
|
||||
} test_spec;
|
||||
|
||||
static test_spec all_tests[MAX_TESTS] = {0};
|
||||
|
||||
static void getPcapdPath(struct pcapdroid *pd, const char *prog_name, char *buf, int bufsize) {
|
||||
snprintf(buf, bufsize, "main/pcapd/libpcapd.so");
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
void add_test(const char *name, void (*test_cb)()) {
|
||||
int len = strlen(name);
|
||||
assert(len < TEST_NAME_MAX_LENGTH);
|
||||
|
||||
for(int i=0; i<MAX_TESTS; i++) {
|
||||
if(all_tests[i].cb == NULL) {
|
||||
memcpy(all_tests[i].name, name, len); // \0 is already there
|
||||
all_tests[i].cb = test_cb;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// MAX_TESTS exceeded
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
void run_test(int argc, char **argv) {
|
||||
assert(argc == 2);
|
||||
const char *test_name = argv[1];
|
||||
test_spec *test = NULL;
|
||||
|
||||
for(int i=0; ((i < MAX_TESTS) && (all_tests[i].cb != NULL)); i++) {
|
||||
if(!strcmp(all_tests[i].name, test_name)) {
|
||||
test = &all_tests[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(test != NULL);
|
||||
|
||||
// run the test
|
||||
test->cb();
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
pcapdroid_t* pd_init(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->app_filter = -1; // don't filter
|
||||
pd->cb.get_libprog_path = getPcapdPath;
|
||||
|
||||
strcpy(pd->cachedir, ".");
|
||||
pd->cachedir_len = 1;
|
||||
|
||||
return pd;
|
||||
}
|
||||
38
app/src/main/jni/tests/test_utils.h
Normal file
38
app/src/main/jni/tests/test_utils.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of PCAPdroid.
|
||||
*
|
||||
* PCAPdroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PCAPdroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2022 - Emanuele Faranda
|
||||
*/
|
||||
|
||||
#ifndef __TEST_UTILS_H__
|
||||
#define __TEST_UTILS_H__
|
||||
|
||||
#include "core/pcapdroid.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define assert0(x) assert((x) == 0)
|
||||
#define assert1(x) assert((x) == 1)
|
||||
|
||||
void add_test(const char *name, void (*test_cb)());
|
||||
void run_test(int argc, char **argv);
|
||||
|
||||
pcapdroid_t* pd_init(const char *ifname);
|
||||
|
||||
static inline void pd_free(pcapdroid_t *pd) {
|
||||
free(pd);
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user