]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pcap-file: add checksum-checks configuration variable
authorEric Leblond <eric@regit.org>
Thu, 20 Jun 2013 07:29:10 +0000 (09:29 +0200)
committerEric Leblond <eric@regit.org>
Mon, 2 Dec 2013 10:05:45 +0000 (11:05 +0100)
This patch adds support for checksum-checks in the pcap-file running
mode. This is the same functionnality as the one already existing for
live interface.

It can be setup in the YAML:
  pcap-file:
    checksum-checks: auto

A message is displayed for small pcap to warn that invalid checksum
rate is big on the pcap file and that checksum-check could
be set to no.

src/source-pcap-file.c
src/source-pcap-file.h
src/stream-tcp.c
suricata.yaml.in

index 6c951a9a267e6b4ef7e41756d15cb041fe90939c..f88cb4517de699002eafa13bda5f2cea73c7cd5e 100644 (file)
@@ -42,6 +42,8 @@
 #include "flow-manager.h"
 #include "util-profiling.h"
 #include "runmode-unix-socket.h"
+#include "util-checksum.h"
+#include "util-atomic.h"
 
 #ifdef __SC_CUDA_SUPPORT__
 
@@ -66,6 +68,10 @@ typedef struct PcapFileGlobalVars_ {
     int datalink;
     struct bpf_program filter;
     uint64_t cnt; /** packet counter */
+    ChecksumValidationMode conf_checksum_mode;
+    ChecksumValidationMode checksum_mode;
+    SC_ATOMIC_DECLARE(unsigned int, invalid_checksums);
+
 } PcapFileGlobalVars;
 
 /** max packets < 65536 */
@@ -149,6 +155,18 @@ void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt) {
         PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);
         SCReturn;
     }
+
+    /* We only check for checksum disable */
+    if (pcap_g.checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
+        p->flags |= PKT_IGNORE_CHECKSUM;
+    } else if (pcap_g.checksum_mode == CHECKSUM_VALIDATION_AUTO) {
+        if (ChecksumAutoModeCheck(ptv->pkts, p->pcap_cnt,
+                                  SC_ATOMIC_GET(pcap_g.invalid_checksums))) {
+            pcap_g.checksum_mode = CHECKSUM_VALIDATION_DISABLE;
+            p->flags |= PKT_IGNORE_CHECKSUM;
+        }
+    }
+
     PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);
 
     if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
@@ -236,6 +254,7 @@ TmEcode ReceivePcapFileLoop(ThreadVars *tv, void *data, void *slot)
 TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data) {
     SCEnter();
     char *tmpbpfstring = NULL;
+    char *tmpstring = NULL;
     if (initdata == NULL) {
         SCLogError(SC_ERR_INVALID_ARGUMENT, "error: initdata == NULL");
         SCReturnInt(TM_ECODE_FAILED);
@@ -310,6 +329,19 @@ TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data) {
             }
     }
 
+    if (ConfGet("pcap-file.checksum-checks", &tmpstring) != 1) {
+        pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO;
+    } else {
+        if (strcmp(tmpstring, "auto") == 0) {
+            pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO;
+        } else if (strcmp(tmpstring, "yes") == 0) {
+            pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_ENABLE;
+        } else if (strcmp(tmpstring, "no") == 0) {
+            pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_DISABLE;
+        }
+    }
+    pcap_g.checksum_mode = pcap_g.conf_checksum_mode;
+
     ptv->tv = tv;
     *data = (void *)ptv;
     SCReturnInt(TM_ECODE_OK);
@@ -319,6 +351,19 @@ void ReceivePcapFileThreadExitStats(ThreadVars *tv, void *data) {
     SCEnter();
     PcapFileThreadVars *ptv = (PcapFileThreadVars *)data;
 
+    if (pcap_g.conf_checksum_mode == CHECKSUM_VALIDATION_AUTO &&
+            pcap_g.cnt < CHECKSUM_SAMPLE_COUNT &&
+            SC_ATOMIC_GET(pcap_g.invalid_checksums)) {
+        uint64_t chrate = pcap_g.cnt / SC_ATOMIC_GET(pcap_g.invalid_checksums);
+        if (chrate < CHECKSUM_INVALID_RATIO)
+            SCLogWarning(SC_ERR_INVALID_CHECKSUM,
+                         "1/%" PRIu64 "th of packets have an invalid checksum,"
+                         " consider setting pcap-file.checksum-checks variable to no",
+                         chrate);
+        else
+            SCLogInfo("1/%" PRIu64 "th of packets have an invalid checksum",
+                      chrate);
+    }
     SCLogInfo("Pcap-file module read %" PRIu32 " packets, %" PRIu64 " bytes", ptv->pkts, ptv->bytes);
     return;
 }
@@ -395,5 +440,11 @@ TmEcode DecodePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data)
     SCReturnInt(TM_ECODE_OK);
 }
 
+
+void PcapIncreaseInvalidChecksum()
+{
+    (void) SC_ATOMIC_ADD(pcap_g.invalid_checksums, 1);
+}
+
 /* eof */
 
index 67bd261b6021bffb1bc86064e5379ad0c1e5dc5f..636cbdeb6da34bc498490f0628978149e48c927b 100644 (file)
@@ -27,5 +27,7 @@
 void TmModuleReceivePcapFileRegister (void);
 void TmModuleDecodePcapFileRegister (void);
 
+void PcapIncreaseInvalidChecksum();
+
 #endif /* __SOURCE_PCAP_FILE_H__ */
 
index 7abf72276c2c2e9236cc20deb53266f5eff377c0..cc3ed39866404f8f30648707b8cc2958d0943b2a 100644 (file)
@@ -71,6 +71,8 @@
 #include "util-misc.h"
 #include "util-validate.h"
 
+#include "source-pcap-file.h"
+
 //#define DEBUG
 
 #define STREAMTCP_DEFAULT_PREALLOC              2048
@@ -4429,6 +4431,8 @@ static inline int StreamTcpValidateChecksum(Packet *p)
         SCLogDebug("Checksum of received packet %p is invalid",p);
         if (p->livedev) {
             (void) SC_ATOMIC_ADD(p->livedev->invalid_checksums, 1);
+        } else if (p->pcap_cnt) {
+            PcapIncreaseInvalidChecksum();
         }
     }
 
index d10186315d101bb12cc49b6d2f5893ab18895850..dbbffb6cb5894ad9c3020930b4e8c6604e955a4e 100644 (file)
@@ -797,6 +797,15 @@ pcap:
   - interface: default
     #checksum-checks: auto
 
+pcap-file:
+  # Possible values are:
+  #  - yes: checksum validation is forced
+  #  - no: checksum validation is disabled
+  #  - auto: suricata uses a statistical approach to detect when
+  #  checksum off-loading is used. (default)
+  # Warning: 'checksum-validation' must be set to yes to have checksum tested
+  checksum-checks: auto
+
 # For FreeBSD ipfw(8) divert(4) support.
 # Please make sure you have ipfw_load="YES" and ipdivert_load="YES"
 # in /etc/loader.conf or kldload'ing the appropriate kernel modules.