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 
36 typedef 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 
46 typedef 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;
55 
56 typedef struct ErfFileThreadVars_ {
58  TmSlot *slot;
59 
60  FILE *erf;
61 
62  uint32_t pkts;
63  uint64_t bytes;
65 
66 static inline TmEcode ReadErfRecord(ThreadVars *, Packet *, void *);
67 TmEcode ReceiveErfFileLoop(ThreadVars *, void *, void *);
68 TmEcode ReceiveErfFileThreadInit(ThreadVars *, const void *, void **);
71 
72 static TmEcode DecodeErfFileThreadInit(ThreadVars *, const void *, void **);
73 static TmEcode DecodeErfFileThreadDeinit(ThreadVars *tv, void *data);
74 static TmEcode DecodeErfFile(ThreadVars *, Packet *, void *);
75 
76 /**
77  * \brief Register the ERF file receiver (reader) module.
78  */
79 void
81 {
82  tmm_modules[TMM_RECEIVEERFFILE].name = "ReceiveErfFile";
92 }
93 
94 /**
95  * \brief Register the ERF file decoder module.
96  */
97 void
99 {
100  tmm_modules[TMM_DECODEERFFILE].name = "DecodeErfFile";
101  tmm_modules[TMM_DECODEERFFILE].ThreadInit = DecodeErfFileThreadInit;
102  tmm_modules[TMM_DECODEERFFILE].Func = DecodeErfFile;
104  tmm_modules[TMM_DECODEERFFILE].ThreadDeinit = DecodeErfFileThreadDeinit;
107 }
108 
109 /**
110  * \brief ERF file reading loop.
111  */
112 TmEcode ReceiveErfFileLoop(ThreadVars *tv, void *data, void *slot)
113 {
114  Packet *p = NULL;
115  ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
116 
117  etv->slot = ((TmSlot *)slot)->slot_next;
118 
119  while (1) {
122  }
123 
124  /* Make sure we have at least one packet in the packet pool,
125  * to prevent us from alloc'ing packets at line rate. */
126  PacketPoolWait();
127 
129  if (unlikely(p == NULL)) {
130  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate a packet.");
131  EngineStop();
133  }
135 
136  if (ReadErfRecord(tv, p, data) != TM_ECODE_OK) {
137  TmqhOutputPacketpool(etv->tv, p);
138  EngineStop();
140  }
141 
142  if (TmThreadsSlotProcessPkt(etv->tv, etv->slot, p) != TM_ECODE_OK) {
143  EngineStop();
145  }
146  }
148 }
149 
150 static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)
151 {
152  SCEnter();
153 
154  ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
155  DagRecord dr;
156 
157  int r = fread(&dr, sizeof(DagRecord), 1, etv->erf);
158  if (r < 1) {
159  if (feof(etv->erf)) {
160  SCLogInfo("End of ERF file reached");
161  }
162  else {
163  SCLogInfo("Error reading ERF record");
164  }
166  }
167  uint16_t rlen = SCNtohs(dr.rlen);
168  uint16_t wlen = SCNtohs(dr.wlen);
169  if (rlen < sizeof(DagRecord)) {
170  SCLogError(SC_ERR_ERF_BAD_RLEN, "Bad ERF record, "
171  "record length less than size of header");
173  }
174  r = fread(GET_PKT_DATA(p), rlen - sizeof(DagRecord), 1, etv->erf);
175  if (r < 1) {
176  if (feof(etv->erf)) {
177  SCLogInfo("End of ERF file reached");
178  }
179  else {
180  SCLogInfo("Error reading ERF record");
181  }
183  }
184 
185  /* Only support ethernet at this time. */
186  if (dr.type != DAG_TYPE_ETH) {
188  "DAG record type %d not implemented.", dr.type);
190  }
191 
192  GET_PKT_LEN(p) = wlen;
194 
195  /* Convert ERF time to timeval - from libpcap. */
196  uint64_t ts = dr.ts;
197  p->ts.tv_sec = ts >> 32;
198  ts = (ts & 0xffffffffULL) * 1000000;
199  ts += 0x80000000; /* rounding */
200  p->ts.tv_usec = ts >> 32;
201  if (p->ts.tv_usec >= 1000000) {
202  p->ts.tv_usec -= 1000000;
203  p->ts.tv_sec++;
204  }
205 
206  etv->pkts++;
207  etv->bytes += wlen;
208 
210 }
211 
212 /**
213  * \brief Initialize the ERF receiver thread.
214  */
215 TmEcode
216 ReceiveErfFileThreadInit(ThreadVars *tv, const void *initdata, void **data)
217 {
218  SCEnter();
219 
220  if (initdata == NULL) {
221  SCLogError(SC_ERR_INVALID_ARGUMENT, "Error: No filename provided.");
223  }
224 
225  FILE *erf = fopen((const char *)initdata, "r");
226  if (erf == NULL) {
227  SCLogError(SC_ERR_FOPEN, "Failed to open %s: %s", (char *)initdata,
228  strerror(errno));
229  exit(EXIT_FAILURE);
230  }
231 
233  if (unlikely(etv == NULL)) {
234  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for ERF file thread vars.");
235  fclose(erf);
237  }
238  memset(etv, 0, sizeof(*etv));
239  etv->erf = erf;
240  etv->tv = tv;
241  *data = (void *)etv;
242 
243  SCLogInfo("Processing ERF file %s", (char *)initdata);
244 
246 
248 }
249 
250 /**
251  * \brief Initialize the ERF decoder thread.
252  */
253 TmEcode
254 DecodeErfFileThreadInit(ThreadVars *tv, const void *initdata, void **data)
255 {
256  SCEnter();
257  DecodeThreadVars *dtv = NULL;
259 
260  if (dtv == NULL)
262 
264 
265  *data = (void *)dtv;
266 
268 }
269 
270 TmEcode DecodeErfFileThreadDeinit(ThreadVars *tv, void *data)
271 {
272  if (data != NULL)
273  DecodeThreadVarsFree(tv, data);
275 }
276 
277 /**
278  * \brief Decode the ERF file.
279  *
280  * This function ups the decoder counters and then passes the packet
281  * off to the ethernet decoder.
282  */
283 TmEcode
284 DecodeErfFile(ThreadVars *tv, Packet *p, void *data)
285 {
286  SCEnter();
288 
290 
291  /* Update counters. */
293 
295 
297 
299 }
300 
301 /**
302  * \brief Print some stats to the log at program exit.
303  *
304  * \param tv Pointer to ThreadVars.
305  * \param data Pointer to data, ErfFileThreadVars.
306  */
307 void
309 {
310  ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
311 
312  SCLogInfo("Packets: %"PRIu32"; Bytes: %"PRIu64, etv->pkts, etv->bytes);
313 }
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:67
TMM_RECEIVEERFFILE
@ TMM_RECEIVEERFFILE
Definition: tm-threads-common.h:50
tm-threads.h
DagRecord_::type
uint8_t type
Definition: source-erf-file.c:48
ts
uint64_t ts
Definition: source-erf-file.c:55
DagRecord_::lctr
uint16_t lctr
Definition: source-erf-file.c:51
DAG_TYPE_ETH
#define DAG_TYPE_ETH
Definition: source-erf-file.c:34
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1222
DagRecord_::ts
uint64_t ts
Definition: source-erf-file.c:47
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DagFlags_::trunc
uint8_t trunc
Definition: source-erf-file.c:39
ReceiveErfFileThreadExitStats
void ReceiveErfFileThreadExitStats(ThreadVars *, void *)
Print some stats to the log at program exit.
Definition: source-erf-file.c:308
DagRecord_::flags
DagFlags flags
Definition: source-erf-file.c:49
TmModuleDecodeErfFileRegister
void TmModuleDecodeErfFileRegister(void)
Register the ERF file decoder module.
Definition: source-erf-file.c:98
SURICATA_STOP
#define SURICATA_STOP
Definition: suricata.h:89
PacketDecodeFinalize
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:150
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:376
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:83
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:54
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:82
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
Packet_::datalink
int datalink
Definition: decode.h:608
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1225
DecodeRegisterPerfCounters
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:526
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:54
DagFlags_::rxerror
uint8_t rxerror
Definition: source-erf-file.c:40
DagFlags_::direction
uint8_t direction
Definition: source-erf-file.c:43
TmModule_::PktAcqBreakLoop
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
SCEnter
#define SCEnter(...)
Definition: util-debug.h:298
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:227
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:56
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:52
DagRecord_::rlen
uint16_t rlen
Definition: source-erf-file.c:50
DagFlags_
Definition: source-erf-file.c:36
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
ErfFileThreadVars
ErfFileThreadVars
Definition: source-erf-file.c:64
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:281
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:85
SC_ERR_FOPEN
@ SC_ERR_FOPEN
Definition: util-error.h:74
Packet_
Definition: decode.h:434
TM_FLAG_DECODE_TM
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:32
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:33
wlen
uint16_t wlen
Definition: source-erf-file.c:60
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:226
TmSlot_
Definition: tm-threads.h:52
DagFlags
struct DagFlags_ DagFlags
TmEcode
TmEcode
Definition: tm-threads-common.h:81
TMM_DECODEERFFILE
@ TMM_DECODEERFFILE
Definition: tm-threads-common.h:51
TmModule_::name
const char * name
Definition: tm-modules.h:44
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:215
TM_FLAG_RECEIVE_TM
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:31
TmModuleReceiveErfFileRegister
void TmModuleReceiveErfFileRegister(void)
Register the ERF file receiver (reader) module.
Definition: source-erf-file.c:80
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:32
ReceiveErfFileThreadDeinit
TmEcode ReceiveErfFileThreadDeinit(ThreadVars *, void *)
__attribute__
struct DagRecord_ __attribute__((packed))
DNP3 application object header.
Definition: source-erf-file.c:54
DecodeThreadVarsFree
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:706
Packet_::ts
struct timeval ts
Definition: decode.h:477
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:395
suricata-common.h
DagFlags_::dserror
uint8_t dserror
Definition: source-erf-file.c:41
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:255
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
EngineStop
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:456
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:31
SC_ERR_UNIMPLEMENTED
@ SC_ERR_UNIMPLEMENTED
Definition: util-error.h:118
TmModule_::ThreadExitPrintStats
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:48
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DagFlags_::vlen
uint8_t vlen
Definition: source-erf-file.c:38
DagRecord_::wlen
uint16_t wlen
Definition: source-erf-file.c:52
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:664
DagFlags_::reserved
uint8_t reserved
Definition: source-erf-file.c:42
source-erf-file.h
DecodeThreadVarsAlloc
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:687
DagFlags_::iface
uint8_t iface
Definition: source-erf-file.c:37
DagRecord_
Definition: source-erf-file.c:46
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
suricata.h
SC_ERR_ERF_BAD_RLEN
@ SC_ERR_ERF_BAD_RLEN
Definition: util-error.h:361
DagRecord_::pad
uint16_t pad
Definition: source-erf-file.c:53
ReceiveErfFileThreadInit
TmEcode ReceiveErfFileThreadInit(ThreadVars *, const void *, void **)
Initialize the ERF receiver thread.
Definition: source-erf-file.c:216
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:302
ReceiveErfFileLoop
TmEcode ReceiveErfFileLoop(ThreadVars *, void *, void *)
ERF file reading loop.
Definition: source-erf-file.c:112
PacketGetFromQueueOrAlloc
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:214
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:42
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:70
DecodeUpdatePacketCounters
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:653
LINKTYPE_ETHERNET
#define LINKTYPE_ETHERNET
Definition: decode.h:1138
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:208
rlen
uint16_t rlen
Definition: source-erf-file.c:58