suricata
output-file.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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 Victor Julien <victor@inliniac.net>
22  *
23  * AppLayer File Logger Output registration functions
24  */
25 
26 #include "suricata-common.h"
27 #include "tm-modules.h"
28 #include "output.h"
29 #include "output-file.h"
30 #include "app-layer.h"
31 #include "app-layer-parser.h"
32 #include "detect-filemagic.h"
33 #include "util-profiling.h"
34 #include "util-validate.h"
35 #include "util-magic.h"
36 
37 typedef struct OutputLoggerThreadStore_ {
38  void *thread_data;
41 
42 /** per thread data for this module, contains a list of per thread
43  * data for the packet loggers. */
44 typedef struct OutputLoggerThreadData_ {
46 #ifdef HAVE_MAGIC
47  magic_t magic_ctx;
48 #endif
50 
51 /* logger instance, a module + a output ctx,
52  * it's perfectly valid that have multiple instances of the same
53  * log module (e.g. http.log) with different output ctx'. */
54 typedef struct OutputFileLogger_ {
58  const char *name;
64 
65 static OutputFileLogger *list = NULL;
66 
71 {
72  OutputFileLogger *op = SCMalloc(sizeof(*op));
73  if (op == NULL)
74  return -1;
75  memset(op, 0x00, sizeof(*op));
76 
77  op->LogFunc = LogFunc;
78  op->output_ctx = output_ctx;
79  op->name = name;
80  op->logger_id = id;
81  op->ThreadInit = ThreadInit;
84 
85  if (list == NULL)
86  list = op;
87  else {
88  OutputFileLogger *t = list;
89  while (t->next)
90  t = t->next;
91  t->next = op;
92  }
93 
94  SCLogDebug("OutputRegisterFileLogger happy");
95  return 0;
96 }
97 
98 static void OutputFileLogFfc(ThreadVars *tv,
99  OutputLoggerThreadData *op_thread_data,
100  Packet *p,
101  FileContainer *ffc, const bool file_close, const bool file_trunc,
102  uint8_t dir)
103 {
104  SCLogDebug("ffc %p", ffc);
105  if (ffc != NULL) {
106  File *ff;
107  for (ff = ffc->head; ff != NULL; ff = ff->next) {
108  if (ff->flags & FILE_LOGGED)
109  continue;
110 
111  SCLogDebug("ff %p", ff);
112 
113  if (file_trunc && ff->state < FILE_STATE_CLOSED)
115 
116  if (file_close && ff->state < FILE_STATE_CLOSED)
118 
119  SCLogDebug("ff %p state %u", ff, ff->state);
120 
121  if (ff->state > FILE_STATE_OPENED) {
122  bool file_logged = false;
123 #ifdef HAVE_MAGIC
124  if (FileForceMagic() && ff->magic == NULL) {
125  FilemagicThreadLookup(&op_thread_data->magic_ctx, ff);
126  }
127 #endif
128  const OutputFileLogger *logger = list;
129  const OutputLoggerThreadStore *store = op_thread_data->store;
130  while (logger && store) {
131  DEBUG_VALIDATE_BUG_ON(logger->LogFunc == NULL);
132 
133  SCLogDebug("logger %p", logger);
135  logger->LogFunc(tv, store->thread_data, (const Packet *)p, (const File *)ff, dir);
137  file_logged = true;
138 
139  logger = logger->next;
140  store = store->next;
141 
142  DEBUG_VALIDATE_BUG_ON(logger == NULL && store != NULL);
143  DEBUG_VALIDATE_BUG_ON(logger != NULL && store == NULL);
144  }
145 
146  if (file_logged) {
147  ff->flags |= FILE_LOGGED;
148  }
149  }
150  }
151  }
152 }
153 
154 static TmEcode OutputFileLog(ThreadVars *tv, Packet *p, void *thread_data)
155 {
156  DEBUG_VALIDATE_BUG_ON(thread_data == NULL);
157 
158  if (list == NULL) {
159  /* No child loggers. */
160  return TM_ECODE_OK;
161  }
162 
163  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
164 
165  /* no flow, no files */
166  Flow * const f = p->flow;
167  if (f == NULL || f->alstate == NULL) {
169  }
170 
171  const bool file_close_ts = ((p->flags & PKT_PSEUDO_STREAM_END) &&
173  const bool file_close_tc = ((p->flags & PKT_PSEUDO_STREAM_END) &&
175  const bool file_trunc = StreamTcpReassembleDepthReached(p);
176 
179 
180  OutputFileLogFfc(tv, op_thread_data, p, ffc_ts, file_close_ts, file_trunc, STREAM_TOSERVER);
181  OutputFileLogFfc(tv, op_thread_data, p, ffc_tc, file_close_tc, file_trunc, STREAM_TOCLIENT);
182 
183  return TM_ECODE_OK;
184 }
185 
186 /** \brief thread init for the tx logger
187  * This will run the thread init functions for the individual registered
188  * loggers */
189 static TmEcode OutputFileLogThreadInit(ThreadVars *tv, const void *initdata, void **data)
190 {
191  OutputLoggerThreadData *td = SCMalloc(sizeof(*td));
192  if (td == NULL)
193  return TM_ECODE_FAILED;
194  memset(td, 0x00, sizeof(*td));
195 
196  *data = (void *)td;
197 
198 #ifdef HAVE_MAGIC
199  td->magic_ctx = MagicInitContext();
200  if (td->magic_ctx == NULL) {
201  SCFree(td);
202  return TM_ECODE_FAILED;
203  }
204 #endif
205 
206  SCLogDebug("OutputFileLogThreadInit happy (*data %p)", *data);
207 
208  OutputFileLogger *logger = list;
209  while (logger) {
210  if (logger->ThreadInit) {
211  void *retptr = NULL;
212  if (logger->ThreadInit(tv, (void *)logger->output_ctx, &retptr) == TM_ECODE_OK) {
213  OutputLoggerThreadStore *ts = SCMalloc(sizeof(*ts));
214 /* todo */ BUG_ON(ts == NULL);
215  memset(ts, 0x00, sizeof(*ts));
216 
217  /* store thread handle */
218  ts->thread_data = retptr;
219 
220  if (td->store == NULL) {
221  td->store = ts;
222  } else {
223  OutputLoggerThreadStore *tmp = td->store;
224  while (tmp->next != NULL)
225  tmp = tmp->next;
226  tmp->next = ts;
227  }
228 
229  SCLogDebug("%s is now set up", logger->name);
230  }
231  }
232 
233  logger = logger->next;
234  }
235 
236  return TM_ECODE_OK;
237 }
238 
239 static TmEcode OutputFileLogThreadDeinit(ThreadVars *tv, void *thread_data)
240 {
241  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
242  OutputLoggerThreadStore *store = op_thread_data->store;
243  OutputFileLogger *logger = list;
244 
245  while (logger && store) {
246  if (logger->ThreadDeinit) {
247  logger->ThreadDeinit(tv, store->thread_data);
248  }
249 
250  OutputLoggerThreadStore *next_store = store->next;
251  SCFree(store);
252  store = next_store;
253  logger = logger->next;
254  }
255 
256 #ifdef HAVE_MAGIC
257  MagicDeinitContext(op_thread_data->magic_ctx);
258 #endif
259 
260  SCFree(op_thread_data);
261  return TM_ECODE_OK;
262 }
263 
264 static void OutputFileLogExitPrintStats(ThreadVars *tv, void *thread_data)
265 {
266  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
267  OutputLoggerThreadStore *store = op_thread_data->store;
268  OutputFileLogger *logger = list;
269 
270  while (logger && store) {
271  if (logger->ThreadExitPrintStats) {
272  logger->ThreadExitPrintStats(tv, store->thread_data);
273  }
274 
275  logger = logger->next;
276  store = store->next;
277  }
278 }
279 
280 static uint32_t OutputFileLoggerGetActiveCount(void)
281 {
282  uint32_t cnt = 0;
283  for (OutputFileLogger *p = list; p != NULL; p = p->next) {
284  cnt++;
285  }
286  return cnt;
287 }
288 
290 {
291  OutputRegisterRootLogger(OutputFileLogThreadInit,
292  OutputFileLogThreadDeinit, OutputFileLogExitPrintStats,
293  OutputFileLog, OutputFileLoggerGetActiveCount);
294 }
295 
297 {
298  OutputFileLogger *logger = list;
299  while (logger) {
300  OutputFileLogger *next_logger = logger->next;
301  SCFree(logger);
302  logger = next_logger;
303  }
304 
305  list = NULL;
306 }
FileContainer_
Definition: util-file.h:100
ts
uint64_t ts
Definition: source-erf-file.c:54
OutputLoggerThreadStore_
Definition: output-file.c:37
OutputLoggerThreadStore_::next
struct OutputLoggerThreadStore_ * next
Definition: output-file.c:39
OutputFileLogger_::logger_id
LoggerId logger_id
Definition: output-file.c:59
StreamTcpReassembleDepthReached
int StreamTcpReassembleDepthReached(Packet *p)
check if stream in pkt direction has depth reached
Definition: stream-tcp-reassemble.c:486
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
OutputFileLoggerRegister
void OutputFileLoggerRegister(void)
Definition: output-file.c:289
OutputRegisterFileLogger
int OutputRegisterFileLogger(LoggerId id, const char *name, FileLogger LogFunc, OutputCtx *output_ctx, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats)
Definition: output-file.c:67
OutputFileLogger
struct OutputFileLogger_ OutputFileLogger
Packet_::flags
uint32_t flags
Definition: decode.h:446
FILE_STATE_OPENED
@ FILE_STATE_OPENED
Definition: util-file.h:54
Flow_
Flow data structure.
Definition: flow.h:343
File_::state
FileState state
Definition: util-file.h:66
LoggerId
LoggerId
Definition: suricata-common.h:439
OutputFileLogger_::next
struct OutputFileLogger_ * next
Definition: output-file.c:57
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:218
tm-modules.h
AppLayerParserGetFiles
FileContainer * AppLayerParserGetFiles(const Flow *f, const uint8_t direction)
Definition: app-layer-parser.c:864
FILE_STATE_TRUNCATED
@ FILE_STATE_TRUNCATED
Definition: util-file.h:57
OutputLoggerThreadData
struct OutputLoggerThreadData_ OutputLoggerThreadData
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:442
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:79
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:78
OutputLoggerThreadStore_::thread_data
void * thread_data
Definition: output-file.c:38
OutputCtx_
Definition: tm-modules.h:78
OutputLoggerThreadData_
Definition: output-file.c:44
FileForceMagic
int FileForceMagic(void)
Definition: util-file.c:143
OutputFileLogger_::LogFunc
FileLogger LogFunc
Definition: output-file.c:55
output-file.h
PKT_PSEUDO_STREAM_END
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1088
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
detect-filemagic.h
FileContainer_::head
File * head
Definition: util-file.h:101
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
ThreadInitFunc
TmEcode(* ThreadInitFunc)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:39
OutputFileLogger_::ThreadExitPrintStats
ThreadExitPrintStatsFunc ThreadExitPrintStats
Definition: output-file.c:62
app-layer-parser.h
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:282
util-profiling.h
OutputFileLogger_
Definition: output-file.c:54
Packet_
Definition: decode.h:411
OutputLoggerThreadStore
struct OutputLoggerThreadStore_ OutputLoggerThreadStore
OutputLoggerThreadData_::store
OutputLoggerThreadStore * store
Definition: output-file.c:45
OutputFileShutdown
void OutputFileShutdown(void)
Definition: output-file.c:296
util-magic.h
TmEcode
TmEcode
Definition: tm-threads-common.h:77
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:219
File_::flags
uint16_t flags
Definition: util-file.h:64
PACKET_PROFILING_LOGGER_END
#define PACKET_PROFILING_LOGGER_END(p, id)
Definition: util-profiling.h:260
FILE_STATE_CLOSED
@ FILE_STATE_CLOSED
Definition: util-file.h:55
File_
Definition: util-file.h:63
Packet_::flow
struct Flow_ * flow
Definition: decode.h:448
suricata-common.h
ThreadExitPrintStatsFunc
void(* ThreadExitPrintStatsFunc)(ThreadVars *, void *)
Definition: tm-modules.h:41
File_::next
struct File_ * next
Definition: util-file.h:77
STREAM_TOCLIENT
#define STREAM_TOCLIENT
Definition: stream.h:32
OutputFileLogger_::ThreadDeinit
ThreadDeinitFunc ThreadDeinit
Definition: output-file.c:61
FileLogger
int(* FileLogger)(ThreadVars *, void *thread_data, const Packet *, const File *, uint8_t direction)
Definition: output-file.h:33
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
Packet_::next
struct Packet_ * next
Definition: decode.h:573
FILE_LOGGED
#define FILE_LOGGED
Definition: util-file.h:44
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:454
OutputFileLogger_::output_ctx
OutputCtx * output_ctx
Definition: output-file.c:56
PACKET_PROFILING_LOGGER_START
#define PACKET_PROFILING_LOGGER_START(p, id)
Definition: util-profiling.h:253
OutputRegisterRootLogger
void OutputRegisterRootLogger(ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats, OutputLogFunc LogFunc, OutputGetActiveCountFunc ActiveCntFunc)
Definition: output.c:1011
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
OutputFileLogger_::name
const char * name
Definition: output-file.c:58
OutputFileLogger_::ThreadInit
ThreadInitFunc ThreadInit
Definition: output-file.c:60
output.h
ThreadDeinitFunc
TmEcode(* ThreadDeinitFunc)(ThreadVars *, void *)
Definition: tm-modules.h:40
app-layer.h