]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
flow/timeout: flag last pseudo packet
authorVictor Julien <victor@inliniac.net>
Fri, 3 Jul 2020 12:42:48 +0000 (14:42 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 28 Jul 2020 09:34:32 +0000 (11:34 +0200)
Flag the last flow timeout pseudo packet so that we can force
TX logging w/o setting both app-layer flags.

Case this fixes:

1. flow times out when only TS TCP data received, but non of it is ACK'd.
   So there is no app-layer proto yet, or app state or Flow::alparser. So
   EOF flags can't be set.

2. Flow timeout sees no reason to create pseudo packet in TC direction.

3. TS pseudo packet finds HTTP, creates HTTP state, flag EOF TS.

4. TX logging skips HTTP logging because:
   - TC progress not reached
   - EOF TC flag not set.

The solution has been to flag the very last packet for the flow as such
and use it has a master-EOF flag.

src/flow-timeout.c
src/flow.h
src/output-tx.c

index 335ec9bf3ddf30ab6caf4c773ddf8f3d8319cd1f..8659a7402fcb8bf7c58b615c38520e3f1d14aa91 100644 (file)
@@ -380,6 +380,9 @@ int FlowForceReassemblyForFlow(Flow *f, int server, int client)
                 goto done;
             }
             PKT_SET_SRC(p2, PKT_SRC_FFR);
+            p2->flowflags |= FLOW_PKT_LAST_PSEUDO;
+        } else {
+            p1->flowflags |= FLOW_PKT_LAST_PSEUDO;
         }
     } else {
         if (server == STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION) {
@@ -388,6 +391,7 @@ int FlowForceReassemblyForFlow(Flow *f, int server, int client)
                 goto done;
             }
             PKT_SET_SRC(p1, PKT_SRC_FFR);
+            p1->flowflags |= FLOW_PKT_LAST_PSEUDO;
         } else {
             /* impossible */
             BUG_ON(1);
index e362f8d40d6c2eb335b71660bfae93cccb3765c8..f625ada1060af6e866922965fb3f46b70a8407b8 100644 (file)
@@ -222,6 +222,9 @@ typedef struct AppLayerParserState_ AppLayerParserState;
 #define FLOW_PKT_TOCLIENT_IPONLY_SET    0x10
 #define FLOW_PKT_TOSERVER_FIRST         0x20
 #define FLOW_PKT_TOCLIENT_FIRST         0x40
+/** last pseudo packet in the flow. Can be used to trigger final clean,
+ *  logging, etc. */
+#define FLOW_PKT_LAST_PSEUDO            0x80
 
 #define FLOW_END_FLAG_STATE_NEW         0x01
 #define FLOW_END_FLAG_STATE_ESTABLISHED 0x02
index 4294d40f4cf286f67e470cd12c5966dea5d40598..ff11b879448f0f1de560d07a1e7dccb3fe6b0a90 100644 (file)
@@ -260,15 +260,20 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data)
             if ((tx_logged_old & (1<<logger->logger_id)) == 0) {
                 SCLogDebug("alproto match %d, logging tx_id %"PRIu64, logger->alproto, tx_id);
 
+                const bool last_pseudo = (p->flowflags & FLOW_PKT_LAST_PSEUDO) != 0;
                 const bool ts_eof = AppLayerParserStateIssetFlag(f->alparser,
                         APP_LAYER_PARSER_EOF_TS) != 0;
                 const bool tc_eof = AppLayerParserStateIssetFlag(f->alparser,
                         APP_LAYER_PARSER_EOF_TC) != 0;
-                SCLogDebug("pcap_cnt %"PRIu64", tx_id %"PRIu64" logger %d. EOFs TS %s TC %s",
+                SCLogDebug("pcap_cnt %"PRIu64", tx_id %"PRIu64" logger %d. "
+                        "EOFs TS %s TC %s LAST PSEUDO %s",
                         p->pcap_cnt, tx_id, logger->logger_id,
-                        ts_eof ? "true" : "false", tc_eof ? "true" : "false");
+                        ts_eof ? "true" : "false", tc_eof ? "true" : "false",
+                        last_pseudo ? "true" : "false");
 
-                if (!(ts_eof && tc_eof)) {
+                if ((ts_eof && tc_eof) || last_pseudo) {
+                    SCLogDebug("EOF, so log now");
+                } else {
                     if (logger->LogCondition) {
                         int r = logger->LogCondition(tv, p, alstate, tx, tx_id);
                         if (r == FALSE) {