suricata
log-tcp-data.c
Go to the documentation of this file.
1/* Copyright (C) 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
24#include "suricata-common.h"
25#include "log-tcp-data.h"
26
27#include "threadvars.h"
28
29#include "util-conf.h"
30#include "util-logopenfile.h"
31#include "util-path.h"
32#include "util-print.h"
33
34#define DEFAULT_LOG_FILENAME "tcp-data.log"
35
36#define MODULE_NAME "LogTcpDataLog"
37
38#define OUTPUT_BUFFER_SIZE 65535
39
40TmEcode LogTcpDataLogThreadInit(ThreadVars *, const void *, void **);
42static void LogTcpDataLogDeInitCtx(OutputCtx *);
43
44int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f, const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags);
45
54
62
63typedef struct LogTcpDataLogThread_ {
65 /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
68
69static int LogTcpDataLoggerDir(ThreadVars *tv, void *thread_data, const Flow *f,
70 const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
71{
72 SCEnter();
73 LogTcpDataLogThread *aft = thread_data;
75 const char *mode = "a";
76
78 mode = "w";
79
80 if (data && data_len) {
81 char srcip[46] = "", dstip[46] = "";
82 if (FLOW_IS_IPV4(f)) {
83 PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip));
84 PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip));
85 } else if (FLOW_IS_IPV6(f)) {
86 PrintInet(AF_INET6, (const void *)f->src.addr_data32, srcip, sizeof(srcip));
87 PrintInet(AF_INET6, (const void *)f->dst.addr_data32, dstip, sizeof(dstip));
88 }
89
90 char name[PATH_MAX];
91
92 char tx[64] = { 0 };
94 snprintf(tx, sizeof(tx), "%"PRIu64, tx_id);
95 }
96
97 snprintf(name, sizeof(name), "%s/%s/%s_%u-%s_%u-%s-%s.data",
98 td->log_dir,
99 td->type == STREAMING_HTTP_BODIES ? "http" : "tcp",
100 srcip, f->sp, dstip, f->dp, tx,
101 flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
102
103 FILE *fp = fopen(name, mode);
104 BUG_ON(fp == NULL);
105
106 // PrintRawDataFp(stdout, (uint8_t *)data, data_len);
107 fwrite(data, data_len, 1, fp);
108
109 fclose(fp);
110 }
112}
113
114static int LogTcpDataLoggerFile(ThreadVars *tv, void *thread_data, const Flow *f,
115 const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
116{
117 SCEnter();
118 LogTcpDataLogThread *aft = thread_data;
120
121 if (data && data_len) {
122 MemBufferReset(aft->buffer);
123
124 char srcip[46] = "", dstip[46] = "";
125 if (FLOW_IS_IPV4(f)) {
126 PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip));
127 PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip));
128 } else if (FLOW_IS_IPV6(f)) {
129 PrintInet(AF_INET6, (const void *)f->src.addr_data32, srcip, sizeof(srcip));
130 PrintInet(AF_INET6, (const void *)f->dst.addr_data32, dstip, sizeof(dstip));
131 }
132
133 char name[PATH_MAX];
134 snprintf(name, sizeof(name), "%s_%u-%s_%u-%s:",
135 srcip, f->sp, dstip, f->dp,
136 flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
137
138 PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
139 aft->buffer->size, (uint8_t *)name,strlen(name));
140 MemBufferWriteString(aft->buffer, "\n");
141
143 aft->buffer->size, (uint8_t *)data,data_len);
144
145 td->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
146 MEMBUFFER_OFFSET(aft->buffer), td->file_ctx);
147 }
149}
150
151int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f,
152 const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
153{
154 SCEnter();
155 LogTcpDataLogThread *aft = thread_data;
157
158 if (td->dir == 1)
159 LogTcpDataLoggerDir(tv, thread_data, f, data, data_len, tx_id, flags);
160 if (td->file == 1)
161 LogTcpDataLoggerFile(tv, thread_data, f, data, data_len, tx_id, flags);
162
164}
165
166TmEcode LogTcpDataLogThreadInit(ThreadVars *t, const void *initdata, void **data)
167{
169 if (unlikely(aft == NULL))
170 return TM_ECODE_FAILED;
171
172 if(initdata == NULL)
173 {
174 SCLogDebug("Error getting context. \"initdata\" argument NULL");
175 SCFree(aft);
176 return TM_ECODE_FAILED;
177 }
178
180 if (aft->buffer == NULL) {
181 SCFree(aft);
182 return TM_ECODE_FAILED;
183 }
184
185 /* Use the Output Context (file pointer and mutex) */
186 aft->tcpdatalog_ctx= ((OutputCtx *)initdata)->data;
187
188 *data = (void *)aft;
189 return TM_ECODE_OK;
190}
191
193{
195 if (aft == NULL) {
196 return TM_ECODE_OK;
197 }
198
199 MemBufferFree(aft->buffer);
200 /* clear memory */
201 memset(aft, 0, sizeof(LogTcpDataLogThread));
202
203 SCFree(aft);
204 return TM_ECODE_OK;
205}
206
207/** \brief Create a new http log LogFileCtx.
208 * \param conf Pointer to ConfNode containing this loggers configuration.
209 * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
210 * */
212{
213 OutputInitResult result = { NULL, false };
214 char filename[PATH_MAX] = "";
215 char dirname[32] = "";
216 strlcpy(filename, DEFAULT_LOG_FILENAME, sizeof(filename));
217
218 LogFileCtx *file_ctx = LogFileNewCtx();
219 if(file_ctx == NULL) {
220 SCLogError("couldn't create new file_ctx");
221 return result;
222 }
223
224 LogTcpDataFileCtx *tcpdatalog_ctx = SCCalloc(1, sizeof(LogTcpDataFileCtx));
225 if (unlikely(tcpdatalog_ctx == NULL)) {
226 LogFileFreeCtx(file_ctx);
227 return result;
228 }
229
230 tcpdatalog_ctx->file_ctx = file_ctx;
231
232 if (conf) {
233 if (conf->name) {
234 if (strcmp(conf->name, "tcp-data") == 0) {
235 tcpdatalog_ctx->type = STREAMING_TCP_DATA;
236 snprintf(filename, sizeof(filename), "%s.log", conf->name);
237 strlcpy(dirname, "tcp", sizeof(dirname));
238 } else if (strcmp(conf->name, "http-body-data") == 0) {
239 tcpdatalog_ctx->type = STREAMING_HTTP_BODIES;
240 snprintf(filename, sizeof(filename), "%s.log", conf->name);
241 strlcpy(dirname, "http", sizeof(dirname));
242 }
243 }
244
245 const char *logtype = SCConfNodeLookupChildValue(conf, "type");
246 if (logtype == NULL)
247 logtype = "file";
248
249 if (strcmp(logtype, "file") == 0) {
250 tcpdatalog_ctx->file = 1;
251 } else if (strcmp(logtype, "dir") == 0) {
252 tcpdatalog_ctx->dir = 1;
253 } else if (strcmp(logtype, "both") == 0) {
254 tcpdatalog_ctx->file = 1;
255 tcpdatalog_ctx->dir = 1;
256 }
257 } else {
258 tcpdatalog_ctx->file = 1;
259 tcpdatalog_ctx->dir = 0;
260 }
261
262 if (tcpdatalog_ctx->file == 1) {
263 SCLogInfo("opening logfile");
264 if (SCConfLogOpenGeneric(conf, file_ctx, filename, 1) < 0) {
265 LogFileFreeCtx(file_ctx);
266 SCFree(tcpdatalog_ctx);
267 return result;
268 }
269 }
270
271 if (tcpdatalog_ctx->dir == 1) {
272 tcpdatalog_ctx->log_dir = SCConfigGetLogDirectory();
273 char dirfull[PATH_MAX];
274
275 /* create the filename to use */
276 snprintf(dirfull, PATH_MAX, "%s/%s", tcpdatalog_ctx->log_dir, dirname);
277
278 SCLogInfo("using directory %s", dirfull);
279
280 /* if mkdir fails file open will fail, so deal with errors there */
281 (void)SCMkDir(dirfull, 0700);
282 }
283
284 OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
285 if (unlikely(output_ctx == NULL)) {
286 goto parsererror;
287 }
288
289 output_ctx->data = tcpdatalog_ctx;
290 output_ctx->DeInit = LogTcpDataLogDeInitCtx;
291
292 SCLogDebug("Streaming log output initialized");
293 result.ctx = output_ctx;
294 result.ok = true;
295 return result;
296
297parsererror:
298 LogFileFreeCtx(file_ctx);
299 SCFree(tcpdatalog_ctx);
300 SCLogError("Syntax error in custom http log format string.");
301 return result;
302
303}
304
305static void LogTcpDataLogDeInitCtx(OutputCtx *output_ctx)
306{
307 LogTcpDataFileCtx *tcpdatalog_ctx = (LogTcpDataFileCtx *)output_ctx->data;
308 LogFileFreeCtx(tcpdatalog_ctx->file_ctx);
309 SCFree(tcpdatalog_ctx);
310 SCFree(output_ctx);
311}
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition conf.c:824
uint8_t flags
Definition decode-gre.h:0
#define FLOW_IS_IPV6(f)
Definition flow.h:172
#define FLOW_IS_IPV4(f)
Definition flow.h:170
ThreadVars * tv
struct LogTcpDataFileCtx_ LogTcpDataFileCtx
void LogTcpDataLogRegister(void)
#define MODULE_NAME
int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f, const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
#define OUTPUT_BUFFER_SIZE
OutputInitResult LogTcpDataLogInitCtx(SCConfNode *conf)
Create a new http log LogFileCtx.
struct LogTcpDataLogThread_ LogTcpDataLogThread
#define DEFAULT_LOG_FILENAME
TmEcode LogTcpDataLogThreadInit(ThreadVars *, const void *, void **)
TmEcode LogTcpDataLogThreadDeinit(ThreadVars *, void *)
#define OUTPUT_STREAMING_FLAG_TRANSACTION
SCOutputStreamingType
@ STREAMING_TCP_DATA
@ STREAMING_HTTP_BODIES
#define OUTPUT_STREAMING_FLAG_TOSERVER
#define OUTPUT_STREAMING_FLAG_OPEN
void OutputRegisterStreamingModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, SCStreamingLogger StreamingLogFunc, enum SCOutputStreamingType stream_type, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Register a streaming data output module.
Definition output.c:532
Flow data structure.
Definition flow.h:356
Port dp
Definition flow.h:372
FlowAddress src
Definition flow.h:359
Port sp
Definition flow.h:361
FlowAddress dst
Definition flow.h:359
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
const char * log_dir
enum SCOutputStreamingType type
LogFileCtx * file_ctx
LogTcpDataFileCtx * tcpdatalog_ctx
uint8_t buffer[]
Definition util-buffer.h:30
uint32_t size
Definition util-buffer.h:28
uint32_t offset
Definition util-buffer.h:29
void * data
Definition tm-modules.h:91
void(* DeInit)(struct OutputCtx_ *)
Definition tm-modules.h:94
OutputCtx * ctx
Definition output.h:47
char * name
Definition conf.h:38
Per thread variable structure.
Definition threadvars.h:58
#define BUG_ON(x)
@ LOGGER_TCP_DATA
size_t strlcpy(char *dst, const char *src, size_t siz)
@ TM_ECODE_FAILED
@ TM_ECODE_OK
const char * name
void MemBufferWriteString(MemBuffer *dst, const char *fmt,...)
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition util-buffer.c:32
void MemBufferFree(MemBuffer *buffer)
Definition util-buffer.c:86
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
Definition util-buffer.h:51
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
Definition util-buffer.h:56
const char * SCConfigGetLogDirectory(void)
Definition util-conf.c:38
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
int SCConfLogOpenGeneric(SCConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate)
open a generic output "log file", which may be a regular file or a socket
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
#define SCMkDir(a, b)
Definition util-path.h:45
void PrintRawDataToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, const uint8_t *src_buf, uint32_t src_buf_len)
Definition util-print.c:149
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition util-print.c:231
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, const uint8_t *buf, size_t buflen)
Definition util-print.c:93