]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
flow: introduce flow swap support
authorVictor Julien <victor@inliniac.net>
Fri, 3 Aug 2018 09:10:26 +0000 (11:10 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 21 Mar 2019 18:19:04 +0000 (19:19 +0100)
src/flow.c
src/flow.h

index a68eb6da2efcdca1a6ef2f71b7219d70bb9470be..269de7c25f705d9d05f9eea58e8281dba63b8b87 100644 (file)
@@ -246,6 +246,72 @@ int FlowChangeProto(Flow *f)
     return 0;
 }
 
+static inline void FlowSwapFlags(Flow *f)
+{
+    SWAP_FLAGS(f->flags, FLOW_TO_SRC_SEEN, FLOW_TO_DST_SEEN);
+    SWAP_FLAGS(f->flags, FLOW_TOSERVER_IPONLY_SET, FLOW_TOCLIENT_IPONLY_SET);
+    SWAP_FLAGS(f->flags, FLOW_SGH_TOSERVER, FLOW_SGH_TOCLIENT);
+
+    SWAP_FLAGS(f->flags, FLOW_TOSERVER_DROP_LOGGED, FLOW_TOCLIENT_DROP_LOGGED);
+    SWAP_FLAGS(f->flags, FLOW_TS_PM_ALPROTO_DETECT_DONE, FLOW_TC_PM_ALPROTO_DETECT_DONE);
+    SWAP_FLAGS(f->flags, FLOW_TS_PP_ALPROTO_DETECT_DONE, FLOW_TC_PP_ALPROTO_DETECT_DONE);
+    SWAP_FLAGS(f->flags, FLOW_TS_PE_ALPROTO_DETECT_DONE, FLOW_TC_PE_ALPROTO_DETECT_DONE);
+
+    SWAP_FLAGS(f->flags, FLOW_PROTO_DETECT_TS_DONE, FLOW_PROTO_DETECT_TC_DONE);
+}
+
+static inline void FlowSwapFileFlags(Flow *f)
+{
+    SWAP_FLAGS(f->file_flags, FLOWFILE_NO_MAGIC_TS, FLOWFILE_NO_MAGIC_TC);
+    SWAP_FLAGS(f->file_flags, FLOWFILE_NO_MAGIC_TS, FLOWFILE_NO_MAGIC_TC);
+    SWAP_FLAGS(f->file_flags, FLOWFILE_NO_MAGIC_TS, FLOWFILE_NO_MAGIC_TC);
+    SWAP_FLAGS(f->file_flags, FLOWFILE_NO_MAGIC_TS, FLOWFILE_NO_MAGIC_TC);
+}
+
+static inline void TcpStreamFlowSwap(Flow *f)
+{
+    TcpSession *ssn = f->protoctx;
+    SWAP_VARS(TcpStream, ssn->server, ssn->client);
+    if (ssn->data_first_seen_dir & STREAM_TOSERVER) {
+        ssn->data_first_seen_dir = STREAM_TOCLIENT;
+    } else if (ssn->data_first_seen_dir & STREAM_TOCLIENT) {
+        ssn->data_first_seen_dir = STREAM_TOSERVER;
+    }
+}
+
+/** \brief swap the flow's direction
+ *  \note leaves the 'header' untouched. Interpret that based
+ *        on FLOW_DIR_REVERSED flag.
+ *  \warning: only valid before applayer parsing started. This
+ *            function doesn't swap anything in Flow::alparser,
+ *            Flow::alstate
+ */
+void FlowSwap(Flow *f)
+{
+    f->flags |= FLOW_DIR_REVERSED;
+
+    SWAP_VARS(uint32_t, f->probing_parser_toserver_alproto_masks,
+                   f->probing_parser_toclient_alproto_masks);
+
+    FlowSwapFlags(f);
+    FlowSwapFileFlags(f);
+
+    if (f->proto == IPPROTO_TCP) {
+        TcpStreamFlowSwap(f);
+    }
+
+    SWAP_VARS(AppProto, f->alproto_ts, f->alproto_tc);
+    SWAP_VARS(uint8_t, f->min_ttl_toserver, f->max_ttl_toserver);
+    SWAP_VARS(uint8_t, f->min_ttl_toclient, f->max_ttl_toclient);
+
+    /* not touching Flow::alparser and Flow::alstate */
+
+    SWAP_VARS(const void *, f->sgh_toclient, f->sgh_toserver);
+
+    SWAP_VARS(uint32_t, f->todstpktcnt, f->tosrcpktcnt);
+    SWAP_VARS(uint64_t, f->todstbytecnt, f->tosrcbytecnt);
+}
+
 /**
  *  \brief determine the direction of the packet compared to the flow
  *  \retval 0 to_server
@@ -253,26 +319,28 @@ int FlowChangeProto(Flow *f)
  */
 int FlowGetPacketDirection(const Flow *f, const Packet *p)
 {
+    const int reverse = (f->flags & FLOW_DIR_REVERSED) != 0;
+
     if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
         if (!(CMP_PORT(p->sp,p->dp))) {
             /* update flags and counters */
             if (CMP_PORT(f->sp,p->sp)) {
-                return TOSERVER;
+                return TOSERVER ^ reverse;
             } else {
-                return TOCLIENT;
+                return TOCLIENT ^ reverse;
             }
         } else {
             if (CMP_ADDR(&f->src,&p->src)) {
-                return TOSERVER;
+                return TOSERVER ^ reverse;
             } else {
-                return TOCLIENT;
+                return TOCLIENT ^ reverse;
             }
         }
     } else if (p->proto == IPPROTO_ICMP || p->proto == IPPROTO_ICMPV6) {
         if (CMP_ADDR(&f->src,&p->src)) {
-            return TOSERVER;
+            return TOSERVER  ^ reverse;
         } else {
-            return TOCLIENT;
+            return TOCLIENT ^ reverse;
         }
     }
 
index 4d972fb6ae5071f565272c14eab08a4608299d69..a35ae0b9ae301b2cdbf718d959224900ff1e041d 100644 (file)
@@ -101,6 +101,8 @@ typedef struct AppLayerParserState_ AppLayerParserState;
 #define FLOW_CHANGE_PROTO               BIT_U32(24)
 
 #define FLOW_WRONG_THREAD               BIT_U32(25)
+/** Protocol detection told us flow is picked up in wrong direction (midstream) */
+#define FLOW_DIR_REVERSED               BIT_U32(26)
 
 /* File flags */
 
@@ -485,6 +487,7 @@ int FlowHasAlerts(const Flow *);
 void FlowSetChangeProtoFlag(Flow *);
 void FlowUnsetChangeProtoFlag(Flow *);
 int FlowChangeProto(Flow *);
+void FlowSwap(Flow *);
 
 void FlowRegisterTests (void);
 int FlowSetProtoTimeout(uint8_t ,uint32_t ,uint32_t ,uint32_t);