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 
36 typedef struct OutputLoggerThreadStore_ {
37  void *thread_data;
40 
41 /** per thread data for this module, contains a list of per thread
42  * data for the packet loggers. */
43 typedef struct OutputLoggerThreadData_ {
46 
47 /* logger instance, a module + a output ctx,
48  * it's perfectly valid that have multiple instances of the same
49  * log module (e.g. http.log) with different output ctx'. */
50 typedef struct OutputFileLogger_ {
54  const char *name;
60 
61 static OutputFileLogger *list = NULL;
62 
67 {
68  OutputFileLogger *op = SCMalloc(sizeof(*op));
69  if (op == NULL)
70  return -1;
71  memset(op, 0x00, sizeof(*op));
72 
73  op->LogFunc = LogFunc;
74  op->output_ctx = output_ctx;
75  op->name = name;
76  op->logger_id = id;
77  op->ThreadInit = ThreadInit;
80 
81  if (list == NULL)
82  list = op;
83  else {
84  OutputFileLogger *t = list;
85  while (t->next)
86  t = t->next;
87  t->next = op;
88  }
89 
90  SCLogDebug("OutputRegisterFileLogger happy");
91  return 0;
92 }
93 
94 static void OutputFileLogFfc(ThreadVars *tv,
95  OutputLoggerThreadData *op_thread_data,
96  Packet *p,
97  FileContainer *ffc, const bool file_close, const bool file_trunc,
98  uint8_t dir)
99 {
100  SCLogDebug("ffc %p", ffc);
101  if (ffc != NULL) {
102  File *ff;
103  for (ff = ffc->head; ff != NULL; ff = ff->next) {
104  if (ff->flags & FILE_LOGGED)
105  continue;
106 
107  SCLogDebug("ff %p", ff);
108 
109  if (file_trunc && ff->state < FILE_STATE_CLOSED)
111 
112  if (file_close && ff->state < FILE_STATE_CLOSED)
114 
115  SCLogDebug("ff %p state %u", ff, ff->state);
116 
117  if (ff->state > FILE_STATE_OPENED) {
118  bool file_logged = false;
119 #ifdef HAVE_MAGIC
120  if (FileForceMagic() && ff->magic == NULL) {
121  FilemagicGlobalLookup(ff);
122  }
123 #endif
124  const OutputFileLogger *logger = list;
125  const OutputLoggerThreadStore *store = op_thread_data->store;
126  while (logger && store) {
127  DEBUG_VALIDATE_BUG_ON(logger->LogFunc == NULL);
128 
129  SCLogDebug("logger %p", logger);
131  logger->LogFunc(tv, store->thread_data, (const Packet *)p, (const File *)ff, dir);
133  file_logged = true;
134 
135  logger = logger->next;
136  store = store->next;
137 
138  DEBUG_VALIDATE_BUG_ON(logger == NULL && store != NULL);
139  DEBUG_VALIDATE_BUG_ON(logger != NULL && store == NULL);
140  }
141 
142  if (file_logged) {
143  ff->flags |= FILE_LOGGED;
144  }
145  }
146  }
147  }
148 }
149 
150 static TmEcode OutputFileLog(ThreadVars *tv, Packet *p, void *thread_data)
151 {
152  DEBUG_VALIDATE_BUG_ON(thread_data == NULL);
153 
154  if (list == NULL) {
155  /* No child loggers. */
156  return TM_ECODE_OK;
157  }
158 
159  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
160 
161  /* no flow, no files */
162  Flow * const f = p->flow;
163  if (f == NULL || f->alstate == NULL) {
165  }
166 
167  const bool file_close_ts = ((p->flags & PKT_PSEUDO_STREAM_END) &&
169  const bool file_close_tc = ((p->flags & PKT_PSEUDO_STREAM_END) &&
171  const bool file_trunc = StreamTcpReassembleDepthReached(p);
172 
177 
178  OutputFileLogFfc(tv, op_thread_data, p, ffc_ts, file_close_ts, file_trunc, STREAM_TOSERVER);
179  OutputFileLogFfc(tv, op_thread_data, p, ffc_tc, file_close_tc, file_trunc, STREAM_TOCLIENT);
180 
181  return TM_ECODE_OK;
182 }
183 
184 /** \brief thread init for the tx logger
185  * This will run the thread init functions for the individual registered
186  * loggers */
187 static TmEcode OutputFileLogThreadInit(ThreadVars *tv, const void *initdata, void **data)
188 {
189  OutputLoggerThreadData *td = SCMalloc(sizeof(*td));
190  if (td == NULL)
191  return TM_ECODE_FAILED;
192  memset(td, 0x00, sizeof(*td));
193 
194  *data = (void *)td;
195 
196  SCLogDebug("OutputFileLogThreadInit happy (*data %p)", *data);
197 
198  OutputFileLogger *logger = list;
199  while (logger) {
200  if (logger->ThreadInit) {
201  void *retptr = NULL;
202  if (logger->ThreadInit(tv, (void *)logger->output_ctx, &retptr) == TM_ECODE_OK) {
203  OutputLoggerThreadStore *ts = SCMalloc(sizeof(*ts));
204 /* todo */ BUG_ON(ts == NULL);
205  memset(ts, 0x00, sizeof(*ts));
206 
207  /* store thread handle */
208  ts->thread_data = retptr;
209 
210  if (td->store == NULL) {
211  td->store = ts;
212  } else {
213  OutputLoggerThreadStore *tmp = td->store;
214  while (tmp->next != NULL)
215  tmp = tmp->next;
216  tmp->next = ts;
217  }
218 
219  SCLogDebug("%s is now set up", logger->name);
220  }
221  }
222 
223  logger = logger->next;
224  }
225 
226  return TM_ECODE_OK;
227 }
228 
229 static TmEcode OutputFileLogThreadDeinit(ThreadVars *tv, void *thread_data)
230 {
231  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
232  OutputLoggerThreadStore *store = op_thread_data->store;
233  OutputFileLogger *logger = list;
234 
235  while (logger && store) {
236  if (logger->ThreadDeinit) {
237  logger->ThreadDeinit(tv, store->thread_data);
238  }
239 
240  OutputLoggerThreadStore *next_store = store->next;
241  SCFree(store);
242  store = next_store;
243  logger = logger->next;
244  }
245 
246  SCFree(op_thread_data);
247  return TM_ECODE_OK;
248 }
249 
250 static void OutputFileLogExitPrintStats(ThreadVars *tv, void *thread_data)
251 {
252  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
253  OutputLoggerThreadStore *store = op_thread_data->store;
254  OutputFileLogger *logger = list;
255 
256  while (logger && store) {
257  if (logger->ThreadExitPrintStats) {
258  logger->ThreadExitPrintStats(tv, store->thread_data);
259  }
260 
261  logger = logger->next;
262  store = store->next;
263  }
264 }
265 
267 {
268  OutputRegisterRootLogger(OutputFileLogThreadInit,
269  OutputFileLogThreadDeinit, OutputFileLogExitPrintStats, OutputFileLog);
270 }
271 
273 {
274  OutputFileLogger *logger = list;
275  while (logger) {
276  OutputFileLogger *next_logger = logger->next;
277  SCFree(logger);
278  logger = next_logger;
279  }
280 
281  list = NULL;
282 }
#define PACKET_PROFILING_LOGGER_START(p, id)
#define SCLogDebug(...)
Definition: util-debug.h:335
struct Flow_ * flow
Definition: decode.h:446
void OutputFileShutdown(void)
Definition: output-file.c:272
ThreadExitPrintStatsFunc ThreadExitPrintStats
Definition: output-file.c:58
#define BUG_ON(x)
LoggerId
void(* ThreadExitPrintStatsFunc)(ThreadVars *, void *)
Definition: tm-modules.h:41
OutputCtx * output_ctx
Definition: output-file.c:52
struct OutputLoggerThreadData_ OutputLoggerThreadData
OutputLoggerThreadStore * store
Definition: output-file.c:44
struct File_ * next
Definition: util-file.h:77
const char * name
Definition: output-file.c:54
TmEcode(* ThreadDeinitFunc)(ThreadVars *, void *)
Definition: tm-modules.h:40
void * alstate
Definition: flow.h:438
#define FILE_LOGGED
Definition: util-file.h:44
uint16_t flags
Definition: util-file.h:64
uint8_t proto
Definition: decode.h:431
struct OutputLoggerThreadStore_ * next
Definition: output-file.c:38
FileLogger LogFunc
Definition: output-file.c:51
ThreadInitFunc ThreadInit
Definition: output-file.c:56
void OutputRegisterRootLogger(ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats, OutputLogFunc LogFunc)
Definition: output.c:1004
uint8_t flowflags
Definition: decode.h:440
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1095
#define SCReturnInt(x)
Definition: util-debug.h:341
struct OutputFileLogger_ * next
Definition: output-file.c:53
int FileForceMagic(void)
Definition: util-file.c:132
#define SCMalloc(a)
Definition: util-mem.h:222
#define SCFree(a)
Definition: util-mem.h:322
int(* FileLogger)(ThreadVars *, void *thread_data, const Packet *, const File *, uint8_t direction)
Definition: output-file.h:33
uint64_t ts
#define STREAM_TOSERVER
Definition: stream.h:31
FileState state
Definition: util-file.h:66
LoggerId logger_id
Definition: output-file.c:55
void OutputFileLoggerRegister(void)
Definition: output-file.c:266
struct OutputLoggerThreadStore_ OutputLoggerThreadStore
Per thread variable structure.
Definition: threadvars.h:57
int StreamTcpReassembleDepthReached(Packet *p)
check if stream in pkt direction has depth reached
TmEcode(* ThreadInitFunc)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:39
#define FLOW_PKT_TOCLIENT
Definition: flow.h:202
AppProto alproto
application level protocol
Definition: flow.h:409
#define PACKET_PROFILING_LOGGER_END(p, id)
uint32_t flags
Definition: decode.h:444
FileContainer * AppLayerParserGetFiles(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t direction)
Flow data structure.
Definition: flow.h:325
struct OutputFileLogger_ OutputFileLogger
int OutputRegisterFileLogger(LoggerId id, const char *name, FileLogger LogFunc, OutputCtx *output_ctx, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats)
Definition: output-file.c:63
ThreadDeinitFunc ThreadDeinit
Definition: output-file.c:57
#define DEBUG_VALIDATE_BUG_ON(exp)