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  if (ffc_ts && (p->flowflags & FLOW_PKT_TOSERVER))
182  FilePrune(ffc_ts);
183  if (ffc_tc && (p->flowflags & FLOW_PKT_TOCLIENT))
184  FilePrune(ffc_tc);
185 
186  return TM_ECODE_OK;
187 }
188 
189 /** \brief thread init for the tx logger
190  * This will run the thread init functions for the individual registered
191  * loggers */
192 static TmEcode OutputFileLogThreadInit(ThreadVars *tv, const void *initdata, void **data)
193 {
194  OutputLoggerThreadData *td = SCMalloc(sizeof(*td));
195  if (td == NULL)
196  return TM_ECODE_FAILED;
197  memset(td, 0x00, sizeof(*td));
198 
199  *data = (void *)td;
200 
201  SCLogDebug("OutputFileLogThreadInit happy (*data %p)", *data);
202 
203  OutputFileLogger *logger = list;
204  while (logger) {
205  if (logger->ThreadInit) {
206  void *retptr = NULL;
207  if (logger->ThreadInit(tv, (void *)logger->output_ctx, &retptr) == TM_ECODE_OK) {
208  OutputLoggerThreadStore *ts = SCMalloc(sizeof(*ts));
209 /* todo */ BUG_ON(ts == NULL);
210  memset(ts, 0x00, sizeof(*ts));
211 
212  /* store thread handle */
213  ts->thread_data = retptr;
214 
215  if (td->store == NULL) {
216  td->store = ts;
217  } else {
218  OutputLoggerThreadStore *tmp = td->store;
219  while (tmp->next != NULL)
220  tmp = tmp->next;
221  tmp->next = ts;
222  }
223 
224  SCLogDebug("%s is now set up", logger->name);
225  }
226  }
227 
228  logger = logger->next;
229  }
230 
231  return TM_ECODE_OK;
232 }
233 
234 static TmEcode OutputFileLogThreadDeinit(ThreadVars *tv, void *thread_data)
235 {
236  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
237  OutputLoggerThreadStore *store = op_thread_data->store;
238  OutputFileLogger *logger = list;
239 
240  while (logger && store) {
241  if (logger->ThreadDeinit) {
242  logger->ThreadDeinit(tv, store->thread_data);
243  }
244 
245  OutputLoggerThreadStore *next_store = store->next;
246  SCFree(store);
247  store = next_store;
248  logger = logger->next;
249  }
250 
251  SCFree(op_thread_data);
252  return TM_ECODE_OK;
253 }
254 
255 static void OutputFileLogExitPrintStats(ThreadVars *tv, void *thread_data)
256 {
257  OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
258  OutputLoggerThreadStore *store = op_thread_data->store;
259  OutputFileLogger *logger = list;
260 
261  while (logger && store) {
262  if (logger->ThreadExitPrintStats) {
263  logger->ThreadExitPrintStats(tv, store->thread_data);
264  }
265 
266  logger = logger->next;
267  store = store->next;
268  }
269 }
270 
272 {
273  OutputRegisterRootLogger(OutputFileLogThreadInit,
274  OutputFileLogThreadDeinit, OutputFileLogExitPrintStats, OutputFileLog);
275 }
276 
278 {
279  OutputFileLogger *logger = list;
280  while (logger) {
281  OutputFileLogger *next_logger = logger->next;
282  SCFree(logger);
283  logger = next_logger;
284  }
285 
286  list = NULL;
287 }
#define PACKET_PROFILING_LOGGER_START(p, id)
#define SCLogDebug(...)
Definition: util-debug.h:335
struct Flow_ * flow
Definition: decode.h:443
void OutputFileShutdown(void)
Definition: output-file.c:277
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:79
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:65
uint8_t proto
Definition: decode.h:428
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:1001
uint8_t flowflags
Definition: decode.h:437
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1093
#define SCReturnInt(x)
Definition: util-debug.h:341
void FilePrune(FileContainer *ffc)
Definition: util-file.c:345
struct OutputFileLogger_ * next
Definition: output-file.c:53
int FileForceMagic(void)
Definition: util-file.c:130
#define SCMalloc(a)
Definition: util-mem.h:166
#define SCFree(a)
Definition: util-mem.h:228
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:67
LoggerId logger_id
Definition: output-file.c:55
void OutputFileLoggerRegister(void)
Definition: output-file.c:271
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:441
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)