From 62346aa67240ced0fb16b6725f16d8fa40eaea60 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 13 Dec 2023 23:32:08 +0000 Subject: [PATCH] mod_pcap add limited support for DLT_LINUX_SLL encapsulation, and fix bug (SIGSEGV) when DLT is rejected --- src/Linux/mod_pcap.c | 82 ++++++++++++++++++++++++++++------------- src/Linux/readPackets.c | 3 +- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/Linux/mod_pcap.c b/src/Linux/mod_pcap.c index 70f47fa..199c50a 100644 --- a/src/Linux/mod_pcap.c +++ b/src/Linux/mod_pcap.c @@ -77,7 +77,8 @@ extern "C" { SFLAdaptor *srcdev = NULL; SFLAdaptor *dstdev = NULL; - if(bpfs->dlt == DLT_EN10MB) { + switch(bpfs->dlt) { + case DLT_EN10MB: { mac_hdr = buf; mac_len = 14; // global MAC -> adaptor @@ -108,6 +109,29 @@ extern "C" { } } } + break; + case DLT_LINUX_SLL: { + // This encapsulation does not give us a normal MAC header + // [16b] + // [16b] + // [16b] + // [always padded to 64b] + // [16b] + // Not sure if we can get 802.1Q or 802.2 header here? + // For now just insist it must be IP or IP6. + uint16_t type_len = (buf[14] << 8) + buf[15]; + if(type_len != 0x0800 + && type_len != 0x86DD) + return; + // We will call takeSample with mac_hdr==NULL and mac_len==16. + // It should then send a sample with header_protocol IP or IP6. + mac_len = 16; + } + break; + case DLT_RAW: + default: + break; + } uint32_t ds_options = (HSP_SAMPLEOPT_DEV_SAMPLER | HSP_SAMPLEOPT_DEV_POLLER); @@ -263,6 +287,17 @@ extern "C" { _________________ tap_open __________________ -----------------___________________________------------------ */ + + static bool chooseDLT(BPFSoc *bpfs, int search) { + for(int ii=0; ii < bpfs->n_dlts; ii++) { + int dlt = bpfs->dlts[ii]; + if(dlt == search) { + bpfs->dlt = dlt; + return YES; + } + } + return NO; + } static void tap_open(EVMod *mod, BPFSoc *bpfs) { HSP_mod_PCAP *mdata = (HSP_mod_PCAP *)mod->data; @@ -327,16 +362,11 @@ extern "C" { // takeSample() call more explicitly. (SFLHEADER_IEEE80211MAC or // SFLHEADER_IEEE80211_AMPUD or SFLHEADER_IEEE80211_AMSDU_SUBFRAME) // TODO: add support for MPLS encapsulation (SFLHEADER_MPLS) - for(int ii=0; ii < bpfs->n_dlts; ii++) { - int dlt = bpfs->dlts[ii]; - if(dlt == DLT_EN10MB - || dlt == DLT_RAW - // || dlt == DLT_IEEE802_11 - ) { - bpfs->dlt = dlt; - break; - } - } + // Apply preference order in case there is a choice... + if(chooseDLT(bpfs, DLT_EN10MB) == NO) + if(chooseDLT(bpfs, DLT_RAW) == NO) + chooseDLT(bpfs, DLT_LINUX_SLL); + // DLT_IEEE802_11 if(bpfs->dlt == -1) { myLog(LOG_ERR, "PCAP: %s has no supported datalink encapsulaton", bpfs->deviceName); tap_close(mod, bpfs); @@ -348,22 +378,22 @@ extern "C" { pcap_datalink_val_to_name(bpfs->dlt)); pcap_set_datalink(bpfs->pcap, bpfs->dlt); } - } - - // get file descriptor - int fd = pcap_fileno(bpfs->pcap); - // configure BPF sampling - if(bpfs->samplingRate > 1) - setKernelSampling(sp, bpfs, fd); - - // register - bpfs->sock = EVBusAddSocket(mod, mdata->packetBus, fd, readPackets_pcap, bpfs); - - // assume we always want to get counters for anything we are tapping. - // Have to force this here in case there are no samples that would - // trigger it in readPackets.c:takeSample() - forceCounterPolling(sp, bpfs->adaptor); + // get file descriptor + int fd = pcap_fileno(bpfs->pcap); + + // configure BPF sampling + if(bpfs->samplingRate > 1) + setKernelSampling(sp, bpfs, fd); + + // register + bpfs->sock = EVBusAddSocket(mod, mdata->packetBus, fd, readPackets_pcap, bpfs); + + // assume we always want to get counters for anything we are tapping. + // Have to force this here in case there are no samples that would + // trigger it in readPackets.c:takeSample() + forceCounterPolling(sp, bpfs->adaptor); + } } /*_________________---------------------------__________________ diff --git a/src/Linux/readPackets.c b/src/Linux/readPackets.c index c8fec23..5028856 100644 --- a/src/Linux/readPackets.c +++ b/src/Linux/readPackets.c @@ -332,7 +332,8 @@ extern "C" { macdst[0]='\0'; macsrc[0]='\0'; uint16_t ethtype = 0; - if(mac_len == 14) { + if(mac_hdr + && mac_len == 14) { printHex(mac_hdr+6,6,macsrc,12,NO); macsrc[12] = '\0'; printHex(mac_hdr+0,6,macdst,12,NO);