suricata
util-file.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2012 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  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
23  *
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "debug.h"
29 #include "flow.h"
30 #include "stream.h"
31 #include "stream-tcp.h"
32 #include "runmodes.h"
33 #include "util-hash.h"
34 #include "util-debug.h"
35 #include "util-memcmp.h"
36 #include "util-print.h"
37 #include "app-layer-parser.h"
38 #include "util-validate.h"
39 
40 /** \brief switch to force filestore on all files
41  * regardless of the rules.
42  */
43 static int g_file_force_filestore = 0;
44 
45 /** \brief switch to force magic checks on all files
46  * regardless of the rules.
47  */
48 static int g_file_force_magic = 0;
49 
50 /** \brief switch to force md5 calculation on all files
51  * regardless of the rules.
52  */
53 static int g_file_force_md5 = 0;
54 
55 /** \brief switch to force sha1 calculation on all files
56  * regardless of the rules.
57  */
58 static int g_file_force_sha1 = 0;
59 
60 /** \brief switch to force sha256 calculation on all files
61  * regardless of the rules.
62  */
63 static int g_file_force_sha256 = 0;
64 
65 /** \brief switch to force tracking off all files
66  * regardless of the rules.
67  */
68 static int g_file_force_tracking = 0;
69 
70 /** \brief switch to use g_file_store_reassembly_depth
71  * to reassembly files
72  */
73 static int g_file_store_enable = 0;
74 
75 /** \brief stream_config.reassembly_depth equivalent
76  * for files
77  */
78 static uint32_t g_file_store_reassembly_depth = 0;
79 
80 /* prototypes */
81 static void FileFree(File *);
82 #ifdef HAVE_NSS
83 static void FileEndSha256(File *ff);
84 #endif
85 
87 {
88  g_file_force_filestore = 1;
89 }
90 
92 {
93  g_file_force_magic = 1;
94 }
95 
97 {
98  g_file_force_md5 = 1;
99 }
100 
102 {
103  g_file_force_sha1 = 1;
104 }
105 
107 {
108  g_file_force_sha256 = 1;
109 }
110 
112 {
113  return g_file_force_filestore;
114 }
115 
116 void FileReassemblyDepthEnable(uint32_t size)
117 {
118  g_file_store_enable = 1;
119  g_file_store_reassembly_depth = size;
120 }
121 
122 uint32_t FileReassemblyDepth(void)
123 {
124  if (g_file_store_enable == 1)
125  return g_file_store_reassembly_depth;
126  else
128 }
129 
130 int FileForceMagic(void)
131 {
132  return g_file_force_magic;
133 }
134 
135 int FileForceMd5(void)
136 {
137  return g_file_force_md5;
138 }
139 
140 int FileForceSha1(void)
141 {
142  return g_file_force_sha1;
143 }
144 
146 {
147  return g_file_force_sha256;
148 }
149 
151 {
152  g_file_force_tracking = 1;
153 }
154 
155 /**
156  * \brief Function to parse forced file hashing configuration.
157  */
159 {
160  BUG_ON(conf == NULL);
161 
162  ConfNode *forcehash_node = NULL;
163 
164  /* legacy option */
165  const char *force_md5 = ConfNodeLookupChildValue(conf, "force-md5");
166  if (force_md5 != NULL) {
167  SCLogWarning(SC_ERR_DEPRECATED_CONF, "deprecated 'force-md5' option "
168  "found. Please use 'force-hash: [md5]' instead");
169 
170  if (ConfValIsTrue(force_md5)) {
171 #ifdef HAVE_NSS
173  SCLogInfo("forcing md5 calculation for logged files");
174 #else
175  SCLogInfo("md5 calculation requires linking against libnss");
176 #endif
177  }
178  }
179 
180  if (conf != NULL)
181  forcehash_node = ConfNodeLookupChild(conf, "force-hash");
182 
183  if (forcehash_node != NULL) {
184  ConfNode *field = NULL;
185 
186  TAILQ_FOREACH(field, &forcehash_node->head, next) {
187  if (strcasecmp("md5", field->val) == 0) {
188 #ifdef HAVE_NSS
190  SCLogConfig("forcing md5 calculation for logged or stored files");
191 #else
192  SCLogInfo("md5 calculation requires linking against libnss");
193 #endif
194  }
195 
196  if (strcasecmp("sha1", field->val) == 0) {
197 #ifdef HAVE_NSS
199  SCLogConfig("forcing sha1 calculation for logged or stored files");
200 #else
201  SCLogInfo("sha1 calculation requires linking against libnss");
202 #endif
203  }
204 
205  if (strcasecmp("sha256", field->val) == 0) {
206 #ifdef HAVE_NSS
208  SCLogConfig("forcing sha256 calculation for logged or stored files");
209 #else
210  SCLogInfo("sha256 calculation requires linking against libnss");
211 #endif
212  }
213  }
214  }
215 }
216 
217 uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
218 {
219  uint16_t flags = 0;
220 
221  if (direction == STREAM_TOSERVER) {
222  if (flow->file_flags & FLOWFILE_NO_STORE_TS) {
223  flags |= FILE_NOSTORE;
224  }
225 
226  if (flow->file_flags & FLOWFILE_NO_MAGIC_TS) {
227  flags |= FILE_NOMAGIC;
228  }
229 
230  if (flow->file_flags & FLOWFILE_NO_MD5_TS) {
231  flags |= FILE_NOMD5;
232  }
233 
234  if (flow->file_flags & FLOWFILE_NO_SHA1_TS) {
235  flags |= FILE_NOSHA1;
236  }
237 
238  if (flow->file_flags & FLOWFILE_NO_SHA256_TS) {
239  flags |= FILE_NOSHA256;
240  }
241  } else {
242  if (flow->file_flags & FLOWFILE_NO_STORE_TC) {
243  flags |= FILE_NOSTORE;
244  }
245 
246  if (flow->file_flags & FLOWFILE_NO_MAGIC_TC) {
247  flags |= FILE_NOMAGIC;
248  }
249 
250  if (flow->file_flags & FLOWFILE_NO_MD5_TC) {
251  flags |= FILE_NOMD5;
252  }
253 
254  if (flow->file_flags & FLOWFILE_NO_SHA1_TC) {
255  flags |= FILE_NOSHA1;
256  }
257 
258  if (flow->file_flags & FLOWFILE_NO_SHA256_TC) {
259  flags |= FILE_NOSHA256;
260  }
261  }
262  return flags;
263 }
264 
265 static int FileMagicSize(void)
266 {
267  /** \todo make this size configurable */
268  return 512;
269 }
270 
271 /**
272  * \brief get the size of the file data
273  *
274  * This doesn't reflect how much of the file we have in memory, just the
275  * total size of filedata so far.
276  */
277 uint64_t FileDataSize(const File *file)
278 {
279  if (file != NULL && file->sb != NULL) {
280  SCLogDebug("returning %"PRIu64,
281  file->sb->stream_offset + file->sb->buf_offset);
282  return file->sb->stream_offset + file->sb->buf_offset;
283  }
284  SCLogDebug("returning 0 (default)");
285  return 0;
286 }
287 
288 /**
289  * \brief get the size of the file
290  *
291  * This doesn't reflect how much of the file we have in memory, just the
292  * total size of file so far.
293  */
294 uint64_t FileTrackedSize(const File *file)
295 {
296  if (file != NULL) {
297  return file->size;
298  }
299  return 0;
300 }
301 
302 static int FilePruneFile(File *file)
303 {
304  SCEnter();
305 #ifdef HAVE_MAGIC
306  if (!(file->flags & FILE_NOMAGIC)) {
307  /* need magic but haven't set it yet, bail out */
308  if (file->magic == NULL)
309  SCReturnInt(0);
310  else
311  SCLogDebug("file->magic %s", file->magic);
312  } else {
313  SCLogDebug("file->flags & FILE_NOMAGIC == true");
314  }
315 #endif
316  uint64_t left_edge = file->content_stored;
317  if (file->flags & FILE_NOSTORE) {
318  left_edge = FileDataSize(file);
319  }
320  if (file->flags & FILE_USE_DETECT) {
321  left_edge = MIN(left_edge, file->content_inspected);
322  }
323 
324  if (left_edge) {
325  StreamingBufferSlideToOffset(file->sb, left_edge);
326  }
327 
328  if (left_edge != FileDataSize(file)) {
329  SCReturnInt(0);
330  }
331 
332  SCLogDebug("file->state %d. Is >= FILE_STATE_CLOSED: %s", file->state, (file->state >= FILE_STATE_CLOSED) ? "yes" : "no");
333 
334  /* file is done when state is closed+, logging/storing is done (if any) */
335  if (file->state >= FILE_STATE_CLOSED &&
336  (!RunModeOutputFileEnabled() || (file->flags & FILE_LOGGED)) &&
338  {
339  SCReturnInt(1);
340  } else {
341  SCReturnInt(0);
342  }
343 }
344 
346 {
347  File *file = ffc->head;
348  File *prev = NULL;
349 
350  while (file) {
351  if (FilePruneFile(file) == 0) {
352  prev = file;
353  file = file->next;
354  continue;
355  }
356 
357  SCLogDebug("removing file %p", file);
358 
359  File *file_next = file->next;
360 
361  if (prev)
362  prev->next = file_next;
363  /* update head and tail */
364  if (file == ffc->head)
365  ffc->head = file_next;
366  if (file == ffc->tail)
367  ffc->tail = prev;
368 
369  FileFree(file);
370  file = file_next;
371  }
372 }
373 
374 /**
375  * \brief allocate a FileContainer
376  *
377  * \retval new newly allocated FileContainer
378  * \retval NULL error
379  */
381 {
382  FileContainer *new = SCMalloc(sizeof(FileContainer));
383  if (unlikely(new == NULL)) {
384  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating mem");
385  return NULL;
386  }
387  memset(new, 0, sizeof(FileContainer));
388  new->head = new->tail = NULL;
389  return new;
390 }
391 
392 /**
393  * \brief Recycle a FileContainer
394  *
395  * \param ffc FileContainer
396  */
398 {
399  if (ffc == NULL)
400  return;
401 
402  File *cur = ffc->head;
403  File *next = NULL;
404  for (;cur != NULL; cur = next) {
405  next = cur->next;
406  FileFree(cur);
407  }
408  ffc->head = ffc->tail = NULL;
409 }
410 
411 /**
412  * \brief Free a FileContainer
413  *
414  * \param ffc FileContainer
415  */
417 {
418  if (ffc == NULL)
419  return;
420 
421  File *ptr = ffc->head;
422  File *next = NULL;
423  for (;ptr != NULL; ptr = next) {
424  next = ptr->next;
425  FileFree(ptr);
426  }
427  ffc->head = ffc->tail = NULL;
428  SCFree(ffc);
429 }
430 
431 /**
432  * \brief Alloc a new File
433  *
434  * \param name character array containing the name (not a string)
435  * \param name_len length in bytes of the name
436  *
437  * \retval new File object or NULL on error
438  */
439 static File *FileAlloc(const uint8_t *name, uint16_t name_len)
440 {
441  File *new = SCMalloc(sizeof(File));
442  if (unlikely(new == NULL)) {
443  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating mem");
444  return NULL;
445  }
446  memset(new, 0, sizeof(File));
447 
448  new->name = SCMalloc(name_len);
449  if (new->name == NULL) {
450  SCFree(new);
451  return NULL;
452  }
453 
454  new->name_len = name_len;
455  memcpy(new->name, name, name_len);
456 
457  new->sid_cnt = 0;
458  new->sid_max = 8;
459  /* SCMalloc() is allowed to fail here because sid well be checked later on */
460  new->sid = SCMalloc(sizeof(uint32_t) * new->sid_max);
461  if (new->sid == NULL)
462  new->sid_max = 0;
463 
464  return new;
465 }
466 
467 static void FileFree(File *ff)
468 {
469  if (ff == NULL)
470  return;
471 
472  if (ff->name != NULL)
473  SCFree(ff->name);
474  if (ff->sid != NULL)
475  SCFree(ff->sid);
476 #ifdef HAVE_MAGIC
477  /* magic returned by libmagic is strdup'd by MagicLookup. */
478  if (ff->magic != NULL)
479  SCFree(ff->magic);
480 #endif
481  if (ff->sb != NULL) {
482  StreamingBufferFree(ff->sb);
483  }
484 
485 #ifdef HAVE_NSS
486  if (ff->md5_ctx)
487  HASH_Destroy(ff->md5_ctx);
488  if (ff->sha1_ctx)
489  HASH_Destroy(ff->sha1_ctx);
490  if (ff->sha256_ctx)
491  HASH_Destroy(ff->sha256_ctx);
492 #endif
493  SCFree(ff);
494 }
495 
497 {
498  if (ffc->head == NULL || ffc->tail == NULL) {
499  ffc->head = ffc->tail = ff;
500  } else {
501  ffc->tail->next = ff;
502  ffc->tail = ff;
503  }
504 }
505 
506 /**
507  * \brief Tag a file for storing
508  *
509  * \param ff The file to store
510  */
511 int FileStore(File *ff)
512 {
513  ff->flags |= FILE_STORE;
514  SCReturnInt(0);
515 }
516 
517 /**
518  * \brief Set the TX id for a file
519  *
520  * \param ff The file to store
521  * \param txid the tx id
522  */
523 int FileSetTx(File *ff, uint64_t txid)
524 {
525  SCLogDebug("ff %p txid %"PRIu64, ff, txid);
526  if (ff != NULL)
527  ff->txid = txid;
528  SCReturnInt(0);
529 }
530 
532 {
533  if (ffc && ffc->tail) {
534  (void)FileSetTx(ffc->tail, tx_id);
535  }
536 }
537 
538 /**
539  * \brief check if we have stored enough
540  *
541  * \param ff file
542  *
543  * \retval 0 limit not reached yet
544  * \retval 1 limit reached
545  */
546 static int FileStoreNoStoreCheck(File *ff)
547 {
548  SCEnter();
549 
550  if (ff == NULL) {
551  SCReturnInt(0);
552  }
553 
554  if (ff->flags & FILE_NOSTORE) {
555  if (ff->state == FILE_STATE_OPENED &&
556  FileDataSize(ff) >= (uint64_t)FileMagicSize())
557  {
558  SCReturnInt(1);
559  }
560  }
561 
562  SCReturnInt(0);
563 }
564 
565 static int AppendData(File *file, const uint8_t *data, uint32_t data_len)
566 {
567  if (StreamingBufferAppendNoTrack(file->sb, data, data_len) != 0) {
568  SCReturnInt(-1);
569  }
570 
571 #ifdef HAVE_NSS
572  if (file->md5_ctx) {
573  HASH_Update(file->md5_ctx, data, data_len);
574  }
575  if (file->sha1_ctx) {
576  HASH_Update(file->sha1_ctx, data, data_len);
577  }
578  if (file->sha256_ctx) {
579  HASH_Update(file->sha256_ctx, data, data_len);
580  }
581 #endif
582  SCReturnInt(0);
583 }
584 
585 /** \internal
586  * \brief Store/handle a chunk of file data in the File structure
587  *
588  * \param ff the file
589  * \param data data chunk
590  * \param data_len data chunk len
591  *
592  * \retval 0 ok
593  * \retval -1 error
594  * \retval -2 no store for this file
595  */
596 static int FileAppendDataDo(File *ff, const uint8_t *data, uint32_t data_len)
597 {
598  SCEnter();
599 #ifdef DEBUG_VALIDATION
600  BUG_ON(ff == NULL);
601 #endif
602 
603  ff->size += data_len;
604 
605  if (ff->state != FILE_STATE_OPENED) {
606  if (ff->flags & FILE_NOSTORE) {
607  SCReturnInt(-2);
608  }
609  SCReturnInt(-1);
610  }
611 
612  if ((ff->flags & FILE_USE_DETECT) == 0 &&
613  FileStoreNoStoreCheck(ff) == 1) {
614 #ifdef HAVE_NSS
615  int hash_done = 0;
616  /* no storage but forced hashing */
617  if (ff->md5_ctx) {
618  HASH_Update(ff->md5_ctx, data, data_len);
619  hash_done = 1;
620  }
621  if (ff->sha1_ctx) {
622  HASH_Update(ff->sha1_ctx, data, data_len);
623  hash_done = 1;
624  }
625  if (ff->sha256_ctx) {
626  HASH_Update(ff->sha256_ctx, data, data_len);
627  hash_done = 1;
628  }
629 
630  if (hash_done)
631  SCReturnInt(0);
632 #endif
633  if (g_file_force_tracking || (!(ff->flags & FILE_NOTRACK)))
634  SCReturnInt(0);
635 
637  SCLogDebug("flowfile state transitioned to FILE_STATE_TRUNCATED");
638  SCReturnInt(-2);
639  }
640 
641  SCLogDebug("appending %"PRIu32" bytes", data_len);
642 
643  int r = AppendData(ff, data, data_len);
644  if (r != 0) {
645  ff->state = FILE_STATE_ERROR;
646  SCReturnInt(r);
647  }
648 
649  SCReturnInt(0);
650 }
651 
652 /**
653  * \brief Store/handle a chunk of file data in the File structure
654  * The last file in the FileContainer will be used.
655  *
656  * \param ffc FileContainer used to append to
657  * \param data data chunk
658  * \param data_len data chunk len
659  *
660  * \retval 0 ok
661  * \retval -1 error
662  * \retval -2 no store for this file
663  */
664 int FileAppendData(FileContainer *ffc, const uint8_t *data, uint32_t data_len)
665 {
666  SCEnter();
667 
668  if (ffc == NULL || ffc->tail == NULL || data == NULL || data_len == 0) {
669  SCReturnInt(-1);
670  }
671  int r = FileAppendDataDo(ffc->tail, data, data_len);
672  SCReturnInt(r);
673 }
674 
675 /**
676  * \brief Store/handle a chunk of file data in the File structure
677  * The file with 'track_id' in the FileContainer will be used.
678  *
679  * \param ffc FileContainer used to append to
680  * \param track_id id to lookup the file
681  * \param data data chunk
682  * \param data_len data chunk len
683  *
684  * \retval 0 ok
685  * \retval -1 error
686  * \retval -2 no store for this file
687  */
688 int FileAppendDataById(FileContainer *ffc, uint32_t track_id,
689  const uint8_t *data, uint32_t data_len)
690 {
691  SCEnter();
692 
693  if (ffc == NULL || ffc->tail == NULL || data == NULL || data_len == 0) {
694  SCReturnInt(-1);
695  }
696  File *ff = ffc->head;
697  for ( ; ff != NULL; ff = ff->next) {
698  if (track_id == ff->file_track_id) {
699  int r = FileAppendDataDo(ff, data, data_len);
700  SCReturnInt(r);
701  }
702  }
703  SCReturnInt(-1);
704 }
705 
706 /**
707  * \brief Store/handle a chunk of file data in the File structure
708  * The file with 'track_id' in the FileContainer will be used.
709  *
710  * \param ffc FileContainer used to append to
711  * \param track_id id to lookup the file
712  * \param data data chunk
713  * \param data_len data chunk len
714  *
715  * \retval 0 ok
716  * \retval -1 error
717  * \retval -2 no store for this file
718  */
719 int FileAppendGAPById(FileContainer *ffc, uint32_t track_id,
720  const uint8_t *data, uint32_t data_len)
721 {
722  SCEnter();
723 
724  if (ffc == NULL || ffc->tail == NULL || data == NULL || data_len == 0) {
725  SCReturnInt(-1);
726  }
727  File *ff = ffc->head;
728  for ( ; ff != NULL; ff = ff->next) {
729  if (track_id == ff->file_track_id) {
730  ff->flags |= FILE_HAS_GAPS;
733  SCLogDebug("FILE_HAS_GAPS set");
734 
735  int r = FileAppendDataDo(ff, data, data_len);
736  SCReturnInt(r);
737  }
738  }
739  SCReturnInt(-1);
740 }
741 
742 /**
743  * \brief Sets the offset range for a file.
744  *
745  * \param ffc the container
746  * \param start start offset
747  * \param end end offset
748  *
749  * \retval 0 ok
750  * \retval -1 error
751  */
752 int FileSetRange(FileContainer *ffc, uint64_t start, uint64_t end)
753 {
754  SCEnter();
755 
756  if (ffc == NULL || ffc->tail == NULL) {
757  SCReturnInt(-1);
758  }
759  ffc->tail->start = start;
760  ffc->tail->end = end;
761  SCReturnInt(0);
762 }
763 
764 /**
765  * \brief Open a new File
766  *
767  * \param ffc flow container
768  * \param sbcfg buffer config
769  * \param name filename character array
770  * \param name_len filename len
771  * \param data initial data
772  * \param data_len initial data len
773  * \param flags open flags
774  *
775  * \retval ff flowfile object
776  *
777  * \note filename is not a string, so it's not nul terminated.
778  */
779 static File *FileOpenFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg,
780  const uint8_t *name, uint16_t name_len,
781  const uint8_t *data, uint32_t data_len, uint16_t flags)
782 {
783  SCEnter();
784 
785  //PrintRawDataFp(stdout, name, name_len);
786 
787  File *ff = FileAlloc(name, name_len);
788  if (ff == NULL) {
789  SCReturnPtr(NULL, "File");
790  }
791 
792  ff->sb = StreamingBufferInit(sbcfg);
793  if (ff->sb == NULL) {
794  FileFree(ff);
795  SCReturnPtr(NULL, "File");
796  }
797  SCLogDebug("ff->sb %p", ff->sb);
798 
799  if (flags & FILE_STORE || g_file_force_filestore) {
800  FileStore(ff);
801  } else if (flags & FILE_NOSTORE) {
802  SCLogDebug("not storing this file");
803  ff->flags |= FILE_NOSTORE;
804  }
805  if (flags & FILE_NOMAGIC) {
806  SCLogDebug("not doing magic for this file");
807  ff->flags |= FILE_NOMAGIC;
808  }
809  if (flags & FILE_NOMD5) {
810  SCLogDebug("not doing md5 for this file");
811  ff->flags |= FILE_NOMD5;
812  }
813  if (flags & FILE_NOSHA1) {
814  SCLogDebug("not doing sha1 for this file");
815  ff->flags |= FILE_NOSHA1;
816  }
817  if (flags & FILE_NOSHA256) {
818  SCLogDebug("not doing sha256 for this file");
819  ff->flags |= FILE_NOSHA256;
820  }
821  if (flags & FILE_USE_DETECT) {
822  SCLogDebug("considering content_inspect tracker when pruning");
823  ff->flags |= FILE_USE_DETECT;
824  }
825 
826 #ifdef HAVE_NSS
827  if (!(ff->flags & FILE_NOMD5) || g_file_force_md5) {
828  ff->md5_ctx = HASH_Create(HASH_AlgMD5);
829  if (ff->md5_ctx != NULL) {
830  HASH_Begin(ff->md5_ctx);
831  }
832  }
833  if (!(ff->flags & FILE_NOSHA1) || g_file_force_sha1) {
834  ff->sha1_ctx = HASH_Create(HASH_AlgSHA1);
835  if (ff->sha1_ctx != NULL) {
836  HASH_Begin(ff->sha1_ctx);
837  }
838  }
839  if (!(ff->flags & FILE_NOSHA256) || g_file_force_sha256) {
840  ff->sha256_ctx = HASH_Create(HASH_AlgSHA256);
841  if (ff->sha256_ctx != NULL) {
842  HASH_Begin(ff->sha256_ctx);
843  }
844  }
845 #endif
846 
847  ff->state = FILE_STATE_OPENED;
848  SCLogDebug("flowfile state transitioned to FILE_STATE_OPENED");
849 
850  ff->fd = -1;
851 
852  FileContainerAdd(ffc, ff);
853 
854  if (data != NULL) {
855  ff->size += data_len;
856  if (AppendData(ff, data, data_len) != 0) {
857  ff->state = FILE_STATE_ERROR;
858  SCReturnPtr(NULL, "File");
859  }
860  SCLogDebug("file size is now %"PRIu64, FileTrackedSize(ff));
861  }
862 
863  SCReturnPtr(ff, "File");
864 }
865 
866 /**
867  * \retval 0 ok
868  * \retval -1 failed */
870  uint32_t track_id, const uint8_t *name, uint16_t name_len,
871  const uint8_t *data, uint32_t data_len, uint16_t flags)
872 {
873  File *ff = FileOpenFile(ffc, sbcfg, name, name_len, data, data_len, flags);
874  if (ff == NULL)
875  return -1;
876 
877  ff->file_track_id = track_id;
878  ff->flags |= FILE_USE_TRACKID;
879  return 0;
880 }
881 
882 int FileCloseFilePtr(File *ff, const uint8_t *data,
883  uint32_t data_len, uint16_t flags)
884 {
885  SCEnter();
886 
887  if (ff == NULL) {
888  SCReturnInt(-1);
889  }
890 
891  if (ff->state != FILE_STATE_OPENED) {
892  SCReturnInt(-1);
893  }
894 
895  if (data != NULL) {
896  ff->size += data_len;
897  if (ff->flags & FILE_NOSTORE) {
898 #ifdef HAVE_NSS
899  /* no storage but hashing */
900  if (ff->md5_ctx)
901  HASH_Update(ff->md5_ctx, data, data_len);
902  if (ff->sha1_ctx)
903  HASH_Update(ff->sha1_ctx, data, data_len);
904  if (ff->sha256_ctx)
905  HASH_Update(ff->sha256_ctx, data, data_len);
906 #endif
907  } else {
908  if (AppendData(ff, data, data_len) != 0) {
909  ff->state = FILE_STATE_ERROR;
910  SCReturnInt(-1);
911  }
912  }
913  }
914 
915  if ((flags & FILE_TRUNCATED) || (ff->flags & FILE_HAS_GAPS)) {
917  SCLogDebug("flowfile state transitioned to FILE_STATE_TRUNCATED");
918 
919  if (flags & FILE_NOSTORE) {
920  SCLogDebug("not storing this file");
921  ff->flags |= FILE_NOSTORE;
922  } else {
923 #ifdef HAVE_NSS
924  if (g_file_force_sha256 && ff->sha256_ctx) {
925  FileEndSha256(ff);
926  }
927 #endif
928  }
929  } else {
930  ff->state = FILE_STATE_CLOSED;
931  SCLogDebug("flowfile state transitioned to FILE_STATE_CLOSED");
932 
933 #ifdef HAVE_NSS
934  if (ff->md5_ctx) {
935  unsigned int len = 0;
936  HASH_End(ff->md5_ctx, ff->md5, &len, sizeof(ff->md5));
937  ff->flags |= FILE_MD5;
938  }
939  if (ff->sha1_ctx) {
940  unsigned int len = 0;
941  HASH_End(ff->sha1_ctx, ff->sha1, &len, sizeof(ff->sha1));
942  ff->flags |= FILE_SHA1;
943  }
944  if (ff->sha256_ctx) {
945  FileEndSha256(ff);
946  }
947 #endif
948  }
949 
950  SCReturnInt(0);
951 }
952 
953 /**
954  * \brief Close a File
955  *
956  * \param ffc the container
957  * \param data final data if any
958  * \param data_len data len if any
959  * \param flags flags
960  *
961  * \retval 0 ok
962  * \retval -1 error
963  */
964 int FileCloseFile(FileContainer *ffc, const uint8_t *data,
965  uint32_t data_len, uint16_t flags)
966 {
967  SCEnter();
968 
969  if (ffc == NULL || ffc->tail == NULL) {
970  SCReturnInt(-1);
971  }
972 
973  if (FileCloseFilePtr(ffc->tail, data, data_len, flags) == -1) {
974  SCReturnInt(-1);
975  }
976 
977  SCReturnInt(0);
978 }
979 
980 int FileCloseFileById(FileContainer *ffc, uint32_t track_id,
981  const uint8_t *data, uint32_t data_len, uint16_t flags)
982 {
983  SCEnter();
984 
985  if (ffc == NULL || ffc->tail == NULL) {
986  SCReturnInt(-1);
987  }
988 
989  File *ff = ffc->head;
990  for ( ; ff != NULL; ff = ff->next) {
991  if (track_id == ff->file_track_id) {
992  int r = FileCloseFilePtr(ff, data, data_len, flags);
993  SCReturnInt(r);
994  }
995  }
996  SCReturnInt(-1);
997 }
998 
999 /**
1000  * \brief disable file storage for a flow
1001  *
1002  * \param f *LOCKED* flow
1003  * \param direction flow direction
1004  */
1005 void FileDisableStoring(Flow *f, uint8_t direction)
1006 {
1007  File *ptr = NULL;
1008 
1009  SCEnter();
1010 
1012 
1013  if (direction == STREAM_TOSERVER)
1015  else
1017 
1018  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1019  if (ffc != NULL) {
1020  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1021  /* if we're already storing, we'll continue */
1022  if (!(ptr->flags & FILE_STORE)) {
1023  SCLogDebug("not storing this file");
1024  ptr->flags |= FILE_NOSTORE;
1025  }
1026  }
1027  }
1028  SCReturn;
1029 }
1030 
1031 /**
1032  * \brief disable file magic lookups for this flow
1033  *
1034  * \param f *LOCKED* flow
1035  * \param direction flow direction
1036  */
1037 void FileDisableMagic(Flow *f, uint8_t direction)
1038 {
1039  File *ptr = NULL;
1040 
1041  SCEnter();
1042 
1044 
1045  if (direction == STREAM_TOSERVER)
1047  else
1049 
1050  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1051  if (ffc != NULL) {
1052  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1053  SCLogDebug("disabling magic for file %p from direction %s",
1054  ptr, direction == STREAM_TOSERVER ? "toserver":"toclient");
1055  ptr->flags |= FILE_NOMAGIC;
1056  }
1057  }
1058 
1059  SCReturn;
1060 }
1061 
1062 /**
1063  * \brief disable file md5 calc for this flow
1064  *
1065  * \param f *LOCKED* flow
1066  * \param direction flow direction
1067  */
1068 void FileDisableMd5(Flow *f, uint8_t direction)
1069 {
1070  File *ptr = NULL;
1071 
1072  SCEnter();
1073 
1075 
1076  if (direction == STREAM_TOSERVER)
1078  else
1080 
1081  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1082  if (ffc != NULL) {
1083  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1084  SCLogDebug("disabling md5 for file %p from direction %s",
1085  ptr, direction == STREAM_TOSERVER ? "toserver":"toclient");
1086  ptr->flags |= FILE_NOMD5;
1087 
1088 #ifdef HAVE_NSS
1089  /* destroy any ctx we may have so far */
1090  if (ptr->md5_ctx != NULL) {
1091  HASH_Destroy(ptr->md5_ctx);
1092  ptr->md5_ctx = NULL;
1093  }
1094 #endif
1095  }
1096  }
1097 
1098  SCReturn;
1099 }
1100 
1101 /**
1102  * \brief disable file sha1 calc for this flow
1103  *
1104  * \param f *LOCKED* flow
1105  * \param direction flow direction
1106 */
1107 void FileDisableSha1(Flow *f, uint8_t direction)
1108 {
1109  File *ptr = NULL;
1110 
1111  SCEnter();
1112 
1114 
1115  if (direction == STREAM_TOSERVER)
1117  else
1119 
1120  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1121  if (ffc != NULL) {
1122  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1123  SCLogDebug("disabling sha1 for file %p from direction %s",
1124  ptr, direction == STREAM_TOSERVER ? "toserver":"toclient");
1125  ptr->flags |= FILE_NOSHA1;
1126 
1127 #ifdef HAVE_NSS
1128  /* destroy any ctx we may have so far */
1129  if (ptr->sha1_ctx != NULL) {
1130  HASH_Destroy(ptr->sha1_ctx);
1131  ptr->sha1_ctx = NULL;
1132  }
1133 #endif
1134  }
1135  }
1136 
1137  SCReturn;
1138 }
1139 
1140 /**
1141  * \brief disable file sha256 calc for this flow
1142  *
1143  * \param f *LOCKED* flow
1144  * \param direction flow direction
1145  */
1146 void FileDisableSha256(Flow *f, uint8_t direction)
1147 {
1148  File *ptr = NULL;
1149 
1150  SCEnter();
1151 
1153 
1154  if (direction == STREAM_TOSERVER)
1156  else
1158 
1159  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1160  if (ffc != NULL) {
1161  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1162  SCLogDebug("disabling sha256 for file %p from direction %s",
1163  ptr, direction == STREAM_TOSERVER ? "toserver":"toclient");
1164  ptr->flags |= FILE_NOSHA256;
1165 
1166 #ifdef HAVE_NSS
1167  /* destroy any ctx we may have so far */
1168  if (ptr->sha256_ctx != NULL) {
1169  HASH_Destroy(ptr->sha256_ctx);
1170  ptr->sha256_ctx = NULL;
1171  }
1172 #endif
1173  }
1174  }
1175 
1176  SCReturn;
1177 }
1178 
1179 /**
1180  * \brief disable file size tracking for this flow
1181  *
1182  * \param f *LOCKED* flow
1183  * \param direction flow direction
1184  */
1185 void FileDisableFilesize(Flow *f, uint8_t direction)
1186 {
1187  File *ptr = NULL;
1188 
1189  SCEnter();
1190 
1192 
1193  if (direction == STREAM_TOSERVER)
1195  else
1197 
1198  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1199  if (ffc != NULL) {
1200  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1201  SCLogDebug("disabling size tracking for file %p from direction %s",
1202  ptr, direction == STREAM_TOSERVER ? "toserver":"toclient");
1203  ptr->flags |= FILE_NOTRACK;
1204  }
1205  }
1206 
1207  SCReturn;
1208 }
1209 
1210 
1211 /**
1212  * \brief set no store flag, close file if needed
1213  *
1214  * \param ff file
1215  */
1216 static void FileDisableStoringForFile(File *ff)
1217 {
1218  SCEnter();
1219 
1220  if (ff == NULL) {
1221  SCReturn;
1222  }
1223 
1224  SCLogDebug("not storing this file");
1225  ff->flags |= FILE_NOSTORE;
1226 
1227  if (ff->state == FILE_STATE_OPENED && FileDataSize(ff) >= (uint64_t)FileMagicSize()) {
1228  if (g_file_force_md5 == 0 && g_file_force_sha1 == 0 && g_file_force_sha256 == 0
1229  && g_file_force_tracking == 0) {
1230  (void)FileCloseFilePtr(ff, NULL, 0,
1232  }
1233  }
1234 }
1235 
1236 /**
1237  * \brief disable file storing for files in a transaction
1238  *
1239  * \param f *LOCKED* flow
1240  * \param direction flow direction
1241  * \param tx_id transaction id
1242  */
1243 void FileDisableStoringForTransaction(Flow *f, uint8_t direction, uint64_t tx_id)
1244 {
1245  File *ptr = NULL;
1246 
1248 
1249  SCEnter();
1250 
1251  FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction);
1252  if (ffc != NULL) {
1253  for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) {
1254  if (ptr->txid == tx_id) {
1255  if (ptr->flags & FILE_STORE) {
1256  /* weird, already storing -- let it continue*/
1257  SCLogDebug("file is already being stored");
1258  } else {
1259  FileDisableStoringForFile(ptr);
1260  }
1261  }
1262  }
1263  }
1264 
1265  SCReturn;
1266 }
1267 
1268 /**
1269  * \brief flag a file with id "file_id" to be stored.
1270  *
1271  * \param fc file store
1272  * \param file_id the file's id
1273  */
1274 void FileStoreFileById(FileContainer *fc, uint32_t file_id)
1275 {
1276  File *ptr = NULL;
1277 
1278  SCEnter();
1279 
1280  if (fc != NULL) {
1281  for (ptr = fc->head; ptr != NULL; ptr = ptr->next) {
1282  if (ptr->file_track_id == file_id) {
1283  FileStore(ptr);
1284  }
1285  }
1286  }
1287 }
1288 
1290 {
1291  File *ptr = NULL;
1292 
1293  SCEnter();
1294 
1295  if (fc != NULL) {
1296  for (ptr = fc->head; ptr != NULL; ptr = ptr->next) {
1297  if (ptr->txid == tx_id) {
1298  FileStore(ptr);
1299  }
1300  }
1301  }
1302 }
1303 
1305 {
1306  File *ptr = NULL;
1307 
1308  SCEnter();
1309 
1310  if (fc != NULL) {
1311  for (ptr = fc->head; ptr != NULL; ptr = ptr->next) {
1312  FileStore(ptr);
1313  }
1314  }
1315 }
1316 
1318 {
1319  File *ptr = NULL;
1320 
1321  SCEnter();
1322 
1323  if (fc != NULL) {
1324  for (ptr = fc->head; ptr != NULL; ptr = ptr->next) {
1325  if (ptr->state == FILE_STATE_OPENED) {
1326  FileCloseFilePtr(ptr, NULL, 0, FILE_TRUNCATED);
1327  }
1328  }
1329  }
1330 }
1331 
1332 /**
1333  * \brief Finish the SHA256 calculation.
1334  */
1335 #ifdef HAVE_NSS
1336 static void FileEndSha256(File *ff)
1337 {
1338  if (!(ff->flags & FILE_SHA256) && ff->sha256_ctx) {
1339  unsigned int len = 0;
1340  HASH_End(ff->sha256_ctx, ff->sha256, &len, sizeof(ff->sha256));
1341  ff->flags |= FILE_SHA256;
1342  }
1343 }
1344 #endif
uint16_t flags
void FileDisableStoringForTransaction(Flow *f, uint8_t direction, uint64_t tx_id)
disable file storing for files in a transaction
Definition: util-file.c:1243
#define SCLogDebug(...)
Definition: util-debug.h:335
StreamingBuffer * StreamingBufferInit(const StreamingBufferConfig *cfg)
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
int FileForceSha256(void)
Definition: util-file.c:145
TcpStreamCnf stream_config
Definition: stream-tcp.h:106
#define BUG_ON(x)
uint8_t proto
Definition: flow.h:344
FileContainer * FileContainerAlloc(void)
allocate a FileContainer
Definition: util-file.c:380
#define FLOWFILE_NO_SHA256_TS
Definition: flow.h:126
int RunModeOutputFileEnabled(void)
Definition: runmodes.c:481
#define unlikely(expr)
Definition: util-optimize.h:35
#define FILE_SHA256
Definition: util-file.h:43
uint64_t size
Definition: util-file.h:91
void FileDisableFilesize(Flow *f, uint8_t direction)
disable file size tracking for this flow
Definition: util-file.c:1185
void FileDisableSha1(Flow *f, uint8_t direction)
disable file sha1 calc for this flow
Definition: util-file.c:1107
void FileDisableMd5(Flow *f, uint8_t direction)
disable file md5 calc for this flow
Definition: util-file.c:1068
uint64_t FileDataSize(const File *file)
get the size of the file data
Definition: util-file.c:277
#define FILE_NOTRACK
Definition: util-file.h:48
#define MIN(x, y)
uint64_t content_inspected
Definition: util-file.h:88
#define FILE_STORE
Definition: util-file.h:46
#define FILE_NOMAGIC
Definition: util-file.h:37
int fd
Definition: util-file.h:73
char * val
Definition: conf.h:34
void FileContainerSetTx(FileContainer *ffc, uint64_t tx_id)
Definition: util-file.c:531
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:815
struct File_ * next
Definition: util-file.h:79
int FileCloseFileById(FileContainer *ffc, uint32_t track_id, const uint8_t *data, uint32_t data_len, uint16_t flags)
Definition: util-file.c:980
void FileReassemblyDepthEnable(uint32_t size)
Definition: util-file.c:116
StreamingBuffer * sb
Definition: util-file.h:68
void FileForceSha1Enable(void)
Definition: util-file.c:101
int FileForceMd5(void)
Definition: util-file.c:135
#define FILE_NOSHA1
Definition: util-file.h:40
void FileForceTrackingEnable(void)
Definition: util-file.c:150
uint64_t start
Definition: util-file.h:92
#define FLOWFILE_NO_MAGIC_TS
Definition: flow.h:111
uint32_t FileReassemblyDepth(void)
Definition: util-file.c:122
void * alstate
Definition: flow.h:438
#define FLOWFILE_NO_MD5_TS
Definition: flow.h:118
void StreamingBufferFree(StreamingBuffer *sb)
#define FILE_LOGGED
Definition: util-file.h:44
#define FLOWFILE_NO_MAGIC_TC
Definition: flow.h:112
#define FILE_USE_TRACKID
Definition: util-file.h:50
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843
int FileStore(File *ff)
Tag a file for storing.
Definition: util-file.c:511
uint16_t flags
Definition: util-file.h:65
void FileStoreAllFilesForTx(FileContainer *fc, uint64_t tx_id)
Definition: util-file.c:1289
#define FLOWFILE_NO_SIZE_TS
Definition: flow.h:130
uint64_t end
Definition: util-file.h:93
uint32_t * sid
Definition: util-file.h:95
void FileStoreFileById(FileContainer *fc, uint32_t file_id)
flag a file with id "file_id" to be stored.
Definition: util-file.c:1274
void FileDisableMagic(Flow *f, uint8_t direction)
disable file magic lookups for this flow
Definition: util-file.c:1037
void StreamingBufferSlideToOffset(StreamingBuffer *sb, uint64_t offset)
slide to absolute offset
#define FILE_HAS_GAPS
Definition: util-file.h:51
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void FileForceHashParseCfg(ConfNode *conf)
Function to parse forced file hashing configuration.
Definition: util-file.c:158
void FileContainerFree(FileContainer *ffc)
Free a FileContainer.
Definition: util-file.c:416
void FileForceMagicEnable(void)
Definition: util-file.c:91
#define DEBUG_ASSERT_FLOW_LOCKED(f)
uint64_t txid
Definition: util-file.h:69
#define SCEnter(...)
Definition: util-debug.h:337
int FileSetRange(FileContainer *ffc, uint64_t start, uint64_t end)
Sets the offset range for a file.
Definition: util-file.c:752
#define FLOWFILE_NO_MD5_TC
Definition: flow.h:119
void FileForceFilestoreEnable(void)
Definition: util-file.c:86
void FileDisableStoring(Flow *f, uint8_t direction)
disable file storage for a flow
Definition: util-file.c:1005
#define SCReturnInt(x)
Definition: util-debug.h:341
#define FILE_MD5
Definition: util-file.h:39
void FilePrune(FileContainer *ffc)
Definition: util-file.c:345
void FileStoreAllFiles(FileContainer *fc)
Definition: util-file.c:1304
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
uint32_t reassembly_depth
Definition: stream-tcp.h:60
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
#define FILE_SHA1
Definition: util-file.h:41
int FileForceFilestore(void)
Definition: util-file.c:111
int FileForceMagic(void)
Definition: util-file.c:130
#define FILE_STORED
Definition: util-file.h:47
Definition: conf.h:32
#define FILE_NOSHA256
Definition: util-file.h:42
#define SCMalloc(a)
Definition: util-mem.h:222
int FileAppendGAPById(FileContainer *ffc, uint32_t track_id, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The file with &#39;track_id&#39; in the FileContainer...
Definition: util-file.c:719
#define FILE_USE_DETECT
Definition: util-file.h:49
void FileContainerAdd(FileContainer *ffc, File *ff)
Definition: util-file.c:496
void FileForceSha256Enable(void)
Definition: util-file.c:106
int RunModeOutputFiledataEnabled(void)
Definition: runmodes.c:486
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void FileContainerRecycle(FileContainer *ffc)
Recycle a FileContainer.
Definition: util-file.c:397
#define SCFree(a)
Definition: util-mem.h:322
#define FLOWFILE_NO_SHA1_TS
Definition: flow.h:122
#define FLOWFILE_NO_STORE_TS
Definition: flow.h:115
uint16_t tx_id
#define FLOWFILE_NO_SIZE_TC
Definition: flow.h:131
#define STREAM_TOSERVER
Definition: stream.h:31
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
FileState state
Definition: util-file.h:67
int FileOpenFileWithId(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *name, uint16_t name_len, const uint8_t *data, uint32_t data_len, uint16_t flags)
Open a new File.
Definition: util-file.c:869
int StreamingBufferAppendNoTrack(StreamingBuffer *sb, const uint8_t *data, uint32_t data_len)
add data w/o tracking a segment
int FileCloseFile(FileContainer *ffc, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
Definition: util-file.c:964
int FileSetTx(File *ff, uint64_t txid)
Set the TX id for a file.
Definition: util-file.c:523
uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
Definition: util-file.c:217
uint64_t content_stored
Definition: util-file.h:90
uint32_t file_track_id
Definition: util-file.h:70
#define FILE_TRUNCATED
Definition: util-file.h:36
int FileForceSha1(void)
Definition: util-file.c:140
int FileAppendDataById(FileContainer *ffc, uint32_t track_id, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The file with &#39;track_id&#39; in the FileContainer...
Definition: util-file.c:688
uint64_t FileTrackedSize(const File *file)
get the size of the file
Definition: util-file.c:294
void FileForceMd5Enable(void)
Definition: util-file.c:96
#define SCReturn
Definition: util-debug.h:339
#define FLOWFILE_NO_SHA1_TC
Definition: flow.h:123
uint8_t len
void FileDisableSha256(Flow *f, uint8_t direction)
disable file sha256 calc for this flow
Definition: util-file.c:1146
uint16_t file_flags
Definition: flow.h:381
AppProto alproto
application level protocol
Definition: flow.h:409
FileContainer * AppLayerParserGetFiles(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t direction)
int FileAppendData(FileContainer *ffc, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The last file in the FileContainer will be us...
Definition: util-file.c:664
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
#define FLOWFILE_NO_SHA256_TC
Definition: flow.h:127
#define FILE_NOSTORE
Definition: util-file.h:45
#define FLOWFILE_NO_STORE_TC
Definition: flow.h:116
int FileCloseFilePtr(File *ff, const uint8_t *data, uint32_t data_len, uint16_t flags)
Definition: util-file.c:882
Flow data structure.
Definition: flow.h:325
uint8_t * name
Definition: util-file.h:75
void FileTruncateAllOpenFiles(FileContainer *fc)
Definition: util-file.c:1317
#define FILE_NOMD5
Definition: util-file.h:38