]> git.ipfire.org Git - people/ms/suricata.git/blame - src/source-pcap-file.c
Fix checking for the stream GAP after the ssn ptr was initialized.
[people/ms/suricata.git] / src / source-pcap-file.c
CommitLineData
9c7f5afa
VJ
1/* Copyright (c) 2009 Victor Julien <victor@inliniac.net> */
2
3/* TODO
4 *
5 *
6 *
7 */
8
af992242 9#if LIBPCAP_VERSION_MAJOR == 1
9c7f5afa 10#include <pcap/pcap.h>
af992242
WM
11#else
12#include <pcap.h>
ba46c16a 13#endif /* LIBPCAP_VERSION_MAJOR */
9c7f5afa 14
ecf86f9c
VJ
15#include "suricata-common.h"
16#include "suricata.h"
9c7f5afa
VJ
17#include "decode.h"
18#include "packet-queue.h"
19#include "threads.h"
20#include "threadvars.h"
21#include "tm-queuehandlers.h"
22#include "tm-modules.h"
23#include "source-pcap-file.h"
24#include "util-time.h"
9ececacd 25#include "util-debug.h"
ba46c16a 26#include "conf.h"
29d51a61 27#include "util-error.h"
070ed778 28#include "util-privs.h"
ba46c16a 29
7142fdb7 30extern int max_pending_packets;
9c7f5afa
VJ
31
32typedef struct PcapFileGlobalVars_ {
33 pcap_t *pcap_handle;
57f71f7e 34 void (*Decoder)(ThreadVars *, DecodeThreadVars *, Packet *, u_int8_t *, u_int16_t, PacketQueue *);
a4fe9718 35 int datalink;
ba46c16a 36 struct bpf_program filter;
9c7f5afa
VJ
37} PcapFileGlobalVars;
38
39typedef struct PcapFileThreadVars_
40{
41 /* counters */
fa5939ca
BR
42 uint32_t pkts;
43 uint64_t bytes;
44 uint32_t errs;
9c7f5afa
VJ
45
46 ThreadVars *tv;
c53dfea3
VJ
47
48 Packet *in_p;
9c7f5afa
VJ
49} PcapFileThreadVars;
50
e0aacac4 51static PcapFileGlobalVars pcap_g;
9c7f5afa 52
40b8afdd
GS
53TmEcode ReceivePcapFile(ThreadVars *, Packet *, void *, PacketQueue *);
54TmEcode ReceivePcapFileThreadInit(ThreadVars *, void *, void **);
9c7f5afa 55void ReceivePcapFileThreadExitStats(ThreadVars *, void *);
40b8afdd 56TmEcode ReceivePcapFileThreadDeinit(ThreadVars *, void *);
9c7f5afa 57
40b8afdd
GS
58TmEcode DecodePcapFile(ThreadVars *, Packet *, void *, PacketQueue *);
59TmEcode DecodePcapFileThreadInit(ThreadVars *, void *, void **);
9c7f5afa
VJ
60
61void TmModuleReceivePcapFileRegister (void) {
e0aacac4
VJ
62 memset(&pcap_g, 0x00, sizeof(pcap_g));
63
9c7f5afa 64 tmm_modules[TMM_RECEIVEPCAPFILE].name = "ReceivePcapFile";
a3910884 65 tmm_modules[TMM_RECEIVEPCAPFILE].ThreadInit = ReceivePcapFileThreadInit;
9c7f5afa 66 tmm_modules[TMM_RECEIVEPCAPFILE].Func = ReceivePcapFile;
a3910884
VJ
67 tmm_modules[TMM_RECEIVEPCAPFILE].ThreadExitPrintStats = ReceivePcapFileThreadExitStats;
68 tmm_modules[TMM_RECEIVEPCAPFILE].ThreadDeinit = NULL;
9c7f5afa 69 tmm_modules[TMM_RECEIVEPCAPFILE].RegisterTests = NULL;
070ed778 70 tmm_modules[TMM_RECEIVEPCAPFILE].cap_flags = 0;
9c7f5afa
VJ
71}
72
73void TmModuleDecodePcapFileRegister (void) {
74 tmm_modules[TMM_DECODEPCAPFILE].name = "DecodePcapFile";
a3910884 75 tmm_modules[TMM_DECODEPCAPFILE].ThreadInit = DecodePcapFileThreadInit;
9c7f5afa 76 tmm_modules[TMM_DECODEPCAPFILE].Func = DecodePcapFile;
a3910884
VJ
77 tmm_modules[TMM_DECODEPCAPFILE].ThreadExitPrintStats = NULL;
78 tmm_modules[TMM_DECODEPCAPFILE].ThreadDeinit = NULL;
9c7f5afa 79 tmm_modules[TMM_DECODEPCAPFILE].RegisterTests = NULL;
070ed778 80 tmm_modules[TMM_DECODEPCAPFILE].cap_flags = 0;
9c7f5afa
VJ
81}
82
83void PcapFileCallback(char *user, struct pcap_pkthdr *h, u_char *pkt) {
29d51a61 84 SCEnter();
c5e15213 85
9c7f5afa 86 PcapFileThreadVars *ptv = (PcapFileThreadVars *)user;
9c7f5afa 87
e26833be 88 SCMutexLock(&mutex_pending);
7142fdb7 89 if (pending > max_pending_packets) {
e26833be 90 SCondWait(&cond_pending, &mutex_pending);
9c7f5afa 91 }
e26833be 92 SCMutexUnlock(&mutex_pending);
9c7f5afa 93
c53dfea3 94 Packet *p = ptv->in_p;
9c7f5afa
VJ
95
96 p->ts.tv_sec = h->ts.tv_sec;
97 p->ts.tv_usec = h->ts.tv_usec;
9ececacd 98 SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
9c7f5afa 99 TimeSet(&p->ts);
a4fe9718 100 p->datalink = pcap_g.datalink;
9c7f5afa
VJ
101
102 ptv->pkts++;
103 ptv->bytes += h->caplen;
104
105 p->pktlen = h->caplen;
106 memcpy(p->pkt, pkt, p->pktlen);
fa5939ca 107 //printf("PcapFileCallback: p->pktlen: %" PRIu32 " (pkt %02x, p->pkt %02x)\n", p->pktlen, *pkt, *p->pkt);
c5e15213
VJ
108
109 SCReturn;
9c7f5afa
VJ
110}
111
c5e15213
VJ
112/**
113 * \brief Main PCAP file reading function
114 */
40b8afdd 115TmEcode ReceivePcapFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) {
29d51a61 116 SCEnter();
9c7f5afa 117
c5e15213 118 PcapFileThreadVars *ptv = (PcapFileThreadVars *)data;
c53dfea3
VJ
119 ptv->in_p = p;
120
53c9276d 121 /* Right now we just support reading packets one at a time. */
c5e15213
VJ
122 int r = pcap_dispatch(pcap_g.pcap_handle, 1,
123 (pcap_handler)PcapFileCallback, (u_char *)ptv);
53c9276d 124 if (r < 0) {
c5e15213
VJ
125 SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s",
126 r, pcap_geterr(pcap_g.pcap_handle));
127
53c9276d 128 EngineStop();
c5e15213 129 SCReturnInt(TM_ECODE_FAILED);
53c9276d 130 } else if (r == 0) {
7dcc1daa 131 SCLogInfo("pcap file end of file reached (pcap err code %" PRId32 ")", r);
c5e15213 132
9c7f5afa 133 EngineStop();
29d51a61 134 SCReturnInt(TM_ECODE_FAILED);
9c7f5afa
VJ
135 }
136
29d51a61 137 SCReturnInt(TM_ECODE_OK);
9c7f5afa
VJ
138}
139
40b8afdd 140TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data) {
29d51a61 141 SCEnter();
e0aacac4 142 char *tmpbpfstring = NULL;
9c7f5afa 143 if (initdata == NULL) {
29d51a61
PR
144 SCLogError(SC_ERR_INVALID_ARGUMENT, "error: initdata == NULL");
145 SCReturnInt(TM_ECODE_FAILED);
9c7f5afa
VJ
146 }
147
e0aacac4
VJ
148 SCLogInfo("reading pcap file %s", (char *)initdata);
149
25a3a5c6 150 PcapFileThreadVars *ptv = SCMalloc(sizeof(PcapFileThreadVars));
9c7f5afa 151 if (ptv == NULL) {
29d51a61
PR
152 SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for PcapFileThreadVars");
153 SCReturnInt(TM_ECODE_FAILED);
9c7f5afa
VJ
154 }
155 memset(ptv, 0, sizeof(PcapFileThreadVars));
156
8c3d0c05 157 char errbuf[PCAP_ERRBUF_SIZE] = "";
9c7f5afa
VJ
158 pcap_g.pcap_handle = pcap_open_offline((char *)initdata, errbuf);
159 if (pcap_g.pcap_handle == NULL) {
52936818 160 SCLogError(SC_ERR_FOPEN, "%s\n", errbuf);
25a3a5c6 161 SCFree(ptv);
52936818 162 exit(EXIT_FAILURE);
9c7f5afa
VJ
163 }
164
ba46c16a 165 if (ConfGet("bpf-filter", &tmpbpfstring) != 1) {
e0aacac4 166 SCLogDebug("could not get bpf or none specified");
ba46c16a 167 } else {
e0aacac4 168 SCLogInfo("using bpf-filter \"%s\"", tmpbpfstring);
ba46c16a
WM
169
170 if(pcap_compile(pcap_g.pcap_handle,&pcap_g.filter,tmpbpfstring,1,0) < 0) {
171 SCLogError(SC_ERR_BPF,"bpf compilation error %s",pcap_geterr(pcap_g.pcap_handle));
25a3a5c6 172 SCFree(ptv);
e0aacac4 173 return TM_ECODE_FAILED;
ba46c16a
WM
174 }
175
176 if(pcap_setfilter(pcap_g.pcap_handle,&pcap_g.filter) < 0) {
177 SCLogError(SC_ERR_BPF,"could not set bpf filter %s",pcap_geterr(pcap_g.pcap_handle));
25a3a5c6 178 SCFree(ptv);
e0aacac4 179 return TM_ECODE_FAILED;
ba46c16a
WM
180 }
181 }
182
a4fe9718 183 pcap_g.datalink = pcap_datalink(pcap_g.pcap_handle);
e0aacac4
VJ
184 SCLogDebug("datalink %" PRId32 "", pcap_g.datalink);
185
a4fe9718 186 switch(pcap_g.datalink) {
dec11038
BS
187 case LINKTYPE_LINUX_SLL:
188 pcap_g.Decoder = DecodeSll;
189 break;
190 case LINKTYPE_ETHERNET:
191 pcap_g.Decoder = DecodeEthernet;
192 break;
193 case LINKTYPE_PPP:
194 pcap_g.Decoder = DecodePPP;
195 break;
8a643213
WM
196 case LINKTYPE_RAW:
197 pcap_g.Decoder = DecodeRaw;
198 break;
199
dec11038 200 default:
25a3a5c6
PR
201 SCLogError(SC_ERR_UNIMPLEMENTED, "datalink type %" PRId32 " not "
202 "(yet) supported in module PcapFile.\n", pcap_g.datalink);
203 SCFree(ptv);
29d51a61 204 SCReturnInt(TM_ECODE_FAILED);
9c7f5afa
VJ
205 }
206
207 ptv->tv = tv;
208 *data = (void *)ptv;
29d51a61 209 SCReturnInt(TM_ECODE_OK);
9c7f5afa
VJ
210}
211
212void ReceivePcapFileThreadExitStats(ThreadVars *tv, void *data) {
29d51a61 213 SCEnter();
9c7f5afa
VJ
214 PcapFileThreadVars *ptv = (PcapFileThreadVars *)data;
215
53c9276d 216 SCLogInfo(" - (%s) Packets %" PRIu32 ", bytes %" PRIu64 ".", tv->name, ptv->pkts, ptv->bytes);
9c7f5afa
VJ
217 return;
218}
219
40b8afdd 220TmEcode ReceivePcapFileThreadDeinit(ThreadVars *tv, void *data) {
29d51a61
PR
221 SCEnter();
222 SCReturnInt(TM_ECODE_OK);
9c7f5afa
VJ
223}
224
40b8afdd 225TmEcode DecodePcapFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
d0e70309 226{
29d51a61 227 SCEnter();
244f5d54
AS
228 DecodeThreadVars *dtv = (DecodeThreadVars *)data;
229
57f71f7e 230 /* update counters */
ceb7e495 231 SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca);
8beef4a9
AS
232 SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca);
233
ceb7e495 234 SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, p->pktlen);
8beef4a9
AS
235 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, p->pktlen);
236 SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca,
237 (p->pktlen * 8)/1000000.0 );
238
ceb7e495
AS
239 SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, p->pktlen);
240 SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, p->pktlen);
d0e70309 241
9c7f5afa 242 /* call the decoder */
57f71f7e 243 pcap_g.Decoder(tv, dtv, p, p->pkt, p->pktlen, pq);
244f5d54 244
29d51a61 245 SCReturnInt(TM_ECODE_OK);
9c7f5afa
VJ
246}
247
40b8afdd 248TmEcode DecodePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data)
d0e70309 249{
29d51a61 250 SCEnter();
244f5d54
AS
251 DecodeThreadVars *dtv = NULL;
252
25a3a5c6 253 if ( (dtv = SCMalloc(sizeof(DecodeThreadVars))) == NULL) {
29d51a61
PR
254 SCLogError(SC_ERR_MEM_ALLOC, "Error Allocating memory for DecodeThreadVars");
255 SCReturnInt(TM_ECODE_FAILED);
244f5d54
AS
256 }
257 memset(dtv, 0, sizeof(DecodeThreadVars));
258
8beef4a9 259 DecodeRegisterPerfCounters(dtv, tv);
244f5d54
AS
260
261 *data = (void *)dtv;
ceb7e495 262
29d51a61 263 SCReturnInt(TM_ECODE_OK);
d0e70309
AS
264}
265
9c7f5afa
VJ
266/* eof */
267