diff --git a/src/output-droplog.c b/src/output-droplog.c index c437cd91e6..cf390bc154 100644 --- a/src/output-droplog.c +++ b/src/output-droplog.c @@ -55,9 +55,17 @@ #include "util-time.h" #include "util-buffer.h" +#define MODULE_NAME "JsonDropLog" + #ifdef HAVE_LIBJANSSON #include +typedef struct JsonDropLogThread_ { + /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ + LogFileCtx* file_ctx; + MemBuffer *buffer; +} JsonDropLogThread; + /** * \brief Log the dropped packets in netfilter format when engine is running * in inline mode @@ -67,11 +75,11 @@ * * \return return TM_EODE_OK on success */ -TmEcode OutputDropLogJSON (AlertJsonThread *aft, Packet *p) +static int DropLogJSON (JsonDropLogThread *aft, const Packet *p) { uint16_t proto = 0; MemBuffer *buffer = (MemBuffer *)aft->buffer; - json_t *js = CreateJSONHeader(p, 0); + json_t *js = CreateJSONHeader((Packet *)p, 0);//TODO const if (unlikely(js == NULL)) return TM_ECODE_OK; @@ -125,7 +133,7 @@ TmEcode OutputDropLogJSON (AlertJsonThread *aft, Packet *p) break; } json_object_set_new(js, "drop", djs); - OutputJSON(js, aft, &aft->drop_cnt); + OutputJSONBuffer(js, aft->file_ctx, buffer); json_object_del(js, "drop"); json_object_clear(js); json_decref(js); @@ -133,52 +141,167 @@ TmEcode OutputDropLogJSON (AlertJsonThread *aft, Packet *p) return TM_ECODE_OK; } +#define OUTPUT_BUFFER_SIZE 65535 +static TmEcode JsonDropLogThreadInit(ThreadVars *t, void *initdata, void **data) +{ + JsonDropLogThread *aft = SCMalloc(sizeof(JsonDropLogThread)); + if (unlikely(aft == NULL)) + return TM_ECODE_FAILED; + memset(aft, 0, sizeof(*aft)); + if(initdata == NULL) + { + SCLogDebug("Error getting context for AlertFastLog. \"initdata\" argument NULL"); + SCFree(aft); + return TM_ECODE_FAILED; + } + + aft->buffer = MemBufferCreateNew(OUTPUT_BUFFER_SIZE); + if (aft->buffer == NULL) { + SCFree(aft); + return TM_ECODE_FAILED; + } + + /** Use the Ouptut Context (file pointer and mutex) */ + aft->file_ctx = ((OutputCtx *)initdata)->data; + + *data = (void *)aft; + return TM_ECODE_OK; +} + +static TmEcode JsonDropLogThreadDeinit(ThreadVars *t, void *data) +{ + JsonDropLogThread *aft = (JsonDropLogThread *)data; + if (aft == NULL) { + return TM_ECODE_OK; + } + + /* clear memory */ + memset(aft, 0, sizeof(*aft)); + + SCFree(aft); + return TM_ECODE_OK; +} + +static void JsonDropLogDeInitCtx(OutputCtx *output_ctx) +{ + LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data; + LogFileFreeCtx(logfile_ctx); + SCFree(output_ctx); +} + +#define DEFAULT_LOG_FILENAME "drop.json" +static OutputCtx *JsonDropLogInitCtx(ConfNode *conf) +{ + LogFileCtx *logfile_ctx = LogFileNewCtx(); + if (logfile_ctx == NULL) { + return NULL; + } + + if (SCConfLogOpenGeneric(conf, logfile_ctx, DEFAULT_LOG_FILENAME) < 0) { + LogFileFreeCtx(logfile_ctx); + return NULL; + } + + OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); + if (unlikely(output_ctx == NULL)) { + return NULL; + } + + output_ctx->data = logfile_ctx; + output_ctx->DeInit = JsonDropLogDeInitCtx; + return output_ctx; +} + /** * \brief Log the dropped packets when engine is running in inline mode * * \param tv Pointer the current thread variables - * \param p Pointer the packet which is being logged * \param data Pointer to the droplog struct + * \param p Pointer the packet which is being logged * - * \return return TM_EODE_OK on success + * \retval 0 on succes */ -TmEcode OutputDropLog (ThreadVars *tv, Packet *p, void *data) +static int JsonDropLogger(ThreadVars *tv, void *thread_data, const Packet *p) { - AlertJsonThread *aft = (AlertJsonThread *)data; + JsonDropLogThread *td = thread_data; + int r = DropLogJSON(td, p); + if (r < 0) + return -1; - /* Check if we are in inline mode or not, if not then no need to log */ + if (p->flow) { + FLOWLOCK_RDLOCK(p->flow); + if (p->flow->flags & FLOW_ACTION_DROP) { + if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED)) + p->flow->flags |= FLOW_TOSERVER_DROP_LOGGED; + else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED)) + p->flow->flags |= FLOW_TOCLIENT_DROP_LOGGED; + } + FLOWLOCK_UNLOCK(p->flow); + } + return 0; +} + + +/** + * \brief Check if we need to drop-log this packet + * + * \param tv Pointer the current thread variables + * \param p Pointer the packet which is tested + * + * \retval bool TRUE or FALSE + */ +static int JsonDropLogCondition(ThreadVars *tv, const Packet *p) { extern uint8_t engine_mode; if (!IS_ENGINE_MODE_IPS(engine_mode)) { SCLogDebug("engine is not running in inline mode, so returning"); - return TM_ECODE_OK; + return FALSE; + } + if (PKT_IS_PSEUDOPKT(p)) { + SCLogDebug("drop log doesn't log pseudo packets"); + return FALSE; } - if ((p->flow != NULL) && (p->flow->flags & FLOW_ACTION_DROP)) { - if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED)) { - p->flow->flags |= FLOW_TOSERVER_DROP_LOGGED; - return OutputDropLogJSON(aft, p); - - } else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED)) { - p->flow->flags |= FLOW_TOCLIENT_DROP_LOGGED; - return OutputDropLogJSON(aft, p); + if (p->flow != NULL) { + int ret = FALSE; + FLOWLOCK_RDLOCK(p->flow); + if (p->flow->flags & FLOW_ACTION_DROP) { + if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED)) + ret = TRUE; + else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED)) + ret = TRUE; } - } else { - return OutputDropLogJSON(aft, p); + FLOWLOCK_UNLOCK(p->flow); + return ret; + } else if (PACKET_TEST_ACTION(p, ACTION_DROP)) { + return TRUE; } - return TM_ECODE_OK; + return FALSE; +} + +void TmModuleJsonDropLogRegister (void) { + tmm_modules[TMM_JSONDROPLOG].name = MODULE_NAME; + tmm_modules[TMM_JSONDROPLOG].ThreadInit = JsonDropLogThreadInit; + tmm_modules[TMM_JSONDROPLOG].ThreadDeinit = JsonDropLogThreadDeinit; + tmm_modules[TMM_JSONDROPLOG].cap_flags = 0; + + OutputRegisterPacketModule(MODULE_NAME, "drop-json-log", + JsonDropLogInitCtx, JsonDropLogger, JsonDropLogCondition); } -OutputCtx *OutputDropLogInit(ConfNode *conf) -{ - OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); - if (unlikely(output_ctx == NULL)) { - return NULL; - } +#else - return output_ctx; +static TmEcode OutputJsonThreadInit(ThreadVars *t, void *initdata, void **data) +{ + SCLogInfo("Can't init JSON output - JSON support was disabled during build."); + return TM_ECODE_FAILED; } +void TmModuleJsonDropLogRegister (void) +{ + tmm_modules[TMM_JSONDROPLOG].name = MODULE_NAME; + tmm_modules[TMM_JSONDROPLOG].ThreadInit = OutputJsonThreadInit; +} #endif diff --git a/src/output-droplog.h b/src/output-droplog.h index 79e5f38cd7..12ccf5e5d0 100644 --- a/src/output-droplog.h +++ b/src/output-droplog.h @@ -28,5 +28,6 @@ TmEcode OutputDropLog (ThreadVars *tv, Packet *p, void *data); OutputCtx *OutputDropLogInit(ConfNode *); +void TmModuleJsonDropLogRegister (void); #endif /* OUTPUT_DROPLOG_H */ diff --git a/src/output-json.c b/src/output-json.c index 9a65b89f50..71ec1cb2d6 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -357,10 +357,6 @@ TmEcode OutputJSON(json_t *js, void *data, uint64_t *count) TmEcode OutputJson (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { - if (output_flags & OUTPUT_DROP) { - OutputDropLog(tv, p, data); - } - if (output_flags & OUTPUT_FILES) { OutputFileLog(tv, p, data); } @@ -535,11 +531,6 @@ OutputCtx *OutputJsonInitCtx(ConfNode *conf) * registration capability */ TAILQ_FOREACH(output, &outputs->head, next) { - if (strcmp(output->val, "drop") == 0) { - SCLogDebug("Enabling drop output"); - output_flags |= OUTPUT_DROP; - continue; - } if (strcmp(output->val, "files") == 0) { SCLogDebug("Enabling files output"); ConfNode *child = ConfNodeLookupChild(output, "files"); diff --git a/src/suricata.c b/src/suricata.c index 6f905d8ba8..3a3576fb03 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -81,6 +81,7 @@ #include "output-json-alert.h" #include "log-droplog.h" +#include "output-droplog.h" #include "log-httplog.h" #include "output-httplog.h" #include "log-dnslog.h" @@ -796,6 +797,7 @@ void RegisterAllModules() TmModuleAlertPcapInfoRegister(); /* drop log */ TmModuleLogDropLogRegister(); + TmModuleJsonDropLogRegister(); /* json log */ TmModuleOutputJsonRegister(); /* http log */ diff --git a/src/tm-threads-common.h b/src/tm-threads-common.h index a349f85cf6..e03d70f7ac 100644 --- a/src/tm-threads-common.h +++ b/src/tm-threads-common.h @@ -85,6 +85,7 @@ typedef enum { TMM_FILELOGGER, TMM_FILEDATALOGGER, TMM_JSONALERTLOG, + TMM_JSONDROPLOG, TMM_JSONHTTPLOG, TMM_JSONDNSLOG, TMM_SIZE,