From c4af4c80b623142d119aaa59c93ee7e456a4d729 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Mon, 11 Jan 2021 23:41:40 +0100 Subject: [PATCH] Fix some broken TCP connections due to big packets --- app/src/main/jni/vpnproxy-jni/pcap.c | 2 +- app/src/main/jni/vpnproxy-jni/vpnproxy.c | 32 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/app/src/main/jni/vpnproxy-jni/pcap.c b/app/src/main/jni/vpnproxy-jni/pcap.c index 1058dcb5..f2ba262f 100644 --- a/app/src/main/jni/vpnproxy-jni/pcap.c +++ b/app/src/main/jni/vpnproxy-jni/pcap.c @@ -40,7 +40,7 @@ static uint8_t pcap_buffer[sizeof(struct pcaprec_hdr_s) + SNAPLEN]; static void write_pcap(int fd, const struct sockaddr *srv, size_t srv_size, const void *ptr, size_t len) { if(sendto(fd, ptr, len, 0, srv, srv_size) < 0) - __android_log_print(ANDROID_LOG_ERROR, PCAP_TAG, "sendto error[%d]: %s", errno, strerror(errno)); + __android_log_print(ANDROID_LOG_ERROR, PCAP_TAG, "sendto(%u) error[%d]: %s", len, errno, strerror(errno)); } /* ******************************************************* */ diff --git a/app/src/main/jni/vpnproxy-jni/vpnproxy.c b/app/src/main/jni/vpnproxy-jni/vpnproxy.c index b92716b3..576932a0 100644 --- a/app/src/main/jni/vpnproxy-jni/vpnproxy.c +++ b/app/src/main/jni/vpnproxy-jni/vpnproxy.c @@ -160,7 +160,7 @@ static void protectSocketCallback(zdtun_t *tun, socket_t sock) { /* ******************************************************* */ -static char* getApplicationByUid(vpnproxy_data_t *proxy, jint uid, char *buf, size_t bufsize) { +static char* getApplicationByUid(vpnproxy_data_t *proxy, jint uid, char *buf, int bufsize) { JNIEnv *env = proxy->env; const char *value = NULL; @@ -228,7 +228,7 @@ const char *getL7ProtoName(struct ndpi_detection_module_struct *mod, ndpi_protoc /* ******************************************************* */ static void process_ndpi_packet(conn_data_t *data, vpnproxy_data_t *proxy, const char *packet, - ssize_t size, uint8_t from_tap) { + int size, uint8_t from_tap) { bool giveup = ((data->sent_pkts + data->rcvd_pkts) >= MAX_DPI_PACKETS); data->l7proto = ndpi_detection_process_packet(proxy->ndpi, data->ndpi_flow, (const u_char *)packet, @@ -310,7 +310,7 @@ static bool shouldIgnoreApp(vpnproxy_data_t *proxy, int uid) { /* ******************************************************* */ -static void account_packet(zdtun_t *tun, const char *packet, ssize_t size, uint8_t from_tap, const zdtun_conn_t *conn_info) { +static void account_packet(zdtun_t *tun, const char *packet, int size, uint8_t from_tap, const zdtun_conn_t *conn_info) { struct sockaddr_in servaddr = {0}; conn_data_t *data = zdtun_conn_get_userdata(conn_info); vpnproxy_data_t *proxy; @@ -607,12 +607,21 @@ static void check_tls_mitm(zdtun_t *tun, struct vpnproxy_data *proxy, zdtun_pkt_ /* ******************************************************* */ -static int net2tap(zdtun_t *tun, char *pkt_buf, ssize_t pkt_size, const zdtun_conn_t *conn_info) { +static int net2tap(zdtun_t *tun, char *pkt_buf, int pkt_size, const zdtun_conn_t *conn_info) { vpnproxy_data_t *proxy = (vpnproxy_data_t*) zdtun_userdata(tun); - // TODO return value check - write(proxy->tapfd, pkt_buf, pkt_size); - return 0; + int rv = write(proxy->tapfd, pkt_buf, pkt_size); + + if(rv < 0) + 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, + "partial tap write (%d / %d)", rv, pkt_size); + else + rv = 0; + + return rv; } /* ******************************************************* */ @@ -819,8 +828,6 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) { /* NOTE: must match ConnDescriptor::setData */ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIJJJJIIII)V"); - log_android(ANDROID_LOG_ERROR, "CLASS: %u", cls.vpn_service); - vpnproxy_data_t proxy = { .tapfd = tapfd, .sdk = sdk, @@ -887,6 +894,11 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) { return(-2); } + // 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); + log_android(ANDROID_LOG_DEBUG, "Starting packet loop [tapfd=%d]", tapfd); notifyServiceStatus(&proxy, "started"); @@ -915,7 +927,7 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) { int max_fd; fd_set fdset; fd_set wrfds; - ssize_t size; + int size; struct timeval timeout = {.tv_sec = 0, .tv_usec = 500*1000}; // wake every 500 ms zdtun_fds(tun, &max_fd, &fdset, &wrfds);