diff --git a/src/app-layer-dns-common.c b/src/app-layer-dns-common.c index 84f944e06a..949d32e318 100644 --- a/src/app-layer-dns-common.c +++ b/src/app-layer-dns-common.c @@ -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); } diff --git a/src/app-layer-dns-common.h b/src/app-layer-dns-common.h index 3d899e4957..25c9896ef2 100644 --- a/src/app-layer-dns-common.h +++ b/src/app-layer-dns-common.h @@ -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); diff --git a/src/app-layer-dns-tcp.c b/src/app-layer-dns-tcp.c index 73602dfee5..dd0611a1e4 100644 --- a/src/app-layer-dns-tcp.c +++ b/src/app-layer-dns-tcp.c @@ -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); diff --git a/src/app-layer-dns-udp.c b/src/app-layer-dns-udp.c index 253ec16836..f73d57265b 100644 --- a/src/app-layer-dns-udp.c +++ b/src/app-layer-dns-udp.c @@ -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); diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 1e3c180e41..c919e75c4e 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -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. */ diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 81c53c7304..9a949c1a79 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -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);