log/pcap: add existing stream logging

This patch update the alert mode of pcap logging.

It uses the packet header data added to the TCP segments
to build packets corresponding to the acked data that did trigger
the alert. It then write it to the pcap file before starting to
dump all packet for the flow that did alert.
pull/7430/head
Eric Leblond 4 years ago committed by Victor Julien
parent b416a4455c
commit e7b1c52c1c

@ -26,7 +26,9 @@
*/
#include "suricata-common.h"
#include "util-buffer.h"
#include "util-fmemopen.h"
#include "stream-tcp-util.h"
#ifdef HAVE_LIBLZ4
#include <lz4frame.h>
@ -189,6 +191,7 @@ typedef struct PcapLogData_ {
typedef struct PcapLogThreadData_ {
PcapLogData *pcap_log;
MemBuffer *buf;
} PcapLogThreadData;
/* Pattern for extracting timestamp from pcap log files. */
@ -516,6 +519,48 @@ static inline int PcapWrite(
return TM_ECODE_OK;
}
struct PcapLogCallbackContext {
PcapLogData *pl;
PcapLogCompressionData *connp;
MemBuffer *buf;
};
static int PcapLogSegmentCallback(
const Packet *p, TcpSegment *seg, void *data, const uint8_t *buf, uint32_t buflen)
{
struct PcapLogCallbackContext *pctx = (struct PcapLogCallbackContext *)data;
if (seg->pcap_hdr_storage->pktlen) {
pctx->pl->h->ts.tv_sec = seg->pcap_hdr_storage->ts.tv_sec;
pctx->pl->h->ts.tv_usec = seg->pcap_hdr_storage->ts.tv_usec;
pctx->pl->h->len = seg->pcap_hdr_storage->pktlen + buflen;
pctx->pl->h->caplen = seg->pcap_hdr_storage->pktlen + buflen;
MemBufferReset(pctx->buf);
MemBufferWriteRaw(pctx->buf, seg->pcap_hdr_storage->pkt_hdr, seg->pcap_hdr_storage->pktlen);
MemBufferWriteRaw(pctx->buf, buf, buflen);
PcapWrite(pctx->pl, pctx->connp, (uint8_t *)pctx->buf->buffer, pctx->pl->h->len);
}
return 1;
}
static void PcapLogDumpSegments(
PcapLogThreadData *td, PcapLogCompressionData *connp, const Packet *p)
{
uint8_t flag;
/* check which side is packet */
if (p->flowflags & FLOW_PKT_TOSERVER) {
flag = STREAM_DUMP_TOCLIENT;
} else {
flag = STREAM_DUMP_TOSERVER;
}
flag |= STREAM_DUMP_HEADERS;
/* Loop on segment from this side */
struct PcapLogCallbackContext data = { td->pcap_log, connp, td->buf };
StreamSegmentForEach(p, flag, PcapLogSegmentCallback, (void *)&data);
}
/**
* \brief Pcap logging main function
*
@ -611,6 +656,19 @@ static int PcapLog (ThreadVars *t, void *thread_data, const Packet *p)
PCAPLOG_PROFILE_START;
/* if we are using alerted logging and if packet is first one with alert in flow
* then we need to dump in the pcap the stream acked by the packet */
if ((p->flags & PKT_FIRST_ALERTS) && (td->pcap_log->conditional == LOGMODE_COND_ALERTS)) {
if (PKT_IS_TCP(p)) {
/* dump fake packets for all segments we have on acked by packet */
#ifdef HAVE_LIBLZ4
PcapLogDumpSegments(td, connp, p);
#else
PcapLogDumpSegments(td, NULL, p);
#endif
}
}
#ifdef HAVE_LIBLZ4
ret = PcapWrite(pl, comp, GET_PKT_DATA(p), len);
#else
@ -984,6 +1042,12 @@ static TmEcode PcapLogDataInit(ThreadVars *t, const void *initdata, void **data)
*data = (void *)td;
if (IsTcpSessionDumpingEnabled()) {
td->buf = MemBufferCreateNew(PCAP_OUTPUT_BUFFER_SIZE);
} else {
td->buf = NULL;
}
if (pl->max_files && (pl->mode == LOGMODE_MULTI || pl->threads == 1)) {
#ifdef INIT_RING_BUFFER
if (PcapLogInitRingBuffer(td->pcap_log) == TM_ECODE_FAILED) {
@ -1094,6 +1158,9 @@ static TmEcode PcapLogDataDeinit(ThreadVars *t, void *thread_data)
PcapLogDataFree(pl);
}
if (td->buf)
MemBufferFree(td->buf);
SCFree(td);
return TM_ECODE_OK;
}
@ -1456,6 +1523,7 @@ static OutputInitResult PcapLogInitCtx(ConfNode *conf)
if (s_conditional != NULL) {
if (strcasecmp(s_conditional, "alerts") == 0) {
pl->conditional = LOGMODE_COND_ALERTS;
EnableTcpSessionDumping();
} else if (strcasecmp(s_conditional, "all") != 0) {
FatalError(SC_ERR_INVALID_ARGUMENT,
"log-pcap: invalid conditional \"%s\". Valid options: \"all\", "

@ -28,6 +28,8 @@
#ifndef __LOG_PCAP_H__
#define __LOG_PCAP_H__
#define PCAP_OUTPUT_BUFFER_SIZE 65535
void PcapLogRegister(void);
void PcapLogProfileSetup(void);

Loading…
Cancel
Save