]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
App layer: add 'StateHasEvents' API call
authorVictor Julien <victor@inliniac.net>
Mon, 1 Jul 2013 13:24:50 +0000 (15:24 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 4 Jul 2013 11:52:12 +0000 (13:52 +0200)
Per TX decoder events resulted in significant overhead to the
detection engine, as it walked all TX' all the time to check
if decoder events were available.

This commit introduces a new API call StateHasEvents, which speeds
up this process, at the expense of keeping a counter in the state.

Implement this for DNS as well.

src/app-layer-dns-common.c
src/app-layer-dns-common.h
src/app-layer-dns-tcp.c
src/app-layer-dns-udp.c
src/app-layer-parser.c
src/app-layer-parser.h

index 84f944e06a12c11ec2c61332fc1640a8a6f68fa7..949d32e31809dbf56eefcc9a934f9225a0d7848e 100644 (file)
@@ -45,6 +45,11 @@ void DNSAppLayerDecoderEventsRegister(int alproto) {
 AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id) {
     DNSState *dns_state = (DNSState *)state;
     DNSTransaction *tx;
+
+    if (dns_state->curr && dns_state->curr->tx_num == (id + 1)) {
+        return dns_state->curr->decoder_events;
+    }
+
     TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
         if (tx->tx_num == (id+1))
             return tx->decoder_events;
@@ -52,6 +57,11 @@ AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id) {
     return NULL;
 }
 
+int DNSHasEvents(void *state) {
+    DNSState *dns_state = (DNSState *)state;
+    return (dns_state->events > 0);
+}
+
 void *DNSStateAlloc(void) {
     void *s = SCMalloc(sizeof(DNSState));
     if (unlikely(s == NULL))
@@ -87,6 +97,9 @@ void *DNSGetTx(void *alstate, uint64_t tx_id) {
     DNSState *dns_state = (DNSState *)alstate;
     DNSTransaction *tx = NULL;
 
+    if (dns_state->curr && dns_state->curr->tx_num == tx_id + 1)
+        return dns_state->curr;
+
     TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
         SCLogDebug("tx->tx_num %u, tx_id %"PRIu64, tx->tx_num, (tx_id+1));
         if ((tx_id+1) != tx->tx_num)
@@ -119,6 +132,7 @@ void DNSSetEvent(DNSState *s, uint8_t e) {
         SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
         AppLayerDecoderEventsSetEventRaw(s->curr->decoder_events, e);
         SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
+        s->events++;
     } else {
         SCLogDebug("couldn't set event %u", e);
     }
index 3d899e495780509ef39784bc57879a941ea18236..25c9896ef2806cdfa03af397ebf3f2e107e624a2 100644 (file)
@@ -142,7 +142,7 @@ typedef struct DNSState_ {
     TAILQ_HEAD(, DNSTransaction_) tx_list;  /**< transaction list */
     DNSTransaction *curr;                   /**< ptr to current tx */
     uint16_t transaction_max;
-    uint16_t transaction_done;
+    uint16_t events;
 
     /* used by TCP only */
     uint16_t offset;
@@ -168,6 +168,7 @@ void DNSSetEvent(DNSState *s, uint8_t e);
 void *DNSStateAlloc(void);
 void DNSStateFree(void *s);
 AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id);
+int DNSHasEvents(void *state);
 
 int DNSValidateRequestHeader(DNSState *, const DNSHeader *dns_header);
 int DNSValidateResponseHeader(DNSState *, const DNSHeader *dns_header);
index 73602dfee51658e5b6067eb4ad288b3320cc6e6f..dd0611a1e476a058f16913d34f31659532371e75 100644 (file)
@@ -603,7 +603,6 @@ void DNSStateTransactionFree(void *state, uint16_t id) {
 
     DNSState *s = state;
 
-    s->transaction_done = id;
     SCLogDebug("state %p, id %"PRIu16, s, id);
 
     /* we can't remove the actual transactions here */
@@ -624,7 +623,9 @@ void RegisterDNSTCPParsers(void) {
                        DNSStateFree);
     AppLayerRegisterTransactionIdFuncs(ALPROTO_DNS_TCP,
             DNSStateUpdateTransactionId, DNSStateTransactionFree);
+
     AppLayerRegisterGetEventsFunc(ALPROTO_DNS_TCP, DNSGetEvents);
+    AppLayerRegisterHasEventsFunc(ALPROTO_DNS_TCP, DNSHasEvents);
 
     AppLayerRegisterGetTx(ALPROTO_DNS_TCP,
             DNSGetTx);
index 253ec168364be5c99bc0db66c5db9ab9dab4c1d7..f73d57265b822b05174ee63ba5832ebcac09a42d 100644 (file)
@@ -324,7 +324,6 @@ static void DNSStateTransactionFree(void *state, uint16_t id) {
 
     DNSState *s = state;
 
-    s->transaction_done = id;
     SCLogDebug("state %p, id %"PRIu16, s, id);
 
     /* we can't remove the actual transactions here */
@@ -345,7 +344,9 @@ void RegisterDNSUDPParsers(void) {
                        DNSStateFree);
     AppLayerRegisterTransactionIdFuncs(ALPROTO_DNS_UDP,
             DNSStateUpdateTransactionId, DNSStateTransactionFree);
+
     AppLayerRegisterGetEventsFunc(ALPROTO_DNS_UDP, DNSGetEvents);
+    AppLayerRegisterHasEventsFunc(ALPROTO_DNS_UDP, DNSHasEvents);
 
     AppLayerRegisterGetTx(ALPROTO_DNS_UDP,
             DNSGetTx);
index 1e3c180e410db704debb69e190ba95dd7d157f5f..c919e75c4e62730ffeb0be78c7a333259d37d698 100644 (file)
@@ -121,10 +121,11 @@ AppLayerDecoderEvents *AppLayerGetEventsFromFlowByTx(Flow *f, uint64_t tx_id) {
     }
 }
 
-/** \brief check if we have decoder events */
+/** \brief check if we have decoder events
+ *  \retval 1 yes
+ *  \retval 0 no */
 int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags) {
     AppLayerDecoderEvents *decoder_events;
-    uint64_t tx_id, max_id;
 
     DEBUG_ASSERT_FLOW_LOCKED(f);
 
@@ -132,13 +133,20 @@ int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags) {
         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)
+        /* fast path if supported by proto */
+        if (al_proto_table[f->alproto].StateHasEvents != NULL) {
+            if (al_proto_table[f->alproto].StateHasEvents(f->alstate) == 1)
                 return 1;
+        } else {
+            /* check each tx */
+            uint64_t tx_id = AppLayerTransactionGetInspectId(f, flags);
+            uint64_t 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;
+            }
         }
     }
 
@@ -802,6 +810,11 @@ void AppLayerRegisterGetEventsFunc(uint16_t proto,
     al_proto_table[proto].StateGetEvents = StateGetEvents;
 }
 
+void AppLayerRegisterHasEventsFunc(uint16_t proto,
+        int (*StateHasEvents)(void *)) {
+    al_proto_table[proto].StateHasEvents = StateHasEvents;
+}
+
 /** \brief Indicate to the app layer parser that a logger is active
  *         for this protocol.
  */
index 81c53c73042b454d54097a0ca494c0d860464d27..9a949c1a79b1aa8fc2e68b5b36af89d9841838dd 100644 (file)
@@ -59,6 +59,8 @@ typedef struct AppLayerProto_ {
     void (*Truncate)(void *, uint8_t);
     FileContainer *(*StateGetFiles)(void *, uint8_t);
     AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
+    /* bool indicating a state has decoder/parser events */
+    int (*StateHasEvents)(void *);
 
     int (*StateGetAlstateProgress)(void *alstate, uint8_t direction);
     uint64_t (*StateGetTxCnt)(void *alstate);
@@ -261,6 +263,9 @@ void AppLayerRegisterGetFilesFunc(uint16_t proto,
         FileContainer *(*StateGetFile)(void *, uint8_t));
 void AppLayerRegisterGetEventsFunc(uint16_t proto,
         AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t));
+void AppLayerRegisterHasEventsFunc(uint16_t proto,
+        int (*StateHasEvents)(void *));
+
 void AppLayerRegisterLogger(uint16_t proto);
 uint16_t AppLayerGetProtoByName(const char *);
 const char *AppLayerGetProtoString(int proto);