]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app layer: add support for per TX decoder events
authorVictor Julien <victor@inliniac.net>
Thu, 2 May 2013 10:00:40 +0000 (12:00 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 27 Jun 2013 16:17:15 +0000 (18:17 +0200)
src/app-layer-parser.c
src/app-layer-parser.h
src/decode-events.h
src/detect-app-layer-event.c
src/detect.c

index 46ee54ea520b91148c1bbb59b99ce05d5486b1bb..1e3c180e410db704debb69e190ba95dd7d157f5f 100644 (file)
@@ -99,6 +99,67 @@ FileContainer *AppLayerGetFilesFromFlow(Flow *f, uint8_t direction) {
     }
 }
 
+/** \brief Get the decoder events from the flow
+ *  \param f flow pointer to a LOCKED flow
+ *  \param tx_id transaction id
+ *  \retval files void pointer to the state
+ *  \retval NULL in case we have no state */
+AppLayerDecoderEvents *AppLayerGetEventsFromFlowByTx(Flow *f, uint64_t tx_id) {
+    SCEnter();
+
+    DEBUG_ASSERT_FLOW_LOCKED(f);
+
+    uint16_t alproto = f->alproto;
+    if (alproto == ALPROTO_UNKNOWN)
+        SCReturnPtr(NULL, "AppLayerDecoderEvents");
+
+    if (al_proto_table[alproto].StateGetEvents != NULL) {
+        AppLayerDecoderEvents *ptr = al_proto_table[alproto].StateGetEvents(AppLayerGetProtoStateFromFlow(f), tx_id);
+        SCReturnPtr(ptr, "AppLayerDecoderEvents");
+    } else {
+        SCReturnPtr(NULL, "AppLayerDecoderEvents");
+    }
+}
+
+/** \brief check if we have decoder events */
+int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags) {
+    AppLayerDecoderEvents *decoder_events;
+    uint64_t tx_id, max_id;
+
+    DEBUG_ASSERT_FLOW_LOCKED(f);
+
+    if (f->alproto <= ALPROTO_UNKNOWN || f->alproto >= ALPROTO_MAX)
+        return 0;
+
+    if (AppLayerProtoIsTxEventAware(f->alproto)) {
+        tx_id = AppLayerTransactionGetInspectId(f, flags);
+        max_id = AppLayerGetTxCnt(f->alproto, f->alstate);
+
+        for ( ; tx_id < max_id; tx_id++) {
+            decoder_events = AppLayerGetEventsFromFlowByTx(f, tx_id);
+            if (decoder_events && decoder_events->cnt)
+                return 1;
+        }
+    }
+
+    decoder_events = AppLayerGetDecoderEventsForFlow(f);
+    if (decoder_events && decoder_events->cnt)
+        return 1;
+
+    return 0;
+}
+
+/** \brief Return true if alproto uses per TX events
+ *  \param alproto proto to check
+ */
+int AppLayerProtoIsTxEventAware(uint16_t alproto) {
+    if (alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_MAX &&
+        al_proto_table[alproto].StateGetEvents != NULL)
+        return 1;
+
+    return 0;
+}
+
 /** \brief Alloc a AppLayerParserResultElmt func for the pool */
 static void *AlpResultElmtPoolAlloc()
 {
@@ -735,6 +796,12 @@ void AppLayerRegisterGetAlstateProgressCompletionStatus(uint16_t alproto,
         StateGetAlstateProgressCompletionStatus;
 }
 
+void AppLayerRegisterGetEventsFunc(uint16_t proto,
+        AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
+{
+    al_proto_table[proto].StateGetEvents = StateGetEvents;
+}
+
 /** \brief Indicate to the app layer parser that a logger is active
  *         for this protocol.
  */
index 3670e046fee74d9b62dc7dfb0b960c49339d4ab8..81c53c73042b454d54097a0ca494c0d860464d27 100644 (file)
@@ -58,6 +58,7 @@ typedef struct AppLayerProto_ {
     /** truncate state after a gap/depth event */
     void (*Truncate)(void *, uint8_t);
     FileContainer *(*StateGetFiles)(void *, uint8_t);
+    AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
 
     int (*StateGetAlstateProgress)(void *alstate, uint8_t direction);
     uint64_t (*StateGetTxCnt)(void *alstate);
@@ -258,6 +259,8 @@ void AppLayerRegisterLocalStorageFunc(uint16_t proto,
 void *AppLayerGetProtocolParserLocalStorage(uint16_t);
 void AppLayerRegisterGetFilesFunc(uint16_t proto,
         FileContainer *(*StateGetFile)(void *, uint8_t));
+void AppLayerRegisterGetEventsFunc(uint16_t proto,
+        AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t));
 void AppLayerRegisterLogger(uint16_t proto);
 uint16_t AppLayerGetProtoByName(const char *);
 const char *AppLayerGetProtoString(int proto);
@@ -332,6 +335,9 @@ void AppLayerPrintProbingParsers(AppLayerProbingParser *);
 
 void AppLayerListSupportedProtocols(void);
 AppLayerDecoderEvents *AppLayerGetDecoderEventsForFlow(Flow *);
+AppLayerDecoderEvents *AppLayerGetEventsFromFlowByTx(Flow *f, uint64_t tx_id);
+int AppLayerProtoIsTxEventAware(uint16_t alproto);
+int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags);
 
 /***** Alproto param retrieval ******/
 
index 6c7f4df7c4bf7ff349bc44c3efd11ab7fcf313f9..93cf8bc605c4062964508e875f415589f73958f2 100644 (file)
@@ -310,6 +310,42 @@ static inline int AppLayerDecoderEventsIsEventSet(int module_id,
 
 #endif /* #if 0 */
 
+/**
+ * \brief Set an app layer decoder event.
+ *
+ * \param sevents Pointer to a DecoderEvents pointer head.  If
+ *                the head points to a DecoderEvents instance, a
+ *                new instance would be created and the pointer head would
+ *                would be updated with this new instance
+ * \param event   The event to be stored.
+ */
+#define AppLayerDecoderEventsSetEventRaw(sevents, event)                \
+    do {                                                                \
+        AppLayerDecoderEvents *devents = (sevents);                     \
+        if (devents == NULL) {                                          \
+            AppLayerDecoderEvents *new_devents =                        \
+                SCMalloc(sizeof(AppLayerDecoderEvents));                \
+            if (new_devents == NULL)                                    \
+                break;                                                  \
+            memset(new_devents, 0, sizeof(AppLayerDecoderEvents));      \
+            (sevents) = devents = new_devents;                          \
+        }                                                               \
+        if (devents->cnt == devents->events_buffer_size) {              \
+            devents->events = SCRealloc(devents->events,                \
+                                       (devents->cnt +                  \
+                                        DECODER_EVENTS_BUFFER_STEPS) *  \
+                                        sizeof(uint8_t));               \
+            if (devents->events == NULL) {                              \
+                devents->events_buffer_size = 0;                        \
+                devents->cnt = 0;                                       \
+                (sevents) = NULL;                                       \
+                break;                                                  \
+            }                                                           \
+            devents->events_buffer_size += DECODER_EVENTS_BUFFER_STEPS; \
+        }                                                               \
+        devents->events[devents->cnt++] = (event);                      \
+    } while (0)
+
 /**
  * \brief Set an app layer decoder event.
  *
index b20417ccb698bb131bff066308ea09f5dd2cc99c..2b6290e97065f91408d16a2e2459be1278c1a97a 100644 (file)
@@ -73,16 +73,36 @@ int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                              SigMatch *m)
 {
     SCEnter();
+    AppLayerDecoderEvents *decoder_events = NULL;
     int r = 0;
-
+    uint64_t tx_id = 0, max_id;
     DetectAppLayerEventData *aled = (DetectAppLayerEventData *)m->ctx;
 
     FLOWLOCK_RDLOCK(f);
 
-    AppLayerDecoderEvents *decoder_events = AppLayerGetDecoderEventsForFlow(f);
-    if (decoder_events != NULL &&
-            AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) {
-        r = 1;
+    /* inspect TX events first if we need to */
+    if (AppLayerProtoIsTxEventAware(f->alproto)) {
+        SCLogDebug("proto is AppLayerProtoIsTxEventAware true");
+
+        tx_id = AppLayerTransactionGetInspectId(f, flags);
+        max_id = AppLayerGetTxCnt(f->alproto, f->alstate);
+
+        for ( ; tx_id < max_id; tx_id++) {
+            decoder_events = AppLayerGetEventsFromFlowByTx(f, tx_id);
+            if (decoder_events != NULL &&
+                    AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) {
+                r = 1;
+                break;
+            }
+        }
+    }
+
+    if (r == 0) {
+        decoder_events = AppLayerGetDecoderEventsForFlow(f);
+        if (decoder_events != NULL &&
+                AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) {
+            r = 1;
+        }
     }
 
     FLOWLOCK_UNLOCK(f);
index cd1e23d8e3c51f9e28cdc271b75f7409773d673b..784d0015d6584e32874e37d6be1f375e3a54aacf 100644 (file)
@@ -1258,10 +1258,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
     SigMatch *sm = NULL;
     uint16_t alversion = 0;
     int reset_de_state = 0;
-    AppLayerDecoderEvents *app_decoder_events = NULL;
-    int app_decoder_events_cnt = 0;
     int alerts = 0;
     int i;
+    int app_decoder_events = 0;
 
     SCEnter();
 
@@ -1346,9 +1345,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
                 SCLogDebug("packet doesn't have established flag set (proto %d)", p->proto);
             }
 
-            app_decoder_events = AppLayerGetDecoderEventsForFlow(p->flow);
-            if (app_decoder_events != NULL)
-                app_decoder_events_cnt = app_decoder_events->cnt;
+            app_decoder_events = AppLayerFlowHasDecoderEvents(p->flow, flags);
         }
         FLOWLOCK_UNLOCK(p->flow);
 
@@ -1447,7 +1444,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
 
     /* create our prefilter mask */
     SignatureMask mask = 0;
-    PacketCreateMask(p, &mask, alproto, alstate, smsg, app_decoder_events_cnt);
+    PacketCreateMask(p, &mask, alproto, alstate, smsg, app_decoder_events);
 
     /* run the mpm for each type */
     PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM);
@@ -2184,7 +2181,7 @@ deonly:
  */
 static void
 PacketCreateMask(Packet *p, SignatureMask *mask, uint16_t alproto, void *alstate, StreamMsg *smsg,
-        int app_decoder_events_cnt)
+        int app_decoder_events)
 {
     if (!(p->flags & PKT_NOPAYLOAD_INSPECTION) && (p->payload_len > 0 || smsg != NULL)) {
         SCLogDebug("packet has payload");
@@ -2194,7 +2191,7 @@ PacketCreateMask(Packet *p, SignatureMask *mask, uint16_t alproto, void *alstate
         (*mask) |= SIG_MASK_REQUIRE_NO_PAYLOAD;
     }
 
-    if (p->events.cnt > 0 || app_decoder_events_cnt > 0) {
+    if (p->events.cnt > 0 || app_decoder_events != 0) {
         SCLogDebug("packet/flow has events set");
         (*mask) |= SIG_MASK_REQUIRE_ENGINE_EVENT;
     }