]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
output: add new logger to log at specified state
authorMats Klepsland <mats.klepsland@gmail.com>
Wed, 27 Apr 2016 12:13:44 +0000 (14:13 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 17 May 2016 10:25:25 +0000 (12:25 +0200)
Sometimes we want to log when we reach a specified state instead of
waiting for the session to end. E.g for TLS we want to log as soon
as the handshake is done.

To do this, a new logger is added, where it is possible to specify
a custom "ProgressCompletionStatus".

src/output-tx.c
src/output-tx.h
src/output.c
src/output.h
src/runmodes.c

index 1e3396bd5f535e325fb9ed386f790c9768a9a4e0..79b896325917797302fbf65ebc7cbd95fd2427d5 100644 (file)
@@ -51,11 +51,16 @@ typedef struct OutputTxLogger_ {
     struct OutputTxLogger_ *next;
     const char *name;
     TmmId module_id;
+    uint32_t id;
+    int tc_log_progress;
+    int ts_log_progress;
 } OutputTxLogger;
 
 static OutputTxLogger *list = NULL;
 
-int OutputRegisterTxLogger(const char *name, AppProto alproto, TxLogger LogFunc, OutputCtx *output_ctx)
+int OutputRegisterTxLogger(const char *name, AppProto alproto, TxLogger LogFunc,
+                           OutputCtx *output_ctx, int tc_log_progress,
+                           int ts_log_progress)
 {
     int module_id = TmModuleGetIdByName(name);
     if (module_id < 0)
@@ -72,12 +77,34 @@ int OutputRegisterTxLogger(const char *name, AppProto alproto, TxLogger LogFunc,
     op->name = name;
     op->module_id = (TmmId) module_id;
 
-    if (list == NULL)
+    if (tc_log_progress) {
+        op->tc_log_progress = tc_log_progress;
+    } else {
+        op->tc_log_progress =
+            AppLayerParserGetStateProgressCompletionStatus(alproto,
+                                                           STREAM_TOCLIENT);
+    }
+
+    if (ts_log_progress) {
+        op->ts_log_progress = ts_log_progress;
+    } else {
+        op->ts_log_progress =
+            AppLayerParserGetStateProgressCompletionStatus(alproto,
+                                                           STREAM_TOSERVER);
+    }
+
+    if (list == NULL) {
+        op->id = 1;
         list = op;
-    else {
+    else {
         OutputTxLogger *t = list;
         while (t->next)
             t = t->next;
+        if (t->id * 2 > UINT32_MAX) {
+            SCLogError(SC_ERR_FATAL, "Too many loggers registered.");
+            exit(EXIT_FAILURE);
+        }
+        op->id = t->id * 2;
         t->next = op;
     }
 
@@ -119,15 +146,10 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQ
 
     uint64_t total_txs = AppLayerParserGetTxCnt(p->proto, alproto, alstate);
     uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser);
-    int tx_progress_done_value_ts =
-        AppLayerParserGetStateProgressCompletionStatus(alproto,
-                                                       STREAM_TOSERVER);
-    int tx_progress_done_value_tc =
-        AppLayerParserGetStateProgressCompletionStatus(alproto,
-                                                       STREAM_TOCLIENT);
+
     for (; tx_id < total_txs; tx_id++)
     {
-        int proto_logged = 0;
+        int logger_not_logged = 0;
 
         void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id);
         if (tx == NULL) {
@@ -135,22 +157,11 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQ
             continue;
         }
 
-        if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF)))
-        {
-            int tx_progress = AppLayerParserGetStateProgress(p->proto, alproto,
-                                                             tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER));
-            if (tx_progress < tx_progress_done_value_ts) {
-                SCLogDebug("progress not far enough, not logging");
-                break;
-            }
+        int tx_progress_ts = AppLayerParserGetStateProgress(p->proto, alproto,
+                tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER));
 
-            tx_progress = AppLayerParserGetStateProgress(p->proto, alproto,
-                                                         tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT));
-            if (tx_progress < tx_progress_done_value_tc) {
-                SCLogDebug("progress not far enough, not logging");
-                break;
-            }
-        }
+        int tx_progress_tc = AppLayerParserGetStateProgress(p->proto, alproto,
+                tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT));
 
         // call each logger here (pseudo code)
         logger = list;
@@ -161,12 +172,38 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQ
             SCLogDebug("logger %p", logger);
             if (logger->alproto == alproto) {
                 SCLogDebug("alproto match, logging tx_id %ju", tx_id);
+
+                if (AppLayerParserGetTxLogged(p->proto, alproto, alstate, tx,
+                        logger->id)) {
+                    SCLogDebug("logger has already logged this transaction");
+
+                    goto next;
+                }
+
+                if (!(AppLayerParserStateIssetFlag(f->alparser,
+                                                   APP_LAYER_PARSER_EOF))) {
+                    if (tx_progress_tc < logger->tc_log_progress) {
+                        SCLogDebug("progress not far enough, not logging");
+                        logger_not_logged = 1;
+                        goto next;
+                    }
+
+                    if (tx_progress_ts < logger->ts_log_progress) {
+                        SCLogDebug("progress not far enough, not logging");
+                        logger_not_logged = 1;
+                        goto next;
+                    }
+                }
+
                 PACKET_PROFILING_TMM_START(p, logger->module_id);
                 logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id);
                 PACKET_PROFILING_TMM_END(p, logger->module_id);
-                proto_logged = 1;
+
+                AppLayerParserSetTxLogged(p->proto, alproto, alstate, tx,
+                                          logger->id);
             }
 
+next:
             logger = logger->next;
             store = store->next;
 
@@ -174,7 +211,7 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQ
             BUG_ON(logger != NULL && store == NULL);
         }
 
-        if (proto_logged) {
+        if (!logger_not_logged) {
             SCLogDebug("updating log tx_id %ju", tx_id);
             AppLayerParserSetTransactionLogId(f->alparser);
         }
index 7ffb8a6d25e8c0e171a18ce82328f662c52b262b..e8e8163d8907783a231639cfc5818b93da8ba6c0 100644 (file)
@@ -36,7 +36,8 @@ typedef int (*TxLogger)(ThreadVars *, void *thread_data, const Packet *, Flow *f
  */
 //typedef int (*TxLogCondition)(ThreadVars *, const Packet *);
 
-int OutputRegisterTxLogger(const char *name, AppProto alproto, TxLogger LogFunc, OutputCtx *);
+int OutputRegisterTxLogger(const char *name, AppProto alproto, TxLogger LogFunc,
+        OutputCtx *, int tc_log_progress, int ts_log_progress);
 
 void TmModuleTxLoggerRegister (void);
 
index 1146b7b22673310b8513bc52a035c046fba4d7d0..d7c5ff910ee9db360d42f0951cb7c316c10ca777 100644 (file)
@@ -150,17 +150,16 @@ error:
 }
 
 /**
- * \brief Register a tx output module.
+ * \brief Register a tx output module with progress.
  *
  * This function will register an output module so it can be
  * configured with the configuration file.
  *
  * \retval Returns 0 on success, -1 on failure.
  */
-void
-OutputRegisterTxModule(const char *name, const char *conf_name,
-    OutputCtx *(*InitFunc)(ConfNode *), AppProto alproto,
-    TxLogger TxLogFunc)
+void OutputRegisterTxModuleWithProgress(const char *name, const char *conf_name,
+        OutputCtx *(*InitFunc)(ConfNode *), AppProto alproto,
+        TxLogger TxLogFunc, int tc_log_progress, int ts_log_progress)
 {
     if (unlikely(TxLogFunc == NULL)) {
         goto error;
@@ -176,6 +175,8 @@ OutputRegisterTxModule(const char *name, const char *conf_name,
     module->InitFunc = InitFunc;
     module->TxLogFunc = TxLogFunc;
     module->alproto = alproto;
+    module->tc_log_progress = tc_log_progress;
+    module->ts_log_progress = ts_log_progress;
     TAILQ_INSERT_TAIL(&output_modules, module, entries);
 
     SCLogDebug("Tx logger \"%s\" registered.", name);
@@ -185,10 +186,10 @@ error:
     exit(EXIT_FAILURE);
 }
 
-void
-OutputRegisterTxSubModule(const char *parent_name, const char *name,
-    const char *conf_name, OutputCtx *(*InitFunc)(ConfNode *, OutputCtx *parent_ctx),
-    AppProto alproto, TxLogger TxLogFunc)
+void OutputRegisterTxSubModuleWithProgress(const char *parent_name,
+        const char *name, const char *conf_name, OutputCtx *(*InitFunc)(ConfNode *,
+        OutputCtx *parent_ctx), AppProto alproto, TxLogger TxLogFunc,
+        int tc_log_progress, int ts_log_progress)
 {
     if (unlikely(TxLogFunc == NULL)) {
         goto error;
@@ -205,6 +206,8 @@ OutputRegisterTxSubModule(const char *parent_name, const char *name,
     module->InitSubFunc = InitFunc;
     module->TxLogFunc = TxLogFunc;
     module->alproto = alproto;
+    module->tc_log_progress = tc_log_progress;
+    module->ts_log_progress = ts_log_progress;
     TAILQ_INSERT_TAIL(&output_modules, module, entries);
 
     SCLogDebug("Tx logger \"%s\" registered.", name);
@@ -214,6 +217,34 @@ error:
     exit(EXIT_FAILURE);
 }
 
+/**
+ * \brief Register a tx output module.
+ *
+ * This function will register an output module so it can be
+ * configured with the configuration file.
+ *
+ * \retval Returns 0 on success, -1 on failure.
+ */
+void
+OutputRegisterTxModule(const char *name, const char *conf_name,
+    OutputCtx *(*InitFunc)(ConfNode *), AppProto alproto,
+    TxLogger TxLogFunc)
+{
+    /* wrapper function */
+    OutputRegisterTxModuleWithProgress(name, conf_name, InitFunc, alproto,
+                                       TxLogFunc, 0, 0);
+}
+
+void
+OutputRegisterTxSubModule(const char *parent_name, const char *name,
+    const char *conf_name, OutputCtx *(*InitFunc)(ConfNode *, OutputCtx *parent_ctx),
+    AppProto alproto, TxLogger TxLogFunc)
+{
+    /* wrapper function */
+    OutputRegisterTxSubModuleWithProgress(parent_name, name, conf_name,
+                                          InitFunc, alproto, TxLogFunc, 0, 0);
+}
+
 /**
  * \brief Register a file output module.
  *
index 9a4add0efb53a632173ddb4cc0f9182cb6f71fd1..152262b72a602a30ef3cb20a7588856c184e3699 100644 (file)
@@ -55,6 +55,8 @@ typedef struct OutputModule_ {
     StatsLogger StatsLogFunc;
     AppProto alproto;
     enum OutputStreamingType stream_type;
+    int tc_log_progress;
+    int ts_log_progress;
 
     TAILQ_ENTRY(OutputModule_) entries;
 } OutputModule;
@@ -75,6 +77,13 @@ void OutputRegisterTxSubModule(const char *parent_name, const char *name,
     const char *conf_name, OutputCtx *(*InitFunc)(ConfNode *, OutputCtx *parent_ctx),
     AppProto alproto, TxLogger TxLogFunc);
 
+void OutputRegisterTxModuleWithProgress(const char *name, const char *conf_name,
+    OutputCtx *(*InitFunc)(ConfNode *), AppProto alproto,
+    TxLogger TxLogFunc, int tc_log_progress, int ts_log_progress);
+void OutputRegisterTxSubModuleWithProgress(const char *parent_name, const char *name,
+    const char *conf_name, OutputCtx *(*InitFunc)(ConfNode *, OutputCtx *parent_ctx),
+    AppProto alproto, TxLogger TxLogFunc, int tc_log_progress, int ts_log_progress);
+
 void OutputRegisterFileModule(const char *name, const char *conf_name,
     OutputCtx *(*InitFunc)(ConfNode *), FileLogger FileLogFunc);
 void OutputRegisterFileSubModule(const char *parent_name, const char *name,
index b4bf31b6c7a74badd4ba9fdacbb68a22494d96c1..e0154a1f55a5d0135164cbe11cb93a00aa5f949e 100644 (file)
@@ -617,7 +617,8 @@ static void SetupOutput(const char *name, OutputModule *module, OutputCtx *outpu
     } else if (module->TxLogFunc) {
         SCLogDebug("%s is a tx logger", module->name);
         OutputRegisterTxLogger(module->name, module->alproto,
-                module->TxLogFunc, output_ctx);
+                module->TxLogFunc, output_ctx, module->tc_log_progress,
+                module->ts_log_progress);
 
         /* need one instance of the tx logger module */
         if (tx_logger_module == NULL) {