]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
log/pcap: conditional logging
authorEric Leblond <eric@regit.org>
Sun, 1 Nov 2020 08:54:47 +0000 (09:54 +0100)
committerVictor Julien <vjulien@oisf.net>
Thu, 26 May 2022 10:45:15 +0000 (12:45 +0200)
Add an option to only write to pcap packets with alerts and flow
that have alerted.

13 files changed:
src/alert-debuglog.c
src/alert-fastlog.c
src/alert-syslog.c
src/log-pcap.c
src/output-json-alert.c
src/output-json-anomaly.c
src/output-json-drop.c
src/output-json-frame.c
src/output-json-metadata.c
src/output-lua.c
src/output-packet.c
src/output-packet.h
suricata.yaml.in

index 8a20a8b5aca601561ceae81fd53d687d82d6d636..a272740dd02e779faf29b45c8f16bbe969261efe 100644 (file)
@@ -468,7 +468,7 @@ error:
     return result;
 }
 
-static int AlertDebugLogCondition(ThreadVars *tv, const Packet *p)
+static int AlertDebugLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
     return (p->alerts.cnt ? TRUE : FALSE);
 }
index 8a07f29822355f0bda2a2d3fb8f0cff046276881..5800ea3075e6e2ca1b89ac28f6cc85c03f02bcf8 100644 (file)
@@ -69,7 +69,7 @@ TmEcode AlertFastLogThreadDeinit(ThreadVars *, void *);
 void AlertFastLogRegisterTests(void);
 static void AlertFastLogDeInitCtx(OutputCtx *);
 
-int AlertFastLogCondition(ThreadVars *tv, const Packet *p);
+int AlertFastLogCondition(ThreadVars *tv, void *thread_data, const Packet *p);
 int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p);
 
 void AlertFastLogRegister(void)
@@ -85,7 +85,7 @@ typedef struct AlertFastLogThread_ {
     LogFileCtx* file_ctx;
 } AlertFastLogThread;
 
-int AlertFastLogCondition(ThreadVars *tv, const Packet *p)
+int AlertFastLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
     return (p->alerts.cnt ? TRUE : FALSE);
 }
index 6307d982d67726509757aeb876d30904cc07796f..bba155c8edf7422e78d90c594d4867d0bd6d6f89 100644 (file)
@@ -367,7 +367,7 @@ static TmEcode AlertSyslogDecoderEvent(ThreadVars *tv, const Packet *p, void *da
     return TM_ECODE_OK;
 }
 
-static int AlertSyslogCondition(ThreadVars *tv, const Packet *p)
+static int AlertSyslogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
     return (p->alerts.cnt > 0 ? TRUE : FALSE);
 }
index a7a5ccd8c4d27fb6b7b06eb719e24b76f194dc26..3c44d3fd2b98f8fa9b30eb4e8f7fdb600af5ee03 100644 (file)
 #define LOGMODE_SGUIL                   1
 #define LOGMODE_MULTI                   2
 
+typedef enum LogModeConditionalType_ {
+    LOGMODE_COND_ALL,
+    LOGMODE_COND_ALERTS
+} LogModeConditionalType;
+
 #define RING_BUFFER_MODE_DISABLED       0
 #define RING_BUFFER_MODE_ENABLED        1
 
@@ -155,6 +160,8 @@ typedef struct PcapLogData_ {
     uint64_t profile_data_size; /**< track in bytes how many bytes we wrote */
     uint32_t file_cnt;          /**< count of pcap files we currently have */
     uint32_t max_files;         /**< maximum files to use in ring buffer mode */
+    LogModeConditionalType
+            conditional; /**< log all packets or just packets and flows with alerts */
 
     PcapLogProfileData profile_lock;
     PcapLogProfileData profile_write;
@@ -200,7 +207,7 @@ static TmEcode PcapLogDataDeinit(ThreadVars *, void *);
 static void PcapLogFileDeInitCtx(OutputCtx *);
 static OutputInitResult PcapLogInitCtx(ConfNode *);
 static void PcapLogProfilingDump(PcapLogData *);
-static int PcapLogCondition(ThreadVars *, const Packet *);
+static int PcapLogCondition(ThreadVars *, void *, const Packet *);
 
 void PcapLogRegister(void)
 {
@@ -220,14 +227,24 @@ void PcapLogRegister(void)
     (prof).total += (UtilCpuGetTicks() - pcaplog_profile_ticks); \
     (prof).cnt++
 
-static int PcapLogCondition(ThreadVars *tv, const Packet *p)
+static int PcapLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
+    PcapLogThreadData *ptd = (PcapLogThreadData *)thread_data;
+
     if (p->flags & PKT_PSEUDO_STREAM_END) {
         return FALSE;
     }
     if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
         return FALSE;
     }
+    /* Log alerted flow */
+    if (ptd->pcap_log->conditional == LOGMODE_COND_ALERTS) {
+        if (p->alerts.cnt || (p->flow && FlowHasAlerts(p->flow))) {
+            return TRUE;
+        } else {
+            return FALSE;
+        }
+    }
     return TRUE;
 }
 
@@ -630,6 +647,7 @@ static PcapLogData *PcapLogDataCopy(const PcapLogData *pl)
     copy->timestamp_format = pl->timestamp_format;
     copy->use_stream_depth = pl->use_stream_depth;
     copy->size_limit = pl->size_limit;
+    copy->conditional = pl->conditional;
 
     const PcapLogCompressionData *comp = &pl->compression;
     PcapLogCompressionData *copy_comp = &copy->compression;
@@ -1194,6 +1212,7 @@ static OutputInitResult PcapLogInitCtx(ConfNode *conf)
     pl->timestamp_format = TS_FORMAT_SEC;
     pl->use_stream_depth = USE_STREAM_DEPTH_DISABLED;
     pl->honor_pass_rules = HONOR_PASS_RULES_DISABLED;
+    pl->conditional = LOGMODE_COND_ALL;
 
     TAILQ_INIT(&pl->pcap_file_list);
 
@@ -1416,6 +1435,21 @@ static OutputInitResult PcapLogInitCtx(ConfNode *conf)
 
         SCLogInfo("Selected pcap-log compression method: %s",
                 compression_str ? compression_str : "none");
+
+        const char *s_conditional = ConfNodeLookupChildValue(conf, "conditional");
+        if (s_conditional != NULL) {
+            if (strcasecmp(s_conditional, "alerts") == 0) {
+                pl->conditional = LOGMODE_COND_ALERTS;
+            } else if (strcasecmp(s_conditional, "all") != 0) {
+                FatalError(SC_ERR_INVALID_ARGUMENT,
+                        "log-pcap: invalid conditional \"%s\". Valid options: \"all\", "
+                        "or \"alerts\" mode ",
+                        s_conditional);
+            }
+        }
+
+        SCLogInfo(
+                "Selected pcap-log conditional logging: %s", s_conditional ? s_conditional : "all");
     }
 
     if (ParseFilename(pl, filename) != 0)
index feafebaf3483bd2c0a21032dc6dad70a73637f98..3f32692d964a45f3d36c76091cb3f9cd105320f1 100644 (file)
@@ -836,7 +836,7 @@ static int JsonAlertLogger(ThreadVars *tv, void *thread_data, const Packet *p)
     return 0;
 }
 
-static int JsonAlertLogCondition(ThreadVars *tv, const Packet *p)
+static int JsonAlertLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
     if (p->alerts.cnt || (p->flags & PKT_HAS_TAG)) {
         return TRUE;
index 7864f8fe5681df033fb5f882a00b578835aa8dfb..c2f9f9709e3e474d72ae62690010512ec77d70e1 100644 (file)
@@ -280,7 +280,7 @@ static int JsonAnomalyLogger(ThreadVars *tv, void *thread_data, const Packet *p)
     return AnomalyJson(tv, aft, p);
 }
 
-static int JsonAnomalyLogCondition(ThreadVars *tv, const Packet *p)
+static int JsonAnomalyLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
     return p->events.cnt > 0 ||
            (p->app_layer_events && p->app_layer_events->cnt > 0) ||
index b2b5925e0a63e8e639f08b11ade750de51fb298f..bd10f49e33d23251c5aaeac4a34c8dd039a540c7 100644 (file)
@@ -324,7 +324,7 @@ static int JsonDropLogger(ThreadVars *tv, void *thread_data, const Packet *p)
  *
  * \retval bool TRUE or FALSE
  */
-static int JsonDropLogCondition(ThreadVars *tv, const Packet *p)
+static int JsonDropLogCondition(ThreadVars *tv, void *data, const Packet *p)
 {
     if (!EngineModeIsIPS()) {
         SCLogDebug("engine is not running in inline mode, so returning");
index ac2bcce0e43a4738d876ceca2d5352652f415b1e..76e0475446b8c5ccb8630d7c8e3e17c34013c849 100644 (file)
@@ -368,7 +368,7 @@ static int JsonFrameLogger(ThreadVars *tv, void *thread_data, const Packet *p)
     return FrameJson(tv, aft, p);
 }
 
-static int JsonFrameLogCondition(ThreadVars *tv, const Packet *p)
+static int JsonFrameLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
 {
     if (p->flow == NULL || p->flow->alproto == ALPROTO_UNKNOWN)
         return FALSE;
index 62583dfcdfd3419a676aa472c52ded79366edc2f..6ec943ddd5b6b7d70cb74b73030d56ad22646b44 100644 (file)
@@ -88,7 +88,7 @@ static int JsonMetadataLogger(ThreadVars *tv, void *thread_data, const Packet *p
     return MetadataJson(tv, aft, p);
 }
 
-static int JsonMetadataLogCondition(ThreadVars *tv, const Packet *p)
+static int JsonMetadataLogCondition(ThreadVars *tv, void *data, const Packet *p)
 {
     if (p->pktvar) {
         return TRUE;
index 09bafc5ac39cc9b1a944e1c3d43bc9c5afe29649..8e1ae3c7e05fe98b9f3c4fc55f03fb68952fff2b 100644 (file)
@@ -230,7 +230,7 @@ not_supported:
     SCReturnInt(0);
 }
 
-static int LuaPacketConditionAlerts(ThreadVars *tv, const Packet *p)
+static int LuaPacketConditionAlerts(ThreadVars *tv, void *data, const Packet *p)
 {
     if (p->alerts.cnt > 0)
         return TRUE;
@@ -280,7 +280,7 @@ not_supported:
     SCReturnInt(0);
 }
 
-static int LuaPacketCondition(ThreadVars *tv, const Packet *p)
+static int LuaPacketCondition(ThreadVars *tv, void *data, const Packet *p)
 {
     return TRUE;
 }
index 8a5e851cfc22cf46eb6eaecbbba0323a3b8e975c..c7b509520d152002f7851954323ce7c0458ba291 100644 (file)
@@ -106,7 +106,7 @@ static TmEcode OutputPacketLog(ThreadVars *tv, Packet *p, void *thread_data)
     while (logger && store) {
         DEBUG_VALIDATE_BUG_ON(logger->LogFunc == NULL || logger->ConditionFunc == NULL);
 
-        if ((logger->ConditionFunc(tv, (const Packet *)p)) == TRUE) {
+        if ((logger->ConditionFunc(tv, store->thread_data, (const Packet *)p)) == TRUE) {
             PACKET_PROFILING_LOGGER_START(p, logger->logger_id);
             logger->LogFunc(tv, store->thread_data, (const Packet *)p);
             PACKET_PROFILING_LOGGER_END(p, logger->logger_id);
index da40ccde47c1e6f5b956643efbfa9948f22e2bf4..d51f8554537583d89a5bc490f3066e9172c99da8 100644 (file)
@@ -35,7 +35,7 @@ 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 *);
+typedef int (*PacketLogCondition)(ThreadVars *, void *thread_data, const Packet *);
 
 int OutputRegisterPacketLogger(LoggerId logger_id, const char *name,
     PacketLogger LogFunc, PacketLogCondition ConditionFunc, OutputCtx *,
index 1876adaf87d119eb9052ed7c380af2c87d4104e9..280c8791bb0b9dfcb44f5a7df597ab373ec07d7d 100644 (file)
@@ -402,6 +402,8 @@ outputs:
       #ts-format: usec # sec or usec second format (default) is filename.sec usec is filename.sec.usec
       use-stream-depth: no #If set to "yes" packets seen after reaching stream inspection depth are ignored. "no" logs all packets
       honor-pass-rules: no # If set to "yes", flows in which a pass rule matched will stop being logged.
+      # Use "all" to log all packets or use "alerts" to log only alerted packets and flows
+      #conditional: all
 
   # a full alert log containing much information for signature writers
   # or for investigating suspected false positives.