/src/suricata/src/source-pcap-file.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2016 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 Victor Julien <victor@inliniac.net> |
22 | | * |
23 | | * File based pcap packet acquisition support |
24 | | */ |
25 | | |
26 | | #include "suricata-common.h" |
27 | | #include "source-pcap-file.h" |
28 | | #include "source-pcap-file-helper.h" |
29 | | #include "source-pcap-file-directory-helper.h" |
30 | | #include "flow-manager.h" |
31 | | #include "util-checksum.h" |
32 | | #include "runmode-unix-socket.h" |
33 | | #include "suricata.h" |
34 | | #include "conf.h" |
35 | | #include "util-misc.h" |
36 | | |
37 | | extern uint32_t max_pending_packets; |
38 | | PcapFileGlobalVars pcap_g; |
39 | | |
40 | | /** |
41 | | * Union determining whether the behavior of the thread is file or directory |
42 | | */ |
43 | | typedef union PcapFileBehaviorVar_ |
44 | | { |
45 | | PcapFileDirectoryVars *directory; |
46 | | PcapFileFileVars *file; |
47 | | } PcapFileBehaviorVar; |
48 | | |
49 | | /** |
50 | | * Data specific to the thread |
51 | | */ |
52 | | typedef struct PcapFileThreadVars_ |
53 | | { |
54 | | PcapFileBehaviorVar behavior; |
55 | | bool is_directory; |
56 | | |
57 | | PcapFileSharedVars shared; |
58 | | } PcapFileThreadVars; |
59 | | |
60 | | static TmEcode ReceivePcapFileLoop(ThreadVars *, void *, void *); |
61 | | static TmEcode ReceivePcapFileThreadInit(ThreadVars *, const void *, void **); |
62 | | static void ReceivePcapFileThreadExitStats(ThreadVars *, void *); |
63 | | static TmEcode ReceivePcapFileThreadDeinit(ThreadVars *, void *); |
64 | | |
65 | | static TmEcode DecodePcapFile(ThreadVars *, Packet *, void *); |
66 | | static TmEcode DecodePcapFileThreadInit(ThreadVars *, const void *, void **); |
67 | | static TmEcode DecodePcapFileThreadDeinit(ThreadVars *tv, void *data); |
68 | | |
69 | | static void CleanupPcapDirectoryFromThreadVars(PcapFileThreadVars *tv, |
70 | | PcapFileDirectoryVars *ptv); |
71 | | static void CleanupPcapFileFromThreadVars(PcapFileThreadVars *tv, PcapFileFileVars *pfv); |
72 | | static void CleanupPcapFileThreadVars(PcapFileThreadVars *tv); |
73 | | static TmEcode PcapFileExit(TmEcode status, struct timespec *last_processed); |
74 | | |
75 | | void CleanupPcapFileFromThreadVars(PcapFileThreadVars *tv, PcapFileFileVars *pfv) |
76 | 18.8k | { |
77 | 18.8k | CleanupPcapFileFileVars(pfv); |
78 | 18.8k | if (tv->is_directory == 0) { |
79 | 18.8k | tv->behavior.file = NULL; |
80 | 18.8k | } |
81 | 18.8k | } |
82 | | |
83 | | void CleanupPcapDirectoryFromThreadVars(PcapFileThreadVars *tv, PcapFileDirectoryVars *ptv) |
84 | 0 | { |
85 | 0 | CleanupPcapFileDirectoryVars(ptv); |
86 | 0 | if (tv->is_directory == 1) { |
87 | 0 | tv->behavior.directory = NULL; |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | void CleanupPcapFileThreadVars(PcapFileThreadVars *ptv) |
92 | 22.6k | { |
93 | 22.6k | if (ptv != NULL) { |
94 | 22.6k | if (ptv->is_directory == 0) { |
95 | 22.6k | if (ptv->behavior.file != NULL) { |
96 | 0 | CleanupPcapFileFromThreadVars(ptv, ptv->behavior.file); |
97 | 0 | } |
98 | 22.6k | ptv->behavior.file = NULL; |
99 | 22.6k | } else { |
100 | 0 | if (ptv->behavior.directory != NULL) { |
101 | 0 | CleanupPcapDirectoryFromThreadVars(ptv, ptv->behavior.directory); |
102 | 0 | } |
103 | 0 | ptv->behavior.directory = NULL; |
104 | 0 | } |
105 | 22.6k | if (ptv->shared.bpf_string != NULL) { |
106 | 0 | SCFree(ptv->shared.bpf_string); |
107 | 0 | ptv->shared.bpf_string = NULL; |
108 | 0 | } |
109 | 22.6k | SCFree(ptv); |
110 | 22.6k | } |
111 | 22.6k | } |
112 | | |
113 | | /** |
114 | | * Pcap File Functionality |
115 | | */ |
116 | | void TmModuleReceivePcapFileRegister (void) |
117 | 71 | { |
118 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].name = "ReceivePcapFile"; |
119 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].ThreadInit = ReceivePcapFileThreadInit; |
120 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].Func = NULL; |
121 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].PktAcqLoop = ReceivePcapFileLoop; |
122 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].PktAcqBreakLoop = NULL; |
123 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].ThreadExitPrintStats = ReceivePcapFileThreadExitStats; |
124 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].ThreadDeinit = ReceivePcapFileThreadDeinit; |
125 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].cap_flags = 0; |
126 | 71 | tmm_modules[TMM_RECEIVEPCAPFILE].flags = TM_FLAG_RECEIVE_TM; |
127 | 71 | } |
128 | | |
129 | | void TmModuleDecodePcapFileRegister (void) |
130 | 71 | { |
131 | 71 | tmm_modules[TMM_DECODEPCAPFILE].name = "DecodePcapFile"; |
132 | 71 | tmm_modules[TMM_DECODEPCAPFILE].ThreadInit = DecodePcapFileThreadInit; |
133 | 71 | tmm_modules[TMM_DECODEPCAPFILE].Func = DecodePcapFile; |
134 | 71 | tmm_modules[TMM_DECODEPCAPFILE].ThreadExitPrintStats = NULL; |
135 | 71 | tmm_modules[TMM_DECODEPCAPFILE].ThreadDeinit = DecodePcapFileThreadDeinit; |
136 | 71 | tmm_modules[TMM_DECODEPCAPFILE].cap_flags = 0; |
137 | 71 | tmm_modules[TMM_DECODEPCAPFILE].flags = TM_FLAG_DECODE_TM; |
138 | 71 | } |
139 | | |
140 | | #if defined(HAVE_SETVBUF) && defined(OS_LINUX) |
141 | 1 | #define PCAP_FILE_BUFFER_SIZE_DEFAULT 131072U // 128 KiB |
142 | 0 | #define PCAP_FILE_BUFFER_SIZE_MIN 4096U // 4 KiB |
143 | 0 | #define PCAP_FILE_BUFFER_SIZE_MAX 67108864U // 64MiB |
144 | | #endif |
145 | | |
146 | | void PcapFileGlobalInit(void) |
147 | 1 | { |
148 | 1 | memset(&pcap_g, 0x00, sizeof(pcap_g)); |
149 | 1 | SC_ATOMIC_INIT(pcap_g.invalid_checksums); |
150 | | |
151 | 1 | #if defined(HAVE_SETVBUF) && defined(OS_LINUX) |
152 | 1 | pcap_g.read_buffer_size = PCAP_FILE_BUFFER_SIZE_DEFAULT; |
153 | | |
154 | 1 | const char *str = NULL; |
155 | 1 | if (SCConfGet("pcap-file.buffer-size", &str) == 1) { |
156 | 0 | uint32_t value = 0; |
157 | 0 | if (ParseSizeStringU32(str, &value) < 0) { |
158 | 0 | SCLogWarning("failed to parse pcap-file.buffer-size %s", str); |
159 | 0 | } |
160 | 0 | if (value >= PCAP_FILE_BUFFER_SIZE_MIN && value <= PCAP_FILE_BUFFER_SIZE_MAX) { |
161 | 0 | SCLogInfo("Pcap-file will use %u buffer size", value); |
162 | 0 | pcap_g.read_buffer_size = value; |
163 | 0 | } else { |
164 | 0 | SCLogWarning("pcap-file.buffer-size value of %u is invalid. Valid range is %u-%u", |
165 | 0 | value, PCAP_FILE_BUFFER_SIZE_MIN, PCAP_FILE_BUFFER_SIZE_MAX); |
166 | 0 | } |
167 | 0 | } |
168 | 1 | #endif |
169 | 1 | } |
170 | | |
171 | | TmEcode PcapFileExit(TmEcode status, struct timespec *last_processed) |
172 | 18.8k | { |
173 | 18.8k | if(RunModeUnixSocketIsActive()) { |
174 | 0 | status = UnixSocketPcapFile(status, last_processed); |
175 | 0 | SCReturnInt(status); |
176 | 18.8k | } else { |
177 | 18.8k | EngineStop(); |
178 | 18.8k | SCReturnInt(status); |
179 | 18.8k | } |
180 | 18.8k | } |
181 | | |
182 | | TmEcode ReceivePcapFileLoop(ThreadVars *tv, void *data, void *slot) |
183 | 18.8k | { |
184 | 18.8k | SCEnter(); |
185 | | |
186 | 18.8k | if(unlikely(data == NULL)) { |
187 | 0 | SCLogError("pcap file reader thread failed to initialize"); |
188 | |
|
189 | 0 | PcapFileExit(TM_ECODE_FAILED, NULL); |
190 | |
|
191 | 0 | SCReturnInt(TM_ECODE_DONE); |
192 | 0 | } |
193 | | |
194 | 18.8k | TmEcode status = TM_ECODE_OK; |
195 | 18.8k | PcapFileThreadVars *ptv = (PcapFileThreadVars *) data; |
196 | 18.8k | TmSlot *s = (TmSlot *)slot; |
197 | | |
198 | 18.8k | ptv->shared.slot = s->slot_next; |
199 | 18.8k | ptv->shared.cb_result = TM_ECODE_OK; |
200 | | |
201 | | // Indicate that the thread is actually running its application level code (i.e., it can poll |
202 | | // packets) |
203 | 18.8k | TmThreadsSetFlag(tv, THV_RUNNING); |
204 | | |
205 | 18.8k | if(ptv->is_directory == 0) { |
206 | 18.8k | SCLogInfo("Starting file run for %s", ptv->behavior.file->filename); |
207 | 18.8k | status = PcapFileDispatch(ptv->behavior.file); |
208 | 18.8k | CleanupPcapFileFromThreadVars(ptv, ptv->behavior.file); |
209 | 18.8k | } else { |
210 | 0 | SCLogInfo("Starting directory run for %s", ptv->behavior.directory->filename); |
211 | 0 | PcapDirectoryDispatch(ptv->behavior.directory); |
212 | 0 | CleanupPcapDirectoryFromThreadVars(ptv, ptv->behavior.directory); |
213 | 0 | } |
214 | | |
215 | 18.8k | SCLogDebug("Pcap file loop complete with status %u", status); |
216 | | |
217 | 18.8k | status = PcapFileExit(status, &ptv->shared.last_processed); |
218 | 18.8k | SCReturnInt(status); |
219 | 18.8k | } |
220 | | |
221 | | TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, const void *initdata, void **data) |
222 | 11.4k | { |
223 | 11.4k | SCEnter(); |
224 | | |
225 | 11.4k | TmEcode status = TM_ECODE_OK; |
226 | 11.4k | const char *tmpstring = NULL; |
227 | 11.4k | const char *tmp_bpf_string = NULL; |
228 | | |
229 | 11.4k | if (initdata == NULL) { |
230 | 0 | SCLogError("error: initdata == NULL"); |
231 | |
|
232 | 0 | SCReturnInt(TM_ECODE_OK); |
233 | 0 | } |
234 | | |
235 | 11.4k | PcapFileThreadVars *ptv = SCCalloc(1, sizeof(PcapFileThreadVars)); |
236 | 11.4k | if (unlikely(ptv == NULL)) { |
237 | 0 | SCReturnInt(TM_ECODE_OK); |
238 | 0 | } |
239 | 11.4k | memset(&ptv->shared.last_processed, 0, sizeof(struct timespec)); |
240 | | |
241 | 11.4k | intmax_t tenant = 0; |
242 | 11.4k | if (SCConfGetInt("pcap-file.tenant-id", &tenant) == 1) { |
243 | 0 | if (tenant > 0 && tenant < UINT_MAX) { |
244 | 0 | ptv->shared.tenant_id = (uint32_t)tenant; |
245 | 0 | SCLogInfo("tenant %u", ptv->shared.tenant_id); |
246 | 0 | } else { |
247 | 0 | SCLogError("tenant out of range"); |
248 | 0 | } |
249 | 0 | } |
250 | | |
251 | 11.4k | if (SCConfGet("bpf-filter", &(tmp_bpf_string)) != 1) { |
252 | 11.4k | SCLogDebug("could not get bpf or none specified"); |
253 | 11.4k | } else { |
254 | 0 | ptv->shared.bpf_string = SCStrdup(tmp_bpf_string); |
255 | 0 | if (unlikely(ptv->shared.bpf_string == NULL)) { |
256 | 0 | SCLogError("Failed to allocate bpf_string"); |
257 | |
|
258 | 0 | CleanupPcapFileThreadVars(ptv); |
259 | |
|
260 | 0 | SCReturnInt(TM_ECODE_OK); |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | 11.4k | int should_delete = 0; |
265 | 11.4k | ptv->shared.should_delete = false; |
266 | 11.4k | if (SCConfGetBool("pcap-file.delete-when-done", &should_delete) == 1) { |
267 | 0 | ptv->shared.should_delete = should_delete == 1; |
268 | 0 | } |
269 | | |
270 | 11.4k | DIR *directory = NULL; |
271 | 11.4k | SCLogDebug("checking file or directory %s", (char*)initdata); |
272 | 11.4k | if(PcapDetermineDirectoryOrFile((char *)initdata, &directory) == TM_ECODE_FAILED) { |
273 | 68 | CleanupPcapFileThreadVars(ptv); |
274 | 68 | SCReturnInt(TM_ECODE_OK); |
275 | 68 | } |
276 | | |
277 | 11.3k | if(directory == NULL) { |
278 | 11.3k | SCLogDebug("argument %s was a file", (char *)initdata); |
279 | 11.3k | const size_t toalloc = sizeof(PcapFileFileVars) + pcap_g.read_buffer_size; |
280 | 11.3k | PcapFileFileVars *pv = SCCalloc(1, toalloc); |
281 | 11.3k | if (unlikely(pv == NULL)) { |
282 | 0 | SCLogError("Failed to allocate file vars"); |
283 | 0 | CleanupPcapFileThreadVars(ptv); |
284 | 0 | SCReturnInt(TM_ECODE_OK); |
285 | 0 | } |
286 | | |
287 | 11.3k | pv->filename = SCStrdup((char *)initdata); |
288 | 11.3k | if (unlikely(pv->filename == NULL)) { |
289 | 0 | SCLogError("Failed to allocate filename"); |
290 | 0 | CleanupPcapFileFileVars(pv); |
291 | 0 | CleanupPcapFileThreadVars(ptv); |
292 | 0 | SCReturnInt(TM_ECODE_OK); |
293 | 0 | } |
294 | | |
295 | 11.3k | pv->shared = &ptv->shared; |
296 | 11.3k | status = InitPcapFile(pv); |
297 | 11.3k | if(status == TM_ECODE_OK) { |
298 | 9.57k | ptv->is_directory = 0; |
299 | 9.57k | ptv->behavior.file = pv; |
300 | 9.57k | } else { |
301 | 1.82k | SCLogWarning("Failed to init pcap file %s, skipping", pv->filename); |
302 | 1.82k | CleanupPcapFileFileVars(pv); |
303 | 1.82k | CleanupPcapFileThreadVars(ptv); |
304 | 1.82k | SCReturnInt(TM_ECODE_OK); |
305 | 1.82k | } |
306 | 11.3k | } else { |
307 | 0 | SCLogInfo("Argument %s was a directory", (char *)initdata); |
308 | 0 | PcapFileDirectoryVars *pv = SCCalloc(1, sizeof(PcapFileDirectoryVars)); |
309 | 0 | if (unlikely(pv == NULL)) { |
310 | 0 | SCLogError("Failed to allocate directory vars"); |
311 | 0 | closedir(directory); |
312 | 0 | CleanupPcapFileThreadVars(ptv); |
313 | 0 | SCReturnInt(TM_ECODE_OK); |
314 | 0 | } |
315 | | |
316 | 0 | pv->filename = SCStrdup((char*)initdata); |
317 | 0 | if (unlikely(pv->filename == NULL)) { |
318 | 0 | SCLogError("Failed to allocate filename"); |
319 | 0 | closedir(directory); |
320 | 0 | CleanupPcapFileDirectoryVars(pv); |
321 | 0 | CleanupPcapFileThreadVars(ptv); |
322 | 0 | SCReturnInt(TM_ECODE_OK); |
323 | 0 | } |
324 | | |
325 | 0 | int should_recurse; |
326 | 0 | pv->should_recurse = false; |
327 | 0 | if (SCConfGetBool("pcap-file.recursive", &should_recurse) == 1) { |
328 | 0 | pv->should_recurse = (should_recurse == 1); |
329 | 0 | } |
330 | |
|
331 | 0 | int should_loop = 0; |
332 | 0 | pv->should_loop = false; |
333 | 0 | if (SCConfGetBool("pcap-file.continuous", &should_loop) == 1) { |
334 | 0 | pv->should_loop = (should_loop == 1); |
335 | 0 | } |
336 | |
|
337 | 0 | if (pv->should_recurse && pv->should_loop) { |
338 | 0 | SCLogError("Error, --pcap-file-continuous and --pcap-file-recursive " |
339 | 0 | "cannot be used together."); |
340 | 0 | closedir(directory); |
341 | 0 | CleanupPcapFileDirectoryVars(pv); |
342 | 0 | CleanupPcapFileThreadVars(ptv); |
343 | 0 | SCReturnInt(TM_ECODE_FAILED); |
344 | 0 | } |
345 | | |
346 | 0 | pv->delay = 30; |
347 | 0 | intmax_t delay = 0; |
348 | 0 | if (SCConfGetInt("pcap-file.delay", &delay) == 1) { |
349 | 0 | if (delay > 0 && delay < UINT_MAX) { |
350 | 0 | pv->delay = (time_t)delay; |
351 | 0 | SCLogDebug("delay %lu", pv->delay); |
352 | 0 | } else { |
353 | 0 | SCLogError("delay out of range"); |
354 | 0 | } |
355 | 0 | } |
356 | |
|
357 | 0 | pv->poll_interval = 5; |
358 | 0 | intmax_t poll_interval = 0; |
359 | 0 | if (SCConfGetInt("pcap-file.poll-interval", &poll_interval) == 1) { |
360 | 0 | if (poll_interval > 0 && poll_interval < UINT_MAX) { |
361 | 0 | pv->poll_interval = (time_t)poll_interval; |
362 | 0 | SCLogDebug("poll-interval %lu", pv->delay); |
363 | 0 | } else { |
364 | 0 | SCLogError("poll-interval out of range"); |
365 | 0 | } |
366 | 0 | } |
367 | |
|
368 | 0 | pv->shared = &ptv->shared; |
369 | 0 | pv->directory = directory; |
370 | 0 | TAILQ_INIT(&pv->directory_content); |
371 | |
|
372 | 0 | ptv->is_directory = 1; |
373 | 0 | ptv->behavior.directory = pv; |
374 | 0 | } |
375 | | |
376 | 9.57k | if (SCConfGet("pcap-file.checksum-checks", &tmpstring) != 1) { |
377 | 0 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO; |
378 | 9.57k | } else { |
379 | 9.57k | if (strcmp(tmpstring, "auto") == 0) { |
380 | 0 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO; |
381 | 9.57k | } else if (SCConfValIsTrue(tmpstring)) { |
382 | 0 | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_ENABLE; |
383 | 9.57k | } else if (SCConfValIsFalse(tmpstring)) { |
384 | 9.57k | pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_DISABLE; |
385 | 9.57k | } |
386 | 9.57k | } |
387 | 9.57k | pcap_g.checksum_mode = pcap_g.conf_checksum_mode; |
388 | | |
389 | 9.57k | ptv->shared.tv = tv; |
390 | 9.57k | *data = (void *)ptv; |
391 | | |
392 | 9.57k | SCReturnInt(TM_ECODE_OK); |
393 | 11.3k | } |
394 | | |
395 | | void ReceivePcapFileThreadExitStats(ThreadVars *tv, void *data) |
396 | 0 | { |
397 | 0 | SCEnter(); |
398 | 0 | if(data != NULL) { |
399 | 0 | PcapFileThreadVars *ptv = (PcapFileThreadVars *)data; |
400 | |
|
401 | 0 | if (pcap_g.conf_checksum_mode == CHECKSUM_VALIDATION_AUTO && |
402 | 0 | pcap_g.cnt < CHECKSUM_SAMPLE_COUNT && |
403 | 0 | SC_ATOMIC_GET(pcap_g.invalid_checksums)) { |
404 | 0 | uint64_t chrate = pcap_g.cnt / SC_ATOMIC_GET(pcap_g.invalid_checksums); |
405 | 0 | if (chrate < CHECKSUM_INVALID_RATIO) |
406 | 0 | SCLogWarning("1/%" PRIu64 "th of packets have an invalid checksum," |
407 | 0 | " consider setting pcap-file.checksum-checks variable to no" |
408 | 0 | " or use '-k none' option on command line.", |
409 | 0 | chrate); |
410 | 0 | else |
411 | 0 | SCLogInfo("1/%" PRIu64 "th of packets have an invalid checksum", |
412 | 0 | chrate); |
413 | 0 | } |
414 | 0 | SCLogNotice("read %" PRIu64 " file%s, %" PRIu64 " packets, %" PRIu64 " bytes", |
415 | 0 | ptv->shared.files, ptv->shared.files == 1 ? "" : "s", ptv->shared.pkts, |
416 | 0 | ptv->shared.bytes); |
417 | 0 | } |
418 | 0 | } |
419 | | |
420 | | TmEcode ReceivePcapFileThreadDeinit(ThreadVars *tv, void *data) |
421 | 18.8k | { |
422 | 18.8k | SCEnter(); |
423 | 18.8k | if(data != NULL) { |
424 | 18.8k | PcapFileThreadVars *ptv = (PcapFileThreadVars *) data; |
425 | 18.8k | CleanupPcapFileThreadVars(ptv); |
426 | 18.8k | } |
427 | 18.8k | SCReturnInt(TM_ECODE_OK); |
428 | 18.8k | } |
429 | | |
430 | | static TmEcode DecodePcapFile(ThreadVars *tv, Packet *p, void *data) |
431 | 19.1M | { |
432 | 19.1M | SCEnter(); |
433 | 19.1M | DecodeThreadVars *dtv = (DecodeThreadVars *)data; |
434 | | |
435 | 19.1M | DEBUG_VALIDATE_BUG_ON(PKT_IS_PSEUDOPKT(p)); |
436 | | |
437 | | /* update counters */ |
438 | 19.1M | DecodeUpdatePacketCounters(tv, dtv, p); |
439 | | |
440 | 19.1M | DecoderFunc decoder; |
441 | 19.1M | if(ValidateLinkType(p->datalink, &decoder) == TM_ECODE_OK) { |
442 | | |
443 | | /* call the decoder */ |
444 | 19.1M | decoder(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p)); |
445 | | |
446 | | #ifdef DEBUG |
447 | | BUG_ON(p->pkt_src != PKT_SRC_WIRE && p->pkt_src != PKT_SRC_FFR); |
448 | | #endif |
449 | | |
450 | 19.1M | PacketDecodeFinalize(tv, dtv, p); |
451 | | |
452 | 19.1M | SCReturnInt(TM_ECODE_OK); |
453 | 19.1M | } else { |
454 | 134 | SCReturnInt(TM_ECODE_FAILED); |
455 | 134 | } |
456 | 19.1M | } |
457 | | |
458 | | TmEcode DecodePcapFileThreadInit(ThreadVars *tv, const void *initdata, void **data) |
459 | 2 | { |
460 | 2 | SCEnter(); |
461 | 2 | DecodeThreadVars *dtv = NULL; |
462 | 2 | dtv = DecodeThreadVarsAlloc(tv); |
463 | | |
464 | 2 | if (dtv == NULL) |
465 | 0 | SCReturnInt(TM_ECODE_FAILED); |
466 | | |
467 | 2 | DecodeRegisterPerfCounters(dtv, tv); |
468 | | |
469 | 2 | *data = (void *)dtv; |
470 | | |
471 | 2 | SCReturnInt(TM_ECODE_OK); |
472 | 2 | } |
473 | | |
474 | | TmEcode DecodePcapFileThreadDeinit(ThreadVars *tv, void *data) |
475 | 0 | { |
476 | 0 | if (data != NULL) |
477 | 0 | DecodeThreadVarsFree(tv, data); |
478 | 0 | SCReturnInt(TM_ECODE_OK); |
479 | 0 | } |
480 | | |
481 | | void PcapIncreaseInvalidChecksum(void) |
482 | 0 | { |
483 | | (void) SC_ATOMIC_ADD(pcap_g.invalid_checksums, 1); |
484 | 0 | } |
485 | | |
486 | | /* eof */ |