Fix packets truncated with root and TSO/GRO

Packets were truncated on some devices employing offloading, in which
case the packet size was bigger than the MTU. A snaplen of 65535 fixes
this problem.

See #182
This commit is contained in:
emanuele-f 2022-01-27 14:20:00 +01:00
parent e1bafef088
commit a2d795152f
6 changed files with 13 additions and 36 deletions

View File

@ -486,7 +486,7 @@ void root_iter_connections(pcapdroid_t *pd, conn_cb cb) {
int run_root(pcapdroid_t *pd) {
int sock = -1;
int rv = -1;
char buffer[65535];
char buffer[PCAPD_SNAPLEN];
u_int64_t next_purge_ms;
zdtun_callbacks_t callbacks = {.send_client = (void*)1};

View File

@ -372,7 +372,7 @@ static void update_conn_status(zdtun_t *zdt, const zdtun_pkt_t *pkt, uint8_t fro
int run_vpn(pcapdroid_t *pd) {
zdtun_t *zdt;
char buffer[32768];
char buffer[VPN_BUFFER_SIZE];
u_int64_t next_purge_ms;
int flags = fcntl(pd->vpn.tunfd, F_GETFL, 0);

View File

@ -22,6 +22,7 @@
#include "pcapdroid.h"
#include "pcap_utils.h"
#include "common/utils.h"
#include "pcapd/pcapd.h"
#include "ndpi_protocol_ids.h"
extern int run_vpn(pcapdroid_t *pd);
@ -1061,9 +1062,10 @@ int pd_run(pcapdroid_t *pd) {
if(pd->pcap_dump.enabled) {
pd->pcap_dump.buffer = pd_malloc(JAVA_PCAP_BUFFER_SIZE);
pd->pcap_dump.buffer_idx = 0;
int max_snaplen = pd->root_capture ? PCAPD_SNAPLEN : VPN_BUFFER_SIZE;
if(pd->pcap_dump.snaplen <= 0)
pd->pcap_dump.snaplen = 65535;
if((pd->pcap_dump.snaplen <= 0) || (pd->pcap_dump.snaplen > max_snaplen))
pd->pcap_dump.snaplen = max_snaplen;
if(!pd->pcap_dump.buffer) {
log_f("malloc(pcap_dump.buffer) failed with code %d/%s",

View File

@ -35,6 +35,7 @@
#define NETD_RESOLVE_DELAY_MS 1000
#define SELECT_TIMEOUT_MS 250
#define MAX_DPI_PACKETS 12
#define VPN_BUFFER_SIZE 32768
#define MAX_HOST_LRU_SIZE 256
#define JAVA_PCAP_BUFFER_SIZE (512*1024) // 512K
#define PERIODIC_PURGE_TIMEOUT_MS 5000

View File

@ -183,25 +183,6 @@ static int get_iface_mac(const char *iface, uint64_t *mac) {
/* ******************************************************* */
static int get_iface_mtu(const char *iface) {
char fpath[128];
int mtu = -1;
snprintf(fpath, sizeof(fpath), "/sys/class/net/%s/mtu", iface);
FILE *f = fopen(fpath, "r");
if(f == NULL)
return -1;
fscanf(f, "%d", &mtu);
fclose(f);
return mtu;
}
/* ******************************************************* */
static int get_iface_ip(const char *iface, uint32_t *ip, uint32_t *netmask) {
struct ifreq ifr;
int fd;
@ -406,18 +387,8 @@ 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;
if(!strstr(ifname, ".pcap"))
log_d("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;
pcap_t *pd = pcap_open_live(ifname, snaplen, 0, 1, errbuf);
pcap_t *pd = pcap_open_live(ifname, PCAPD_SNAPLEN, 0, 1, errbuf);
if(!pd) {
// try to open as file
pd = pcap_open_offline(ifname, errbuf);
@ -427,8 +398,7 @@ static int open_interface(pcapd_iface_t *iface, pcapd_runtime_t *rt, const char
return -1;
}
is_file = 1;
} else
log_d("Using a %d snaplen (MTU %d)", snaplen, mtu);
}
// Fixes pcap_next_ex sometimes hanging on interface down
// https://github.com/the-tcpdump-group/libpcap/issues/899

View File

@ -18,6 +18,10 @@
#include <time.h>
#include <stdint.h>
// Using a snaplen large enough to avoid truncating packets even with TSO/GRO. Size is currently
// limited to 16 bits by pcapd_hdr_t.len
#define PCAPD_SNAPLEN 65535
// pcap/dlt.h
#define PCAPD_DLT_ETHERNET 1
#define PCAPD_DLT_RAW 12