pcap-file: add checksum-checks configuration variable

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.
pull/671/head
Eric Leblond 13 years ago
parent b2c58b8d14
commit 8b5be26f49

@ -42,6 +42,8 @@
#include "flow-manager.h" #include "flow-manager.h"
#include "util-profiling.h" #include "util-profiling.h"
#include "runmode-unix-socket.h" #include "runmode-unix-socket.h"
#include "util-checksum.h"
#include "util-atomic.h"
#ifdef __SC_CUDA_SUPPORT__ #ifdef __SC_CUDA_SUPPORT__
@ -66,6 +68,10 @@ typedef struct PcapFileGlobalVars_ {
int datalink; int datalink;
struct bpf_program filter; struct bpf_program filter;
uint64_t cnt; /** packet counter */ uint64_t cnt; /** packet counter */
ChecksumValidationMode conf_checksum_mode;
ChecksumValidationMode checksum_mode;
SC_ATOMIC_DECLARE(unsigned int, invalid_checksums);
} PcapFileGlobalVars; } PcapFileGlobalVars;
/** max packets < 65536 */ /** 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); PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);
SCReturn; 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); PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);
if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) { 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) { TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data) {
SCEnter(); SCEnter();
char *tmpbpfstring = NULL; char *tmpbpfstring = NULL;
char *tmpstring = NULL;
if (initdata == NULL) { if (initdata == NULL) {
SCLogError(SC_ERR_INVALID_ARGUMENT, "error: initdata == NULL"); SCLogError(SC_ERR_INVALID_ARGUMENT, "error: initdata == NULL");
SCReturnInt(TM_ECODE_FAILED); 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; ptv->tv = tv;
*data = (void *)ptv; *data = (void *)ptv;
SCReturnInt(TM_ECODE_OK); SCReturnInt(TM_ECODE_OK);
@ -319,6 +351,19 @@ void ReceivePcapFileThreadExitStats(ThreadVars *tv, void *data) {
SCEnter(); SCEnter();
PcapFileThreadVars *ptv = (PcapFileThreadVars *)data; 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); SCLogInfo("Pcap-file module read %" PRIu32 " packets, %" PRIu64 " bytes", ptv->pkts, ptv->bytes);
return; return;
} }
@ -395,5 +440,11 @@ TmEcode DecodePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data)
SCReturnInt(TM_ECODE_OK); SCReturnInt(TM_ECODE_OK);
} }
void PcapIncreaseInvalidChecksum()
{
(void) SC_ATOMIC_ADD(pcap_g.invalid_checksums, 1);
}
/* eof */ /* eof */

@ -27,5 +27,7 @@
void TmModuleReceivePcapFileRegister (void); void TmModuleReceivePcapFileRegister (void);
void TmModuleDecodePcapFileRegister (void); void TmModuleDecodePcapFileRegister (void);
void PcapIncreaseInvalidChecksum();
#endif /* __SOURCE_PCAP_FILE_H__ */ #endif /* __SOURCE_PCAP_FILE_H__ */

@ -71,6 +71,8 @@
#include "util-misc.h" #include "util-misc.h"
#include "util-validate.h" #include "util-validate.h"
#include "source-pcap-file.h"
//#define DEBUG //#define DEBUG
#define STREAMTCP_DEFAULT_PREALLOC 2048 #define STREAMTCP_DEFAULT_PREALLOC 2048
@ -4429,6 +4431,8 @@ static inline int StreamTcpValidateChecksum(Packet *p)
SCLogDebug("Checksum of received packet %p is invalid",p); SCLogDebug("Checksum of received packet %p is invalid",p);
if (p->livedev) { if (p->livedev) {
(void) SC_ATOMIC_ADD(p->livedev->invalid_checksums, 1); (void) SC_ATOMIC_ADD(p->livedev->invalid_checksums, 1);
} else if (p->pcap_cnt) {
PcapIncreaseInvalidChecksum();
} }
} }

@ -797,6 +797,15 @@ pcap:
- interface: default - interface: default
#checksum-checks: auto #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. # For FreeBSD ipfw(8) divert(4) support.
# Please make sure you have ipfw_load="YES" and ipdivert_load="YES" # Please make sure you have ipfw_load="YES" and ipdivert_load="YES"
# in /etc/loader.conf or kldload'ing the appropriate kernel modules. # in /etc/loader.conf or kldload'ing the appropriate kernel modules.

Loading…
Cancel
Save