From: Victor Julien Date: Fri, 23 May 2014 12:54:05 +0000 (+0200) Subject: flow: add flow_end_flags field, add logging X-Git-Tag: suricata-2.1beta1~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f55ca00576b9eb04feb9267f08814af7acf3772;p=thirdparty%2Fsuricata.git flow: add flow_end_flags field, add logging The flow end flags field is filled by the flow manager or the flow hash (in case of forced timeout of a flow) to record the timeout conditions in the flow: - emergency mode - state - reason (timed out or forced) Add logging to the flow logger. --- diff --git a/src/flow-hash.c b/src/flow-hash.c index 607e00c532..698b5bd707 100644 --- a/src/flow-hash.c +++ b/src/flow-hash.c @@ -666,6 +666,19 @@ static Flow *FlowGetUsedFlow(ThreadVars *tv, DecodeThreadVars *dtv) f->fb = NULL; FBLOCK_UNLOCK(fb); + int state = FlowGetFlowState(f); + if (state == FLOW_STATE_NEW) + f->flow_end_flags |= FLOW_END_FLAG_STATE_NEW; + else if (state == FLOW_STATE_ESTABLISHED) + f->flow_end_flags |= FLOW_END_FLAG_STATE_ESTABLISHED; + else if (state == FLOW_STATE_CLOSED) + f->flow_end_flags |= FLOW_END_FLAG_STATE_CLOSED; + + f->flow_end_flags |= FLOW_END_FLAG_FORCED; + + if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) + f->flow_end_flags |= FLOW_END_FLAG_EMERGENCY; + /* invoke flow log api */ if (dtv && dtv->output_flow_thread_data) (void)OutputFlowLog(tv, dtv->output_flow_thread_data, f); diff --git a/src/flow-manager.c b/src/flow-manager.c index fb6d2a1077..4dbd7e58bc 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -275,6 +275,17 @@ static uint32_t FlowManagerHashRowTimeout(Flow *f, struct timeval *ts, f->hnext = NULL; f->hprev = NULL; + if (state == FLOW_STATE_NEW) + f->flow_end_flags |= FLOW_END_FLAG_STATE_NEW; + else if (state == FLOW_STATE_ESTABLISHED) + f->flow_end_flags |= FLOW_END_FLAG_STATE_ESTABLISHED; + else if (state == FLOW_STATE_CLOSED) + f->flow_end_flags |= FLOW_END_FLAG_STATE_CLOSED; + + if (emergency) + f->flow_end_flags |= FLOW_END_FLAG_EMERGENCY; + f->flow_end_flags |= FLOW_END_FLAG_TIMEOUT; + // FlowClearMemory (f, f->protomap); /* no one is referring to this flow, use_cnt 0, removed from hash diff --git a/src/flow-util.h b/src/flow-util.h index afa7cf8a9c..5e4a0ae53e 100644 --- a/src/flow-util.h +++ b/src/flow-util.h @@ -48,6 +48,7 @@ (f)->lastts.tv_usec = 0; \ FLOWLOCK_INIT((f)); \ (f)->protoctx = NULL; \ + (f)->flow_end_flags = 0; \ (f)->alproto = 0; \ (f)->alproto_ts = 0; \ (f)->alproto_tc = 0; \ @@ -87,6 +88,7 @@ (f)->lastts.tv_sec = 0; \ (f)->lastts.tv_usec = 0; \ (f)->protoctx = NULL; \ + (f)->flow_end_flags = 0; \ (f)->alparser = NULL; \ (f)->alstate = NULL; \ (f)->alproto = 0; \ diff --git a/src/flow.h b/src/flow.h index 1cec317603..99dd7f9738 100644 --- a/src/flow.h +++ b/src/flow.h @@ -178,6 +178,13 @@ typedef struct AppLayerParserState_ AppLayerParserState; /** \todo only used by flow keyword internally. */ #define FLOW_PKT_ONLYSTREAM 0x80 +#define FLOW_END_FLAG_STATE_NEW 0x01 +#define FLOW_END_FLAG_STATE_ESTABLISHED 0x02 +#define FLOW_END_FLAG_STATE_CLOSED 0x04 +#define FLOW_END_FLAG_EMERGENCY 0x08 +#define FLOW_END_FLAG_TIMEOUT 0x10 +#define FLOW_END_FLAG_FORCED 0x20 + /** Mutex or RWLocks for the flow. */ //#define FLOWLOCK_RWLOCK #define FLOWLOCK_MUTEX @@ -334,7 +341,9 @@ typedef struct Flow_ /** mapping to Flow's protocol specific protocols for timeouts and state and free functions. */ uint8_t protomap; - uint8_t pad0; + + uint8_t flow_end_flags; + /* coccinelle: Flow:flow_end_flags:FLOW_END_FLAG_ */ AppProto alproto; /**< \brief application level protocol */ AppProto alproto_ts; diff --git a/src/output-json-flow.c b/src/output-json-flow.c index 869bdc0f18..91623f14fa 100644 --- a/src/output-json-flow.c +++ b/src/output-json-flow.c @@ -208,6 +208,27 @@ static void JsonFlowLogJSON(JsonFlowLogThread *aft, json_t *js, Flow *f) json_object_set_new(hjs, "age", json_integer(age)); + if (f->flow_end_flags & FLOW_END_FLAG_EMERGENCY) + json_object_set_new(hjs, "emergency", json_true()); + const char *state = NULL; + if (f->flow_end_flags & FLOW_END_FLAG_STATE_NEW) + state = "new"; + else if (f->flow_end_flags & FLOW_END_FLAG_STATE_ESTABLISHED) + state = "established"; + else if (f->flow_end_flags & FLOW_END_FLAG_STATE_CLOSED) + state = "closed"; + + json_object_set_new(hjs, "state", + json_string(state)); + + const char *reason = NULL; + if (f->flow_end_flags & FLOW_END_FLAG_TIMEOUT) + reason = "timeout"; + else if (f->flow_end_flags & FLOW_END_FLAG_FORCED) + reason = "forced"; + + json_object_set_new(hjs, "reason", + json_string(reason)); json_object_set_new(js, "flow", hjs);