]>
Commit | Line | Data |
---|---|---|
c3efc4e0 | 1 | /* Copyright (C) 2007-2016 Open Information Security Foundation |
ce019275 WM |
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. | |
9c7f5afa | 11 | * |
ce019275 WM |
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 | |
9c7f5afa | 20 | * |
ce019275 | 21 | * \author Victor Julien <victor@inliniac.net> |
9c7f5afa | 22 | * |
ce019275 | 23 | * File based pcap packet acquisition support |
9c7f5afa VJ |
24 | */ |
25 | ||
ecf86f9c | 26 | #include "suricata-common.h" |
9c7f5afa | 27 | #include "source-pcap-file.h" |
3ab91208 DH |
28 | #include "source-pcap-file-helper.h" |
29 | #include "source-pcap-file-directory-helper.h" | |
5133098b | 30 | #include "flow-manager.h" |
8b5be26f | 31 | #include "util-checksum.h" |
ba46c16a | 32 | |
7142fdb7 | 33 | extern int max_pending_packets; |
3ab91208 | 34 | PcapFileGlobalVars pcap_g; |
53acf089 | 35 | |
3ab91208 DH |
36 | /** |
37 | * Union determining whether the behavior of the thread is file or directory | |
38 | */ | |
39 | typedef union PcapFileBehaviorVar_ | |
40 | { | |
41 | PcapFileDirectoryVars *directory; | |
42 | PcapFileFileVars *file; | |
43 | } PcapFileBehaviorVar; | |
9c7f5afa | 44 | |
3ab91208 DH |
45 | /** |
46 | * Data specific to the thread | |
47 | */ | |
9c7f5afa VJ |
48 | typedef struct PcapFileThreadVars_ |
49 | { | |
3ab91208 DH |
50 | PcapFileBehaviorVar behavior; |
51 | bool is_directory; | |
bea66156 | 52 | |
3ab91208 DH |
53 | PcapFileSharedVars shared; |
54 | } PcapFileThreadVars; | |
4e7df60b | 55 | |
3ab91208 DH |
56 | static TmEcode ReceivePcapFileLoop(ThreadVars *, void *, void *); |
57 | static TmEcode ReceivePcapFileThreadInit(ThreadVars *, const void *, void **); | |
58 | static void ReceivePcapFileThreadExitStats(ThreadVars *, void *); | |
59 | static TmEcode ReceivePcapFileThreadDeinit(ThreadVars *, void *); | |
67cea099 | 60 | |
f8aed4ce | 61 | static TmEcode DecodePcapFile(ThreadVars *, Packet *, void *); |
3ab91208 DH |
62 | static TmEcode DecodePcapFileThreadInit(ThreadVars *, const void *, void **); |
63 | static TmEcode DecodePcapFileThreadDeinit(ThreadVars *tv, void *data); | |
9c7f5afa | 64 | |
3ab91208 DH |
65 | static void CleanupPcapDirectoryFromThreadVars(PcapFileThreadVars *tv, |
66 | PcapFileDirectoryVars *ptv); | |
67 | static void CleanupPcapFileFromThreadVars(PcapFileThreadVars *tv, PcapFileFileVars *pfv); | |
68 | static void CleanupPcapFileThreadVars(PcapFileThreadVars *tv); | |
c0ab45aa | 69 | static TmEcode PcapFileExit(TmEcode status, struct timespec *last_processed); |
9c7f5afa | 70 | |
3ab91208 DH |
71 | void CleanupPcapFileFromThreadVars(PcapFileThreadVars *tv, PcapFileFileVars *pfv) |
72 | { | |
73 | CleanupPcapFileFileVars(pfv); | |
74 | if (tv->is_directory == 0) { | |
75 | tv->behavior.file = NULL; | |
76 | } | |
77 | } | |
b753ecce | 78 | |
3ab91208 DH |
79 | void CleanupPcapDirectoryFromThreadVars(PcapFileThreadVars *tv, PcapFileDirectoryVars *ptv) |
80 | { | |
81 | CleanupPcapFileDirectoryVars(ptv); | |
82 | if (tv->is_directory == 1) { | |
83 | tv->behavior.directory = NULL; | |
84 | } | |
85 | } | |
9c7f5afa | 86 | |
3ab91208 DH |
87 | void CleanupPcapFileThreadVars(PcapFileThreadVars *tv) |
88 | { | |
89 | if(tv != NULL) { | |
90 | if (tv->is_directory == 0) { | |
91 | if (tv->behavior.file != NULL) { | |
92 | CleanupPcapFileFromThreadVars(tv, tv->behavior.file); | |
93 | } | |
94 | tv->behavior.file = NULL; | |
95 | } else { | |
96 | if (tv->behavior.directory != NULL) { | |
97 | CleanupPcapDirectoryFromThreadVars(tv, tv->behavior.directory); | |
98 | } | |
99 | tv->behavior.directory = NULL; | |
100 | } | |
101 | if (tv->shared.bpf_string != NULL) { | |
102 | SCFree(tv->shared.bpf_string); | |
103 | tv->shared.bpf_string = NULL; | |
104 | } | |
105 | SCFree(tv); | |
106 | } | |
107 | } | |
9c7f5afa | 108 | |
3ab91208 DH |
109 | /** |
110 | * Pcap File Functionality | |
111 | */ | |
8f1d7503 KS |
112 | void TmModuleReceivePcapFileRegister (void) |
113 | { | |
9c7f5afa | 114 | tmm_modules[TMM_RECEIVEPCAPFILE].name = "ReceivePcapFile"; |
a3910884 | 115 | tmm_modules[TMM_RECEIVEPCAPFILE].ThreadInit = ReceivePcapFileThreadInit; |
b753ecce VJ |
116 | tmm_modules[TMM_RECEIVEPCAPFILE].Func = NULL; |
117 | tmm_modules[TMM_RECEIVEPCAPFILE].PktAcqLoop = ReceivePcapFileLoop; | |
57e0bd39 | 118 | tmm_modules[TMM_RECEIVEPCAPFILE].PktAcqBreakLoop = NULL; |
a3910884 | 119 | tmm_modules[TMM_RECEIVEPCAPFILE].ThreadExitPrintStats = ReceivePcapFileThreadExitStats; |
84f2645e | 120 | tmm_modules[TMM_RECEIVEPCAPFILE].ThreadDeinit = ReceivePcapFileThreadDeinit; |
070ed778 | 121 | tmm_modules[TMM_RECEIVEPCAPFILE].cap_flags = 0; |
3f1c4efc | 122 | tmm_modules[TMM_RECEIVEPCAPFILE].flags = TM_FLAG_RECEIVE_TM; |
9c7f5afa VJ |
123 | } |
124 | ||
8f1d7503 KS |
125 | void TmModuleDecodePcapFileRegister (void) |
126 | { | |
9c7f5afa | 127 | tmm_modules[TMM_DECODEPCAPFILE].name = "DecodePcapFile"; |
a3910884 | 128 | tmm_modules[TMM_DECODEPCAPFILE].ThreadInit = DecodePcapFileThreadInit; |
9c7f5afa | 129 | tmm_modules[TMM_DECODEPCAPFILE].Func = DecodePcapFile; |
a3910884 | 130 | tmm_modules[TMM_DECODEPCAPFILE].ThreadExitPrintStats = NULL; |
bb2e9af4 | 131 | tmm_modules[TMM_DECODEPCAPFILE].ThreadDeinit = DecodePcapFileThreadDeinit; |
070ed778 | 132 | tmm_modules[TMM_DECODEPCAPFILE].cap_flags = 0; |
bc6cf438 | 133 | tmm_modules[TMM_DECODEPCAPFILE].flags = TM_FLAG_DECODE_TM; |
9c7f5afa VJ |
134 | } |
135 | ||
ee7422de EL |
136 | void PcapFileGlobalInit() |
137 | { | |
d05883af | 138 | memset(&pcap_g, 0x00, sizeof(pcap_g)); |
ee7422de EL |
139 | SC_ATOMIC_INIT(pcap_g.invalid_checksums); |
140 | } | |
141 | ||
c0ab45aa | 142 | TmEcode PcapFileExit(TmEcode status, struct timespec *last_processed) |
697a5a19 DB |
143 | { |
144 | if(RunModeUnixSocketIsActive()) { | |
c0ab45aa DB |
145 | status = UnixSocketPcapFile(status, last_processed); |
146 | SCReturnInt(status); | |
697a5a19 DB |
147 | } else { |
148 | EngineStop(); | |
149 | SCReturnInt(status); | |
150 | } | |
151 | } | |
152 | ||
34581ce9 AS |
153 | TmEcode ReceivePcapFileLoop(ThreadVars *tv, void *data, void *slot) |
154 | { | |
155 | SCEnter(); | |
156 | ||
c0ab45aa DB |
157 | if(unlikely(data == NULL)) { |
158 | SCLogError(SC_ERR_INVALID_ARGUMENT, "pcap file reader thread failed to initialize"); | |
159 | ||
160 | PcapFileExit(TM_ECODE_FAILED, NULL); | |
161 | ||
162 | SCReturnInt(TM_ECODE_DONE); | |
163 | } | |
164 | ||
3ab91208 DH |
165 | TmEcode status = TM_ECODE_OK; |
166 | PcapFileThreadVars *ptv = (PcapFileThreadVars *) data; | |
b753ecce | 167 | TmSlot *s = (TmSlot *)slot; |
34581ce9 | 168 | |
3ab91208 DH |
169 | ptv->shared.slot = s->slot_next; |
170 | ptv->shared.cb_result = TM_ECODE_OK; | |
1d74797b | 171 | |
3ab91208 DH |
172 | if(ptv->is_directory == 0) { |
173 | SCLogInfo("Starting file run for %s", ptv->behavior.file->filename); | |
174 | status = PcapFileDispatch(ptv->behavior.file); | |
3ab91208 DH |
175 | CleanupPcapFileFromThreadVars(ptv, ptv->behavior.file); |
176 | } else { | |
177 | SCLogInfo("Starting directory run for %s", ptv->behavior.directory->filename); | |
178 | PcapDirectoryDispatch(ptv->behavior.directory); | |
179 | CleanupPcapDirectoryFromThreadVars(ptv, ptv->behavior.directory); | |
4e7df60b VJ |
180 | } |
181 | ||
3ab91208 DH |
182 | SCLogDebug("Pcap file loop complete with status %u", status); |
183 | ||
c0ab45aa | 184 | status = PcapFileExit(status, &ptv->shared.last_processed); |
697a5a19 | 185 | SCReturnInt(status); |
9c7f5afa VJ |
186 | } |
187 | ||
ab1200fb | 188 | TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, const void *initdata, void **data) |
8f1d7503 | 189 | { |
29d51a61 | 190 | SCEnter(); |
c3efc4e0 | 191 | |
697a5a19 | 192 | TmEcode status = TM_ECODE_OK; |
ab1200fb | 193 | const char *tmpstring = NULL; |
3ab91208 | 194 | const char *tmp_bpf_string = NULL; |
c3efc4e0 | 195 | |
9c7f5afa | 196 | if (initdata == NULL) { |
29d51a61 | 197 | SCLogError(SC_ERR_INVALID_ARGUMENT, "error: initdata == NULL"); |
697a5a19 | 198 | |
c0ab45aa | 199 | SCReturnInt(TM_ECODE_OK); |
9c7f5afa VJ |
200 | } |
201 | ||
25a3a5c6 | 202 | PcapFileThreadVars *ptv = SCMalloc(sizeof(PcapFileThreadVars)); |
697a5a19 | 203 | if (unlikely(ptv == NULL)) { |
c0ab45aa | 204 | SCReturnInt(TM_ECODE_OK); |
697a5a19 | 205 | } |
9c7f5afa | 206 | memset(ptv, 0, sizeof(PcapFileThreadVars)); |
4b897c90 | 207 | memset(&ptv->shared.last_processed, 0, sizeof(struct timespec)); |
9c7f5afa | 208 | |
bea66156 VJ |
209 | intmax_t tenant = 0; |
210 | if (ConfGetInt("pcap-file.tenant-id", &tenant) == 1) { | |
211 | if (tenant > 0 && tenant < UINT_MAX) { | |
3ab91208 DH |
212 | ptv->shared.tenant_id = (uint32_t)tenant; |
213 | SCLogInfo("tenant %u", ptv->shared.tenant_id); | |
bea66156 VJ |
214 | } else { |
215 | SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant out of range"); | |
216 | } | |
217 | } | |
218 | ||
3ab91208 DH |
219 | if (ConfGet("bpf-filter", &(tmp_bpf_string)) != 1) { |
220 | SCLogDebug("could not get bpf or none specified"); | |
221 | } else { | |
222 | ptv->shared.bpf_string = SCStrdup(tmp_bpf_string); | |
223 | if (unlikely(ptv->shared.bpf_string == NULL)) { | |
224 | SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate bpf_string"); | |
c0ab45aa | 225 | |
3ab91208 | 226 | CleanupPcapFileThreadVars(ptv); |
697a5a19 | 227 | |
c0ab45aa | 228 | SCReturnInt(TM_ECODE_OK); |
20a8b9db | 229 | } |
9c7f5afa VJ |
230 | } |
231 | ||
2dc6b6ee DB |
232 | int should_delete = 0; |
233 | ptv->shared.should_delete = false; | |
234 | if (ConfGetBool("pcap-file.delete-when-done", &should_delete) == 1) { | |
235 | ptv->shared.should_delete = should_delete == 1; | |
236 | } | |
237 | ||
3ab91208 | 238 | DIR *directory = NULL; |
63569aeb | 239 | SCLogDebug("checking file or directory %s", (char*)initdata); |
3ab91208 DH |
240 | if(PcapDetermineDirectoryOrFile((char *)initdata, &directory) == TM_ECODE_FAILED) { |
241 | CleanupPcapFileThreadVars(ptv); | |
c0ab45aa | 242 | SCReturnInt(TM_ECODE_OK); |
3ab91208 DH |
243 | } |
244 | ||
245 | if(directory == NULL) { | |
63569aeb | 246 | SCLogDebug("argument %s was a file", (char *)initdata); |
3ab91208 DH |
247 | PcapFileFileVars *pv = SCMalloc(sizeof(PcapFileFileVars)); |
248 | if (unlikely(pv == NULL)) { | |
249 | SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate file vars"); | |
250 | CleanupPcapFileThreadVars(ptv); | |
c0ab45aa | 251 | SCReturnInt(TM_ECODE_OK); |
3ab91208 DH |
252 | } |
253 | memset(pv, 0, sizeof(PcapFileFileVars)); | |
254 | ||
255 | pv->filename = SCStrdup((char *)initdata); | |
256 | if (unlikely(pv->filename == NULL)) { | |
257 | SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate filename"); | |
258 | CleanupPcapFileFileVars(pv); | |
259 | CleanupPcapFileThreadVars(ptv); | |
c0ab45aa | 260 | SCReturnInt(TM_ECODE_OK); |
3ab91208 DH |
261 | } |
262 | ||
54d36206 | 263 | pv->shared = &ptv->shared; |
697a5a19 DB |
264 | status = InitPcapFile(pv); |
265 | if(status == TM_ECODE_OK) { | |
3ab91208 DH |
266 | ptv->is_directory = 0; |
267 | ptv->behavior.file = pv; | |
268 | } else { | |
269 | SCLogWarning(SC_ERR_PCAP_DISPATCH, | |
c0ab45aa | 270 | "Failed to init pcap file %s, skipping", pv->filename); |
3ab91208 DH |
271 | CleanupPcapFileFileVars(pv); |
272 | CleanupPcapFileThreadVars(ptv); | |
c0ab45aa | 273 | SCReturnInt(TM_ECODE_OK); |
3ab91208 | 274 | } |
ba46c16a | 275 | } else { |
3ab91208 DH |
276 | SCLogInfo("Argument %s was a directory", (char *)initdata); |
277 | PcapFileDirectoryVars *pv = SCMalloc(sizeof(PcapFileDirectoryVars)); | |
278 | if (unlikely(pv == NULL)) { | |
279 | SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate directory vars"); | |
e2043668 | 280 | closedir(directory); |
3ab91208 | 281 | CleanupPcapFileThreadVars(ptv); |
c0ab45aa | 282 | SCReturnInt(TM_ECODE_OK); |
3ab91208 DH |
283 | } |
284 | memset(pv, 0, sizeof(PcapFileDirectoryVars)); | |
285 | ||
286 | pv->filename = SCStrdup((char*)initdata); | |
287 | if (unlikely(pv->filename == NULL)) { | |
288 | SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate filename"); | |
289 | CleanupPcapFileDirectoryVars(pv); | |
290 | CleanupPcapFileThreadVars(ptv); | |
c0ab45aa | 291 | SCReturnInt(TM_ECODE_OK); |
3ab91208 | 292 | } |
db5b73d9 JD |
293 | pv->cur_dir_depth = 0; |
294 | ||
295 | int should_recurse; | |
296 | pv->should_recurse = false; | |
297 | if (ConfGetBool("pcap-file.recursive", &should_recurse) == 1) { | |
298 | pv->should_recurse = (should_recurse == 1); | |
299 | } | |
ba46c16a | 300 | |
3ab91208 DH |
301 | int should_loop = 0; |
302 | pv->should_loop = false; | |
303 | if (ConfGetBool("pcap-file.continuous", &should_loop) == 1) { | |
db5b73d9 JD |
304 | pv->should_loop = (should_loop == 1); |
305 | } | |
306 | ||
307 | if (pv->should_recurse == true && pv->should_loop == true) { | |
308 | SCLogError(SC_ERR_INVALID_ARGUMENT, "Error, --pcap-file-continuous and --pcap-file-recursive " | |
309 | "cannot be used together."); | |
5155982b VJ |
310 | CleanupPcapFileDirectoryVars(pv); |
311 | CleanupPcapFileThreadVars(ptv); | |
db5b73d9 | 312 | SCReturnInt(TM_ECODE_FAILED); |
ba46c16a WM |
313 | } |
314 | ||
3ab91208 DH |
315 | pv->delay = 30; |
316 | intmax_t delay = 0; | |
317 | if (ConfGetInt("pcap-file.delay", &delay) == 1) { | |
318 | if (delay > 0 && delay < UINT_MAX) { | |
319 | pv->delay = (time_t)delay; | |
320 | SCLogDebug("delay %lu", pv->delay); | |
321 | } else { | |
322 | SCLogError(SC_ERR_INVALID_ARGUMENT, "delay out of range"); | |
323 | } | |
ba46c16a | 324 | } |
ba46c16a | 325 | |
3ab91208 DH |
326 | pv->poll_interval = 5; |
327 | intmax_t poll_interval = 0; | |
328 | if (ConfGetInt("pcap-file.poll-interval", &poll_interval) == 1) { | |
329 | if (poll_interval > 0 && poll_interval < UINT_MAX) { | |
330 | pv->poll_interval = (time_t)poll_interval; | |
331 | SCLogDebug("poll-interval %lu", pv->delay); | |
5b067e1a | 332 | } else { |
3ab91208 | 333 | SCLogError(SC_ERR_INVALID_ARGUMENT, "poll-interval out of range"); |
5b067e1a | 334 | } |
3ab91208 DH |
335 | } |
336 | ||
337 | pv->shared = &ptv->shared; | |
338 | pv->directory = directory; | |
339 | TAILQ_INIT(&pv->directory_content); | |
340 | ||
341 | ptv->is_directory = 1; | |
342 | ptv->behavior.directory = pv; | |
9c7f5afa VJ |
343 | } |
344 | ||
8b5be26f EL |
345 | if (ConfGet("pcap-file.checksum-checks", &tmpstring) != 1) { |
346 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO; | |
347 | } else { | |
348 | if (strcmp(tmpstring, "auto") == 0) { | |
349 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO; | |
524c6271 | 350 | } else if (ConfValIsTrue(tmpstring)){ |
8b5be26f | 351 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_ENABLE; |
524c6271 | 352 | } else if (ConfValIsFalse(tmpstring)) { |
8b5be26f EL |
353 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_DISABLE; |
354 | } | |
355 | } | |
356 | pcap_g.checksum_mode = pcap_g.conf_checksum_mode; | |
357 | ||
3ab91208 | 358 | ptv->shared.tv = tv; |
9c7f5afa | 359 | *data = (void *)ptv; |
3c6e01f6 | 360 | |
29d51a61 | 361 | SCReturnInt(TM_ECODE_OK); |
9c7f5afa VJ |
362 | } |
363 | ||
8f1d7503 KS |
364 | void ReceivePcapFileThreadExitStats(ThreadVars *tv, void *data) |
365 | { | |
29d51a61 | 366 | SCEnter(); |
c0ab45aa DB |
367 | if(data != NULL) { |
368 | PcapFileThreadVars *ptv = (PcapFileThreadVars *)data; | |
369 | ||
370 | if (pcap_g.conf_checksum_mode == CHECKSUM_VALIDATION_AUTO && | |
371 | pcap_g.cnt < CHECKSUM_SAMPLE_COUNT && | |
372 | SC_ATOMIC_GET(pcap_g.invalid_checksums)) { | |
373 | uint64_t chrate = pcap_g.cnt / SC_ATOMIC_GET(pcap_g.invalid_checksums); | |
374 | if (chrate < CHECKSUM_INVALID_RATIO) | |
375 | SCLogWarning(SC_ERR_INVALID_CHECKSUM, | |
8b5be26f | 376 | "1/%" PRIu64 "th of packets have an invalid checksum," |
3ab91208 DH |
377 | " consider setting pcap-file.checksum-checks variable to no" |
378 | " or use '-k none' option on command line.", | |
8b5be26f | 379 | chrate); |
c0ab45aa DB |
380 | else |
381 | SCLogInfo("1/%" PRIu64 "th of packets have an invalid checksum", | |
8b5be26f | 382 | chrate); |
c0ab45aa DB |
383 | } |
384 | SCLogNotice( | |
3ab91208 DH |
385 | "Pcap-file module read %" PRIu64 " files, %" PRIu64 " packets, %" PRIu64 " bytes", |
386 | ptv->shared.files, | |
387 | ptv->shared.pkts, | |
388 | ptv->shared.bytes | |
c0ab45aa DB |
389 | ); |
390 | } | |
9c7f5afa VJ |
391 | } |
392 | ||
8f1d7503 KS |
393 | TmEcode ReceivePcapFileThreadDeinit(ThreadVars *tv, void *data) |
394 | { | |
29d51a61 | 395 | SCEnter(); |
c0ab45aa DB |
396 | if(data != NULL) { |
397 | PcapFileThreadVars *ptv = (PcapFileThreadVars *) data; | |
398 | CleanupPcapFileThreadVars(ptv); | |
399 | } | |
29d51a61 | 400 | SCReturnInt(TM_ECODE_OK); |
9c7f5afa VJ |
401 | } |
402 | ||
f8aed4ce | 403 | static TmEcode DecodePcapFile(ThreadVars *tv, Packet *p, void *data) |
d0e70309 | 404 | { |
29d51a61 | 405 | SCEnter(); |
244f5d54 AS |
406 | DecodeThreadVars *dtv = (DecodeThreadVars *)data; |
407 | ||
7810f224 | 408 | BUG_ON(PKT_IS_PSEUDOPKT(p)); |
f7b1aefa | 409 | |
57f71f7e | 410 | /* update counters */ |
14466a80 | 411 | DecodeUpdatePacketCounters(tv, dtv, p); |
d0e70309 | 412 | |
579cc9f0 | 413 | DecoderFunc decoder; |
3ab91208 DH |
414 | if(ValidateLinkType(p->datalink, &decoder) == TM_ECODE_OK) { |
415 | ||
416 | /* call the decoder */ | |
f8aed4ce | 417 | decoder(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p)); |
244f5d54 | 418 | |
17c763f8 | 419 | #ifdef DEBUG |
3ab91208 | 420 | BUG_ON(p->pkt_src != PKT_SRC_WIRE && p->pkt_src != PKT_SRC_FFR); |
17c763f8 AS |
421 | #endif |
422 | ||
3ab91208 | 423 | PacketDecodeFinalize(tv, dtv, p); |
17c763f8 | 424 | |
3ab91208 DH |
425 | SCReturnInt(TM_ECODE_OK); |
426 | } else { | |
427 | SCReturnInt(TM_ECODE_FAILED); | |
428 | } | |
9c7f5afa VJ |
429 | } |
430 | ||
ab1200fb | 431 | TmEcode DecodePcapFileThreadInit(ThreadVars *tv, const void *initdata, void **data) |
d0e70309 | 432 | { |
29d51a61 | 433 | SCEnter(); |
244f5d54 | 434 | DecodeThreadVars *dtv = NULL; |
5f307aca | 435 | dtv = DecodeThreadVarsAlloc(tv); |
244f5d54 | 436 | |
8cc525c9 | 437 | if (dtv == NULL) |
29d51a61 | 438 | SCReturnInt(TM_ECODE_FAILED); |
244f5d54 | 439 | |
8beef4a9 | 440 | DecodeRegisterPerfCounters(dtv, tv); |
244f5d54 AS |
441 | |
442 | *data = (void *)dtv; | |
ceb7e495 | 443 | |
29d51a61 | 444 | SCReturnInt(TM_ECODE_OK); |
d0e70309 AS |
445 | } |
446 | ||
bb2e9af4 VJ |
447 | TmEcode DecodePcapFileThreadDeinit(ThreadVars *tv, void *data) |
448 | { | |
449 | if (data != NULL) | |
98c88d51 | 450 | DecodeThreadVarsFree(tv, data); |
bb2e9af4 VJ |
451 | SCReturnInt(TM_ECODE_OK); |
452 | } | |
8b5be26f EL |
453 | |
454 | void PcapIncreaseInvalidChecksum() | |
455 | { | |
456 | (void) SC_ATOMIC_ADD(pcap_g.invalid_checksums, 1); | |
457 | } | |
458 | ||
9c7f5afa | 459 | /* eof */ |