suricata
source-erf-file.c
Go to the documentation of this file.
1/* Copyright (C) 2010-2014 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Endace Technology Limited.
22 *
23 * Support for reading ERF files.
24 *
25 * Only ethernet supported at this time.
26 */
27
28#include "suricata-common.h"
29#include "suricata.h"
30#include "tm-threads.h"
31#include "source-erf-file.h"
32#include "util-datalink.h"
33
34#define DAG_TYPE_ETH 2
35
36typedef struct DagFlags_ {
37 uint8_t iface:2;
38 uint8_t vlen:1;
39 uint8_t trunc:1;
40 uint8_t rxerror:1;
41 uint8_t dserror:1;
42 uint8_t reserved:1;
43 uint8_t direction:1;
45
46typedef struct DagRecord_ {
47 uint64_t ts;
48 uint8_t type;
50 uint16_t rlen;
51 uint16_t lctr;
52 uint16_t wlen;
53 uint16_t pad;
54} __attribute__((packed)) DagRecord;
56typedef struct ErfFileThreadVars_ {
58 TmSlot *slot;
60 FILE *erf;
62 uint32_t pkts;
63 uint64_t bytes;
65
66static inline TmEcode ReadErfRecord(ThreadVars *, Packet *, void *);
67TmEcode ReceiveErfFileLoop(ThreadVars *, void *, void *);
68TmEcode ReceiveErfFileThreadInit(ThreadVars *, const void *, void **);
71
72static TmEcode DecodeErfFileThreadInit(ThreadVars *, const void *, void **);
73static TmEcode DecodeErfFileThreadDeinit(ThreadVars *tv, void *data);
74static TmEcode DecodeErfFile(ThreadVars *, Packet *, void *);
75
76/**
77 * \brief Register the ERF file receiver (reader) module.
78 */
79void
93
94/**
95 * \brief Register the ERF file decoder module.
96 */
97void
108
109/**
110 * \brief ERF file reading loop.
111 */
112TmEcode ReceiveErfFileLoop(ThreadVars *tv, void *data, void *slot)
113{
114 Packet *p = NULL;
116
117 etv->slot = ((TmSlot *)slot)->slot_next;
118
119 // Indicate that the thread is actually running its application level code (i.e., it can poll
120 // packets)
122
123 while (1) {
126 }
127
128 /* Make sure we have at least one packet in the packet pool,
129 * to prevent us from alloc'ing packets at line rate. */
131
133 if (unlikely(p == NULL)) {
134 SCLogError("Failed to allocate a packet.");
135 EngineStop();
137 }
139
140 if (ReadErfRecord(tv, p, data) != TM_ECODE_OK) {
141 TmqhOutputPacketpool(etv->tv, p);
142 EngineStop();
144 }
145
146 if (TmThreadsSlotProcessPkt(etv->tv, etv->slot, p) != TM_ECODE_OK) {
147 EngineStop();
149 }
150 }
152}
153
154static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)
155{
156 SCEnter();
157
159 DagRecord dr;
160
161 size_t r = fread(&dr, sizeof(DagRecord), 1, etv->erf);
162 if (r < 1) {
163 if (feof(etv->erf)) {
164 SCLogInfo("End of ERF file reached");
165 }
166 else {
167 SCLogInfo("Error reading ERF record");
168 }
170 }
171 uint16_t rlen = SCNtohs(dr.rlen);
172 uint16_t wlen = SCNtohs(dr.wlen);
173 if (rlen < sizeof(DagRecord)) {
174 SCLogError("Bad ERF record, "
175 "record length less than size of header");
177 }
178 r = fread(GET_PKT_DATA(p), rlen - sizeof(DagRecord), 1, etv->erf);
179 if (r < 1) {
180 if (feof(etv->erf)) {
181 SCLogInfo("End of ERF file reached");
182 }
183 else {
184 SCLogInfo("Error reading ERF record");
185 }
187 }
188
189 /* Only support ethernet at this time. */
190 if (dr.type != DAG_TYPE_ETH) {
191 SCLogError("DAG record type %d not implemented.", dr.type);
193 }
194
195 GET_PKT_LEN(p) = wlen;
197
198 /* Convert ERF time to SCTime_t */
199 uint64_t ts = dr.ts;
200 p->ts = SCTIME_FROM_SECS(ts >> 32);
201 ts = (ts & 0xffffffffULL) * 1000000;
202 ts += 0x80000000; /* rounding */
203 uint64_t usecs = (ts >> 32);
204 p->ts = SCTIME_ADD_USECS(p->ts, usecs);
205
206 etv->pkts++;
207 etv->bytes += wlen;
208
210}
211
212/**
213 * \brief Initialize the ERF receiver thread.
214 */
216ReceiveErfFileThreadInit(ThreadVars *tv, const void *initdata, void **data)
217{
218 SCEnter();
219
220 if (initdata == NULL) {
221 SCLogError("Error: No filename provided.");
223 }
224
225 FILE *erf = fopen((const char *)initdata, "r");
226 if (erf == NULL) {
227 SCLogError("Failed to open %s: %s", (char *)initdata, strerror(errno));
228 exit(EXIT_FAILURE);
229 }
230
232 if (unlikely(etv == NULL)) {
233 SCLogError("Failed to allocate memory for ERF file thread vars.");
234 fclose(erf);
236 }
237 etv->erf = erf;
238 etv->tv = tv;
239 *data = (void *)etv;
240
241 SCLogInfo("Processing ERF file %s", (char *)initdata);
242
244
246}
247
248/**
249 * \brief Initialize the ERF decoder thread.
250 */
252DecodeErfFileThreadInit(ThreadVars *tv, const void *initdata, void **data)
253{
254 SCEnter();
255 DecodeThreadVars *dtv = NULL;
257
258 if (dtv == NULL)
260
262
263 *data = (void *)dtv;
264
266}
267
268TmEcode DecodeErfFileThreadDeinit(ThreadVars *tv, void *data)
269{
270 if (data != NULL)
273}
274
275/**
276 * \brief Decode the ERF file.
277 *
278 * This function ups the decoder counters and then passes the packet
279 * off to the ethernet decoder.
280 */
282DecodeErfFile(ThreadVars *tv, Packet *p, void *data)
283{
284 SCEnter();
286
288
289 /* Update counters. */
291
293
295
297}
298
299/**
300 * \brief Print some stats to the log at program exit.
301 *
302 * \param tv Pointer to ThreadVars.
303 * \param data Pointer to data, ErfFileThreadVars.
304 */
305void
307{
309
310 SCLogInfo("Packets: %"PRIu32"; Bytes: %"PRIu64, etv->pkts, etv->bytes);
311}
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
#define PKT_SET_SRC(p, src_val)
Definition decode.h:1325
#define GET_PKT_DATA(p)
Definition decode.h:209
#define GET_PKT_LEN(p)
Definition decode.h:208
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition decode.h:1321
@ PKT_SRC_WIRE
Definition decode.h:52
struct PrefilterEngineFlowbits __attribute__
DNP3 application header.
DecodeThreadVars * dtv
ThreadVars * tv
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition decode.c:293
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition decode.c:628
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition decode.c:232
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition decode.c:804
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition decode.c:822
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition decode.c:770
ErfFileThreadVars
uint64_t ts
void ReceiveErfFileThreadExitStats(ThreadVars *, void *)
Print some stats to the log at program exit.
uint16_t rlen
void TmModuleDecodeErfFileRegister(void)
Register the ERF file decoder module.
TmEcode ReceiveErfFileThreadInit(ThreadVars *, const void *, void **)
Initialize the ERF receiver thread.
struct DagFlags_ DagFlags
#define DAG_TYPE_ETH
uint16_t wlen
void TmModuleReceiveErfFileRegister(void)
Register the ERF file receiver (reader) module.
TmEcode ReceiveErfFileThreadDeinit(ThreadVars *, void *)
TmEcode ReceiveErfFileLoop(ThreadVars *, void *, void *)
ERF file reading loop.
uint8_t iface
uint8_t direction
uint8_t dserror
uint8_t reserved
uint8_t trunc
uint8_t rxerror
DagFlags flags
uint16_t lctr
uint16_t wlen
uint16_t rlen
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
SCTime_t ts
Definition decode.h:555
int datalink
Definition decode.h:639
Per thread variable structure.
Definition threadvars.h:58
const char * name
Definition tm-modules.h:48
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition tm-modules.h:53
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition tm-modules.h:52
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition tm-modules.h:61
uint8_t cap_flags
Definition tm-modules.h:77
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition tm-modules.h:56
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition tm-modules.h:58
uint8_t flags
Definition tm-modules.h:80
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition tm-modules.h:51
#define SCNtohs(x)
#define BUG_ON(x)
volatile uint8_t suricata_ctl_flags
Definition suricata.c:172
void EngineStop(void)
make sure threads can stop the engine by calling this function. Purpose: pcap file mode needs to be a...
Definition suricata.c:470
#define SURICATA_STOP
Definition suricata.h:94
#define THV_RUNNING
Definition threadvars.h:55
TmModule tmm_modules[TMM_SIZE]
Definition tm-modules.c:29
#define TM_FLAG_RECEIVE_TM
Definition tm-modules.h:32
#define TM_FLAG_DECODE_TM
Definition tm-modules.h:33
@ TMM_DECODEERFFILE
@ TMM_RECEIVEERFFILE
@ TM_ECODE_FAILED
@ TM_ECODE_OK
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition tm-threads.c:101
void PacketPoolWait(void)
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
#define SCEnter(...)
Definition util-debug.h:277
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
#define SCTIME_FROM_SECS(s)
Definition util-time.h:69
#define SCTIME_ADD_USECS(ts, us)
Definition util-time.h:59