Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 34 additions & 27 deletions src/source-erf-dag.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ NoErfDagSupportExit(ThreadVars *tv, const void *initdata, void **data)
/* Number of bytes per loop to process before fetching more data. */
#define BYTES_PER_LOOP (4 * 1024 * 1024) /* 4 MB */

#define ERF_EXT_LEN 8
#define ERF_ETH_PAD_LEN 2

extern uint32_t max_pending_packets;

typedef struct ErfDagThreadVars_ {
Expand Down Expand Up @@ -394,6 +397,10 @@ ProcessErfDagRecords(ErfDagThreadVars *ewtn, uint8_t *top, uint32_t *pkts_read)
while (((top - ewtn->btm) >= dag_record_size) &&
((processed + dag_record_size) < BYTES_PER_LOOP)) {

if (suricata_ctl_flags & SURICATA_STOP) {
SCReturnInt(TM_ECODE_OK);
}

/* Make sure we have at least one packet in the packet pool,
* to prevent us from alloc'ing packets at line rate. */
PacketPoolWait();
Expand All @@ -419,25 +426,25 @@ ProcessErfDagRecords(ErfDagThreadVars *ewtn, uint8_t *top, uint32_t *pkts_read)
processed += rlen;

/* Only support ethernet at this time. */
switch (hdr_type & 0x7f) {
case ERF_TYPE_PAD:
case ERF_TYPE_META:
/* Skip. */
continue;
case ERF_TYPE_DSM_COLOR_ETH:
case ERF_TYPE_COLOR_ETH:
case ERF_TYPE_COLOR_HASH_ETH:
/* In these types the color value overwrites the lctr
* (drop count). */
break;
case ERF_TYPE_ETH:
if (dr->lctr) {
StatsCounterAddI64(&ewtn->tv->stats, ewtn->drops, SCNtohs(dr->lctr));
}
break;
default:
SCLogError("Processing of DAG record type: %d not implemented.", dr->type);
SCReturnInt(TM_ECODE_FAILED);
switch (hdr_type & ERF_TYPE_MASK) {
case ERF_TYPE_PAD:
case ERF_TYPE_META:
/* Skip. */
continue;
case ERF_TYPE_DSM_COLOR_ETH:
case ERF_TYPE_COLOR_ETH:
case ERF_TYPE_COLOR_HASH_ETH:
/* In these types the color value overwrites the lctr
* (drop count). */
break;
case ERF_TYPE_ETH:
if (dr->lctr) {
StatsCounterAddI64(&ewtn->tv->stats, ewtn->drops, SCNtohs(dr->lctr));
}
break;
default:
SCLogError("Processing of DAG record type: %d not implemented.", dr->type);
SCReturnInt(TM_ECODE_FAILED);
}

err = ProcessErfDagRecord(ewtn, prec);
Expand All @@ -461,10 +468,10 @@ ProcessErfDagRecord(ErfDagThreadVars *ewtn, char *prec)
{
SCEnter();

int wlen = 0;
int rlen = 0;
uint16_t wlen = 0;
uint16_t rlen = 0;
int hdr_num = 0;
char hdr_type = 0;
uint8_t hdr_type = 0;
dag_record_t *dr = (dag_record_t*)prec;
erf_payload_t *pload;
Packet *p;
Expand All @@ -474,23 +481,23 @@ ProcessErfDagRecord(ErfDagThreadVars *ewtn, char *prec)
rlen = SCNtohs(dr->rlen);

/* count extension headers */
while (hdr_type & 0x80) {
if (rlen < (dag_record_size + (hdr_num * 8))) {
while (hdr_type & ERF_TYPE_MORE_EXT) {
if (rlen < (dag_record_size + (hdr_num * ERF_EXT_LEN))) {
SCLogError("Insufficient captured packet length.");
SCReturnInt(TM_ECODE_FAILED);
}
hdr_type = prec[(dag_record_size + (hdr_num * 8))];
hdr_type = prec[(dag_record_size + (hdr_num * ERF_EXT_LEN))];
hdr_num++;
}

/* Check that the whole frame was captured */
if (rlen < (dag_record_size + (8 * hdr_num) + 2 + wlen)) {
if (rlen < (dag_record_size + (hdr_num * ERF_EXT_LEN) + ERF_ETH_PAD_LEN + wlen)) {
SCLogInfo("Incomplete frame captured.");
SCReturnInt(TM_ECODE_OK);
}

/* skip over extension headers */
pload = (erf_payload_t *)(prec + dag_record_size + (8 * hdr_num));
pload = (erf_payload_t *)(prec + dag_record_size + (hdr_num * ERF_EXT_LEN));

p = PacketGetFromQueueOrAlloc();
if (p == NULL) {
Expand Down
95 changes: 84 additions & 11 deletions src/source-erf-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,21 @@
#include "source-erf-file.h"
#include "util-datalink.h"

#define DAG_TYPE_ETH 2
#define ERF_HEADER_LEN 16
#define ERF_EXT_LEN 8
#define ERF_ETH_PAD_LEN 2

#ifndef HAVE_DAG
#define ERF_TYPE_MASK 0x7f
#define ERF_TYPE_MORE_EXT 0x80
#define ERF_TYPE_ETH 2
#define ERF_TYPE_COLOR_ETH 11
#define ERF_TYPE_DSM_COLOR_ETH 16
#define ERF_TYPE_COLOR_HASH_ETH 20

#else /* Implied we do have DAG support */
#include <dagapi.h>
#endif

typedef struct DagFlags_ {
uint8_t iface:2;
Expand All @@ -50,7 +64,6 @@ typedef struct DagRecord_ {
uint16_t rlen;
uint16_t lctr;
uint16_t wlen;
uint16_t pad;
} __attribute__((packed)) DagRecord;

typedef struct ErfFileThreadVars_ {
Expand All @@ -61,6 +74,8 @@ typedef struct ErfFileThreadVars_ {

uint32_t pkts;
uint64_t bytes;

uint8_t buffer[MAX_PAYLOAD_SIZE];
} ErfFileThreadVars;

static inline TmEcode ReadErfRecord(ThreadVars *, Packet *, void *);
Expand Down Expand Up @@ -129,7 +144,9 @@ TmEcode ReceiveErfFileLoop(ThreadVars *tv, void *data, void *slot)
* to prevent us from alloc'ing packets at line rate. */
PacketPoolWait();

p = PacketGetFromQueueOrAlloc();
if (p == NULL) {
p = PacketGetFromQueueOrAlloc();
}
if (unlikely(p == NULL)) {
SCLogError("Failed to allocate a packet.");
EngineStop();
Expand All @@ -142,11 +159,15 @@ TmEcode ReceiveErfFileLoop(ThreadVars *tv, void *data, void *slot)
EngineStop();
SCReturnInt(TM_ECODE_FAILED);
}
if (GET_PKT_LEN(p) == 0) {
continue;
}

if (TmThreadsSlotProcessPkt(etv->tv, etv->slot, p) != TM_ECODE_OK) {
EngineStop();
SCReturnInt(TM_ECODE_FAILED);
}
p = NULL;
}
SCReturnInt(TM_ECODE_FAILED);
}
Expand All @@ -157,6 +178,8 @@ static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)

ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
DagRecord dr;
unsigned int hdr_num = 0;
char ext_hdr[ERF_EXT_LEN];

size_t r = fread(&dr, sizeof(DagRecord), 1, etv->erf);
if (r < 1) {
Expand All @@ -168,14 +191,55 @@ static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)
}
SCReturnInt(TM_ECODE_FAILED);
}
uint8_t hdr_type = dr.type;
uint16_t rlen = SCNtohs(dr.rlen);
uint16_t wlen = SCNtohs(dr.wlen);
if (rlen < sizeof(DagRecord)) {
if (rlen < ERF_HEADER_LEN) {
SCLogError("Bad ERF record, "
"record length less than size of header");
SCReturnInt(TM_ECODE_FAILED);
}
r = fread(GET_PKT_DATA(p), rlen - sizeof(DagRecord), 1, etv->erf);

/* count extension headers */
while (hdr_type & ERF_TYPE_MORE_EXT) {
if (rlen < (ERF_HEADER_LEN + ((hdr_num + 1) * 8))) {
SCLogError("Insufficient captured packet length.");
SCReturnInt(TM_ECODE_FAILED);
}
r = fread(ext_hdr, ERF_EXT_LEN, 1, etv->erf);
if (r < 1) {
if (feof(etv->erf)) {
SCLogInfo("End of ERF file reached");
} else {
SCLogInfo("Error reading ERF record");
}
SCReturnInt(TM_ECODE_FAILED);
}
hdr_type = ext_hdr[0];
hdr_num++;
}

/* read and discard ERF Ethernet pad */
if (rlen < (ERF_HEADER_LEN + (hdr_num * ERF_EXT_LEN) + ERF_ETH_PAD_LEN)) {
SCLogError("Insufficient captured packet length.");
SCReturnInt(TM_ECODE_FAILED);
}
r = fread(ext_hdr, ERF_ETH_PAD_LEN, 1, etv->erf);
if (r < 1) {
if (feof(etv->erf)) {
SCLogInfo("End of ERF file reached");
} else {
SCLogInfo("Error reading ERF record");
}
SCReturnInt(TM_ECODE_FAILED);
}

uint32_t caplen = rlen - (hdr_num * ERF_EXT_LEN) - ERF_HEADER_LEN - ERF_ETH_PAD_LEN;
if (caplen > MAX_PACKET_SIZE) {
SCLogError("Bad ERF record, capture length %u exceeds max %d", caplen, MAX_PACKET_SIZE);
SCReturnInt(TM_ECODE_FAILED);
}

r = fread(etv->buffer, caplen, 1, etv->erf);
if (r < 1) {
if (feof(etv->erf)) {
SCLogInfo("End of ERF file reached");
Expand All @@ -186,13 +250,22 @@ static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)
SCReturnInt(TM_ECODE_FAILED);
}

/* Only support ethernet at this time. */
if (dr.type != DAG_TYPE_ETH) {
SCLogError("DAG record type %d not implemented.", dr.type);
/* Only support ethernet at this time. Return TM_ECODE_OK with pkt len = 0 to indicate skipped
* record */
switch (dr.type & ERF_TYPE_MASK) {
case ERF_TYPE_DSM_COLOR_ETH:
case ERF_TYPE_COLOR_ETH:
case ERF_TYPE_COLOR_HASH_ETH:
case ERF_TYPE_ETH:
break;
default:
SCReturnInt(TM_ECODE_OK);
}

if (PacketCopyData(p, etv->buffer, caplen) != 0) {
SCReturnInt(TM_ECODE_FAILED);
}

GET_PKT_LEN(p) = wlen;
p->datalink = LINKTYPE_ETHERNET;

/* Convert ERF time to SCTime_t */
Expand All @@ -204,7 +277,7 @@ static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)
p->ts = SCTIME_ADD_USECS(p->ts, usecs);

etv->pkts++;
etv->bytes += wlen;
etv->bytes += caplen;

SCReturnInt(TM_ECODE_OK);
}
Expand Down
Loading