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"
32 
33 #define DAG_TYPE_ETH 2
34 
35 typedef struct DagFlags_ {
36  uint8_t iface:2;
37  uint8_t vlen:1;
38  uint8_t trunc:1;
39  uint8_t rxerror:1;
40  uint8_t dserror:1;
41  uint8_t reserved:1;
42  uint8_t direction:1;
43 } DagFlags;
44 
45 typedef struct DagRecord_ {
46  uint64_t ts;
47  uint8_t type;
49  uint16_t rlen;
50  uint16_t lctr;
51  uint16_t wlen;
52  uint16_t pad;
53 } __attribute__((packed)) DagRecord;
54 
55 typedef struct ErfFileThreadVars_ {
56  ThreadVars *tv;
57  TmSlot *slot;
58 
59  FILE *erf;
60 
61  uint32_t pkts;
62  uint64_t bytes;
64 
65 static inline TmEcode ReadErfRecord(ThreadVars *, Packet *, void *);
66 TmEcode ReceiveErfFileLoop(ThreadVars *, void *, void *);
67 TmEcode ReceiveErfFileThreadInit(ThreadVars *, const void *, void **);
70 
71 TmEcode DecodeErfFileThreadInit(ThreadVars *, const void *, void **);
74 
75 /**
76  * \brief Register the ERF file receiver (reader) module.
77  */
78 void
80 {
81  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";
108 }
109 
110 /**
111  * \brief ERF file reading loop.
112  */
113 TmEcode ReceiveErfFileLoop(ThreadVars *tv, void *data, void *slot)
114 {
115  Packet *p = NULL;
116  ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
117 
118  etv->slot = ((TmSlot *)slot)->slot_next;
119 
120  while (1) {
123  }
124 
125  /* Make sure we have at least one packet in the packet pool,
126  * to prevent us from alloc'ing packets at line rate. */
127  PacketPoolWait();
128 
130  if (unlikely(p == NULL)) {
131  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate a packet.");
132  EngineStop();
134  }
136 
137  if (ReadErfRecord(tv, p, data) != TM_ECODE_OK) {
138  TmqhOutputPacketpool(etv->tv, p);
139  EngineStop();
141  }
142 
143  if (TmThreadsSlotProcessPkt(etv->tv, etv->slot, p) != TM_ECODE_OK) {
144  EngineStop();
146  }
147  }
149 }
150 
151 static inline TmEcode ReadErfRecord(ThreadVars *tv, Packet *p, void *data)
152 {
153  SCEnter();
154 
155  ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
156  DagRecord dr;
157 
158  int r = fread(&dr, sizeof(DagRecord), 1, etv->erf);
159  if (r < 1) {
160  if (feof(etv->erf)) {
161  SCLogInfo("End of ERF file reached");
162  }
163  else {
164  SCLogInfo("Error reading ERF record");
165  }
167  }
168  int rlen = SCNtohs(dr.rlen);
169  int wlen = SCNtohs(dr.wlen);
170  r = fread(GET_PKT_DATA(p), rlen - sizeof(DagRecord), 1, etv->erf);
171  if (r < 1) {
172  if (feof(etv->erf)) {
173  SCLogInfo("End of ERF file reached");
174  }
175  else {
176  SCLogInfo("Error reading ERF record");
177  }
179  }
180 
181  /* Only support ethernet at this time. */
182  if (dr.type != DAG_TYPE_ETH) {
184  "DAG record type %d not implemented.", dr.type);
186  }
187 
188  GET_PKT_LEN(p) = wlen;
190 
191  /* Convert ERF time to timeval - from libpcap. */
192  uint64_t ts = dr.ts;
193  p->ts.tv_sec = ts >> 32;
194  ts = (ts & 0xffffffffULL) * 1000000;
195  ts += 0x80000000; /* rounding */
196  p->ts.tv_usec = ts >> 32;
197  if (p->ts.tv_usec >= 1000000) {
198  p->ts.tv_usec -= 1000000;
199  p->ts.tv_sec++;
200  }
201 
202  etv->pkts++;
203  etv->bytes += wlen;
204 
206 }
207 
208 /**
209  * \brief Initialize the ERF receiver thread.
210  */
211 TmEcode
212 ReceiveErfFileThreadInit(ThreadVars *tv, const void *initdata, void **data)
213 {
214  SCEnter();
215 
216  if (initdata == NULL) {
217  SCLogError(SC_ERR_INVALID_ARGUMENT, "Error: No filename provided.");
219  }
220 
221  FILE *erf = fopen((const char *)initdata, "r");
222  if (erf == NULL) {
223  SCLogError(SC_ERR_FOPEN, "Failed to open %s: %s", (char *)initdata,
224  strerror(errno));
225  exit(EXIT_FAILURE);
226  }
227 
229  if (unlikely(etv == NULL)) {
230  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for ERF file thread vars.");
231  fclose(erf);
233  }
234  memset(etv, 0, sizeof(*etv));
235  etv->erf = erf;
236  etv->tv = tv;
237  *data = (void *)etv;
238 
239  SCLogInfo("Processing ERF file %s", (char *)initdata);
240 
242 }
243 
244 /**
245  * \brief Initialize the ERF decoder thread.
246  */
247 TmEcode
248 DecodeErfFileThreadInit(ThreadVars *tv, const void *initdata, void **data)
249 {
250  SCEnter();
251  DecodeThreadVars *dtv = NULL;
252  dtv = DecodeThreadVarsAlloc(tv);
253 
254  if (dtv == NULL)
256 
258 
259  *data = (void *)dtv;
260 
262 }
263 
265 {
266  if (data != NULL)
267  DecodeThreadVarsFree(tv, data);
269 }
270 
271 /**
272  * \brief Decode the ERF file.
273  *
274  * This function ups the decoder counters and then passes the packet
275  * off to the ethernet decoder.
276  */
277 TmEcode
278 DecodeErfFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
279 {
280  SCEnter();
281  DecodeThreadVars *dtv = (DecodeThreadVars *)data;
282 
283  /* XXX HACK: flow timeout can call us for injected pseudo packets
284  * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
285  if (p->flags & PKT_PSEUDO_STREAM_END)
286  return TM_ECODE_OK;
287 
288  /* Update counters. */
289  DecodeUpdatePacketCounters(tv, dtv, p);
290 
291  DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
292 
293  PacketDecodeFinalize(tv, dtv, p);
294 
296 }
297 
298 /**
299  * \brief Print some stats to the log at program exit.
300  *
301  * \param tv Pointer to ThreadVars.
302  * \param data Pointer to data, ErfFileThreadVars.
303  */
304 void
306 {
307  ErfFileThreadVars *etv = (ErfFileThreadVars *)data;
308 
309  SCLogInfo("Packets: %"PRIu32"; Bytes: %"PRIu64, etv->pkts, etv->bytes);
310 }
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:32
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:592
uint8_t cap_flags
Definition: tm-modules.h:67
uint8_t trunc
TmEcode DecodeErfFileThreadInit(ThreadVars *, const void *, void **)
Initialize the ERF decoder thread.
uint8_t flags
Definition: tm-modules.h:70
uint8_t type
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:114
#define unlikely(expr)
Definition: util-optimize.h:35
TmEcode(* Func)(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
Definition: tm-modules.h:52
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:453
uint16_t rlen
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:199
struct DagRecord_ __attribute__((packed))
DNP3 application object header.
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:176
DagFlags flags
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:54
uint16_t rlen
TmEcode ReceiveErfFileThreadDeinit(ThreadVars *, void *)
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1134
uint8_t rxerror
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:31
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
struct DagFlags_ DagFlags
#define SURICATA_STOP
Definition: suricata.h:95
ErfFileThreadVars
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
int datalink
Definition: decode.h:574
TmEcode DecodeErfFile(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
Decode the ERF file.
uint8_t direction
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
Structure to hold thread specific data for all decode modules.
Definition: decode.h:632
uint16_t wlen
void(* RegisterTests)(void)
Definition: tm-modules.h:65
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
#define SCEnter(...)
Definition: util-debug.h:337
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1093
TmEcode ReceiveErfFileLoop(ThreadVars *, void *, void *)
ERF file reading loop.
#define SCReturnInt(x)
Definition: util-debug.h:341
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:48
void PacketPoolWait(void)
const char * name
Definition: tm-modules.h:44
uint8_t dserror
#define SCMalloc(a)
Definition: util-mem.h:166
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCNtohs(x)
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.h:73
uint8_t vlen
uint16_t wlen
uint64_t ts
uint16_t pad
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
void ReceiveErfFileThreadExitStats(ThreadVars *, void *)
Print some stats to the log at program exit.
uint64_t ts
uint8_t iface
#define GET_PKT_DATA(p)
Definition: decode.h:223
TmEcode DecodeErfFileThreadDeinit(ThreadVars *tv, void *data)
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:558
TmEcode ReceiveErfFileThreadInit(ThreadVars *, const void *, void **)
Initialize the ERF receiver thread.
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:420
#define LINKTYPE_ETHERNET
Definition: decode.h:1072
Per thread variable structure.
Definition: threadvars.h:57
struct timeval ts
Definition: decode.h:449
#define GET_PKT_LEN(p)
Definition: decode.h:222
uint32_t flags
Definition: decode.h:441
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:618
uint8_t reserved
#define DAG_TYPE_ETH
uint16_t lctr
void TmModuleReceiveErfFileRegister(void)
Register the ERF file receiver (reader) module.
void TmModuleDecodeErfFileRegister(void)
Register the ERF file decoder module.