]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Introduce packet logging output API
authorVictor Julien <victor@inliniac.net>
Thu, 5 Dec 2013 14:35:15 +0000 (15:35 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 27 Jan 2014 14:20:58 +0000 (15:20 +0100)
This patch introduces a new API for outputs that log based on the
packet, such as alert outputs. In converts fast-log to the new API.

The API gets rid of the concept of each logger being a thread module,
but instead there is one thread module that runs all packet loggers.
Through the registration function OutputRegisterPacketModule a log
module can register itself to be considered for each packet.

Each logger registers itself to this new API with 2 functions and the
OutputCtx object that was already used in the old implementation.
The function pointers are:

LogFunc:       the log function

ConditionFunc: this function is called before the LogFunc and only
               if this returns TRUE the LogFunc is called.

For a simple alert logger like fast-log, the condition function will
simply return TRUE if p->alerts.cnt > 0.

src/Makefile.am
src/alert-fastlog.c
src/output-packet.c [new file with mode: 0644]
src/output-packet.h [new file with mode: 0644]
src/output.c
src/output.h
src/runmodes.c
src/suricata.c
src/tm-threads-common.h

index 39bc612ae01da80f48cfed30f9a0ff368a7ded27..5737ad86d2f0c5b244537d404e9a96193ff15fff 100644 (file)
@@ -214,6 +214,7 @@ log-httplog.c log-httplog.h \
 log-pcap.c log-pcap.h \
 log-tlslog.c log-tlslog.h \
 output.c output.h \
+output-packet.c output-packet.h \
 packet-queue.c packet-queue.h \
 pkt-var.c pkt-var.h \
 reputation.c reputation.h \
index fe9a42c2372cd5618dfad0e3ff39d5df7b47fc99..425c2794ddddb2317dcac384276b33a50bac7fc4 100644 (file)
@@ -71,34 +71,19 @@ void AlertFastLogExitPrintStats(ThreadVars *, void *);
 void AlertFastLogRegisterTests(void);
 static void AlertFastLogDeInitCtx(OutputCtx *);
 
+int AlertFastLogCondition(ThreadVars *tv, const Packet *p);
+int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p);
+
 void TmModuleAlertFastLogRegister (void) {
     tmm_modules[TMM_ALERTFASTLOG].name = MODULE_NAME;
     tmm_modules[TMM_ALERTFASTLOG].ThreadInit = AlertFastLogThreadInit;
-    tmm_modules[TMM_ALERTFASTLOG].Func = AlertFastLog;
     tmm_modules[TMM_ALERTFASTLOG].ThreadExitPrintStats = AlertFastLogExitPrintStats;
     tmm_modules[TMM_ALERTFASTLOG].ThreadDeinit = AlertFastLogThreadDeinit;
     tmm_modules[TMM_ALERTFASTLOG].RegisterTests = AlertFastLogRegisterTests;
     tmm_modules[TMM_ALERTFASTLOG].cap_flags = 0;
 
-    OutputRegisterModule(MODULE_NAME, "fast", AlertFastLogInitCtx);
-}
-
-void TmModuleAlertFastLogIPv4Register (void) {
-    tmm_modules[TMM_ALERTFASTLOG4].name = "AlertFastLogIPv4";
-    tmm_modules[TMM_ALERTFASTLOG4].ThreadInit = AlertFastLogThreadInit;
-    tmm_modules[TMM_ALERTFASTLOG4].Func = AlertFastLogIPv4;
-    tmm_modules[TMM_ALERTFASTLOG4].ThreadExitPrintStats = AlertFastLogExitPrintStats;
-    tmm_modules[TMM_ALERTFASTLOG4].ThreadDeinit = AlertFastLogThreadDeinit;
-    tmm_modules[TMM_ALERTFASTLOG4].RegisterTests = NULL;
-}
-
-void TmModuleAlertFastLogIPv6Register (void) {
-    tmm_modules[TMM_ALERTFASTLOG6].name = "AlertFastLogIPv6";
-    tmm_modules[TMM_ALERTFASTLOG6].ThreadInit = AlertFastLogThreadInit;
-    tmm_modules[TMM_ALERTFASTLOG6].Func = AlertFastLogIPv6;
-    tmm_modules[TMM_ALERTFASTLOG6].ThreadExitPrintStats = AlertFastLogExitPrintStats;
-    tmm_modules[TMM_ALERTFASTLOG6].ThreadDeinit = AlertFastLogThreadDeinit;
-    tmm_modules[TMM_ALERTFASTLOG6].RegisterTests = NULL;
+    OutputRegisterPacketModule(MODULE_NAME, "fast",
+            AlertFastLogInitCtx, AlertFastLogger, AlertFastLogCondition);
 }
 
 typedef struct AlertFastLogThread_ {
@@ -106,75 +91,34 @@ typedef struct AlertFastLogThread_ {
     LogFileCtx* file_ctx;
 } AlertFastLogThread;
 
-TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
-{
-    AlertFastLogThread *aft = (AlertFastLogThread *)data;
-    int i;
-    char timebuf[64];
-    char *action = "";
-    extern uint8_t engine_mode;
-
-    if (p->alerts.cnt == 0)
-        return TM_ECODE_OK;
-
-    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
-
-    char srcip[16], dstip[16];
-    PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
-    PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
-
-    for (i = 0; i < p->alerts.cnt; i++) {
-        PacketAlert *pa = &p->alerts.alerts[i];
-        if (unlikely(pa->s == NULL)) {
-            continue;
-        }
-
-        if ((pa->action & ACTION_DROP) && IS_ENGINE_MODE_IPS(engine_mode)) {
-            action = "[Drop] ";
-        } else if (pa->action & ACTION_DROP) {
-            action = "[wDrop] ";
-        }
-
-        char proto[16] = "";
-        if (SCProtoNameValid(IPV4_GET_IPPROTO(p)) == TRUE) {
-            strlcpy(proto, known_proto[IPV4_GET_IPPROTO(p)], sizeof(proto));
-        } else {
-            snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IPV4_GET_IPPROTO(p));
-        }
-
-        SCMutexLock(&aft->file_ctx->fp_mutex);
-        fprintf(aft->file_ctx->fp, "%s  %s[**] [%" PRIu32 ":%" PRIu32 ":%"
-                PRIu32 "] %s [**] [Classification: %s] [Priority: %"PRIu32"]"
-                " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, action,
-                pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
-                proto, srcip, p->sp, dstip, p->dp);
-        fflush(aft->file_ctx->fp);
-        aft->file_ctx->alerts++;
-        SCMutexUnlock(&aft->file_ctx->fp_mutex);
-    }
-
-    return TM_ECODE_OK;
+int AlertFastLogCondition(ThreadVars *tv, const Packet *p) {
+    return (p->alerts.cnt ? TRUE : FALSE);
 }
 
-TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
+int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p)
 {
     AlertFastLogThread *aft = (AlertFastLogThread *)data;
     int i;
     char timebuf[64];
     char *action = "";
     extern uint8_t engine_mode;
-
-    if (p->alerts.cnt == 0)
-        return TM_ECODE_OK;
+    int decoder_event = 0;
 
     CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
 
     char srcip[46], dstip[46];
-    PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
-    PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
+    if (PKT_IS_IPV4(p)) {
+        PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
+        PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
+    } else if (PKT_IS_IPV6(p)) {
+        PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
+        PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
+    } else {
+        decoder_event = 1;
+    }
 
     for (i = 0; i < p->alerts.cnt; i++) {
-        PacketAlert *pa = &p->alerts.alerts[i];
+        const PacketAlert *pa = &p->alerts.alerts[i];
         if (unlikely(pa->s == NULL)) {
             continue;
         }
@@ -186,67 +130,33 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
         }
 
         char proto[16] = "";
-        if (SCProtoNameValid(IP_GET_IPPROTO(p)) == TRUE) {
-            strlcpy(proto, known_proto[IP_GET_IPPROTO(p)], sizeof(proto));
-        } else {
-            snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IP_GET_IPPROTO(p));
-        }
-
-        SCMutexLock(&aft->file_ctx->fp_mutex);
-        fprintf(aft->file_ctx->fp, "%s  %s[**] [%" PRIu32 ":%" PRIu32 ":%"
-                PRIu32 "] %s [**] [Classification: %s] [Priority: %"
-                PRIu32 "] {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf,
-                action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
-                pa->s->prio, proto, srcip, p->sp,
-                dstip, p->dp);
-
-        fflush(aft->file_ctx->fp);
-        aft->file_ctx->alerts++;
-        SCMutexUnlock(&aft->file_ctx->fp_mutex);
-    }
-
-    return TM_ECODE_OK;
-}
-
-TmEcode AlertFastLogDecoderEvent(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
-{
-    AlertFastLogThread *aft = (AlertFastLogThread *)data;
-    int i;
-    char timebuf[64];
-    char *action = "";
-    extern uint8_t engine_mode;
-
-    if (p->alerts.cnt == 0)
-        return TM_ECODE_OK;
-
-    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
-
-    for (i = 0; i < p->alerts.cnt; i++) {
-        PacketAlert *pa = &p->alerts.alerts[i];
-        if (unlikely(pa->s == NULL)) {
-            continue;
-        }
-
-        if ((pa->action & ACTION_DROP) && IS_ENGINE_MODE_IPS(engine_mode)) {
-            action = "[Drop] ";
-        } else if (pa->action & ACTION_DROP) {
-            action = "[wDrop] ";
+        if (likely(decoder_event == 0)) {
+            if (SCProtoNameValid(IP_GET_IPPROTO(p)) == TRUE) {
+                strlcpy(proto, known_proto[IP_GET_IPPROTO(p)], sizeof(proto));
+            } else {
+                snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IP_GET_IPPROTO(p));
+            }
         }
 
         SCMutexLock(&aft->file_ctx->fp_mutex);
-        fprintf(aft->file_ctx->fp, "%s  %s[**] [%" PRIu32 ":%" PRIu32
-                ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: "
-                "%" PRIu32 "] [**] [Raw pkt: ", timebuf, action, pa->s->gid,
-                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio);
-
-        PrintRawLineHexFp(aft->file_ctx->fp, GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32);
-
-        if (p->pcap_cnt != 0) {
-            fprintf(aft->file_ctx->fp, "] [pcap file packet: %"PRIu64"]\n", p->pcap_cnt);
+        if (likely(decoder_event == 0)) {
+            fprintf(aft->file_ctx->fp, "%s  %s[**] [%" PRIu32 ":%" PRIu32 ":%"
+                    PRIu32 "] %s [**] [Classification: %s] [Priority: %"PRIu32"]"
+                    " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, action,
+                    pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
+                    proto, srcip, p->sp, dstip, p->dp);
         } else {
-            fprintf(aft->file_ctx->fp, "]\n");
+            fprintf(aft->file_ctx->fp, "%s  %s[**] [%" PRIu32 ":%" PRIu32
+                    ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: "
+                    "%" PRIu32 "] [**] [Raw pkt: ", timebuf, action, pa->s->gid,
+                    pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio);
+            PrintRawLineHexFp(aft->file_ctx->fp, GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32);
+            if (p->pcap_cnt != 0) {
+                fprintf(aft->file_ctx->fp, "] [pcap file packet: %"PRIu64"]\n", p->pcap_cnt);
+            } else {
+                fprintf(aft->file_ctx->fp, "]\n");
+            }
         }
-
         fflush(aft->file_ctx->fp);
         aft->file_ctx->alerts++;
         SCMutexUnlock(&aft->file_ctx->fp_mutex);
@@ -255,18 +165,6 @@ TmEcode AlertFastLogDecoderEvent(ThreadVars *tv, Packet *p, void *data, PacketQu
     return TM_ECODE_OK;
 }
 
-TmEcode AlertFastLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
-{
-    if (PKT_IS_IPV4(p)) {
-        return AlertFastLogIPv4(tv, p, data, pq, postpq);
-    } else if (PKT_IS_IPV6(p)) {
-        return AlertFastLogIPv6(tv, p, data, pq, postpq);
-    } else if (p->events.cnt > 0) {
-        return AlertFastLogDecoderEvent(tv, p, data, pq, postpq);
-    }
-
-    return TM_ECODE_OK;
-}
 
 TmEcode AlertFastLogThreadInit(ThreadVars *t, void *initdata, void **data)
 {
diff --git a/src/output-packet.c b/src/output-packet.c
new file mode 100644 (file)
index 0000000..aa8daf9
--- /dev/null
@@ -0,0 +1,214 @@
+/* Copyright (C) 2007-2013 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * Packet Logger Output registration functions
+ */
+
+#include "suricata-common.h"
+#include "tm-modules.h"
+#include "output-packet.h"
+
+typedef struct OutputLoggerThreadStore_ {
+    void *thread_data;
+    struct OutputLoggerThreadStore_ *next;
+} OutputLoggerThreadStore;
+
+/** per thread data for this module, contains a list of per thread
+ *  data for the packet loggers. */
+typedef struct OutputLoggerThreadData_ {
+    OutputLoggerThreadStore *store;
+} OutputLoggerThreadData;
+
+/* logger instance, a module + a output ctx,
+ * it's perfectly valid that have multiple instances of the same
+ * log module (e.g. fast.log) with different output ctx'. */
+typedef struct OutputPacketLogger_ {
+    PacketLogger LogFunc;
+    PacketLogCondition ConditionFunc;
+    OutputCtx *output_ctx;
+    struct OutputPacketLogger_ *next;
+    const char *name;
+} OutputPacketLogger;
+
+static OutputPacketLogger *list = NULL;
+
+int OutputRegisterPacketLogger(char *name, PacketLogger LogFunc, PacketLogCondition ConditionFunc, OutputCtx *output_ctx) {
+    OutputPacketLogger *op = SCMalloc(sizeof(*op));
+    if (op == NULL)
+        return -1;
+    memset(op, 0x00, sizeof(*op));
+
+    op->LogFunc = LogFunc;
+    op->ConditionFunc = ConditionFunc;
+    op->output_ctx = output_ctx;
+    op->name = SCStrdup(name);
+    if (op->name == NULL) {
+        SCFree(op);
+        return -1;
+    }
+
+    if (list == NULL)
+        list = op;
+    else {
+        OutputPacketLogger *t = list;
+        while (t->next)
+            t = t->next;
+        t->next = op;
+    }
+
+    SCLogDebug("OutputRegisterPacketLogger happy");
+    return 0;
+}
+
+static TmEcode OutputPacketLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQueue *pq, PacketQueue *postpq) {
+    BUG_ON(thread_data == NULL);
+    BUG_ON(list == NULL);
+
+    OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
+    OutputPacketLogger *logger = list;
+    OutputLoggerThreadStore *store = op_thread_data->store;
+
+    BUG_ON(logger == NULL && store != NULL);
+    BUG_ON(logger != NULL && store == NULL);
+    BUG_ON(logger == NULL && store == NULL);
+
+    while (logger && store) {
+        BUG_ON(logger->LogFunc == NULL || logger->ConditionFunc == NULL);
+
+        if ((logger->ConditionFunc(tv, (const Packet *)p)) == TRUE) {
+            logger->LogFunc(tv, store->thread_data, (const Packet *)p);
+        }
+
+        logger = logger->next;
+        store = store->next;
+
+        BUG_ON(logger == NULL && store != NULL);
+        BUG_ON(logger != NULL && store == NULL);
+    }
+
+    return TM_ECODE_OK;
+}
+
+/** \brief thread init for the packet logger
+ *  This will run the thread init functions for the individual registered
+ *  loggers */
+static TmEcode OutputPacketLogThreadInit(ThreadVars *tv, void *initdata, void **data) {
+    OutputLoggerThreadData *td = SCMalloc(sizeof(*td));
+    if (td == NULL)
+        return TM_ECODE_FAILED;
+    memset(td, 0x00, sizeof(*td));
+
+    *data = (void *)td;
+
+    SCLogDebug("OutputPacketLogThreadInit happy (*data %p)", *data);
+
+    OutputPacketLogger *logger = list;
+    while (logger) {
+        TmModule *tm_module = TmModuleGetByName((char *)logger->name);
+        if (tm_module == NULL) {
+            SCLogError(SC_ERR_INVALID_ARGUMENT,
+                    "TmModuleGetByName for %s failed", logger->name);
+            exit(EXIT_FAILURE);
+        }
+
+        if (tm_module->ThreadInit) {
+            void *retptr = NULL;
+            if (tm_module->ThreadInit(tv, (void *)logger->output_ctx, &retptr) == TM_ECODE_OK) {
+                OutputLoggerThreadStore *ts = SCMalloc(sizeof(*ts));
+/* todo */      BUG_ON(ts == NULL);
+                memset(ts, 0x00, sizeof(*ts));
+
+                /* store thread handle */
+                ts->thread_data = retptr;
+
+                if (td->store == NULL) {
+                    td->store = ts;
+                } else {
+                    OutputLoggerThreadStore *tmp = td->store;
+                    while (tmp->next != NULL)
+                        tmp = tmp->next;
+                    tmp->next = ts;
+                }
+
+                SCLogDebug("%s is now set up", logger->name);
+            }
+        }
+
+        logger = logger->next;
+    }
+
+    return TM_ECODE_OK;
+}
+
+static TmEcode OutputPacketLogThreadDeinit(ThreadVars *tv, void *thread_data) {
+    OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
+    OutputLoggerThreadStore *store = op_thread_data->store;
+    OutputPacketLogger *logger = list;
+
+    while (logger && store) {
+        TmModule *tm_module = TmModuleGetByName((char *)logger->name);
+        if (tm_module == NULL) {
+            SCLogError(SC_ERR_INVALID_ARGUMENT,
+                    "TmModuleGetByName for %s failed", logger->name);
+            exit(EXIT_FAILURE);
+        }
+
+        if (tm_module->ThreadDeinit) {
+            tm_module->ThreadDeinit(tv, store->thread_data);
+        }
+
+        logger = logger->next;
+        store = store->next;
+    }
+    return TM_ECODE_OK;
+}
+
+static void OutputPacketLogExitPrintStats(ThreadVars *tv, void *thread_data) {
+    OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
+    OutputLoggerThreadStore *store = op_thread_data->store;
+    OutputPacketLogger *logger = list;
+
+    while (logger && store) {
+        TmModule *tm_module = TmModuleGetByName((char *)logger->name);
+        if (tm_module == NULL) {
+            SCLogError(SC_ERR_INVALID_ARGUMENT,
+                    "TmModuleGetByName for %s failed", logger->name);
+            exit(EXIT_FAILURE);
+        }
+
+        if (tm_module->ThreadExitPrintStats) {
+            tm_module->ThreadExitPrintStats(tv, store->thread_data);
+        }
+
+        logger = logger->next;
+        store = store->next;
+    }
+}
+
+void TmModulePacketLoggerRegister (void) {
+    tmm_modules[TMM_PACKETLOGGER].name = "__packet_logger__";
+    tmm_modules[TMM_PACKETLOGGER].ThreadInit = OutputPacketLogThreadInit;
+    tmm_modules[TMM_PACKETLOGGER].Func = OutputPacketLog;
+    tmm_modules[TMM_PACKETLOGGER].ThreadExitPrintStats = OutputPacketLogExitPrintStats;
+    tmm_modules[TMM_PACKETLOGGER].ThreadDeinit = OutputPacketLogThreadDeinit;
+    tmm_modules[TMM_PACKETLOGGER].cap_flags = 0;
+}
diff --git a/src/output-packet.h b/src/output-packet.h
new file mode 100644 (file)
index 0000000..42e524c
--- /dev/null
@@ -0,0 +1,44 @@
+/* Copyright (C) 2007-2013 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * Packet Logger Output registration functions
+ */
+
+#ifndef __OUTPUT_PACKET_H__
+#define __OUTPUT_PACKET_H__
+
+#include "decode.h"
+
+/** packet logger function pointer type */
+typedef int (*PacketLogger)(ThreadVars *, void *thread_data, const Packet *);
+
+/** packet logger condition function pointer type,
+ *  must return true for packets that should be logged
+ */
+typedef int (*PacketLogCondition)(ThreadVars *, const Packet *);
+
+int OutputRegisterPacketLogger(char *name, PacketLogger LogFunc,
+        PacketLogCondition ConditionFunc, OutputCtx *);
+
+void TmModulePacketLoggerRegister (void);
+
+#endif /* __OUTPUT_PACKET_H__ */
index 5010672023a65a017d423e71549fb42b1b1c4996..ea01aa5cb86b7fdbae2e33acb18506e46429e3b9 100644 (file)
@@ -68,6 +68,46 @@ error:
     exit(EXIT_FAILURE);
 }
 
+/**
+ * \brief Register a packet 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
+OutputRegisterPacketModule(char *name, char *conf_name,
+    OutputCtx *(*InitFunc)(ConfNode *),
+    PacketLogger PacketLogFunc, PacketLogCondition PacketConditionFunc)
+{
+    if (unlikely(PacketLogFunc == NULL || PacketConditionFunc == NULL)) {
+        goto error;
+    }
+
+    OutputModule *module = SCCalloc(1, sizeof(*module));
+    if (unlikely(module == NULL)) {
+        goto error;
+    }
+
+    module->name = SCStrdup(name);
+    if (unlikely(module->name == NULL))
+        goto error;
+    module->conf_name = SCStrdup(conf_name);
+    if (unlikely(module->conf_name == NULL))
+        goto error;
+    module->InitFunc = InitFunc;
+    module->PacketLogFunc = PacketLogFunc;
+    module->PacketConditionFunc = PacketConditionFunc;
+    TAILQ_INSERT_TAIL(&output_modules, module, entries);
+
+    SCLogDebug("Packet logger \"%s\" registered.", name);
+    return;
+error:
+    SCLogError(SC_ERR_FATAL, "Fatal error encountered. Exiting...");
+    exit(EXIT_FAILURE);
+}
+
 /**
  * \brief Get an output module by name.
  *
index ba47dca2941b8738196776decee2abc9c5e9a189..d8604ca94ef3cbc6123b7e5eb62470cea6c212c7 100644 (file)
 #define DEFAULT_LOG_MODE_APPEND     "yes"
 #define DEFAULT_LOG_FILETYPE        "regular"
 
+#include "output-packet.h"
+
 typedef struct OutputModule_ {
     char *name;
     char *conf_name;
     OutputCtx *(*InitFunc)(ConfNode *);
 
+    PacketLogger PacketLogFunc;
+    PacketLogCondition PacketConditionFunc;
+
     TAILQ_ENTRY(OutputModule_) entries;
 } OutputModule;
 
 void OutputRegisterModule(char *, char *, OutputCtx *(*)(ConfNode *));
+
+void OutputRegisterPacketModule(char *name, char *conf_name,
+    OutputCtx *(*InitFunc)(ConfNode *),
+    PacketLogger LogFunc, PacketLogCondition ConditionFunc);
+
 OutputModule *OutputGetModuleByConfName(char *name);
 void OutputDeregisterAll(void);
 
index c394ae19d22cfe740386e6108c3d443f40834b50..e4398b5c3e70eb72e651b05a70ab462f9f6812bb 100644 (file)
@@ -423,6 +423,7 @@ void RunModeInitializeOutputs(void)
 
     ConfNode *output, *output_config;
     TmModule *tm_module;
+    TmModule *pkt_logger_module = NULL;
     const char *enabled;
 
     TAILQ_FOREACH(output, &outputs->head, next) {
@@ -466,7 +467,6 @@ void RunModeInitializeOutputs(void)
                 "No output module named %s, ignoring", output->val);
             continue;
         }
-
         OutputCtx *output_ctx = NULL;
         if (module->InitFunc != NULL) {
             output_ctx = module->InitFunc(output_config);
@@ -485,12 +485,39 @@ void RunModeInitializeOutputs(void)
         if (strcmp(tmm_modules[TMM_ALERTDEBUGLOG].name, tm_module->name) == 0)
             debuglog_enabled = 1;
 
-        RunModeOutput *runmode_output = SCCalloc(1, sizeof(RunModeOutput));
-        if (unlikely(runmode_output == NULL))
-            return;
-        runmode_output->tm_module = tm_module;
-        runmode_output->output_ctx = output_ctx;
-        TAILQ_INSERT_TAIL(&RunModeOutputs, runmode_output, entries);
+        if (module->PacketLogFunc) {
+            SCLogDebug("%s is a packet logger", module->name);
+            OutputRegisterPacketLogger(module->name, module->PacketLogFunc,
+                    module->PacketConditionFunc, output_ctx);
+
+            /* need one instance of the packet logger module */
+            if (pkt_logger_module == NULL) {
+                pkt_logger_module = TmModuleGetByName("__packet_logger__");
+                if (pkt_logger_module == NULL) {
+                    SCLogError(SC_ERR_INVALID_ARGUMENT,
+                            "TmModuleGetByName for __packet_logger__ failed");
+                    exit(EXIT_FAILURE);
+                }
+
+                RunModeOutput *runmode_output = SCCalloc(1, sizeof(RunModeOutput));
+                if (unlikely(runmode_output == NULL))
+                    return;
+                runmode_output->tm_module = pkt_logger_module;
+                runmode_output->output_ctx = NULL;
+                TAILQ_INSERT_TAIL(&RunModeOutputs, runmode_output, entries);
+                SCLogDebug("__packet_logger__ added");
+            }
+
+        } else {
+            SCLogDebug("%s is a regular logger", module->name);
+
+            RunModeOutput *runmode_output = SCCalloc(1, sizeof(RunModeOutput));
+            if (unlikely(runmode_output == NULL))
+                return;
+            runmode_output->tm_module = tm_module;
+            runmode_output->output_ctx = output_ctx;
+            TAILQ_INSERT_TAIL(&RunModeOutputs, runmode_output, entries);
+        }
     }
 }
 
index fd529ece90f25df8b05d1420b113efe108fb4760..c81c6e4c5c6c077b5b94fe91bfbeefb0c4a93cc9 100644 (file)
 #include "reputation.h"
 
 #include "output.h"
+#include "output-packet.h"
 #include "util-privs.h"
 
 #include "tmqh-packetpool.h"
@@ -774,8 +775,6 @@ void RegisterAllModules()
 
     /* fast log */
     TmModuleAlertFastLogRegister();
-    TmModuleAlertFastLogIPv4Register();
-    TmModuleAlertFastLogIPv6Register();
     /* debug log */
     TmModuleAlertDebugLogRegister();
     /* prelue log */
@@ -804,7 +803,7 @@ void RegisterAllModules()
     TmModuleLogFilestoreRegister();
     /* dns log */
     TmModuleLogDnsLogRegister();
-    /* cuda */
+    TmModulePacketLoggerRegister();
     TmModuleDebugList();
 
 }
index a7e8ad7638caee03364532e672754b8ef94af796..bb50770ac553869da721e9b097378f5211d1d079 100644 (file)
@@ -79,6 +79,7 @@ typedef enum {
 #endif
     TMM_RECEIVENAPATECH,
     TMM_DECODENAPATECH,
+    TMM_PACKETLOGGER,
     TMM_SIZE,
 } TmmId;